You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by mp...@apache.org on 2015/01/07 12:02:34 UTC

svn commit: r1650034 [1/2] - in /sling/trunk/contrib/extensions/distribution: core/src/main/java/org/apache/sling/distribution/agent/impl/ core/src/main/java/org/apache/sling/distribution/component/impl/ core/src/main/java/org/apache/sling/distribution...

Author: mpetria
Date: Wed Jan  7 11:02:33 2015
New Revision: 1650034

URL: http://svn.apache.org/r1650034
Log:
SLING-4289: refactoring the resourceproviders for osgi configs and osgi services

Added:
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DefaultDistributionConfigurationManager.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponent.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentKind.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentProvider.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionConfiguration.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionConfigurationManager.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionConfigurationResourceProvider.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionConfigurationResourceProviderFactory.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionServiceResourceProvider.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionServiceResourceProviderFactory.java
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.author/publish/
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.author/publish-multiple/
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.author/publish-multiple/org.apache.sling.distribution.agent.impl.ForwardDistributionAgentFactory-publish-multiple.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.author/publish-reverse/
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.author/publish-reverse/org.apache.sling.distribution.agent.impl.ReverseDistributionAgentFactory-publish-reverse.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.author/publish-reverse/org.apache.sling.distribution.trigger.impl.LocalDistributionTriggerFactory-publish-reverse-scheduled.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.author/publish/org.apache.sling.distribution.agent.impl.ForwardDistributionAgentFactory-publish.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.author/pubsync/
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.author/pubsync/org.apache.sling.distribution.agent.impl.SyncDistributionAgentFactory-pubsync.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.author/pubsync/org.apache.sling.distribution.trigger.impl.LocalDistributionTriggerFactory-pubsync-scheduled-trigger.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.publish/cache-flush/
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.publish/cache-flush/org.apache.sling.distribution.agent.impl.SimpleDistributionAgentFactory-cache-flush.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.publish/cache-flush/org.apache.sling.distribution.packaging.impl.importer.AdvancedRemoteDistributionPackageImporter-cache-flush.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.publish/org.apache.sling.distribution.packaging.impl.exporter.AgentDistributionPackageExporterFactory-reverse.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.publish/org.apache.sling.distribution.packaging.impl.exporter.LocalDistributionPackageExporterFactory-default.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.publish/org.apache.sling.distribution.packaging.impl.importer.LocalDistributionPackageImporterFactory-default.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.publish/reverse/
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.publish/reverse-pubsync/
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.publish/reverse-pubsync/org.apache.sling.distribution.agent.impl.QueueDistributionAgentFactory-reverse-pubsync.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.publish/reverse/org.apache.sling.distribution.agent.impl.QueueDistributionAgentFactory-reverse.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.publish/reverse/org.apache.sling.distribution.trigger.impl.LocalDistributionTriggerFactory-reverse-userGeneratedContent.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install/resources/services/org.apache.sling.distribution.resources.impl.DistributionServiceResourceProviderFactory-agents.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install/resources/services/org.apache.sling.distribution.resources.impl.DistributionServiceResourceProviderFactory-exporters.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install/resources/services/org.apache.sling.distribution.resources.impl.DistributionServiceResourceProviderFactory-importers.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install/resources/services/org.apache.sling.distribution.resources.impl.DistributionServiceResourceProviderFactory-triggers.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install/resources/settings/org.apache.sling.distribution.resources.impl.DistributionConfigurationResourceProviderFactory-agents.json
Removed:
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/OsgiConfigurationResourceProvider.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/OsgiPropertiesResourceProviderFactory.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/OsgiServicePropertiesResourceProvider.java
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.author/org.apache.sling.distribution.component.impl.ResourceBasedDistributionComponentFactory.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.osgi.author/
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.osgi.publish/
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install.publish/org.apache.sling.distribution.component.impl.ResourceBasedDistributionComponentFactory.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install/resources/services/org.apache.sling.distribution.resources.impl.OsgiPropertiesResourceProviderFactory-agents.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install/resources/services/org.apache.sling.distribution.resources.impl.OsgiPropertiesResourceProviderFactory-exporters.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install/resources/services/org.apache.sling.distribution.resources.impl.OsgiPropertiesResourceProviderFactory-importers.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install/resources/services/org.apache.sling.distribution.resources.impl.OsgiPropertiesResourceProviderFactory-triggers.json
    sling/trunk/contrib/extensions/distribution/sample/src/main/resources/SLING-CONTENT/libs/sling/distribution/install/resources/settings/org.apache.sling.distribution.resources.impl.OsgiPropertiesResourceProviderFactory-simpleAgents.json
Modified:
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/agent/impl/AbstractDistributionAgentFactory.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/agent/impl/SyncDistributionAgentFactory.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DefaultDistributionComponentProvider.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentUtils.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/impl/DefaultDistributor.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/OsgiUtils.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/common/AbstractModifyingResourceProvider.java
    sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/common/AbstractReadableResourceProvider.java
    sling/trunk/contrib/extensions/distribution/it/src/test/java/org/apache/sling/distribution/it/DistributionIntegrationTestBase.java
    sling/trunk/contrib/extensions/distribution/it/src/test/java/org/apache/sling/distribution/it/DistributionUtils.java

Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/agent/impl/AbstractDistributionAgentFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/agent/impl/AbstractDistributionAgentFactory.java?rev=1650034&r1=1650033&r2=1650034&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/agent/impl/AbstractDistributionAgentFactory.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/agent/impl/AbstractDistributionAgentFactory.java Wed Jan  7 11:02:33 2015
@@ -90,7 +90,9 @@ public abstract class AbstractDistributi
 
             agentName = PropertiesUtil.toString(config.get(NAME), null);
             props.put(NAME, agentName);
-            props.put(DistributionConstants.PN_IS_RESOURCE, config.get(DistributionConstants.PN_IS_RESOURCE));
+
+            boolean isResource = PropertiesUtil.toBoolean(config.get(DistributionConstants.PN_IS_RESOURCE), false);
+            props.put(DistributionConstants.PN_IS_RESOURCE, isResource);
 
             if (componentReg == null) {
 

Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/agent/impl/SyncDistributionAgentFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/agent/impl/SyncDistributionAgentFactory.java?rev=1650034&r1=1650033&r2=1650034&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/agent/impl/SyncDistributionAgentFactory.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/agent/impl/SyncDistributionAgentFactory.java Wed Jan  7 11:02:33 2015
@@ -79,7 +79,7 @@ import java.util.concurrent.CopyOnWriteA
 @Reference(name = "triggers", referenceInterface = DistributionTrigger.class,
         policy = ReferencePolicy.DYNAMIC, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
         bind = "bindDistributionTrigger", unbind = "unbindDistributionTrigger")
-public class SyncDistributionAgentFactory {
+public class SyncDistributionAgentFactory extends AbstractDistributionAgentFactory {
     private final Logger log = LoggerFactory.getLogger(getClass());
 
     @Property(label = "Name")
@@ -133,101 +133,44 @@ public class SyncDistributionAgentFactor
     @Reference
     private ResourceResolverFactory resourceResolverFactory;
 
-    private ServiceRegistration componentReg;
-    private BundleContext savedContext;
-    private Map<String, Object> savedConfig;
-    private String agentName;
-    private final List<DistributionTrigger> triggers = new CopyOnWriteArrayList<DistributionTrigger>();
-
-    private SimpleDistributionAgent agent;
 
     @Activate
     protected void activate(BundleContext context, Map<String, Object> config) {
-        log.info("activating with config {}", OsgiUtils.osgiPropertyMapToString(config));
-
-
-        savedContext = context;
-        savedConfig = config;
-
-        // inject configuration
-        Dictionary<String, Object> props = new Hashtable<String, Object>();
-
-        boolean enabled = PropertiesUtil.toBoolean(config.get(ENABLED), true);
-
-        if (enabled) {
-            props.put(ENABLED, true);
-
-            agentName = PropertiesUtil.toString(config.get(NAME), null);
-            props.put(NAME, agentName);
-            props.put(DistributionConstants.PN_IS_RESOURCE, config.get(DistributionConstants.PN_IS_RESOURCE));
-
-            if (componentReg == null) {
-
-                String serviceName = PropertiesUtil.toString(config.get(SERVICE_NAME), null);
-
-
-
-                try {
-
-
-                    String[] exporterEndpoints = PropertiesUtil.toStringArray(config.get(EXPORTER_ENDPOINTS), new String[0]);
-                    Map<String, String> importerEndpointsMap = SettingsUtils.toUriMap(config.get(IMPORTER_ENDPOINTS));
+        super.activate(context, config);
+    }
 
+    protected void bindDistributionTrigger(DistributionTrigger distributionTrigger, Map<String, Object> config) {
+        super.bindDistributionTrigger(distributionTrigger, config);
 
-                    DistributionPackageExporter packageExporter = new RemoteDistributionPackageExporter(packageBuilder, transportSecretProvider, exporterEndpoints, TransportEndpointStrategyType.All, 1);
-                    DistributionPackageImporter packageImporter = new RemoteDistributionPackageImporter(transportSecretProvider, importerEndpointsMap, TransportEndpointStrategyType.All);
-                    DistributionQueueProvider queueProvider =  new JobHandlingDistributionQueueProvider(agentName, jobManager, savedContext);
-                    DistributionQueueDispatchingStrategy dispatchingStrategy = new SingleQueueDispatchingStrategy();
+    }
 
-                    agent = new SimpleDistributionAgent(agentName, false, serviceName,
-                            packageImporter, packageExporter, requestAuthorizationStrategy,
-                            queueProvider, dispatchingStrategy, distributionEventFactory, resourceResolverFactory, triggers);
-                }
-                catch (IllegalArgumentException e) {
-                    log.warn("cannot create agent", e);
-                }
+    protected void unbindDistributionTrigger(DistributionTrigger distributionTrigger, Map<String, Object> config) {
+        super.unbindDistributionTrigger(distributionTrigger, config);
+    }
 
-                log.debug("activated agent {}", agentName);
+    @Deactivate
+    protected void deactivate(BundleContext context) {
+        super.deactivate(context);
+    }
 
-                if (agent != null) {
 
-                    // register agent service
-                    componentReg = context.registerService(DistributionAgent.class.getName(), agent, props);
-                    agent.enable();
-                }
-            }
-        }
-    }
+    @Override
+    protected SimpleDistributionAgent createAgent(String agentName, BundleContext context, Map<String, Object> config) {
+        String serviceName = PropertiesUtil.toString(config.get(SERVICE_NAME), null);
 
-    private void bindDistributionTrigger(DistributionTrigger distributionTrigger, Map<String, Object> config) {
-        triggers.add(distributionTrigger);
-        if (agent != null) {
-            agent.enableTrigger(distributionTrigger);
-        }
 
-    }
+        String[] exporterEndpoints = PropertiesUtil.toStringArray(config.get(EXPORTER_ENDPOINTS), new String[0]);
+        Map<String, String> importerEndpointsMap = SettingsUtils.toUriMap(config.get(IMPORTER_ENDPOINTS));
 
-    private void unbindDistributionTrigger(DistributionTrigger distributionTrigger, Map<String, Object> config) {
-        triggers.remove(distributionTrigger);
 
-        if (agent != null) {
-            agent.disableTrigger(distributionTrigger);
-        }
-    }
+        DistributionPackageExporter packageExporter = new RemoteDistributionPackageExporter(packageBuilder, transportSecretProvider, exporterEndpoints, TransportEndpointStrategyType.All, 1);
+        DistributionPackageImporter packageImporter = new RemoteDistributionPackageImporter(transportSecretProvider, importerEndpointsMap, TransportEndpointStrategyType.All);
+        DistributionQueueProvider queueProvider =  new JobHandlingDistributionQueueProvider(agentName, jobManager, context);
+        DistributionQueueDispatchingStrategy dispatchingStrategy = new SingleQueueDispatchingStrategy();
 
-    @Deactivate
-    protected void deactivate(BundleContext context) {
-        if (componentReg != null) {
-            ServiceReference reference = componentReg.getReference();
-            Object service = context.getService(reference);
-            if (service instanceof SimpleDistributionAgent) {
-                ((SimpleDistributionAgent) service).disable();
-            }
-
-            componentReg.unregister();
-            componentReg = null;
-            agent = null;
-        }
+        return new SimpleDistributionAgent(agentName, false, serviceName,
+                packageImporter, packageExporter, requestAuthorizationStrategy,
+                queueProvider, dispatchingStrategy, distributionEventFactory, resourceResolverFactory, triggers);
 
     }
 }

Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DefaultDistributionComponentProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DefaultDistributionComponentProvider.java?rev=1650034&r1=1650033&r2=1650034&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DefaultDistributionComponentProvider.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DefaultDistributionComponentProvider.java Wed Jan  7 11:02:33 2015
@@ -18,8 +18,8 @@
  */
 package org.apache.sling.distribution.component.impl;
 
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -52,35 +52,61 @@ import org.slf4j.LoggerFactory;
         @Reference(name = "distributionQueueDistributionStrategy", referenceInterface = DistributionQueueDispatchingStrategy.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC),
         @Reference(name = "distributionTransportSecretProvider", referenceInterface = DistributionTransportSecretProvider.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC)
 })
-@Service(DefaultDistributionComponentProvider.class)
-public class DefaultDistributionComponentProvider {
+@Service(DistributionComponentProvider.class)
+public class DefaultDistributionComponentProvider implements DistributionComponentProvider {
 
     public static final String NAME = DistributionComponentUtils.PN_NAME;
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
-    private Map<String, DistributionAgent> distributionAgentMap = new ConcurrentHashMap<String, DistributionAgent>();
-    private Map<String, DistributionQueueProvider> distributionQueueProviderMap = new ConcurrentHashMap<String, DistributionQueueProvider>();
-    private Map<String, DistributionQueueDispatchingStrategy> distributionQueueDistributionStrategyMap = new ConcurrentHashMap<String, DistributionQueueDispatchingStrategy>();
-    private Map<String, DistributionTransportSecretProvider> distributionTransportSecretProviderMap = new ConcurrentHashMap<String, DistributionTransportSecretProvider>();
-    private Map<String, DistributionPackageImporter> distributionPackageImporterMap = new ConcurrentHashMap<String, DistributionPackageImporter>();
-    private Map<String, DistributionPackageExporter> distributionPackageExporterMap = new ConcurrentHashMap<String, DistributionPackageExporter>();
+    private Map<String, DistributionComponent<DistributionAgent>> distributionAgentMap = new ConcurrentHashMap<String, DistributionComponent<DistributionAgent>>();
+    private Map<String, DistributionComponent<DistributionQueueProvider>> distributionQueueProviderMap = new ConcurrentHashMap<String, DistributionComponent<DistributionQueueProvider>>();
+    private Map<String, DistributionComponent<DistributionQueueDispatchingStrategy>> distributionQueueDistributionStrategyMap = new ConcurrentHashMap<String, DistributionComponent<DistributionQueueDispatchingStrategy>>();
+    private Map<String, DistributionComponent<DistributionTransportSecretProvider>> distributionTransportSecretProviderMap = new ConcurrentHashMap<String, DistributionComponent<DistributionTransportSecretProvider>>();
+    private Map<String, DistributionComponent<DistributionPackageImporter>> distributionPackageImporterMap = new ConcurrentHashMap<String, DistributionComponent<DistributionPackageImporter>>();
+    private Map<String, DistributionComponent<DistributionPackageExporter>> distributionPackageExporterMap = new ConcurrentHashMap<String, DistributionComponent<DistributionPackageExporter>>();
     private BundleContext bundleContext;
 
-    public <ComponentType> ComponentType getComponent(@Nonnull Class<ComponentType> type,
-                                                                                   @Nullable String componentName) {
+
+    public DistributionComponent getComponent(DistributionComponentKind kind, String componentName) {
+        Map<String, DistributionComponent> componentMap = getComponentMap(kind.asClass());
+        return componentMap.get(componentName);
+    }
+
+    public List<DistributionComponent> getComponents(DistributionComponentKind kind) {
+        Map<String, DistributionComponent> componentMap = getComponentMap(kind.asClass());
+
+        List<DistributionComponent> componentList = new ArrayList<DistributionComponent>();
+        componentList.addAll(componentMap.values());
+
+        return componentList;
+    }
+
+    public <ComponentType> ComponentType getService(Class<ComponentType> type, String componentName) {
+        Map<String, DistributionComponent<ComponentType>> componentMap = getComponentMap(type);
+        DistributionComponent<ComponentType> component = componentMap.get(componentName);
+
+        if (component == null) {
+            return null;
+        }
+
+        return component.getService();
+    }
+
+
+    private <ComponentType> Map<String, DistributionComponent<ComponentType>> getComponentMap(Class<ComponentType> type) {
         if (type.isAssignableFrom(DistributionAgent.class)) {
-            return (ComponentType) distributionAgentMap.get(componentName);
+            return (Map) distributionAgentMap;
         } else if (type.isAssignableFrom(DistributionPackageExporter.class)) {
-            return (ComponentType) distributionPackageExporterMap.get(componentName);
+            return (Map) distributionPackageExporterMap;
         } else if (type.isAssignableFrom(DistributionPackageImporter.class)) {
-            return (ComponentType) distributionPackageImporterMap.get(componentName);
+            return (Map) distributionPackageImporterMap;
         } else if (type.isAssignableFrom(DistributionQueueProvider.class)) {
-            return (ComponentType) distributionQueueProviderMap.get(componentName);
+            return (Map) distributionQueueProviderMap;
         } else if (type.isAssignableFrom(DistributionQueueDispatchingStrategy.class)) {
-            return (ComponentType) distributionQueueDistributionStrategyMap.get(componentName);
+            return (Map) distributionQueueDistributionStrategyMap;
         } else if (type.isAssignableFrom(DistributionTransportSecretProvider.class)) {
-            return (ComponentType) distributionTransportSecretProviderMap.get(componentName);
+            return (Map) distributionTransportSecretProviderMap;
         }
 
         return null;
@@ -88,103 +114,88 @@ public class DefaultDistributionComponen
 
     private void bindDistributionQueueProvider(DistributionQueueProvider distributionQueueProvider, Map<String, Object> config) {
 
-        String name = PropertiesUtil.toString(config.get(NAME), null);
-        if (name != null) {
-            distributionQueueProviderMap.put(name, distributionQueueProvider);
-        }
+       put(DistributionQueueProvider.class, distributionQueueProvider, config);
     }
 
     private void unbindDistributionQueueProvider(DistributionQueueProvider distributionQueueProvider, Map<String, Object> config) {
 
-        String name = PropertiesUtil.toString(config.get(NAME), null);
-        if (name != null) {
-            distributionQueueProviderMap.remove(name);
-        }
+        remove(DistributionQueueProvider.class, distributionQueueProvider, config);
     }
 
     private void bindDistributionQueueDistributionStrategy(DistributionQueueDispatchingStrategy distributionQueueDispatchingStrategy, Map<String, Object> config) {
 
-        String name = PropertiesUtil.toString(config.get(NAME), null);
-        if (name != null) {
-            distributionQueueDistributionStrategyMap.put(name, distributionQueueDispatchingStrategy);
-        }
+        put(DistributionQueueDispatchingStrategy.class, distributionQueueDispatchingStrategy, config);
     }
 
     private void unbindDistributionQueueDistributionStrategy(DistributionQueueDispatchingStrategy distributionQueueDispatchingStrategy, Map<String, Object> config) {
 
-        String name = PropertiesUtil.toString(config.get(NAME), null);
-        if (name != null) {
-            distributionQueueDistributionStrategyMap.remove(name);
-        }
+        remove(DistributionQueueDispatchingStrategy.class, distributionQueueDispatchingStrategy, config);
     }
 
     private void bindDistributionTransportSecretProvider(DistributionTransportSecretProvider distributionTransportSecretProvider, Map<String, Object> config) {
 
-        String name = PropertiesUtil.toString(config.get(NAME), null);
-        if (name != null) {
-            distributionTransportSecretProviderMap.put(name, distributionTransportSecretProvider);
-
-        }
+        put(DistributionTransportSecretProvider.class, distributionTransportSecretProvider, config);
 
     }
 
     private void unbindDistributionTransportSecretProvider(DistributionTransportSecretProvider distributionTransportSecretProvider, Map<String, Object> config) {
 
-        String name = PropertiesUtil.toString(config.get(NAME), null);
-        if (name != null) {
-            distributionTransportSecretProviderMap.remove(name);
-
-        }
+       remove(DistributionTransportSecretProvider.class, distributionTransportSecretProvider, config);
     }
 
     private void bindDistributionPackageImporter(DistributionPackageImporter distributionPackageImporter, Map<String, Object> config) {
 
-        String name = PropertiesUtil.toString(config.get(NAME), null);
-        if (name != null) {
-            distributionPackageImporterMap.put(name, distributionPackageImporter);
-
-        }
+       put(DistributionPackageImporter.class, distributionPackageImporter, config);
     }
 
     private void unbindDistributionPackageImporter(DistributionPackageImporter distributionPackageImporter, Map<String, Object> config) {
 
-        String name = PropertiesUtil.toString(config.get(NAME), null);
-        if (name != null) {
-            distributionPackageImporterMap.remove(name);
-        }
+       remove(DistributionPackageImporter.class, distributionPackageImporter, config);
     }
 
     private void bindDistributionPackageExporter(DistributionPackageExporter distributionPackageExporter, Map<String, Object> config) {
 
-        String name = PropertiesUtil.toString(config.get(NAME), null);
-        if (name != null) {
-            distributionPackageExporterMap.put(name, distributionPackageExporter);
-        }
+        put(DistributionPackageExporter.class, distributionPackageExporter, config);
     }
 
     private void unbindDistributionPackageExporter(DistributionPackageExporter distributionPackageExporter, Map<String, Object> config) {
 
-        String name = PropertiesUtil.toString(config.get(NAME), null);
-        if (name != null) {
-            distributionPackageExporterMap.remove(name);
-        }
+        remove(DistributionPackageExporter.class, distributionPackageExporter, config);
 
     }
 
     private void bindDistributionAgent(DistributionAgent distributionAgent, Map<String, Object> config) {
 
+       put(DistributionAgent.class, distributionAgent, config);
+    }
+
+    private void unbindDistributionAgent(DistributionAgent distributionAgent, Map<String, Object> config) {
+
+        remove(DistributionAgent.class, distributionAgent, config);
+
+    }
+
+    private <ComponentType> void put(Class<ComponentType> typeClass, ComponentType service, Map<String, Object> config) {
+        Map<String, DistributionComponent<ComponentType>> componentMap = getComponentMap(typeClass);
+
         String name = PropertiesUtil.toString(config.get(NAME), null);
-        if (name != null) {
-            distributionAgentMap.put(name, distributionAgent);
+        DistributionComponentKind kind = DistributionComponentKind.fromClass(typeClass);
+        if (name != null && kind!=null) {
+            componentMap.put(name, new DistributionComponent<ComponentType>(kind, name, service, config));
         }
+
     }
 
-    private void unbindDistributionAgent(DistributionAgent distributionAgent, Map<String, Object> config) {
+    private <ComponentType> void remove(Class<ComponentType> typeClass, ComponentType service, Map<String, Object> config) {
+
+        Map<String, DistributionComponent<ComponentType>> componentMap = getComponentMap(typeClass);
 
         String name = PropertiesUtil.toString(config.get(NAME), null);
         if (name != null) {
-            distributionAgentMap.remove(name);
+            componentMap.remove(name);
         }
 
     }
+
+
 }

Added: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DefaultDistributionConfigurationManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DefaultDistributionConfigurationManager.java?rev=1650034&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DefaultDistributionConfigurationManager.java (added)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DefaultDistributionConfigurationManager.java Wed Jan  7 11:02:33 2015
@@ -0,0 +1,259 @@
+/*
+ * 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.distribution.component.impl;
+
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.distribution.resources.impl.OsgiUtils;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * {@link org.apache.sling.distribution.component.impl.DistributionComponentManager} implementation based on OSGI configs.
+ * For each tree of properties a set of OSGI configs is generated and registered in ConfigurationAdmin.
+ * To delete a component all configs owned by that component will be unregistered from ConfigurationAdmin.
+ */
+@Component
+@Service(DistributionConfigurationManager.class)
+public class DefaultDistributionConfigurationManager implements DistributionConfigurationManager {
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    @Reference
+    ConfigurationAdmin configurationAdmin;
+
+
+    public List<DistributionConfiguration> getConfigs(DistributionComponentKind kind) {
+        List<Configuration> configurations = getOsgiConfigurations(kind, null);
+
+        List<DistributionConfiguration> result = new ArrayList<DistributionConfiguration>();
+        if (configurations == null || configurations.size() == 0) {
+            return result;
+        }
+
+
+        for(Configuration configuration : configurations) {
+            Dictionary propertiesDict = configuration.getProperties();
+            Map<String, Object> properties = OsgiUtils.fromDictionary(propertiesDict);
+
+            properties = filterBeforeRead(properties);
+            String name = PropertiesUtil.toString(properties.get(DistributionComponentUtils.PN_NAME), null);
+            result.add(new DistributionConfiguration(kind, name, properties));
+
+        }
+
+        return result;
+    }
+
+    public DistributionConfiguration getConfig(DistributionComponentKind kind, String name) {
+        List<Configuration> configurations = getOsgiConfigurations(kind, name);
+
+        if (configurations == null || configurations.size() == 0) {
+            return null;
+        }
+
+        Configuration configuration = configurations.get(0);
+
+        if (configuration != null) {
+            Dictionary properties = configuration.getProperties();
+            Map<String, Object> result = OsgiUtils.fromDictionary(properties);
+
+            String factoryPid = PropertiesUtil.toString(result.get(ConfigurationAdmin.SERVICE_FACTORYPID), null);
+            String type = kind.getType(factoryPid);
+
+            result.put(DistributionComponentUtils.PN_TYPE, type);
+            result = filterBeforeRead(result);
+            return new DistributionConfiguration(kind, name, result);
+        }
+
+        return null;
+    }
+
+    public void saveConfig(DistributionConfiguration config) {
+        String componentName = config.getName();
+        DistributionComponentKind componentKind = config.getKind();
+        Map<String, Object> properties = config.getProperties();
+        String componentType = PropertiesUtil.toString(properties.get(DistributionComponentUtils.PN_TYPE), null);
+
+        if (componentKind == null || componentType == null) {
+            throw new IllegalArgumentException("kind and type are required");
+        }
+
+        String factoryPid = componentKind.getFactory(componentType);
+        if (factoryPid != null) {
+            properties.put(DistributionComponentUtils.PN_NAME, componentName);
+            Configuration configuration = saveOsgiConfig(factoryPid, componentName, properties);
+        }
+
+    }
+
+    public void deleteConfig(DistributionComponentKind kind, String name) {
+        List<Configuration> configs = getOsgiConfigurations(kind, name);
+
+        deleteOsgiConfigs(configs);
+
+        log.info("Delete component {}", name);
+
+    }
+
+
+    private void deleteOsgiConfigs(List<Configuration> configurations) {
+        for (Configuration configuration : configurations) {
+            String pid = configuration.getPid();
+
+            try {
+                configuration.delete();
+                log.info("Deleted configuration {}", pid);
+            } catch (IOException e) {
+                log.warn("Cannot delete configuration {}", pid, e);
+            }
+        }
+    }
+
+    public List<Configuration> getOsgiConfigurations(DistributionComponentKind kind, String componentName) {
+        List<String> factoryPids = kind.getFactories();
+
+        List<Configuration> allConfigurations = new ArrayList<Configuration>();
+        for (String factoryPid : factoryPids) {
+            List<Configuration> configurations = getOsgiConfigurationsFromFactory(factoryPid, componentName);
+            allConfigurations.addAll(configurations);
+        }
+
+       return allConfigurations;
+    }
+
+
+    private Configuration saveOsgiConfig(String factoryPid, String componentName, Map<String, Object> properties) {
+        try {
+            List<Configuration> configurations = getOsgiConfigurationsFromFactory(factoryPid, componentName);
+            Configuration configuration = null;
+            if (configurations == null || configurations.size() == 0) {
+                configuration = configurationAdmin.createFactoryConfiguration(factoryPid);
+            }
+            else {
+                configuration = configurations.get(0);
+            }
+
+            properties = filterBeforeSave(properties);
+
+            configuration.update(OsgiUtils.toDictionary(properties));
+
+            return configuration;
+        } catch (IOException e) {
+            log.error("Cannot create configuration with factory {}", factoryPid, e);
+        }
+
+        return null;
+    }
+
+    private List<Configuration> getOsgiConfigurationsFromFactory(String factoryPid, String componentName) {
+        List<Configuration> result = new ArrayList<Configuration>();
+
+        try {
+            String filter = OsgiUtils.getFilter(factoryPid, DistributionComponentUtils.PN_NAME, componentName);
+
+            Configuration[] configurations = configurationAdmin.listConfigurations(filter);
+            if (configurations != null) {
+                result.addAll(Arrays.asList(configurations));
+            }
+        } catch (IOException e) {
+        } catch (InvalidSyntaxException e) {
+        }
+
+        return result;
+    }
+
+    private Map<String, Object> filterBeforeSave(Map<String, Object> properties) {
+        Map<String, Object> result = new HashMap<String, Object>();
+
+        for (Map.Entry<String, Object> entry : properties.entrySet()) {
+            if (entry.getKey().endsWith(".target")) {
+                String entryValue = (String) entry.getValue();
+                entryValue = packOsgiFilter(entryValue);
+                if (entryValue != null) {
+                    result.put(entry.getKey(), entryValue);
+                }
+            } else {
+                result.put(entry.getKey(), entry.getValue());
+            }
+
+        }
+
+        result = OsgiUtils.sanitize(result);
+        return result;
+    }
+
+    private Map<String, Object> filterBeforeRead(Map<String, Object> properties) {
+        Map<String, Object> result = new HashMap<String, Object>();
+
+        for (Map.Entry<String, Object> entry : properties.entrySet()) {
+            if (entry.getKey().endsWith(".target")) {
+                String entryValue = (String) entry.getValue();
+                entryValue = unpackOsgiFilter(entryValue);
+                if (entryValue != null) {
+                    result.put(entry.getKey(), entryValue);
+                }
+            } else {
+                result.put(entry.getKey(), entry.getValue());
+            }
+
+        }
+
+        result = OsgiUtils.sanitize(result);
+        return result;
+    }
+
+
+    private String unpackOsgiFilter(String propertyValue) {
+
+        String result = null;
+
+        String namePattern = "\\(" + DistributionComponentUtils.PN_NAME + "=(.*?)\\)";
+
+        Pattern r = Pattern.compile(namePattern);
+        Matcher m = r.matcher(propertyValue);
+
+        if (m.matches()) {
+            result = m.group(1);
+        }
+
+        return result;
+    }
+
+    private String packOsgiFilter(String propertyValue) {
+        return "(" + DistributionComponentUtils.PN_NAME + "=" + OsgiUtils.escape(propertyValue) + ")";
+    }
+
+}

Added: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponent.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponent.java?rev=1650034&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponent.java (added)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponent.java Wed Jan  7 11:02:33 2015
@@ -0,0 +1,58 @@
+/*
+ * 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.distribution.component.impl;
+
+
+import java.util.Map;
+
+/**
+ * A distribution component holds a registered service that takes part in distribution process.
+ * @param <ServiceType> the actual type of the service
+ */
+public class DistributionComponent<ServiceType> {
+
+    private final DistributionComponentKind kind;
+    private final String name;
+    private final ServiceType service;
+    private final Map<String, Object> properties;
+
+    public DistributionComponent(DistributionComponentKind kind, String name, ServiceType service, Map<String, Object> properties) {
+        this.kind = kind;
+        this.name = name;
+
+        this.service = service;
+        this.properties = properties;
+    }
+
+    public ServiceType getService() {
+        return service;
+    }
+
+    public Map<String, Object> getProperties() {
+        return properties;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public DistributionComponentKind getKind() {
+        return kind;
+    }
+}

Added: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentKind.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentKind.java?rev=1650034&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentKind.java (added)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentKind.java Wed Jan  7 11:02:33 2015
@@ -0,0 +1,195 @@
+/*
+ * 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.distribution.component.impl;
+
+
+import org.apache.sling.distribution.agent.DistributionAgent;
+import org.apache.sling.distribution.agent.impl.DistributionRequestAuthorizationStrategy;
+import org.apache.sling.distribution.agent.impl.ForwardDistributionAgentFactory;
+import org.apache.sling.distribution.agent.impl.PrivilegeDistributionRequestAuthorizationStrategy;
+import org.apache.sling.distribution.agent.impl.QueueDistributionAgentFactory;
+import org.apache.sling.distribution.agent.impl.ReverseDistributionAgentFactory;
+import org.apache.sling.distribution.agent.impl.SimpleDistributionAgentFactory;
+import org.apache.sling.distribution.agent.impl.SyncDistributionAgentFactory;
+import org.apache.sling.distribution.packaging.DistributionPackageExporter;
+import org.apache.sling.distribution.packaging.DistributionPackageImporter;
+import org.apache.sling.distribution.packaging.impl.exporter.AgentDistributionPackageExporterFactory;
+import org.apache.sling.distribution.packaging.impl.exporter.LocalDistributionPackageExporterFactory;
+import org.apache.sling.distribution.packaging.impl.exporter.RemoteDistributionPackageExporterFactory;
+import org.apache.sling.distribution.packaging.impl.importer.LocalDistributionPackageImporterFactory;
+import org.apache.sling.distribution.packaging.impl.importer.RemoteDistributionPackageImporterFactory;
+import org.apache.sling.distribution.queue.DistributionQueueProvider;
+import org.apache.sling.distribution.queue.impl.DistributionQueueDispatchingStrategy;
+import org.apache.sling.distribution.serialization.DistributionPackageBuilder;
+import org.apache.sling.distribution.serialization.impl.vlt.VaultDistributionPackageBuilderFactory;
+import org.apache.sling.distribution.transport.DistributionTransportSecretProvider;
+import org.apache.sling.distribution.transport.impl.UserCredentialsDistributionTransportSecretProvider;
+import org.apache.sling.distribution.trigger.DistributionTrigger;
+import org.apache.sling.distribution.trigger.impl.LocalDistributionTriggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Enum that represents the main distribution component kinds that can be configured for distribution.
+ */
+public enum DistributionComponentKind {
+
+    AGENT("agent"),
+    IMPORTER("importer"),
+    EXPORTER("exporter"),
+    QUEUE_PROVIDER("queueProvider"),
+    QUEUE_STRATEGY("queueStrategy"),
+    TRANSPORT_SECRET_PROVIDER("transportSecretProvider"),
+    PACKAGE_BUILDER("packageBuilder"),
+    REQUEST_AUTHORIZATION("requestAuthorization"),
+    TRIGGER("trigger");
+
+
+
+
+    private static Map<DistributionComponentKind, Class> classMap = new HashMap<DistributionComponentKind, Class>();
+    private static Map<DistributionComponentKind, Map<String, Class>> factoryMap = new HashMap<DistributionComponentKind, Map<String, Class>>();
+
+    static {
+        registerKind(AGENT, DistributionAgent.class);
+        registerKind(IMPORTER, DistributionPackageImporter.class);
+        registerKind(EXPORTER, DistributionPackageExporter.class);
+        registerKind(QUEUE_PROVIDER, DistributionQueueProvider.class);
+        registerKind(QUEUE_STRATEGY, DistributionQueueDispatchingStrategy.class);
+        registerKind(TRANSPORT_SECRET_PROVIDER, DistributionTransportSecretProvider.class);
+        registerKind(REQUEST_AUTHORIZATION, DistributionRequestAuthorizationStrategy.class);
+        registerKind(PACKAGE_BUILDER, DistributionPackageBuilder.class);
+        registerKind(TRIGGER, DistributionTrigger.class);
+
+
+        // register "core" factories kind, type -> ComponentFactoryClass
+        registerFactory(DistributionComponentKind.AGENT, "simple", SimpleDistributionAgentFactory.class);
+        registerFactory(DistributionComponentKind.AGENT, "sync", SyncDistributionAgentFactory.class);
+        registerFactory(DistributionComponentKind.AGENT, "forward", ForwardDistributionAgentFactory.class);
+        registerFactory(DistributionComponentKind.AGENT, "reverse", ReverseDistributionAgentFactory.class);
+        registerFactory(DistributionComponentKind.AGENT, "queue", QueueDistributionAgentFactory.class);
+
+        registerFactory(DistributionComponentKind.EXPORTER, "local", LocalDistributionPackageExporterFactory.class);
+        registerFactory(DistributionComponentKind.EXPORTER, "remote", RemoteDistributionPackageExporterFactory.class);
+        registerFactory(DistributionComponentKind.EXPORTER, "agent", AgentDistributionPackageExporterFactory.class);
+
+        registerFactory(DistributionComponentKind.IMPORTER, "local", LocalDistributionPackageImporterFactory.class);
+        registerFactory(DistributionComponentKind.IMPORTER, "remote", RemoteDistributionPackageImporterFactory.class);
+
+        registerFactory(DistributionComponentKind.PACKAGE_BUILDER, "filevlt", VaultDistributionPackageBuilderFactory.class);
+        registerFactory(DistributionComponentKind.PACKAGE_BUILDER, "jcrvlt", VaultDistributionPackageBuilderFactory.class);
+
+        registerFactory(DistributionComponentKind.REQUEST_AUTHORIZATION, "privilege", PrivilegeDistributionRequestAuthorizationStrategy.class);
+
+        registerFactory(DistributionComponentKind.TRANSPORT_SECRET_PROVIDER, "user", UserCredentialsDistributionTransportSecretProvider.class);
+
+        registerFactory(DistributionComponentKind.TRIGGER, "resourceEvent", LocalDistributionTriggerFactory.class);
+        registerFactory(DistributionComponentKind.TRIGGER, "scheduledEvent", LocalDistributionTriggerFactory.class);
+        registerFactory(DistributionComponentKind.TRIGGER, "distributionEvent", LocalDistributionTriggerFactory.class);
+        registerFactory(DistributionComponentKind.TRIGGER, "persistedJcrEvent", LocalDistributionTriggerFactory.class);
+
+    }
+
+    private final String name;
+
+    DistributionComponentKind(String name) {
+        this.name = name;
+    }
+
+    public Class asClass() {
+        return classMap.get(this);
+    }
+
+    public static DistributionComponentKind fromClass(Class type) {
+        for (DistributionComponentKind kind : classMap.keySet()) {
+            Class kindClass = classMap.get(kind);
+
+            if (kindClass.equals(type)) {
+                return kind;
+            }
+        }
+
+        return null;
+    }
+
+    public static DistributionComponentKind fromName(String name) {
+        for (DistributionComponentKind kind : classMap.keySet()) {
+
+            if (kind.getName().equals(name)) {
+                return kind;
+            }
+        }
+
+        return null;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+
+    private static void registerKind(DistributionComponentKind kind, Class kindClass) {
+        classMap.put(kind, kindClass);
+    }
+
+    private static void registerFactory(DistributionComponentKind kind, String type, Class factoryClass) {
+
+        if (!factoryMap.containsKey(kind)) {
+            factoryMap.put(kind, new HashMap<String, Class>());
+        }
+
+        Map<String, Class> kindMap = factoryMap.get(kind);
+
+        kindMap.put(type, factoryClass);
+    }
+
+
+    public String getFactory(String type) {
+        Class factory = factoryMap.get(this).get(type);
+        return factory.getName();
+    }
+
+    public List<String> getFactories() {
+        List<String> result = new ArrayList<String>();
+        for (Class factory : factoryMap.get(this).values()) {
+            result.add(factory.getName());
+        }
+
+        return result;
+
+    }
+
+    public String getType(String factory) {
+        for (String type : factoryMap.get(this).keySet()) {
+            Class factoryClass = factoryMap.get(this).get(type);
+
+            if (factoryClass.getName().equals(factory)) {
+                return type;
+            }
+        }
+
+        return null;
+
+    }
+
+
+}

Added: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentProvider.java?rev=1650034&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentProvider.java (added)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentProvider.java Wed Jan  7 11:02:33 2015
@@ -0,0 +1,35 @@
+/*
+ * 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.distribution.component.impl;
+
+
+import java.util.List;
+
+/**
+ * A provider that allows access to registered distribution services.
+ */
+public interface DistributionComponentProvider {
+    DistributionComponent getComponent(DistributionComponentKind kind, String componentName);
+
+    List<DistributionComponent> getComponents(DistributionComponentKind kind);
+
+    <ComponentType> ComponentType getService(Class<ComponentType> type, String componentName);
+
+}

Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentUtils.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentUtils.java?rev=1650034&r1=1650033&r2=1650034&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentUtils.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionComponentUtils.java Wed Jan  7 11:02:33 2015
@@ -93,61 +93,6 @@ public class DistributionComponentUtils
     static final String PN_PARENT_ID = "parent.ref.id";
     static final String PN_OWNER_ID = "owner.ref.id";
 
-    static  {
-        osgiConfigFactoryMap = new HashMap<String, String>();
-        osgiServiceMap = new HashMap<String, String>();
-
-        // register "core" services kind -> ComponentClass
-        registerService("agent", DistributionAgent.class);
-        registerService("exporter", DistributionPackageExporter.class);
-        registerService("importer", DistributionPackageImporter.class);
-        registerService("packageBuilder", DistributionPackageBuilder.class);
-        registerService("requestAuthorization", DistributionRequestAuthorizationStrategy.class);
-        registerService("transportSecretProvider", DistributionTransportSecretProvider.class);
-        registerService("trigger", DistributionTrigger.class);
-
-
-        // register "core" factories kind, type -> ComponentFactoryClass
-        registerFactory("agent", "simple", SimpleDistributionAgentFactory.class);
-        registerFactory("agent", "sync", SyncDistributionAgentFactory.class);
-        registerFactory("agent", "forward", ForwardDistributionAgentFactory.class);
-        registerFactory("agent", "reverse", ReverseDistributionAgentFactory.class);
-        registerFactory("agent", "queue", QueueDistributionAgentFactory.class);
-
-        registerFactory("exporter", "local", LocalDistributionPackageExporterFactory.class);
-        registerFactory("exporter", "remote", RemoteDistributionPackageExporterFactory.class);
-        registerFactory("exporter", "agent", AgentDistributionPackageExporterFactory.class);
-
-        registerFactory("importer", "local", LocalDistributionPackageImporterFactory.class);
-        registerFactory("importer", "remote", RemoteDistributionPackageImporterFactory.class);
-
-        registerFactory("packageBuilder", "filevlt", VaultDistributionPackageBuilderFactory.class);
-        registerFactory("packageBuilder", "jcrvlt", VaultDistributionPackageBuilderFactory.class);
-
-
-        registerFactory("requestAuthorization", "privilege", PrivilegeDistributionRequestAuthorizationStrategy.class);
-
-        registerFactory("transportSecretProvider", "user", UserCredentialsDistributionTransportSecretProvider.class);
-
-        registerFactory("trigger", "resourceEvent", LocalDistributionTriggerFactory.class);
-        registerFactory("trigger", "scheduledEvent", LocalDistributionTriggerFactory.class);
-        registerFactory("trigger", "distributionEvent", LocalDistributionTriggerFactory.class);
-        registerFactory("trigger", "persistedJcrEvent", LocalDistributionTriggerFactory.class);
-
-        // TODO: allow external registration of factories
-
-    }
-
-
-    final static Map<String, String> osgiConfigFactoryMap;
-    final static Map<String, String> osgiServiceMap;
-
-
-
-    public DistributionComponentUtils() {
-
-    }
-
 
     /**
      * Returns the list of osgi configs in topological order
@@ -235,33 +180,36 @@ public class DistributionComponentUtils
 
 
     public String  getFactoryPid(String kind, String type) {
-        String key = kind + DESCRIPTOR_SEPARATOR + type;
-        return osgiConfigFactoryMap.get(key);
+        DistributionComponentKind componentKind = DistributionComponentKind.fromName(kind);
+        if (componentKind != null) {
+            componentKind.getFactory(type);
+        }
+
+        return null;
     }
 
+
     public List<String> getAllFactoryPids() {
         List<String> result = new ArrayList<String>();
 
-        result.addAll(osgiConfigFactoryMap.values());
+        for (DistributionComponentKind kind : DistributionComponentKind.values()) {
+            List<String> factories = kind.getFactories();
+            result.addAll(factories);
+        }
 
         return result;
     }
 
+
+
+
     public boolean isSupportedKind(String kind) {
-        return osgiServiceMap.keySet().contains(kind);
+        return DistributionComponentKind.fromName(kind) != null;
     }
 
-    private static void registerService(String kind, Class serviceClass) {
-        osgiServiceMap.put(kind, serviceClass.getName());
-    }
 
-    private static void registerFactory(String kind, String type, Class factoryClass) {
-        osgiConfigFactoryMap.put(kind + DESCRIPTOR_SEPARATOR + type, factoryClass.getName());
-    }
 
     public String getComponentID(String componentKind, String componentName) {
         return componentKind + NAME_SEPARATOR + componentName;
     }
-
-
 }

Added: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionConfiguration.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionConfiguration.java?rev=1650034&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionConfiguration.java (added)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionConfiguration.java Wed Jan  7 11:02:33 2015
@@ -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.distribution.component.impl;
+
+
+import java.util.Map;
+
+/**
+ * A distribution configuration holds the properties needed to configure a distribution component.
+ */
+public class DistributionConfiguration {
+
+    private final DistributionComponentKind kind;
+    private final String name;
+    private final Map<String, Object> properties;
+
+
+    public DistributionConfiguration(DistributionComponentKind kind, String name, Map<String, Object> properties) {
+
+        this.kind = kind;
+        this.name = name;
+        this.properties = properties;
+    }
+
+    public Map<String, Object> getProperties() {
+        return properties;
+    }
+
+    public DistributionComponentKind getKind() {
+        return kind;
+    }
+
+
+    public String getName() {
+        return name;
+    }
+}

Added: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionConfigurationManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionConfigurationManager.java?rev=1650034&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionConfigurationManager.java (added)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/component/impl/DistributionConfigurationManager.java Wed Jan  7 11:02:33 2015
@@ -0,0 +1,36 @@
+/*
+ * 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.distribution.component.impl;
+
+import java.util.List;
+
+/**
+ * A configuration manager allows basic access/editing operations on distribution configurations.
+ */
+public interface DistributionConfigurationManager {
+
+    List<DistributionConfiguration> getConfigs(DistributionComponentKind kind);
+
+    DistributionConfiguration getConfig(DistributionComponentKind kind, String name);
+
+    void saveConfig(DistributionConfiguration config);
+
+    void deleteConfig(DistributionComponentKind kind, String name);
+}

Modified: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/impl/DefaultDistributor.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/impl/DefaultDistributor.java?rev=1650034&r1=1650033&r2=1650034&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/impl/DefaultDistributor.java (original)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/impl/DefaultDistributor.java Wed Jan  7 11:02:33 2015
@@ -29,7 +29,7 @@ import org.apache.sling.distribution.Dis
 import org.apache.sling.distribution.Distributor;
 import org.apache.sling.distribution.agent.DistributionAgent;
 import org.apache.sling.distribution.agent.DistributionAgentException;
-import org.apache.sling.distribution.component.impl.DefaultDistributionComponentProvider;
+import org.apache.sling.distribution.component.impl.DistributionComponentProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,11 +46,11 @@ public class DefaultDistributor implemen
 
 
     @Reference
-    DefaultDistributionComponentProvider componentProvider;
+    DistributionComponentProvider componentProvider;
 
     @Nonnull
     public DistributionResponse distribute(@Nonnull String agentName, @Nonnull ResourceResolver resourceResolver, @Nonnull DistributionRequest distributionRequest) {
-       DistributionAgent agent = componentProvider.getComponent(DistributionAgent.class, agentName);
+        DistributionAgent agent = componentProvider.getService(DistributionAgent.class, agentName);
 
         if (agent == null) {
             return new SimpleDistributionResponse(DistributionRequestState.DROPPED, "Agent is not available");

Added: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionConfigurationResourceProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionConfigurationResourceProvider.java?rev=1650034&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionConfigurationResourceProvider.java (added)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionConfigurationResourceProvider.java Wed Jan  7 11:02:33 2015
@@ -0,0 +1,127 @@
+/*
+ * 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.distribution.resources.impl;
+
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.sling.api.resource.ModifyingResourceProvider;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.distribution.component.impl.DistributionComponentKind;
+import org.apache.sling.distribution.component.impl.DistributionConfiguration;
+import org.apache.sling.distribution.component.impl.DistributionConfigurationManager;
+import org.apache.sling.distribution.resources.impl.common.AbstractModifyingResourceProvider;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link ResourceProvider} for Osgi configurations for a specific configuration factory.
+ * All CRUD operations are supported for the underlying resources.
+ * The accepted path is resourceRoot/{friendlyNameProperty}/childResourceName.
+ */
+public class DistributionConfigurationResourceProvider extends AbstractModifyingResourceProvider implements ResourceProvider, ModifyingResourceProvider {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    private final DistributionConfigurationManager configurationManager;
+
+    private final DistributionComponentKind kind;
+
+    public DistributionConfigurationResourceProvider(DistributionConfigurationManager configurationManager, String kind,
+                                                     String resourceRoot, Map<String, String> additionalResourceProperties) {
+        super(resourceRoot, additionalResourceProperties);
+        this.configurationManager = configurationManager;
+        this.kind = DistributionComponentKind.fromName(kind);
+
+    }
+
+    @Override
+    protected void save(ResourceResolver resourceResolver, Map<String, Map<String, Object>> changedResources,
+                        Set<String> deletedResources) throws PersistenceException {
+        for (Map.Entry<String, Map<String, Object>> entry : changedResources.entrySet()) {
+            String resourceName = entry.getKey();
+            Map<String, Object> properties = entry.getValue();
+
+            String componentName = getConfigName(resourceName);
+
+            DistributionConfiguration config = new DistributionConfiguration(kind, componentName, properties);
+            configurationManager.saveConfig(config);
+        }
+
+        for (String resourceName : deletedResources) {
+            String componentName = getConfigName(resourceName);
+
+            configurationManager.deleteConfig(kind, componentName);
+        }
+    }
+
+    @Override
+    protected Map<String, Object> getResourceRootProperties() {
+        List<DistributionConfiguration> configsList = configurationManager.getConfigs(kind);
+
+        List<String> nameList = new ArrayList<String>();
+        for (DistributionConfiguration config : configsList) {
+            nameList.add(config.getName());
+        }
+
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.put("items", nameList.toArray(new String[nameList.size()]));
+
+        return result;
+    }
+
+    @Override
+    protected Map<String, Object> getResourceProperties(String resourceName) {
+
+        String componentName = getConfigName(resourceName);
+
+        DistributionConfiguration config = configurationManager.getConfig(kind, componentName);
+
+        if (config != null) {
+            return config.getProperties();
+        }
+
+        return null;
+    }
+
+
+    public Iterator<Resource> listChildren(Resource parent) {
+        return null;
+    }
+
+
+    private String getConfigName(String configName) {
+        return configName;
+    }
+}

Added: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionConfigurationResourceProviderFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionConfigurationResourceProviderFactory.java?rev=1650034&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionConfigurationResourceProviderFactory.java (added)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionConfigurationResourceProviderFactory.java Wed Jan  7 11:02:33 2015
@@ -0,0 +1,113 @@
+/*
+ * 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.distribution.resources.impl;
+
+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.Deactivate;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceProviderFactory;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.distribution.component.impl.DistributionComponentUtils;
+import org.apache.sling.distribution.component.impl.DistributionConfigurationManager;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+
+
+@Component(label = "Distribution Configuration Resource Provider Factory",
+        description = "Distribution Configuration Resource Provider Factory",
+        specVersion = "1.1",
+        policy = ConfigurationPolicy.REQUIRE,
+        metatype = true)
+@Service(value = ResourceProviderFactory.class)
+@Properties({
+        @Property(name = ResourceProvider.ROOTS),
+        @Property(name = ResourceProvider.OWNS_ROOTS, boolValue = true, propertyPrivate = true)
+})
+public class DistributionConfigurationResourceProviderFactory implements ResourceProviderFactory {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+
+
+    @Property
+    public final static String KIND = DistributionComponentUtils.PN_KIND;
+
+    /**
+     * resourceProperties contains the list of properties returned by this provider.
+     * Properties can be configured for the main resource, for the root resource and for child resources.
+     * Root resource properties are static and can be configured as follows:
+     * ../rootResourcePropertyName = rootResourcePropertyValue
+     * <p/>
+     * Main resource properties can be static or dynamic (depending on the underlying resource) are configured as follows:
+     * mainResourceStaticPropertyName = mainResourceStaticPropertyValue
+     * mainResourceDynamicPropertyName = {mainResourceSourcePropertyName}
+     * <p/>
+     * Child resource properties are static an can be configured as follows:
+     * childResourceName/childResourcePropertyName=childResourcePropertyValue
+     */
+    @Property(cardinality = Integer.MAX_VALUE)
+    public final static String RESOURCE_PROPERTIES = "resourceProperties";
+
+    @Reference
+    DistributionConfigurationManager configurationManager;
+
+    private String resourceRoot;
+    private String kind;
+    Map<String, String> additionalResourceProperties;
+
+    @Activate
+    public void activate(BundleContext context, Map<String, Object> properties) {
+
+        log.debug("activating resource provider with config {}", properties);
+
+        resourceRoot = PropertiesUtil.toString(properties.get(ResourceProvider.ROOTS), null);
+        kind = PropertiesUtil.toString(properties.get(KIND), null);
+
+
+
+        additionalResourceProperties = PropertiesUtil.toMap(properties.get(RESOURCE_PROPERTIES), new String[0]);
+
+    }
+
+    @Deactivate
+    public void deactivate(BundleContext context) {
+
+    }
+
+    public ResourceProvider getResourceProvider(Map<String, Object> authenticationInfo) throws LoginException {
+        return new DistributionConfigurationResourceProvider(configurationManager, kind,
+                resourceRoot,
+                additionalResourceProperties);
+    }
+
+    public ResourceProvider getAdministrativeResourceProvider(Map<String, Object> authenticationInfo) throws LoginException {
+        return getResourceProvider(authenticationInfo);
+    }
+}

Added: sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionServiceResourceProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionServiceResourceProvider.java?rev=1650034&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionServiceResourceProvider.java (added)
+++ sling/trunk/contrib/extensions/distribution/core/src/main/java/org/apache/sling/distribution/resources/impl/DistributionServiceResourceProvider.java Wed Jan  7 11:02:33 2015
@@ -0,0 +1,103 @@
+/*
+ * 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.distribution.resources.impl;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.distribution.component.impl.DefaultDistributionComponentProvider;
+import org.apache.sling.distribution.component.impl.DistributionComponent;
+import org.apache.sling.distribution.component.impl.DistributionComponentKind;
+import org.apache.sling.distribution.component.impl.DistributionComponentProvider;
+import org.apache.sling.distribution.component.impl.DistributionComponentUtils;
+import org.apache.sling.distribution.component.impl.DistributionConfiguration;
+import org.apache.sling.distribution.resources.DistributionConstants;
+import org.apache.sling.distribution.resources.impl.common.AbstractReadableResourceProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+/**
+ * {@link ResourceProvider} for Osgi services for a specific service interface.
+ * The main resource contains a list of service properties and can be adapted to the underlying service.
+ * The accepted path is resourceRoot/{friendlyNameProperty}/childResourceName.
+ */
+public class DistributionServiceResourceProvider extends AbstractReadableResourceProvider  {
+
+    private final DistributionComponentKind kind;
+    private final DistributionComponentProvider componentProvider;
+
+
+    public DistributionServiceResourceProvider(String kind,
+                                               DistributionComponentProvider componentProvider,
+                                               String resourceRoot,
+                                               Map<String, String> additionalResourceProperties) {
+        super(resourceRoot, additionalResourceProperties);
+        this.kind = DistributionComponentKind.fromName(kind);
+        this.componentProvider = componentProvider;
+    }
+
+    @Override
+    protected Map<String, Object> getResourceProperties(String resourceName) {
+
+        DistributionComponent component = componentProvider.getComponent(kind, resourceName);
+
+        if (component != null) {
+            Map<String, Object> properties = new HashMap<String, Object>();
+
+            properties.put(DistributionComponentUtils.PN_NAME, resourceName);
+            properties.put(ADAPTABLE_PROPERTY_NAME, component.getService());
+            return properties;
+        }
+
+        return null;
+    }
+
+    @Override
+    protected Map<String, Object> getResourceRootProperties() {
+
+        List<DistributionComponent> componentList = componentProvider.getComponents(kind);
+
+        List<String> nameList = new ArrayList<String>();
+        for (DistributionComponent component : componentList) {
+            nameList.add(component.getName());
+        }
+
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.put("items", nameList.toArray(new String[nameList.size()]));
+
+        return result;
+    }
+
+    public Iterator<Resource> listChildren(Resource parent) {
+        return null;
+    }
+
+}