You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by to...@apache.org on 2014/03/17 16:26:46 UTC

svn commit: r1578436 [1/2] - in /sling/trunk/contrib/extensions/replication/src: main/java/org/apache/sling/replication/agent/impl/ main/java/org/apache/sling/replication/resources/ main/java/org/apache/sling/replication/resources/impl/ main/java/org/a...

Author: tommaso
Date: Mon Mar 17 15:26:45 2014
New Revision: 1578436

URL: http://svn.apache.org/r1578436
Log:
SLING-3352 - applied Marius's patch to expose OSGI configuration via HTTP

Added:
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/ReplicationConstants.java   (with props)
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiConfigurationResourceProvider.java   (with props)
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiPropertiesResourceProviderFactory.java   (with props)
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiServicePropertiesResourceProvider.java   (with props)
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiUtils.java   (with props)
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/AbstractModifyingResourceProvider.java   (with props)
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/AbstractReadableResourceProvider.java   (with props)
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleModifiableResource.java   (with props)
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleModifiableValueMap.java   (with props)
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimplePathInfo.java   (with props)
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleReadableResource.java   (with props)
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentQueueServlet.java   (with props)
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationPackageImporterServlet.java   (with props)
    sling/trunk/contrib/extensions/replication/src/main/resources/SLING-CONTENT/libs/sling/replication/config/resourceproviders/
    sling/trunk/contrib/extensions/replication/src/main/resources/SLING-CONTENT/libs/sling/replication/config/resourceproviders/org.apache.sling.replication.resources.impl.OsgiPropertiesResourceProviderFactory-replicationAgents.json
    sling/trunk/contrib/extensions/replication/src/main/resources/SLING-CONTENT/libs/sling/replication/config/resourceproviders/org.apache.sling.replication.resources.impl.OsgiPropertiesResourceProviderFactory-replicationAgentsConfig.json
    sling/trunk/contrib/extensions/replication/src/main/resources/SLING-CONTENT/libs/sling/replication/config/resourceproviders/org.apache.sling.replication.resources.impl.OsgiPropertiesResourceProviderFactory-replicationImporters.json
Removed:
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/agent/impl/ReplicationAgentConfigurationResource.java
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/agent/impl/ReplicationAgentQueueResource.java
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/agent/impl/ReplicationAgentResource.java
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/agent/impl/ReplicationAgentResourceProvider.java
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationConfigurationRootServlet.java
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationConfigurationServlet.java
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationQueueServlet.java
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationReceiverServlet.java
    sling/trunk/contrib/extensions/replication/src/test/java/org/apache/sling/replication/agent/impl/ReplicationAgentConfigurationResourceTest.java
    sling/trunk/contrib/extensions/replication/src/test/java/org/apache/sling/replication/agent/impl/ReplicationAgentResourceProviderTest.java
    sling/trunk/contrib/extensions/replication/src/test/java/org/apache/sling/replication/agent/impl/ReplicationAgentResourceTest.java
Modified:
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/rule/impl/ReplicateOnQueueEventRule.java
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/serialization/impl/DefaultReplicationPackageImporter.java
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentQueueEventServlet.java
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentRootServlet.java
    sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentServlet.java
    sling/trunk/contrib/extensions/replication/src/main/resources/SLING-CONTENT/libs/sling/replication/config/org.apache.sling.replication.transport.impl.HttpTransportHandlerFactory-http-publish-receive.json

Added: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/ReplicationConstants.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/ReplicationConstants.java?rev=1578436&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/ReplicationConstants.java (added)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/ReplicationConstants.java Mon Mar 17 15:26:45 2014
@@ -0,0 +1,32 @@
+/*
+ * 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.replication.resources;
+
+public class ReplicationConstants {
+    public static final String  AGENT_RESOURCE_TYPE = "replication/agent";
+    public static final String  AGENT_QUEUE_RESOURCE_TYPE = "replication/agent/queue";
+    public static final String  AGENT_QUEUE_EVENT_RESOURCE_TYPE = "replication/agent/queue";
+    public static final String  AGENT_ROOT_RESOURCE_TYPE = "replication/agents";
+    public static final String  IMPORTER_ROOT_RESOURCE_TYPE = "replication/importers";
+    public static final String  IMPORTER_RESOURCE_TYPE = "replication/importer";
+
+    public static final String SUFFIX_AGENT_QUEUE = "/queue";
+    public static final String SUFFIX_AGENT_QUEUE_EVENT = "/queue/event";
+}

Propchange: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/ReplicationConstants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiConfigurationResourceProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiConfigurationResourceProvider.java?rev=1578436&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiConfigurationResourceProvider.java (added)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiConfigurationResourceProvider.java Mon Mar 17 15:26:45 2014
@@ -0,0 +1,197 @@
+/*
+ * 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.replication.resources.impl;
+
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+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.replication.resources.impl.common.AbstractModifyingResourceProvider;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * {@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 OsgiConfigurationResourceProvider extends AbstractModifyingResourceProvider implements ResourceProvider, ModifyingResourceProvider {
+
+    private final ConfigurationAdmin configurationAdmin;
+    private final String configFactory;
+    private final String friendlyNameProperty;
+
+    public OsgiConfigurationResourceProvider(ConfigurationAdmin configurationAdmin,
+                                             String configFactory,
+                                             String friendlyNameProperty,
+                                             String resourceRoot,
+                                             Map<String, String> additionalResourceProperties) {
+        super(resourceRoot, additionalResourceProperties);
+
+        this.configurationAdmin = configurationAdmin;
+        this.configFactory = configFactory;
+        this.friendlyNameProperty = friendlyNameProperty;
+    }
+
+    @Override
+    protected void save(ResourceResolver resourceResolver, Map<String, Map<String, Object>> changedResources,
+                        Set<String> deletedResources) throws PersistenceException {
+        try {
+            for (Map.Entry<String, Map<String, Object>> entry : changedResources.entrySet()) {
+                String configName = entry.getKey();
+                Map<String, Object> properties = entry.getValue();
+
+                Configuration configuration = getConfiguration(configName);
+
+                if (configuration == null) {
+                    configuration = configurationAdmin.createFactoryConfiguration(configFactory);
+                }
+                configuration.update(toDictionary(properties));
+            }
+
+            for (String configName : deletedResources) {
+                Configuration configuration = getConfiguration(configName);
+                if (configuration != null) {
+                    configuration.delete();
+                }
+            }
+        } catch (IOException e) {
+            throw new PersistenceException("Resources cannot be commited", e);
+        }
+    }
+
+    @Override
+    protected Map<String, Object> getResourceRootProperties() {
+        Configuration[] configurations = getConfigurations(null);
+
+        List<String> nameList = new ArrayList<String>();
+
+        for (Configuration configuration : configurations) {
+            String configName = (String) configuration.getProperties().get(friendlyNameProperty);
+            nameList.add(configName);
+        }
+
+        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) {
+
+        Configuration configuration = getConfiguration(resourceName);
+
+
+        if (configuration == null) {
+            return null;
+        }
+
+        if (!configFactory.equals(configuration.getFactoryPid())) {
+            return null;
+        }
+
+
+        return toMap(configuration);
+    }
+
+
+    public Iterator<Resource> listChildren(Resource parent) {
+        return null;
+    }
+
+    Configuration getConfiguration(String configName) {
+        Configuration[] configurations = getConfigurations(configName);
+
+        if (configurations == null || configurations.length != 1) {
+            return null;
+        }
+
+        return configurations[0];
+    }
+
+    Configuration[] getConfigurations(String configName) {
+        try {
+            String filter = getFilter(configName);
+
+            return configurationAdmin.listConfigurations(filter);
+        } catch (IOException e) {
+            return null;
+        } catch (InvalidSyntaxException e) {
+            return null;
+        }
+    }
+
+    String getFilter(String configName) {
+        if (configName != null) {
+            return "(&(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + OsgiUtils.escape(configFactory) + ")("
+                    + friendlyNameProperty + "=" + OsgiUtils.escape(configName) + "))";
+        } else if (configFactory != null) {
+            return "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + OsgiUtils.escape(configFactory) + ")";
+        }
+
+        return null;
+    }
+
+
+    private Map<String, Object> toMap(Configuration configuration) {
+        return fromDictionary(configuration.getProperties());
+    }
+
+
+    public static <K, V> Map<K, V> fromDictionary(Dictionary<K, V> dictionary) {
+        if (dictionary == null) {
+            return null;
+        }
+        Map<K, V> map = new HashMap<K, V>(dictionary.size());
+        Enumeration<K> keys = dictionary.keys();
+        while (keys.hasMoreElements()) {
+            K key = keys.nextElement();
+            map.put(key, dictionary.get(key));
+        }
+        return map;
+    }
+
+    public static <K, V> Dictionary<K, V> toDictionary(Map<K, V> map) {
+        if (map == null) {
+            return null;
+        }
+        Dictionary<K, V> dictionary = new Hashtable<K, V>(map.size());
+        for (Map.Entry<K, V> entry : map.entrySet()) {
+            dictionary.put(entry.getKey(), entry.getValue());
+        }
+
+        return dictionary;
+
+    }
+
+}

Propchange: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiConfigurationResourceProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiPropertiesResourceProviderFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiPropertiesResourceProviderFactory.java?rev=1578436&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiPropertiesResourceProviderFactory.java (added)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiPropertiesResourceProviderFactory.java Mon Mar 17 15:26:45 2014
@@ -0,0 +1,160 @@
+/*
+ * 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.replication.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.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+@Component(label="Osgi Service Properties Resource Provider Factory",
+        description="Osgi Service Properties Resource Provider Factory",
+        configurationFactory=true,
+        policy= ConfigurationPolicy.REQUIRE,
+        name = OsgiPropertiesResourceProviderFactory.SERVICE_PID,
+        metatype=true)
+@Service(value=ResourceProviderFactory.class)
+@Properties({
+        @Property(name= ResourceProvider.ROOTS),
+        @Property(name = ResourceProvider.OWNS_ROOTS, boolValue=true, propertyPrivate=true)
+})
+public class OsgiPropertiesResourceProviderFactory implements ResourceProviderFactory {
+    public final static String SERVICE_PID = "org.apache.sling.replication.resources.impl.OsgiPropertiesResourceProviderFactory";
+
+    /**
+     * The name of the class that is used for resource resolution.
+     * For Osgi configuration this is the factoryPid.
+     * For Osgi services this is the service interface.
+     */
+    @Property
+    public final static String SERVICE_INTERFACE = "serviceType";
+
+    public final static String DEFAULT_FRIENDLY_NAME_PROPERTY = "name";
+    /**
+     * nameProperty contains the name of the property that will be used to expose
+     * the underlying resources.
+     *
+     * resourceRoot/resourceName/childResourceName
+     */
+    @Property(value = DEFAULT_FRIENDLY_NAME_PROPERTY)
+    public final static String FRIENDLY_NAME_PROPERTY = "nameProperty";
+
+    /**
+     * 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
+     *
+     * Main resource properties can be static or dynamic (depending on the underlying resource) are configured as follows:
+     *      mainResourceStaticPropertyName = mainResourceStaticPropertyValue
+     *      mainResourceDynamicPropertyName = {mainResourceSourcePropertyName}
+     *
+     * Child resource properties are static an can be configured as follows:
+     *      childResourceName/childResourcePropertyName=childResourcePropertyValue
+     *
+     */
+    @Property(cardinality = 100)
+    public final static String RESOURCE_PROPERTIES = "resourceProperties";
+
+    public final static String DEFAULT_PROVIDER_TYPE = "osgiService";
+    /**
+     * The providerType can be osgiService or osgiConfig.
+     * A provider of type osgiService will allow read only access to osgi service properties of a particuar interface.
+     * The resource can be adapted to the underlying service instance.
+     *
+     * A provider of type osgiConfig will allow CRUD access to osgi configurations registered for a particular factory.     *
+     */
+    @Property(value = DEFAULT_PROVIDER_TYPE)
+    public final static String PROVIDER_TYPE = "providerType";
+
+    @Reference
+    public ConfigurationAdmin configurationAdmin;
+
+    private ServiceTracker serviceTracker;
+    private ResourceProvider resourceProvider;
+
+    @Activate
+    public void activate(BundleContext context, Map<String, Object> properties) {
+        String friendlyNameProperty = PropertiesUtil.toString(properties.get(FRIENDLY_NAME_PROPERTY), DEFAULT_FRIENDLY_NAME_PROPERTY);
+        String type = PropertiesUtil.toString(properties.get(SERVICE_INTERFACE), null);
+        String resourceRoot = PropertiesUtil.toString(properties.get(ResourceProvider.ROOTS), null);
+
+        Map<String, String> additionalResourceProperties = PropertiesUtil.toMap(properties.get(RESOURCE_PROPERTIES),
+                new String[]{friendlyNameProperty + "=" + friendlyNameProperty});
+        boolean isConfig = !DEFAULT_PROVIDER_TYPE.equalsIgnoreCase(PropertiesUtil.toString(properties.get(PROVIDER_TYPE), DEFAULT_PROVIDER_TYPE));
+
+
+        if (isConfig) {
+            resourceProvider = new OsgiConfigurationResourceProvider(configurationAdmin,
+                    type,
+                    friendlyNameProperty,
+                    resourceRoot,
+                    additionalResourceProperties);
+
+        }
+        else {
+            OsgiServicePropertiesResourceProvider servicePropertiesResourceProvider;
+            resourceProvider = servicePropertiesResourceProvider = new OsgiServicePropertiesResourceProvider(context,
+                    type,
+                    friendlyNameProperty,
+                    resourceRoot,
+                    additionalResourceProperties);
+
+            serviceTracker = new ServiceTracker(context, type, servicePropertiesResourceProvider);
+            serviceTracker.open();
+        }
+    }
+
+    @Deactivate
+    public void deactivate(BundleContext context) {
+        if (serviceTracker != null) {
+            serviceTracker.close();
+            serviceTracker = null;
+        }
+    }
+
+    public ResourceProvider getResourceProvider(Map<String, Object> authenticationInfo) throws LoginException {
+        return resourceProvider;
+    }
+
+    public ResourceProvider getAdministrativeResourceProvider(Map<String, Object> authenticationInfo) throws LoginException {
+        return getResourceProvider(authenticationInfo);
+    }
+}

Propchange: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiPropertiesResourceProviderFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiServicePropertiesResourceProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiServicePropertiesResourceProvider.java?rev=1578436&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiServicePropertiesResourceProvider.java (added)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiServicePropertiesResourceProvider.java Mon Mar 17 15:26:45 2014
@@ -0,0 +1,133 @@
+/*
+ * 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.replication.resources.impl;
+
+
+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.commons.osgi.PropertiesUtil;
+import org.apache.sling.replication.resources.impl.common.AbstractReadableResourceProvider;
+import org.apache.sling.replication.resources.impl.common.SimpleModifiableResource;
+import org.apache.sling.replication.resources.impl.common.SimplePathInfo;
+import org.apache.sling.replication.resources.impl.common.SimpleReadableResource;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * {@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 OsgiServicePropertiesResourceProvider extends AbstractReadableResourceProvider implements ServiceTrackerCustomizer {
+
+    private final BundleContext context;
+    private final String serviceInterface;
+    private final String friendlyNameProperty;
+
+    private final Map<String, Object> services = new ConcurrentHashMap<String, Object>();
+    private final Map<String, Map<String, Object>> serviceProperties = new ConcurrentHashMap<String, Map<String, Object>>();
+
+    public OsgiServicePropertiesResourceProvider(BundleContext context,
+                                                 String serviceInterface,
+                                                 String friendlyNameProperty,
+                                                 String resourceRoot,
+                                                 Map<String, String> additionalResourceProperties) {
+        super(resourceRoot, additionalResourceProperties);
+        this.context = context;
+        this.serviceInterface = serviceInterface;
+        this.friendlyNameProperty = friendlyNameProperty;
+    }
+
+    @Override
+    protected Map<String, Object> getResourceProperties(String resourceName) {
+        Map<String, Object> properties = serviceProperties.get(resourceName);
+        Object service = services.get(resourceName);
+
+        if (service != null && properties != null) {
+            properties.put(ADAPTABLE_PROPERTY_NAME, service);
+            return properties;
+        }
+
+        return null;
+    }
+
+    @Override
+    protected Map<String, Object> getResourceRootProperties() {
+        Set<String> serviceNames = services.keySet();
+
+        Collection<Object> serviceObjects = services.values();
+
+        Map<String, Object> result = new HashMap<String, Object>();
+
+        result.put("items", serviceNames.toArray(new String[serviceNames.size()]));
+        result.put(ADAPTABLE_PROPERTY_NAME, serviceObjects.toArray(new Object[serviceObjects.size()]));
+
+        return result;
+    }
+
+    public Iterator<Resource> listChildren(Resource parent) {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public Object addingService(ServiceReference serviceReference) {
+        String serviceName = PropertiesUtil.toString(serviceReference.getProperty(friendlyNameProperty), null);
+        Map<String, Object> properties = new HashMap<String, Object>();
+
+        for (String key : serviceReference.getPropertyKeys()) {
+            properties.put(key, serviceReference.getProperty(key));
+        }
+
+        Object service = context.getService(serviceReference);
+
+        services.put(serviceName, service);
+        serviceProperties.put(serviceName, properties);
+
+
+        return service;
+    }
+
+    public void modifiedService(ServiceReference serviceReference, Object o) {
+        // do nothing
+    }
+
+    public void removedService(ServiceReference serviceReference, Object o) {
+        String serviceName = PropertiesUtil.toString(serviceReference.getProperty(friendlyNameProperty), null);
+
+        services.remove(serviceName);
+        serviceProperties.remove(serviceName);
+
+        context.ungetService(serviceReference);
+    }
+}

Propchange: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiServicePropertiesResourceProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiUtils.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiUtils.java?rev=1578436&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiUtils.java (added)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiUtils.java Mon Mar 17 15:26:45 2014
@@ -0,0 +1,31 @@
+/*
+ * 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.replication.resources.impl;
+
+public class OsgiUtils {
+    /**
+     * Encode the value for the ldap filter: \, *, (, and ) should be escaped.
+     */
+    public static String escape(final String value) {
+        return value.replace("\\", "\\\\")
+                .replace("*", "\\*")
+                .replace("(", "\\(")
+                .replace(")", "\\)");
+    }
+}

Propchange: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/OsgiUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/AbstractModifyingResourceProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/AbstractModifyingResourceProvider.java?rev=1578436&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/AbstractModifyingResourceProvider.java (added)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/AbstractModifyingResourceProvider.java Mon Mar 17 15:26:45 2014
@@ -0,0 +1,148 @@
+/*
+ * 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.replication.resources.impl.common;
+
+
+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.ResourceResolver;
+
+import javax.jcr.Session;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public abstract class AbstractModifyingResourceProvider extends AbstractReadableResourceProvider
+        implements ModifyingResourceProvider {
+
+    private final Map<String, Map<String, Object>> changedResources = new HashMap<String, Map<String, Object>>();
+    private final Set<String> deletedResources = new HashSet<String>();
+
+    public AbstractModifyingResourceProvider(String resourceRoot,
+                                              Map<String,String> additionalResourceProperties){
+        super(resourceRoot, additionalResourceProperties);
+
+    }
+
+    public Resource create(ResourceResolver resolver, String path, Map<String, Object> properties) throws PersistenceException {
+        SimplePathInfo pathInfo = extractPathInfo(path);
+
+        if (pathInfo == null) {
+            throw new PersistenceException("Invalid path: " + path, null);
+        }
+
+        if (!hasPermission(resolver, pathInfo.getResourcePath(), Session.ACTION_ADD_NODE)) {
+            throw new PersistenceException("Not enough permissions");
+        }
+
+
+        String resourceName = pathInfo.getMainResourceName();
+
+        final boolean deleted = this.deletedResources.remove(resourceName);
+        Map existingResource = getMainResourceProperties(resourceName);
+        if (!deleted && existingResource != null) {
+            throw new PersistenceException("Resource already exists at " + path, null, resourceName, null);
+        }
+
+        properties = unbindMainResourceProperties(properties);
+        this.changedResources.put(resourceName, properties);
+
+        return buildMainResource(resolver, pathInfo, properties);
+    }
+
+    public void delete(ResourceResolver resolver, String requestPath) throws PersistenceException {
+        SimplePathInfo pathInfo = extractPathInfo(requestPath);
+
+        if (pathInfo == null) {
+            throw new PersistenceException("Invalid path: " + requestPath, null);
+        }
+
+        if (!hasPermission(resolver, pathInfo.getResourcePath(), Session.ACTION_REMOVE)) {
+            throw new PersistenceException("Not enough permissions");
+        }
+
+        String resourceName = pathInfo.getMainResourceName();
+
+        if (!deletedResources.contains(resourceName)) {
+           deletedResources.add(resourceName);
+           changedResources.remove(resourceName);
+        }
+    }
+
+    public void revert(ResourceResolver resolver) {
+        changedResources.clear();
+        deletedResources.clear();
+    }
+
+    public void commit(ResourceResolver resolver) throws PersistenceException {
+        save(resolver, changedResources, deletedResources);
+        revert(resolver);
+    }
+
+    public boolean hasChanges(ResourceResolver resolver) {
+        return changedResources.size() > 0 || deletedResources.size() > 0;
+    }
+
+    public void change(ResourceResolver resourceResolver, String requestPath, Map<String, Object> properties) {
+        SimplePathInfo pathInfo = extractPathInfo(requestPath);
+
+        if (pathInfo == null) {
+            return;
+        }
+
+        if (!hasPermission(resourceResolver, pathInfo.getResourcePath(), Session.ACTION_SET_PROPERTY)) {
+            return;
+        }
+
+        String resourceName = pathInfo.getMainResourceName();
+
+        this.deletedResources.remove(resourceName);
+
+        properties = unbindMainResourceProperties(properties);
+        this.changedResources.put(resourceName, properties);
+    }
+
+    @Override
+    public Map<String, Object> getMainResourceProperties(String resourceName) {
+
+        if (deletedResources.contains(resourceName)) {
+            return null;
+        }
+
+        if (changedResources.containsKey(resourceName)) {
+            return changedResources.get(resourceName);
+        }
+
+        return super.getMainResourceProperties(resourceName);
+    }
+
+    @Override
+    protected Resource buildMainResource(ResourceResolver resourceResolver, SimplePathInfo pathInfo, Map<String, Object> properties, Object... adapters) {
+        return new SimpleModifiableResource(resourceResolver, this, pathInfo.getResourcePath(), properties);
+    }
+
+    protected abstract void save(ResourceResolver resourceResolver,
+                                 Map<String, Map<String, Object>> changedResources,
+                                 Set<String> deletedResources) throws PersistenceException;
+
+
+
+}

Propchange: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/AbstractModifyingResourceProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/AbstractReadableResourceProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/AbstractReadableResourceProvider.java?rev=1578436&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/AbstractReadableResourceProvider.java (added)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/AbstractReadableResourceProvider.java Mon Mar 17 15:26:45 2014
@@ -0,0 +1,200 @@
+/*
+ * 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.replication.resources.impl.common;
+
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.api.resource.ResourceResolver;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public abstract class AbstractReadableResourceProvider implements ResourceProvider {
+
+    protected static final String ADAPTABLE_PROPERTY_NAME = "adaptable";
+
+    private static final String MAIN_RESOURCE_PREFIX = ".";
+    private static final String ROOT_RESOURCE_PREFIX = "..";
+
+    private final String resourceRoot;
+    private final Map<String, Map<String, String>> additionalResourcePropertiesMap = new HashMap<String, Map<String, String>>();
+
+    public AbstractReadableResourceProvider(String resourceRoot,
+                                            Map<String,String> additionalResourceProperties) {
+
+        this.resourceRoot = resourceRoot;
+
+        additionalResourcePropertiesMap.put(ROOT_RESOURCE_PREFIX, new HashMap<String, String>());
+        additionalResourcePropertiesMap.put(MAIN_RESOURCE_PREFIX, new HashMap<String, String>());
+        for (Map.Entry<String, String> entry : additionalResourceProperties.entrySet()) {
+            String resourceName = MAIN_RESOURCE_PREFIX;
+            String propertyName = entry.getKey();
+            int idx =propertyName.indexOf("/");
+            if (idx >=0) {
+                resourceName = propertyName.substring(0, idx);
+                propertyName = propertyName.substring(idx+1);
+            }
+
+            if (!additionalResourcePropertiesMap.containsKey(resourceName)) {
+                additionalResourcePropertiesMap.put(resourceName, new HashMap<String, String>());
+            }
+
+            additionalResourcePropertiesMap.get(resourceName).put(propertyName, entry.getValue());
+        }
+    }
+
+    public Resource getResource(ResourceResolver resourceResolver, HttpServletRequest request, String path) {
+        return getResource(resourceResolver, path);
+    }
+
+    public Resource getResource(ResourceResolver resourceResolver, String path) {
+        SimplePathInfo pathInfo = extractPathInfo(path);
+
+        if (pathInfo == null) {
+            return null;
+        }
+
+        if (pathInfo.getResourcePathInfo() != null && pathInfo.getResourcePathInfo().length() > 0) {
+            return null;
+        }
+
+        if(!hasPermission(resourceResolver, pathInfo.getResourcePath(), Session.ACTION_READ)) {
+            return null;
+        }
+
+        Resource resource = null;
+
+        if (pathInfo.isRoot()) {
+
+            Map<String, Object> properties = getResourceRootProperties();
+
+            if (properties != null) {
+                Object adaptable = properties.remove(ADAPTABLE_PROPERTY_NAME);
+
+                Map<String, String > additionalProperties = additionalResourcePropertiesMap.get(ROOT_RESOURCE_PREFIX);
+                properties.putAll(additionalProperties);
+
+                resource = new SimpleReadableResource(resourceResolver, pathInfo.getResourcePath(), properties, adaptable);
+            }
+        }
+        else if (pathInfo.isMain()) {
+            Map<String, Object> properties = getMainResourceProperties(pathInfo.getMainResourceName());
+
+            Object adaptable = properties.remove(ADAPTABLE_PROPERTY_NAME);
+
+            properties = bindMainResourceProperties(properties);
+
+            resource = buildMainResource(resourceResolver, pathInfo, properties, adaptable);
+        }
+        else if (pathInfo.isChild()) {
+            Map<String, String> childProperties = additionalResourcePropertiesMap.get(pathInfo.getChildResourceName());
+
+            if (childProperties != null) {
+                Map<String, Object> mainProperties = getMainResourceProperties(pathInfo.getMainResourceName());
+                Object adaptable = mainProperties.remove(ADAPTABLE_PROPERTY_NAME);
+
+                Map<String, Object> properties = new HashMap<String, Object>();
+                properties.putAll(childProperties);
+                resource = new SimpleReadableResource(resourceResolver, pathInfo.getResourcePath(), properties, adaptable);
+            }
+        }
+
+        return resource;
+    }
+
+    protected Map<String, Object> getMainResourceProperties(String resourceName) {
+        return getResourceProperties(resourceName);
+    }
+
+    protected Map<String, Object> bindMainResourceProperties(Map<String, Object> properties) {
+        Map<String, Object> result = new HashMap<String, Object>();
+
+        Map<String, String > resourceProperties = additionalResourcePropertiesMap.get(MAIN_RESOURCE_PREFIX);
+
+        for (Map.Entry<String, String> entry : resourceProperties.entrySet()) {
+            String key = entry.getKey();
+            String value = entry.getValue();
+            Object objectValue = value;
+            if (value.startsWith("{") && value.endsWith("}")) {
+                objectValue = properties.get(value.substring(1, value.length()-1));
+                if (objectValue == null) continue;
+            }
+
+            result.put(key, objectValue);
+        }
+        return result;
+    }
+
+    protected Map<String, Object> unbindMainResourceProperties(Map<String, Object> properties) {
+        Map<String, Object> result = new HashMap<String, Object>();
+
+        Map<String, String > resourceProperties = additionalResourcePropertiesMap.get(MAIN_RESOURCE_PREFIX);
+
+        for (Map.Entry<String, String> entry : resourceProperties.entrySet()) {
+            String key = entry.getKey();
+            String value = entry.getValue();
+            Object objectValue = value;
+            if (value.startsWith("{") && value.endsWith("}")) {
+                objectValue = properties.get(key);
+
+                if (objectValue != null) {
+                    result.put(key, objectValue);
+                }
+            }
+        }
+        return result;
+    }
+
+    protected Resource buildMainResource(ResourceResolver resourceResolver,
+                                         SimplePathInfo pathInfo,
+                                         Map<String, Object> properties,
+                                         Object... adapters) {
+        return new SimpleReadableResource(resourceResolver, pathInfo.getResourcePath(), properties, adapters);
+    }
+
+    protected  SimplePathInfo extractPathInfo(String path) {
+        return SimplePathInfo.parsePathInfo(resourceRoot, path);
+    }
+
+    protected boolean hasPermission(ResourceResolver resourceResolver, String resourcePath, String permission) {
+
+        boolean hasPermission = false;
+        Session session = resourceResolver.adaptTo(Session.class);
+
+        if (session != null) {
+            try {
+                hasPermission = session.hasPermission(resourcePath, permission);
+            } catch (RepositoryException e) {
+                hasPermission = false;
+            }
+        }
+
+        return hasPermission;
+    }
+
+
+    protected abstract Map<String, Object> getResourceProperties(String resourceName);
+    protected abstract Map<String, Object> getResourceRootProperties();
+}

Propchange: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/AbstractReadableResourceProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleModifiableResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleModifiableResource.java?rev=1578436&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleModifiableResource.java (added)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleModifiableResource.java Mon Mar 17 15:26:45 2014
@@ -0,0 +1,55 @@
+/*
+ * 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.replication.resources.impl.common;
+
+import org.apache.sling.api.resource.AbstractResource;
+import org.apache.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ValueMap;
+
+import java.util.Map;
+
+/**
+ * Resource that can be adapted to a ModifiableValueMap
+ */
+public class SimpleModifiableResource extends SimpleReadableResource {
+
+    private final AbstractModifyingResourceProvider resourceProvider;
+
+    public SimpleModifiableResource(ResourceResolver resourceResolver, AbstractModifyingResourceProvider resourceProvider,
+                                    String resourcePath,
+                                    Map<String, Object> properties) {
+        super(resourceResolver, resourcePath, properties);
+        this.resourceProvider = resourceProvider;
+    }
+
+    @Override
+    public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+
+        if (type == ValueMap.class || type == Map.class) {
+            return (AdapterType) new SimpleModifiableValueMap(getResourceResolver(), resourceProvider, this);
+
+        } else if (type == ModifiableValueMap.class) {
+            return (AdapterType) new SimpleModifiableValueMap(getResourceResolver(), resourceProvider, this);
+        }
+
+        return super.adaptTo(type);
+    }
+}

Propchange: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleModifiableResource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleModifiableValueMap.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleModifiableValueMap.java?rev=1578436&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleModifiableValueMap.java (added)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleModifiableValueMap.java Mon Mar 17 15:26:45 2014
@@ -0,0 +1,81 @@
+/*
+ * 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.replication.resources.impl.common;
+
+import org.apache.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.wrappers.ModifiableValueMapDecorator;
+import org.apache.sling.replication.resources.impl.common.AbstractModifyingResourceProvider;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * ValueMap that signals to the underlying resource provider the its values are changed.
+ */
+public class SimpleModifiableValueMap extends ModifiableValueMapDecorator
+        implements ModifiableValueMap {
+
+    private final ResourceResolver resourceResolver;
+    private final AbstractModifyingResourceProvider resourceProvider;
+    private final SimpleModifiableResource resource;
+
+    public SimpleModifiableValueMap(ResourceResolver resourceResolver,
+                                    AbstractModifyingResourceProvider resourceProvider,
+                                    SimpleModifiableResource resource) {
+        super(resource.getProperties());
+        this.resourceResolver = resourceResolver;
+        this.resourceProvider = resourceProvider;
+        this.resource = resource;
+    }
+
+    @Override
+    public Object put(String key, Object value) {
+        Object result = super.put(key, value);
+        changed();
+        return result;
+    }
+
+    @Override
+    public Object remove(Object key) {
+        Object result = super.remove(key);
+        changed();
+        return result;
+    }
+
+    @Override
+    public void putAll(Map<? extends String, ?> t) {
+        super.putAll(t);
+        changed();
+    }
+
+    @Override
+    public void clear() {
+        super.clear();
+        changed();
+    }
+
+    private void changed() {
+        Map<String, Object> newProperties = new HashMap<String, Object>();
+        for (Entry<String, Object> entry : entrySet()) {
+            newProperties.put(entry.getKey(), entry.getValue());
+        }
+        resourceProvider.change(resourceResolver, resource.getPath(), newProperties);
+    }
+}

Propchange: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleModifiableValueMap.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimplePathInfo.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimplePathInfo.java?rev=1578436&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimplePathInfo.java (added)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimplePathInfo.java Mon Mar 17 15:26:45 2014
@@ -0,0 +1,122 @@
+/*
+ * 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.replication.resources.impl.common;
+
+/**
+ * Path info representing a main resource.
+ * The requestPath = resourcePath + resourcePathInfo
+ * The identified resource can be of three types:
+ *      root  - resourcePath = resourceRoot
+ *      main  - resourcePath = resourceRoot + mainResourceName
+ *      child - resourcePath = resourceRoot + mainResourceName + childResourceName
+ */
+public class SimplePathInfo {
+
+    String resourcePathInfo;
+
+    // resourcePath = resourceRoot + "/" + mainResourceName + "/" + childResourceName
+    private String resourceRoot;
+    private String mainResourceName;
+    private String childResourceName;
+
+    public SimplePathInfo(String resourcePathInfo, String resourceRoot, String resourceName, String childResourceName) {
+
+        this.resourcePathInfo = resourcePathInfo;
+        this.resourceRoot = resourceRoot;
+        this.mainResourceName = resourceName;
+        this.childResourceName = childResourceName;
+    }
+
+    public String getResourcePathInfo() {
+        return resourcePathInfo;
+    }
+
+    public String getMainResourceName() {
+        return mainResourceName;
+    }
+
+    public String getChildResourceName() {
+        return childResourceName;
+    }
+
+    public boolean isRoot() {
+        return mainResourceName == null;
+    }
+
+    public boolean isMain() {
+        return mainResourceName != null && childResourceName == null;
+    }
+
+    public boolean isChild() {
+        return mainResourceName != null && childResourceName != null;
+    }
+
+    public String  getResourcePath() {
+        if (isRoot()) {
+            return resourceRoot;
+        }
+        else if (isMain()) {
+            return resourceRoot + "/" + mainResourceName;
+        }
+        else if (isChild()) {
+            return resourceRoot + "/" + mainResourceName + "/" + childResourceName;
+        }
+
+        return null;
+    }
+
+
+    public static SimplePathInfo parsePathInfo(String resourceRoot, String requestPath) {
+        if (!requestPath.startsWith(resourceRoot)) {
+            return null;
+        }
+
+        String resourceName = null;
+        String resourcePathInfo = null;
+
+        if(requestPath.startsWith(resourceRoot + "/")) {
+            resourceName = requestPath.substring(resourceRoot.length()+1);
+            int idx = resourceName.indexOf(".");
+            if (idx >= 0) {
+                resourcePathInfo = resourceName.substring(idx);
+                resourceName = resourceName.substring(0, idx);
+            }
+        }
+        else {
+            int idx = requestPath.indexOf(".");
+            if (requestPath.contains(".")) {
+                resourcePathInfo = requestPath.substring(idx);
+            }
+        }
+
+        String childResourceName = null;
+
+        if (resourceName != null) {
+            int idx = resourceName.indexOf("/");
+            if (idx >= 0) {
+                childResourceName = resourceName.substring(idx+1);
+                resourceName = resourceName.substring(0, idx);
+            }
+        }
+        return new SimplePathInfo(resourcePathInfo, resourceRoot, resourceName, childResourceName);
+    }
+}
+
+

Propchange: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimplePathInfo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleReadableResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleReadableResource.java?rev=1578436&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleReadableResource.java (added)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleReadableResource.java Mon Mar 17 15:26:45 2014
@@ -0,0 +1,131 @@
+/*
+ * 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.replication.resources.impl.common;
+
+
+import org.apache.sling.api.resource.AbstractResource;
+import org.apache.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.api.wrappers.ValueMapDecorator;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * Read only resource that can adapt to one of the object provided as parameter.
+ */
+public class SimpleReadableResource extends AbstractResource {
+
+    private final ResourceResolver resourceResolver;
+    private final String resourcePath;
+    private final Map<String, Object> properties;
+    private final Object[] adapters;
+
+    private final ResourceMetadata metadata = new ResourceMetadata();
+
+
+    public SimpleReadableResource(ResourceResolver resourceResolver, String resourcePath,
+                                    Map<String, Object> properties, Object... adapters) {
+
+        this.resourceResolver = resourceResolver;
+        this.resourcePath = resourcePath;
+        this.properties = properties;
+        this.adapters = adapters;
+    }
+
+    public String getPath() {
+        return resourcePath;
+    }
+
+    public String getResourceType() {
+        // get resource type from data
+        final Object rt = this.properties.get("sling:resourceType");
+        if ( rt != null ) {
+            return rt.toString();
+        }
+        return "nt:unstructured";
+    }
+
+    public String getResourceSuperType() {
+        // get resource type from data
+        final Object rt = this.properties.get("sling:resourceSuperType");
+        if ( rt != null ) {
+            return rt.toString();
+        }
+        return "nt:unstructured";
+    }
+
+    public ResourceMetadata getResourceMetadata() {
+        return metadata;
+    }
+
+    public ResourceResolver getResourceResolver() {
+        return resourceResolver;
+    }
+
+    public Map<String, Object> getProperties() {
+        return properties;
+    }
+
+
+    @Override
+    public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+
+        if (type == ValueMap.class || type == Map.class) {
+            return (AdapterType) new ValueMapDecorator(getProperties());
+        }
+        else {
+            if (adapters != null) {
+                for (Object adapter : adapters) {
+                    if (adapter == null) continue;
+
+                    if (type.isArray()) {
+                        if (adapter.getClass().isArray()) {
+                            Object[] adapterArray = (Object[]) adapter;
+                            AdapterType result = convertArray(type, adapterArray);
+
+                            return result;
+                        }
+                    }
+                    else if (type.isAssignableFrom(adapter.getClass())) {
+                        return (AdapterType) adapter;
+                    }
+                }
+            }
+        }
+        return super.adaptTo(type);
+    }
+
+
+    private  <ArrayType> ArrayType convertArray(Class<ArrayType> arrayType, Object[] array) {
+        Object[] result = (Object[]) Array.newInstance(arrayType.getComponentType(), array.length);
+        for (int i=0; i < array.length; i++) {
+           if (array[i] != null && !arrayType.getComponentType().isAssignableFrom(array[i].getClass())) {
+            return null;
+           }
+           result[i] = array[i];
+        }
+
+        return (ArrayType) result;
+    }
+}
\ No newline at end of file

Propchange: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/resources/impl/common/SimpleReadableResource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/rule/impl/ReplicateOnQueueEventRule.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/rule/impl/ReplicateOnQueueEventRule.java?rev=1578436&r1=1578435&r2=1578436&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/rule/impl/ReplicateOnQueueEventRule.java (original)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/rule/impl/ReplicateOnQueueEventRule.java Mon Mar 17 15:26:45 2014
@@ -49,10 +49,9 @@ import org.apache.sling.replication.agen
 import org.apache.sling.replication.agent.ReplicationAgent;
 import org.apache.sling.replication.agent.ReplicationAgentConfiguration;
 import org.apache.sling.replication.agent.ReplicationAgentConfigurationManager;
-import org.apache.sling.replication.agent.impl.ReplicationAgentQueueResource;
-import org.apache.sling.replication.agent.impl.ReplicationAgentResource;
 import org.apache.sling.replication.communication.ReplicationActionType;
 import org.apache.sling.replication.communication.ReplicationRequest;
+import org.apache.sling.replication.resources.ReplicationConstants;
 import org.apache.sling.replication.rule.ReplicationRule;
 import org.apache.sling.replication.transport.TransportHandler;
 import org.osgi.framework.BundleContext;
@@ -206,9 +205,9 @@ public class ReplicateOnQueueEventRule i
 
                     log.info("endpoint {} props {}", endpoints, authenticationProperties);
                     // only works with HTTP
-                    if (endpoints.length == 1 && endpoints[0].startsWith("http") && endpoints[0].contains(ReplicationAgentResource.BASE_PATH) && authenticationProperties != null) {
+                    if (endpoints.length == 1 && endpoints[0].startsWith("http") && authenticationProperties != null) {
                         log.info("getting event queue URI");
-                        URI eventEndpoint = URI.create(endpoints[0] + ReplicationAgentQueueResource.EVENT_SUFFIX_PATH);
+                        URI eventEndpoint = URI.create(endpoints[0] + ReplicationConstants.SUFFIX_AGENT_QUEUE_EVENT);
                         String userName = authenticationProperties.get("user");
                         String password = authenticationProperties.get("password");
 

Modified: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/serialization/impl/DefaultReplicationPackageImporter.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/serialization/impl/DefaultReplicationPackageImporter.java?rev=1578436&r1=1578435&r2=1578436&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/serialization/impl/DefaultReplicationPackageImporter.java (original)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/serialization/impl/DefaultReplicationPackageImporter.java Mon Mar 17 15:26:45 2014
@@ -23,6 +23,7 @@ import java.util.Arrays;
 import java.util.Dictionary;
 import java.util.Hashtable;
 import org.apache.felix.scr.annotations.Component;
+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.replication.event.ReplicationEventFactory;
@@ -40,8 +41,11 @@ import org.slf4j.LoggerFactory;
  */
 @Component(label = "Default Replication Package Importer")
 @Service(value = ReplicationPackageImporter.class)
+@Property(name = "name", value = DefaultReplicationPackageImporter.NAME)
 public class DefaultReplicationPackageImporter implements ReplicationPackageImporter {
 
+    public static final String NAME = "default";
+
     private static final String QUEUE_NAME = "replication-package-import";
     private static final String QUEUE_TOPIC = "org/apache/sling/replication/import";
 

Modified: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentQueueEventServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentQueueEventServlet.java?rev=1578436&r1=1578435&r2=1578436&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentQueueEventServlet.java (original)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentQueueEventServlet.java Mon Mar 17 15:26:45 2014
@@ -34,16 +34,14 @@ import org.apache.felix.scr.annotations.
 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.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.servlets.SlingAllMethodsServlet;
 import org.apache.sling.replication.agent.ReplicationAgent;
-import org.apache.sling.replication.agent.ReplicationAgentsManager;
-import org.apache.sling.replication.agent.impl.ReplicationAgentQueueResource;
 import org.apache.sling.replication.event.ReplicationEvent;
 import org.apache.sling.replication.event.ReplicationEventType;
+import org.apache.sling.replication.resources.ReplicationConstants;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.event.Event;
@@ -59,7 +57,7 @@ import org.slf4j.LoggerFactory;
 @Component(metatype = false)
 @Service(value = Servlet.class)
 @Properties({
-        @Property(name = "sling.servlet.resourceTypes", value = ReplicationAgentQueueResource.EVENT_RESOURCE_TYPE),
+        @Property(name = "sling.servlet.resourceTypes", value = ReplicationConstants.AGENT_QUEUE_EVENT_RESOURCE_TYPE),
         @Property(name = "sling.servlet.methods", value = "GET")
 })
 public class ReplicationAgentQueueEventServlet extends SlingAllMethodsServlet {
@@ -68,9 +66,6 @@ public class ReplicationAgentQueueEventS
 
     private static final Map<String, Collection<String>> cachedEvents = new ConcurrentHashMap<String, Collection<String>>();
 
-    @Reference
-    private ReplicationAgentsManager replicationAgentsManager;
-
     private ServiceRegistration registration;
 
     @Activate

Added: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentQueueServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentQueueServlet.java?rev=1578436&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentQueueServlet.java (added)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentQueueServlet.java Mon Mar 17 15:26:45 2014
@@ -0,0 +1,137 @@
+/*
+ * 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.replication.servlet;
+
+import java.io.IOException;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.servlets.SlingAllMethodsServlet;
+
+import org.apache.sling.replication.agent.ReplicationAgent;
+import org.apache.sling.replication.communication.ReplicationHeader;
+import org.apache.sling.replication.queue.ReplicationQueue;
+import org.apache.sling.replication.queue.ReplicationQueueItem;
+import org.apache.sling.replication.queue.ReplicationQueueItemState;
+import org.apache.sling.replication.resources.ReplicationConstants;
+
+/**
+ * Servlet to retrieve a {@link org.apache.sling.replication.queue.ReplicationQueue} status.
+ */
+@SuppressWarnings("serial")
+@Component(metatype = false)
+@Service(value = Servlet.class)
+@Properties({
+        @Property(name = "sling.servlet.resourceTypes", value = ReplicationConstants.AGENT_QUEUE_RESOURCE_TYPE),
+        @Property(name = "sling.servlet.methods", value = { "GET", "POST", "DELETE" } ) })
+public class ReplicationAgentQueueServlet extends SlingAllMethodsServlet {
+
+    @Override
+    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
+            throws ServletException, IOException {
+        response.setContentType("application/json");
+
+        String queueName = request.getParameter(ReplicationHeader.QUEUE.toString());
+
+        ReplicationAgent agent = request.getResource().adaptTo(ReplicationAgent.class);
+
+        if (agent != null) {
+            try {
+                ReplicationQueue queue = agent.getQueue("");
+
+                response.getWriter().write(toJSoN(queue));
+            } catch (Exception e) {
+                response.getWriter().write("{\"status\" : \"error\",\"message\":\"error reading from the queue\"}");
+            }
+        } else {
+            response.getWriter().write("{\"status\" : \"error\",\"message\":\"queue not found\"}");
+        }
+    }
+
+
+    @Override
+     protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
+            throws ServletException, IOException {
+        @SuppressWarnings("unchecked")
+        String operation = request.getParameter(":operation");
+
+        if("delete".equals(operation)) {
+            doDelete(request, response);
+            return;
+        };
+    }
+
+
+    @Override
+    protected void doDelete(SlingHttpServletRequest request, SlingHttpServletResponse response)
+            throws ServletException, IOException {
+        ReplicationQueue queue = request.getResource().adaptTo(ReplicationQueue.class);
+
+        while(!queue.isEmpty()){
+            queue.removeHead();
+        }
+    }
+
+    private String toJSoN(ReplicationQueue queue) throws Exception {
+        StringBuilder builder = new StringBuilder("{\"name\":\"" + queue.getName() + "\",\"empty\":" + queue.isEmpty());
+        if (!queue.isEmpty()) {
+            builder.append(",\"items\":[");
+            for (ReplicationQueueItem item : queue.getItems()) {
+                builder.append('{');
+                builder.append(toJSoN(item));
+                builder.append(',');
+                builder.append(toJSoN(queue.getStatus(item)));
+                builder.append("},");
+            }
+            if (queue.getItems().size() > 0) {
+                builder.deleteCharAt(builder.length() - 1);
+            }
+            builder.append(']');
+        }
+        builder.append('}');
+        return builder.toString();
+    }
+
+    private String toJSoN(ReplicationQueueItemState status) {
+        return "\"attempts\":" + status.getAttempts() + ",\"state\":\"" + status.getItemState().name() + "\",\"entered\":\"" + status.getEntered().getTime() + "\"";
+    }
+
+    private String toJSoN(ReplicationQueueItem item) {
+        StringBuilder builder = new StringBuilder();
+        builder.append("\"id\":\"").append(item.getId().replace("\\", "\\\\"));
+        builder.append("\",\"paths\":[");
+        for (int i = 0; i < item.getPaths().length; i++) {
+            builder.append("\"");
+            builder.append(item.getPaths()[i]);
+            builder.append("\",");
+        }
+        builder.deleteCharAt(builder.length() - 1);
+        builder.append(']');
+        builder.append(",\"action\":\"").append(item.getAction());
+        builder.append("\",\"type\":\"").append(item.getType());
+        builder.append("\"");
+        return builder.toString();
+    }
+}

Propchange: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentQueueServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentRootServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentRootServlet.java?rev=1578436&r1=1578435&r2=1578436&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentRootServlet.java (original)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentRootServlet.java Mon Mar 17 15:26:45 2014
@@ -19,8 +19,6 @@
 package org.apache.sling.replication.servlet;
 
 import java.io.IOException;
-import java.util.Collection;
-import java.util.SortedSet;
 
 import javax.servlet.Servlet;
 import javax.servlet.ServletException;
@@ -28,18 +26,16 @@ import javax.servlet.ServletException;
 import org.apache.felix.scr.annotations.Component;
 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.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.servlets.SlingAllMethodsServlet;
-import org.apache.sling.replication.agent.impl.ReplicationAgentResource;
+import org.apache.sling.replication.resources.ReplicationConstants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.sling.replication.agent.AgentReplicationException;
 import org.apache.sling.replication.agent.ReplicationAgent;
-import org.apache.sling.replication.agent.ReplicationAgentsManager;
 import org.apache.sling.replication.communication.ReplicationActionType;
 import org.apache.sling.replication.communication.ReplicationRequest;
 
@@ -50,8 +46,8 @@ import org.apache.sling.replication.comm
 @Component(metatype = false)
 @Service(value = Servlet.class)
 @Properties({
-    @Property(name = "sling.servlet.resourceTypes", value = ReplicationAgentResource.RESOURCE_ROOT_TYPE),
-    @Property(name = "sling.servlet.methods", value = {"POST", "GET" })
+    @Property(name = "sling.servlet.resourceTypes", value = ReplicationConstants.AGENT_ROOT_RESOURCE_TYPE),
+    @Property(name = "sling.servlet.methods", value = {"POST" })
 })
 public class ReplicationAgentRootServlet extends SlingAllMethodsServlet {
 
@@ -61,18 +57,18 @@ public class ReplicationAgentRootServlet
 
     private static final String ACTION_PARAMETER = "action";
 
-    @Reference
-    private ReplicationAgentsManager replicationAgentsManager;
 
     @Override
     protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
                     throws ServletException, IOException {
 
+        ReplicationAgent[] agents = request.getResource().adaptTo(ReplicationAgent[].class);
+
         String a = request.getParameter(ACTION_PARAMETER);
         String[] paths = request.getParameterValues(PATH_PARAMETER);
 
         ReplicationActionType action = ReplicationActionType.fromName(a);
-        SortedSet<ReplicationAgent> agents = replicationAgentsManager.getAgentsFor(action, paths);
+
 
         ReplicationRequest replicationRequest = new ReplicationRequest(System.currentTimeMillis(),
                         action, paths);
@@ -98,49 +94,4 @@ public class ReplicationAgentRootServlet
             response.setStatus(200);
         }
     }
-
-
-
-    @Override
-    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
-            throws ServletException, IOException {
-
-        Collection<ReplicationAgent> agents = replicationAgentsManager.getAllAvailableAgents();
-
-        response.getWriter().append(toJson(agents));
-    }
-
-    String toJson(Collection<ReplicationAgent> agents) {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append("{");
-
-        sb.append("\"items\": ");
-
-        sb.append("[");
-
-        for(ReplicationAgent agent : agents) {
-            sb.append(toJson(agent));
-            sb.append(",");
-        }
-
-        if(sb.charAt(sb.length()-1) == ',')
-            sb.deleteCharAt(sb.length()-1);
-
-        sb.append("]");
-
-        sb.append("}");
-
-        return sb.toString();
-    }
-
-
-    String toJson(ReplicationAgent agent) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("{");
-        sb.append("\"name\": "+ agent.getName());
-        sb.append("}");
-
-        return sb.toString();
-    }
 }

Modified: sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentServlet.java?rev=1578436&r1=1578435&r2=1578436&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentServlet.java (original)
+++ sling/trunk/contrib/extensions/replication/src/main/java/org/apache/sling/replication/servlet/ReplicationAgentServlet.java Mon Mar 17 15:26:45 2014
@@ -39,12 +39,12 @@ import org.apache.sling.api.servlets.Sli
 
 import org.apache.sling.replication.agent.AgentReplicationException;
 import org.apache.sling.replication.agent.ReplicationAgent;
-import org.apache.sling.replication.agent.impl.ReplicationAgentResource;
 import org.apache.sling.replication.communication.ReplicationActionType;
 import org.apache.sling.replication.communication.ReplicationHeader;
 import org.apache.sling.replication.communication.ReplicationRequest;
 import org.apache.sling.replication.communication.ReplicationResponse;
 import org.apache.sling.replication.queue.ReplicationQueueItemState.ItemState;
+import org.apache.sling.replication.resources.ReplicationConstants;
 import org.apache.sling.replication.serialization.ReplicationPackage;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -56,7 +56,7 @@ import org.slf4j.LoggerFactory;
 @Component(metatype = false)
 @Service(value = Servlet.class)
 @Properties({
-        @Property(name = "sling.servlet.resourceTypes", value = ReplicationAgentResource.RESOURCE_TYPE),
+        @Property(name = "sling.servlet.resourceTypes", value = ReplicationConstants.AGENT_RESOURCE_TYPE),
         @Property(name = "sling.servlet.methods", value = "POST") })
 public class ReplicationAgentServlet extends SlingAllMethodsServlet {