You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:59:07 UTC

[sling-org-apache-sling-resourcemerger] 02/05: SLING-3418 : Wrong path handling wrt search paths SLING-3419 : Component name specified instead of component label SLING-3420 : Implement ModifyingResourceProvider - first version

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

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

commit f043a2386cf2234cef716dc5b1163e369682b7b4
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Wed Feb 26 12:57:27 2014 +0000

    SLING-3418 : Wrong path handling wrt search paths
    SLING-3419 : Component name specified instead of component label
    SLING-3420 : Implement ModifyingResourceProvider - first version
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/resourcemerger@1572039 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |   5 +
 .../sling/resourcemerger/impl/MergedResource.java  |  39 ++-
 .../impl/MergedResourceProvider.java               | 314 +++++++++++++++------
 .../impl/MergedResourceProviderFactory.java        |   2 +-
 .../impl/MergedResourceProviderTest.java           |  55 +++-
 5 files changed, 321 insertions(+), 94 deletions(-)

diff --git a/pom.xml b/pom.xml
index 476da85..7778442 100644
--- a/pom.xml
+++ b/pom.xml
@@ -89,6 +89,11 @@
             <artifactId>junit</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.testing.resourceresolver-mock</artifactId>
             <version>0.2.0</version>
diff --git a/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java b/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java
index f799c6c..34c98af 100644
--- a/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java
+++ b/src/main/java/org/apache/sling/resourcemerger/impl/MergedResource.java
@@ -21,9 +21,12 @@ package org.apache.sling.resourcemerger.impl;
 import java.util.List;
 
 import org.apache.sling.api.resource.AbstractResource;
+import org.apache.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceMetadata;
 import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.resource.ValueMap;
 
 /**
@@ -44,7 +47,10 @@ public class MergedResource extends AbstractResource {
     private final ResourceMetadata metadata = new ResourceMetadata();
 
     /** Cache value map. */
-    private ValueMap properties;
+    private final ValueMap properties;
+
+    /** Root path */
+    private final String mergedRootPath;
 
     /**
      * Constructor
@@ -58,7 +64,8 @@ public class MergedResource extends AbstractResource {
                    final String mergeRootPath,
                    final String relativePath,
                    final List<Resource> mappedResources,
-                   final List<ValueMap> valueMaps) {
+                   final List<ValueMap> valueMaps,
+                   final String mergedRootPath) {
         this.resolver = resolver;
         this.path = (relativePath.length() == 0 ? mergeRootPath : mergeRootPath + "/" + relativePath);
         this.properties = new MergedValueMap(valueMaps);
@@ -71,6 +78,7 @@ public class MergedResource extends AbstractResource {
             i++;
         }
         metadata.put(MergedResourceConstants.METADATA_RESOURCES, resourcePaths);
+        this.mergedRootPath = mergedRootPath;
     }
 
     /**
@@ -115,11 +123,34 @@ public class MergedResource extends AbstractResource {
      */
     @Override
     @SuppressWarnings("unchecked")
-    public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+    public <AdapterType> AdapterType adaptTo(final Class<AdapterType> type) {
         if (type == ValueMap.class) {
             return (AdapterType) this.properties;
         }
-
+        if (type == ModifiableValueMap.class) {
+            final String paths[] = (String[])this.metadata.get(MergedResourceConstants.METADATA_RESOURCES);
+            final String[] searchPaths = resolver.getSearchPath();
+            final String lastSearchPath = searchPaths[searchPaths.length-1];
+
+            if ( paths.length == 1 && paths[0].startsWith(lastSearchPath) ) {
+                final Resource copyResource = resolver.getResource(paths[0]);
+                if ( searchPaths.length == 1 ) {
+                    return (AdapterType)copyResource.adaptTo(ModifiableValueMap.class);
+                }
+                final String prefix = searchPaths[searchPaths.length-2];
+                final String createPath = prefix + path.substring(this.mergedRootPath.length() + 1);
+                try {
+                    final Resource newResource = ResourceUtil.getOrCreateResource(resolver, ResourceUtil.getParent(createPath),copyResource.getResourceType(), null, false);
+                    return (AdapterType)newResource.adaptTo(ModifiableValueMap.class);
+                } catch ( final PersistenceException pe) {
+                    // we ignore this for now
+                    return null;
+                }
+            }
+            final String resourcePath = paths[paths.length-1];
+            final Resource rsrc = resolver.getResource(resourcePath);
+            return (AdapterType)rsrc.adaptTo(ModifiableValueMap.class);
+        }
         return super.adaptTo(type);
     }
 
diff --git a/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java b/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java
index 5f86a32..ece03c0 100644
--- a/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java
+++ b/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProvider.java
@@ -19,11 +19,15 @@
 package org.apache.sling.resourcemerger.impl;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
 
+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;
@@ -34,7 +38,8 @@ import org.apache.sling.api.resource.ValueMap;
  * The <code>MergedResourceProvider</code> is the resource provider providing
  * access to {@link MergedResource} objects.
  */
-public class MergedResourceProvider implements ResourceProvider {
+public class MergedResourceProvider
+    implements ResourceProvider, ModifyingResourceProvider {
 
     private final String mergeRootPath;
 
@@ -49,6 +54,52 @@ public class MergedResourceProvider implements ResourceProvider {
         return getResource(resolver, path);
     }
 
+    private static final class ExcludeEntry {
+
+        public final String name;
+        public final boolean exclude;
+
+        public ExcludeEntry(final String value) {
+            if ( value.startsWith("!!") ) {
+                this.name = value.substring(1);
+                this.exclude = false;
+            } else if ( value.startsWith("!") ) {
+                this.name = value.substring(1);
+                this.exclude = true;
+            } else {
+                this.name = value;
+                this.exclude = false;
+            }
+        }
+    }
+
+    private static final class ParentHidingHandler {
+
+        private final List<ExcludeEntry> entries = new ArrayList<MergedResourceProvider.ExcludeEntry>();
+
+        public ParentHidingHandler(final Resource parent) {
+            final ValueMap parentProps = ResourceUtil.getValueMap(parent);
+            final String[] childrenToHideArray = parentProps.get(MergedResourceConstants.PN_HIDE_CHILDREN, String[].class);
+            if ( childrenToHideArray != null ) {
+                for(final String value : childrenToHideArray) {
+                    final ExcludeEntry entry = new ExcludeEntry(value);
+                    this.entries.add(entry);
+                }
+            }
+        }
+
+        public boolean isHidden(final String name) {
+            boolean hidden = false;
+            for(final ExcludeEntry entry : this.entries) {
+                if ( entry.name.equals("*") || entry.name.equals(name) ) {
+                    hidden = !entry.exclude;
+                    break;
+                }
+            }
+            return hidden;
+        }
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -64,22 +115,12 @@ public class MergedResourceProvider implements ResourceProvider {
                 final String basePath = searchPaths[i];
 
                 // Try to get the corresponding physical resource for this base path
-                final String fullPath = basePath + "/" + relativePath;
+                final String fullPath = basePath + relativePath;
 
                 // check parent for hiding
                 final Resource parent = resolver.getResource(ResourceUtil.getParent(fullPath));
                 if ( parent != null ) {
-                    boolean hidden = false;
-                    final ValueMap parentProps = ResourceUtil.getValueMap(parent);
-                    final String[] childrenToHideArray = parentProps.get(MergedResourceConstants.PN_HIDE_CHILDREN, String[].class);
-                    if ( childrenToHideArray != null ) {
-                        for(final String name : childrenToHideArray ) {
-                            if ( name.equals(holder.name) || name.equals("*") ) {
-                                hidden = true;
-                                break;
-                            }
-                        }
-                    }
+                    final boolean hidden = new ParentHidingHandler(parent).isHidden(holder.name);
                     if ( hidden ) {
                         holder.resources.clear();
                     } else {
@@ -116,39 +157,23 @@ public class MergedResourceProvider implements ResourceProvider {
         while ( index < holder.resources.size() ) {
             final Resource baseRes = holder.resources.get(index);
             // check if resource is hidden
-            boolean hidden = false;
             final ValueMap props = ResourceUtil.getValueMap(baseRes);
             holder.valueMaps.add(props);
             if ( props.get(MergedResourceConstants.PN_HIDE_RESOURCE, Boolean.FALSE) ) {
-                hidden = true;
-            }
-            if ( !hidden ) {
-                // check parent
-                final ValueMap parentProps = ResourceUtil.getValueMap(baseRes.getParent());
-                final String[] childrenToHideArray = parentProps.get(MergedResourceConstants.PN_HIDE_CHILDREN, String[].class);
-                if ( childrenToHideArray != null ) {
-                    for(final String name : childrenToHideArray ) {
-                        if ( name.equals(baseRes.getName()) || name.equals("*") ) {
-                            hidden = true;
-                            break;
-                        }
-                    }
-                }
-            }
-            if ( hidden ) {
                 // clear everything up to now
                 for(int i=0;i<=index;i++) {
                     holder.resources.remove(0);
                 }
                 holder.valueMaps.clear();
-                index = -1; // start at zero
+                index = 0; // start at zero
+            } else {
+                index++;
             }
-            index++;
         }
 
         if (!holder.resources.isEmpty()) {
             // create a new merged resource based on the list of mapped physical resources
-            return new MergedResource(resolver, mergeRootPath, relativePath, holder.resources, holder.valueMaps);
+            return new MergedResource(resolver, mergeRootPath, relativePath, holder.resources, holder.valueMaps, this.mergeRootPath);
         }
         return null;
     }
@@ -168,69 +193,51 @@ public class MergedResourceProvider implements ResourceProvider {
             final String[] searchPaths = resolver.getSearchPath();
             for(int i=searchPaths.length-1; i >= 0; i--) {
                 final String basePath = searchPaths[i];
-                final Resource parentResource = resolver.getResource(basePath + "/" + relativePath);
+                final Resource parentResource = resolver.getResource(basePath + relativePath);
                 if ( parentResource != null ) {
-                    final ValueMap parentProps = ResourceUtil.getValueMap(parentResource);
-                    List<String> childrenToHide = new ArrayList<String>();
-                    boolean hideAll = false;
-                    final String[] childrenToHideArray = parentProps.get(MergedResourceConstants.PN_HIDE_CHILDREN, String[].class);
-                    if ( childrenToHideArray != null ) {
-                        for(final String name : childrenToHideArray ) {
-                            if ( name.equals("*") ) {
-                                hideAll = true;
-                            } else {
-                                childrenToHide.add(name);
+                    final ParentHidingHandler handler = new ParentHidingHandler(parentResource);
+                    for(final Resource child : parentResource.getChildren()) {
+                        final String rsrcName = child.getName();
+                        ResourceHolder holder = null;
+                        for(final ResourceHolder current : candidates) {
+                            if ( current.name.equals(rsrcName) ) {
+                                holder = current;
+                                break;
                             }
                         }
-                    }
-                    if ( hideAll ) {
-                        candidates.clear();
-                    } else {
-                        for(final Resource child : parentResource.getChildren()) {
-                            final String rsrcName = child.getName();
-                            ResourceHolder holder = null;
-                            for(final ResourceHolder current : candidates) {
-                                if ( current.name.equals(rsrcName) ) {
-                                    holder = current;
+                        if ( holder == null ) {
+                            holder = new ResourceHolder(rsrcName);
+                            candidates.add(holder);
+                        }
+                        holder.resources.add(child);
+
+                        // Check if children need reordering
+                        int orderBeforeIndex = -1;
+                        final ValueMap vm = ResourceUtil.getValueMap(child);
+                        final String orderBefore = vm.get(MergedResourceConstants.PN_ORDER_BEFORE, String.class);
+                        if (orderBefore != null && !orderBefore.equals(rsrcName)) {
+                            // search entry
+                            int index = 0;
+                            while (index < candidates.size()) {
+                                final ResourceHolder current = candidates.get(index);
+                                if ( current.name.equals(orderBefore) ) {
+                                    orderBeforeIndex = index;
                                     break;
                                 }
+                                index++;
                             }
-                            if ( holder == null ) {
-                                holder = new ResourceHolder(rsrcName);
-                                candidates.add(holder);
-                            }
-                            holder.resources.add(child);
-
-                            // Check if children need reordering
-                            int orderBeforeIndex = -1;
-                            final ValueMap vm = ResourceUtil.getValueMap(child);
-                            final String orderBefore = vm.get(MergedResourceConstants.PN_ORDER_BEFORE, String.class);
-                            if (orderBefore != null && !orderBefore.equals(rsrcName)) {
-                                // search entry
-                                int index = 0;
-                                while (index < candidates.size()) {
-                                    final ResourceHolder current = candidates.get(index);
-                                    if ( current.name.equals(orderBefore) ) {
-                                        orderBeforeIndex = index;
-                                        break;
-                                    }
-                                    index++;
-                                }
-                            }
+                        }
 
-                            if (orderBeforeIndex > -1) {
-                                candidates.add(orderBeforeIndex, holder);
-                                candidates.remove(candidates.size() - 1);
-                            }
+                        if (orderBeforeIndex > -1) {
+                            candidates.add(orderBeforeIndex, holder);
+                            candidates.remove(candidates.size() - 1);
                         }
-                        if ( childrenToHide.size() > 0 ) {
-                            final Iterator<ResourceHolder> iter = candidates.iterator();
-                            while ( iter.hasNext() ) {
-                                final ResourceHolder holder = iter.next();
-                                if ( childrenToHide.contains(holder.name) ) {
-                                    iter.remove();
-                                }
-                            }
+                    }
+                    final Iterator<ResourceHolder> iter = candidates.iterator();
+                    while ( iter.hasNext() ) {
+                        final ResourceHolder holder = iter.next();
+                        if ( handler.isHidden(holder.name) ) {
+                            iter.remove();
                         }
                     }
                 }
@@ -265,4 +272,135 @@ public class MergedResourceProvider implements ResourceProvider {
         }
         return null;
     }
+
+    private ResourceHolder getAllResources(final ResourceResolver resolver,
+            final String path,
+            final String relativePath) {
+        final ResourceHolder holder = new ResourceHolder(ResourceUtil.getName(path));
+
+        // Loop over provided base paths, start with least import
+        final String[] searchPaths = resolver.getSearchPath();
+        for(int i=searchPaths.length-1; i >= 0; i--) {
+            final String basePath = searchPaths[i];
+
+            // Try to get the corresponding physical resource for this base path
+            final String fullPath = basePath + relativePath;
+
+            // check parent for hiding
+            final Resource parent = resolver.getResource(ResourceUtil.getParent(fullPath));
+            if ( parent != null ) {
+                final boolean hidden = new ParentHidingHandler(parent).isHidden(holder.name);
+                if ( hidden ) {
+                    holder.resources.clear();
+                } else {
+                    final Resource baseRes = resolver.getResource(fullPath);
+                    if (baseRes != null) {
+                        holder.resources.add(baseRes);
+                    }
+                }
+            }
+        }
+        return holder;
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.ModifyingResourceProvider#create(org.apache.sling.api.resource.ResourceResolver, java.lang.String, java.util.Map)
+     */
+    public Resource create(final ResourceResolver resolver,
+            final String path,
+            final Map<String, Object> properties)
+    throws PersistenceException {
+        // we only support modifications if there is more than one search path
+        final String[] searchPaths = resolver.getSearchPath();
+        if ( searchPaths.length < 2 ) {
+            throw new PersistenceException("Modifying is only supported with at least two search paths", null, path, null);
+        }
+        // check if the resource exists
+        final Resource mountResource = this.getResource(resolver, path);
+        if ( mountResource != null ) {
+            throw new PersistenceException("Resource at " + path + " already exists.", null, path, null);
+        }
+        // creating of the root mount resource is not supported
+        final String relativePath = getRelativePath(path);
+        if ( relativePath == null || relativePath.length() == 0 ) {
+            throw new PersistenceException("Resource at " + path + " can't be created.", null, path, null);
+        }
+
+        final String lastSearchPath = searchPaths[searchPaths.length-1];
+        final ResourceHolder holder = this.getAllResources(resolver, path, relativePath);
+        if ( holder.resources.size() == 0 || holder.resources.size() == 1 && holder.resources.get(0).getPath().startsWith(lastSearchPath) ) {
+            final String useSearchPath = searchPaths[searchPaths.length-2];
+
+            final String createPath = useSearchPath + path.substring(this.mergeRootPath.length() + 1);
+            final Resource parentResource = ResourceUtil.getOrCreateResource(resolver, ResourceUtil.getParent(createPath), (String)null, null, false);
+            resolver.create(parentResource, ResourceUtil.getName(createPath), properties);
+        }
+        // TODO check hiding flag
+        return this.getResource(resolver, path);
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.ModifyingResourceProvider#delete(org.apache.sling.api.resource.ResourceResolver, java.lang.String)
+     */
+    public void delete(final ResourceResolver resolver, final String path)
+    throws PersistenceException {
+        // we only support modifications if there is more than one search path
+        final String[] searchPaths = resolver.getSearchPath();
+        if ( searchPaths.length < 2 ) {
+            throw new PersistenceException("Modifying is only supported with at least two search paths");
+        }
+        // deleting of the root mount resource is not supported
+        final String relativePath = getRelativePath(path);
+        if ( relativePath == null || relativePath.length() == 0 ) {
+            throw new PersistenceException("Resource at " + path + " can't be created.", null, path, null);
+        }
+
+        // check if the resource exists
+        final Resource mntResource = this.getResource(resolver, path);
+        if ( mntResource == null ) {
+            throw new PersistenceException("Resource at " + path + " does not exist", null, path, null);
+        }
+        final ResourceHolder holder = this.getAllResources(resolver, path, relativePath);
+        final String lastSearchPath = searchPaths[searchPaths.length-1];
+
+        int deleted = 0;
+        for(final Resource rsrc : holder.resources) {
+            final String p = rsrc.getPath();
+            if ( !p.startsWith(lastSearchPath) ) {
+                resolver.delete(rsrc);
+                deleted++;
+            }
+        }
+        if ( deleted < holder.resources.size() ) {
+            // create overlay resource which is hiding the other
+            final String prefix = searchPaths[searchPaths.length-2];
+            final String createPath = prefix + path.substring(this.mergeRootPath.length() + 1);
+            final Resource parentResource = ResourceUtil.getOrCreateResource(resolver, ResourceUtil.getParent(createPath), (String)null, null, false);
+            final Map<String, Object> properties = new HashMap<String, Object>();
+            properties.put(MergedResourceConstants.PN_HIDE_RESOURCE, Boolean.TRUE);
+            resolver.create(parentResource, ResourceUtil.getName(createPath), properties);
+        }
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.ModifyingResourceProvider#revert(org.apache.sling.api.resource.ResourceResolver)
+     */
+    public void revert(final ResourceResolver resolver) {
+        // the provider for the search paths will revert
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.ModifyingResourceProvider#commit(org.apache.sling.api.resource.ResourceResolver)
+     */
+    public void commit(final ResourceResolver resolver) throws PersistenceException {
+        // the provider for the search paths will commit
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.ModifyingResourceProvider#hasChanges(org.apache.sling.api.resource.ResourceResolver)
+     */
+    public boolean hasChanges(final ResourceResolver resolver) {
+        // the provider for the search paths will return in case of changes
+        return false;
+    }
 }
diff --git a/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderFactory.java b/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderFactory.java
index e093a45..5cbdfb2 100644
--- a/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderFactory.java
+++ b/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderFactory.java
@@ -33,7 +33,7 @@ import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.apache.sling.resourcemerger.api.ResourceMergerService;
 
-@Component(name = "Apache Sling Merged Resource Provider Factory",
+@Component(label = "Apache Sling Merged Resource Provider Factory",
            description = "This resource provider delivers merged resources based on the search paths.",
            metatype=true)
 @Service(value = {ResourceProviderFactory.class, ResourceMergerService.class})
diff --git a/src/test/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderTest.java b/src/test/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderTest.java
index 08bbab2..0034a79 100644
--- a/src/test/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderTest.java
+++ b/src/test/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderTest.java
@@ -20,18 +20,23 @@ package org.apache.sling.resourcemerger.impl;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
+import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.testing.resourceresolver.MockHelper;
 import org.apache.sling.testing.resourceresolver.MockResourceResolverFactory;
+import org.apache.sling.testing.resourceresolver.MockResourceResolverFactoryOptions;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -42,7 +47,9 @@ public class MergedResourceProviderTest {
     private MergedResourceProvider provider;
 
     @Before public void setup() throws Exception {
-        final ResourceResolverFactory factory = new MockResourceResolverFactory();
+        final MockResourceResolverFactoryOptions options = new MockResourceResolverFactoryOptions();
+        options.setSearchPaths(new String[] {"/apps/", "/libs/"});
+        final ResourceResolverFactory factory = new MockResourceResolverFactory(options);
         this.resolver = factory.getAdministrativeResourceResolver(null);
         MockHelper.create(this.resolver).resource("/apps")
                                           .resource("a").p(MergedResourceConstants.PN_HIDE_CHILDREN, new String[] {"Z", "x", "y"})
@@ -70,6 +77,27 @@ public class MergedResourceProviderTest {
         this.provider = new MergedResourceProvider("/merged");
     }
 
+    @Test public void testHideChildren() {
+        // check preconditions in libs and apps
+        assertNotNull(this.resolver.getResource("/libs/a/Z"));
+        assertNull(this.resolver.getResource("/libs/a/X"));
+        assertNotNull(this.resolver.getResource("/libs/a/Y"));
+        assertNull(this.resolver.getResource("/libs/a/x"));
+        assertNull(this.resolver.getResource("/libs/a/y"));
+        assertNull(this.resolver.getResource("/apps/a/Z"));
+        assertNotNull(this.resolver.getResource("/apps/a/X"));
+        assertNull(this.resolver.getResource("/apps/a/Y"));
+        assertNull(this.resolver.getResource("/apps/a/x"));
+        assertNull(this.resolver.getResource("/apps/a/y"));
+
+        // now do the real checks
+        assertNull(this.provider.getResource(this.resolver, "/merged/a/Z"));
+        assertNotNull(this.provider.getResource(this.resolver, "/merged/a/Y"));
+        assertNotNull(this.provider.getResource(this.resolver, "/merged/a/X"));
+        assertNull(this.provider.getResource(this.resolver, "/merged/a/x"));
+        assertNull(this.provider.getResource(this.resolver, "/merged/a/y"));
+    }
+
     @Test public void testListChildren() {
         final Resource rsrcA = this.provider.getResource(this.resolver, "/merged/a");
         assertNotNull(rsrcA);
@@ -125,4 +153,29 @@ public class MergedResourceProviderTest {
         assertEquals("2", vm.get("e"));
         assertEquals("x", vm.get("b"));
     }
+
+    @Test public void testSimpleCreateAndDelete() throws PersistenceException {
+        final String path = "/merged/a/new";
+        try {
+            final Resource rsrc = this.provider.create(this.resolver, path, Collections.singletonMap("foo", (Object)"bla"));
+            assertNotNull(rsrc);
+            assertEquals(path, rsrc.getPath());
+            final ValueMap vm = ResourceUtil.getValueMap(rsrc);
+            assertEquals("bla", vm.get("foo"));
+
+            final Resource realResource = this.resolver.getResource("/apps/a/new");
+            assertNotNull(realResource);
+            final ValueMap vmReal = ResourceUtil.getValueMap(realResource);
+            assertEquals("bla", vmReal.get("foo"));
+            assertNull(this.resolver.getResource("/libs/a/new"));
+
+            this.provider.delete(this.resolver, path);
+            assertNull(this.provider.getResource(this.resolver, path));
+            assertNull(this.resolver.getResource("/libs/a/new"));
+            assertNull(this.resolver.getResource("/apps/a/new"));
+
+        } finally {
+            this.resolver.revert();
+        }
+    }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.