This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.resourcemerger-1.2.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourcemerger.git
commit 02e184dabca598e4c7476c9c38849d315c2675df Author: Carsten Ziegeler <[email protected]> AuthorDate: Sat Sep 13 13:08:08 2014 +0000 SLING-3909 : Merged ResourceProviders should be optionally modifiable git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/resourcemerger@1624734 13f79535-47bb-0310-9956-ffa450edef68 --- .../resourcemerger/impl/CRUDMergedResource.java | 88 ++++++++++ .../impl/CRUDMergedResourceProvider.java | 186 +++++++++++++++++++++ .../impl/MergedResourcePickerWhiteboard.java | 3 +- .../impl/MergedResourceProviderFactory.java | 21 ++- .../impl/MergingResourceProvider.java | 68 +++++--- .../impl/MergingResourceProviderFactory.java | 24 ++- .../resourcemerger/spi/MergedResourcePicker.java | 10 +- .../impl/MergedResourceProviderTest.java | 85 +++++++++- .../impl/OverridingResourceProviderTest.java | 10 +- 9 files changed, 454 insertions(+), 41 deletions(-) diff --git a/src/main/java/org/apache/sling/resourcemerger/impl/CRUDMergedResource.java b/src/main/java/org/apache/sling/resourcemerger/impl/CRUDMergedResource.java new file mode 100644 index 0000000..f662c02 --- /dev/null +++ b/src/main/java/org/apache/sling/resourcemerger/impl/CRUDMergedResource.java @@ -0,0 +1,88 @@ +/* + * 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.resourcemerger.impl; + +import java.util.Iterator; +import java.util.List; + +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.ResourceResolver; +import org.apache.sling.api.resource.ResourceUtil; +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.resourcemerger.spi.MergedResourcePicker; + +/** + * {@inheritDoc} + */ +public class CRUDMergedResource extends MergedResource { + + private final MergedResourcePicker picker; + + private final String relativePath; + + /** + * Constructor + * + * @param resolver Resource resolver + * @param mergeRootPath Merge root path + * @param relativePath Relative path + * @param mappedResources List of physical mapped resources' paths + */ + CRUDMergedResource(final ResourceResolver resolver, + final String mergeRootPath, + final String relativePath, + final List<Resource> mappedResources, + final List<ValueMap> valueMaps, + final MergedResourcePicker picker) { + super(resolver, mergeRootPath, relativePath, mappedResources, valueMaps); + this.picker = picker; + this.relativePath = relativePath; + } + + /** + * {@inheritDoc} + */ + @Override + @SuppressWarnings("unchecked") + public <AdapterType> AdapterType adaptTo(final Class<AdapterType> type) { + if (type == ModifiableValueMap.class) { + final Iterator<Resource> iter = this.picker.pickResources(this.getResourceResolver(), this.relativePath); + Resource highestRsrc = null; + while ( iter.hasNext() ) { + highestRsrc = iter.next(); + } + if ( ResourceUtil.isNonExistingResource(highestRsrc) ) { + final String paths[] = (String[])this.getResourceMetadata().get(MergedResourceConstants.METADATA_RESOURCES); + + final Resource copyResource = this.getResourceResolver().getResource(paths[paths.length - 1]); + try { + final Resource newResource = ResourceUtil.getOrCreateResource(this.getResourceResolver(), highestRsrc.getPath(), copyResource.getResourceType(), null, false); + return (AdapterType)newResource.adaptTo(ModifiableValueMap.class); + } catch ( final PersistenceException pe) { + // we ignore this for now + return null; + } + } + return (AdapterType)highestRsrc.adaptTo(ModifiableValueMap.class); + } + return super.adaptTo(type); + } +} diff --git a/src/main/java/org/apache/sling/resourcemerger/impl/CRUDMergedResourceProvider.java b/src/main/java/org/apache/sling/resourcemerger/impl/CRUDMergedResourceProvider.java new file mode 100644 index 0000000..96a667b --- /dev/null +++ b/src/main/java/org/apache/sling/resourcemerger/impl/CRUDMergedResourceProvider.java @@ -0,0 +1,186 @@ +/* + * 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.resourcemerger.impl; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.apache.sling.api.resource.ModifiableValueMap; +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 org.apache.sling.api.resource.ResourceUtil; +import org.apache.sling.resourcemerger.spi.MergedResourcePicker; + +/** + * This is a modifiable resource provider. + */ +public class CRUDMergedResourceProvider + extends MergingResourceProvider + implements ModifyingResourceProvider { + + public CRUDMergedResourceProvider(final String mergeRootPath, + final MergedResourcePicker picker) { + super(mergeRootPath, picker, false); + } + + private static final class ExtendedResourceHolder { + public ResourceHolder holder; + public int count; + public String lowestResourcePath; + public String highestResourcePath; + } + private ExtendedResourceHolder getAllResources(final ResourceResolver resolver, + final String path, + final String relativePath) { + final ExtendedResourceHolder holder = new ExtendedResourceHolder(); + holder.holder = new ResourceHolder(ResourceUtil.getName(path)); + + holder.count = 0; + + // Loop over resources + final Iterator<Resource> iter = this.picker.pickResources(resolver, relativePath); + while ( iter.hasNext() ) { + final Resource rsrc = iter.next(); + holder.count++; + if ( holder.count == 1 ) { + holder.lowestResourcePath = rsrc.getPath(); + } + holder.highestResourcePath = rsrc.getPath(); + if ( !ResourceUtil.isNonExistingResource(rsrc) ) { + // check parent for hiding + final Resource parent = rsrc.getParent(); + if ( parent != null ) { + final boolean hidden = new ParentHidingHandler(parent).isHidden(holder.holder.name); + if ( hidden ) { + holder.holder.resources.clear(); + } else { + holder.holder.resources.add(rsrc); + } + } + } + } + + 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 { + // 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 ExtendedResourceHolder holder = this.getAllResources(resolver, path, relativePath); + // we only support modifications if there is more than one location merged + if ( holder.count < 2 ) { + throw new PersistenceException("Modifying is only supported with at least two potentially merged resources.", null, path, null); + } + if ( holder.holder.resources.size() == 0 + || (holder.holder.resources.size() < holder.count && !holder.holder.resources.get(holder.holder.resources.size() - 1).getPath().equals(holder.highestResourcePath) )) { + final String createPath = holder.highestResourcePath; + final Resource parentResource = ResourceUtil.getOrCreateResource(resolver, ResourceUtil.getParent(createPath), (String)null, null, false); + resolver.create(parentResource, ResourceUtil.getName(createPath), properties); + } else { + final Resource hidingResource = resolver.getResource(holder.highestResourcePath); + if ( hidingResource != null ) { + final ModifiableValueMap mvm = hidingResource.adaptTo(ModifiableValueMap.class); + mvm.remove(MergedResourceConstants.PN_HIDE_RESOURCE); + mvm.putAll(properties); + } + // TODO check parent hiding + } + 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 { + // 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 ExtendedResourceHolder holder = this.getAllResources(resolver, path, relativePath); + // we only support modifications if there is more than one location merged + if ( holder.count < 2 ) { + throw new PersistenceException("Modifying is only supported with at least two potentially merged resources.", null, path, null); + } + + int deleted = 0; + for(final Resource rsrc : holder.holder.resources) { + final String p = rsrc.getPath(); + if ( !p.equals(holder.lowestResourcePath) ) { + resolver.delete(rsrc); + deleted++; + } + } + if ( deleted < holder.holder.resources.size() ) { + // create overlay resource which is hiding the other + final String createPath = holder.highestResourcePath; + 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 merged resources 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 merged resources 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 merged resources will return changes + return false; + } +} diff --git a/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourcePickerWhiteboard.java b/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourcePickerWhiteboard.java index b6bd79e..8954a75 100644 --- a/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourcePickerWhiteboard.java +++ b/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourcePickerWhiteboard.java @@ -63,7 +63,8 @@ public class MergedResourcePickerWhiteboard implements ServiceTrackerCustomizer if ( picker != null ) { final String mergeRoot = PropertiesUtil.toString(reference.getProperty(MergedResourcePicker.MERGE_ROOT), null); if (mergeRoot != null) { - final ResourceProviderFactory providerFactory = new MergingResourceProviderFactory(mergeRoot, picker); + final ResourceProviderFactory providerFactory = new MergingResourceProviderFactory(mergeRoot, picker, + PropertiesUtil.toBoolean(reference.getProperty(MergedResourcePicker.READ_ONLY), true)); final Dictionary<Object, Object> props = new Hashtable<Object, Object>(); props.put(ResourceProvider.ROOTS, mergeRoot); props.put(ResourceProvider.OWNS_ROOTS, true); 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 e5ba8bf..a8d33e6 100644 --- a/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderFactory.java +++ b/src/main/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderFactory.java @@ -25,6 +25,7 @@ import java.util.Map; import org.apache.felix.scr.annotations.Activate; 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.resource.NonExistingResource; @@ -38,10 +39,16 @@ import org.apache.sling.resourcemerger.spi.MergedResourcePicker; @Component(label = "Apache Sling Merged Resource Provider Factory", description = "This resource provider delivers merged resources based on the search paths.", metatype=true) -@Service -@Property(name=MergedResourcePicker.MERGE_ROOT, value=MergedResourceProviderFactory.DEFAULT_ROOT, - label="Root", - description="The mount point of merged resources") +@Service(value={MergedResourcePicker.class, ResourceMergerService.class}) +@Properties({ + @Property(name=MergedResourcePicker.MERGE_ROOT, value=MergedResourceProviderFactory.DEFAULT_ROOT, + label="Root", + description="The mount point of merged resources"), + @Property(name=MergedResourcePicker.READ_ONLY, boolValue=true, + label="Read Only", + description="Specifies if the resources are read-only or can be modified.") + +}) /** * The <code>MergedResourceProviderFactory</code> creates merged resource * providers and implements the <code>ResourceMergerService</code>. @@ -52,13 +59,13 @@ public class MergedResourceProviderFactory implements MergedResourcePicker, Reso private String mergeRootPath; - public Iterator<Resource> pickResources(ResourceResolver resolver, String relativePath) { - List<Resource> resources = new ArrayList<Resource>(); + public Iterator<Resource> pickResources(final ResourceResolver resolver, final String relativePath) { + final List<Resource> resources = new ArrayList<Resource>(); final String[] searchPaths = resolver.getSearchPath(); for (int i = searchPaths.length - 1; i >= 0; i--) { final String basePath = searchPaths[i]; final String fullPath = basePath + relativePath; - Resource resource = resolver.getResource(fullPath); + final Resource resource = resolver.getResource(fullPath); if (resource != null) { resources.add(resource); } else { diff --git a/src/main/java/org/apache/sling/resourcemerger/impl/MergingResourceProvider.java b/src/main/java/org/apache/sling/resourcemerger/impl/MergingResourceProvider.java index 05fa13c..66df03e 100644 --- a/src/main/java/org/apache/sling/resourcemerger/impl/MergingResourceProvider.java +++ b/src/main/java/org/apache/sling/resourcemerger/impl/MergingResourceProvider.java @@ -33,34 +33,61 @@ import org.apache.sling.resourcemerger.spi.MergedResourcePicker; class MergingResourceProvider implements ResourceProvider { - private final String mergeRootPath; + protected final String mergeRootPath; - private final MergedResourcePicker picker; + protected final MergedResourcePicker picker; - MergingResourceProvider(String mergeRootPath, MergedResourcePicker picker) { + private final boolean readOnly; + + MergingResourceProvider(final String mergeRootPath, + final MergedResourcePicker picker, + final boolean readOnly) { this.mergeRootPath = mergeRootPath; this.picker = picker; + this.readOnly = readOnly; } - private static final class ParentHidingHandler { + protected static final class ExcludeEntry { - private final String[] childrenToHideArray; + 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; + } + } + } + + protected static final class ParentHidingHandler { + + private List<ExcludeEntry> entries; public ParentHidingHandler(final Resource parent) { - if (parent == null) { - this.childrenToHideArray = null; - } else { - final ValueMap parentProps = parent.getValueMap(); - this.childrenToHideArray = parentProps.get(MergedResourceConstants.PN_HIDE_CHILDREN, String[].class); + final ValueMap parentProps = ResourceUtil.getValueMap(parent); + final String[] childrenToHideArray = parentProps.get(MergedResourceConstants.PN_HIDE_CHILDREN, String[].class); + if ( childrenToHideArray != null ) { + this.entries = new ArrayList<ExcludeEntry>(); + for(final String value : childrenToHideArray) { + final ExcludeEntry entry = new ExcludeEntry(value); + this.entries.add(entry); + } } } public boolean isHidden(final String name) { boolean hidden = false; - if (this.childrenToHideArray != null) { - for (final String entry : childrenToHideArray) { - if (entry.equals("*") || entry.equals(name)) { - hidden = true; + if ( this.entries != null ) { + for(final ExcludeEntry entry : this.entries) { + if ( entry.name.equals("*") || entry.name.equals(name) ) { + hidden = !entry.exclude; break; } } @@ -69,7 +96,7 @@ class MergingResourceProvider implements ResourceProvider { } } - private static final class ResourceHolder { + protected static final class ResourceHolder { public final String name; public final List<Resource> resources = new ArrayList<Resource>(); public final List<ValueMap> valueMaps = new ArrayList<ValueMap>(); @@ -104,7 +131,10 @@ class MergingResourceProvider implements ResourceProvider { 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); + if ( this.readOnly ) { + return new MergedResource(resolver, mergeRootPath, relativePath, holder.resources, holder.valueMaps); + } + return new CRUDMergedResource(resolver, mergeRootPath, relativePath, holder.resources, holder.valueMaps, this.picker); } return null; } @@ -115,7 +145,7 @@ class MergingResourceProvider implements ResourceProvider { * @param path Absolute path * @return Relative path */ - private String getRelativePath(String path) { + protected String getRelativePath(String path) { if (path.startsWith(mergeRootPath)) { path = path.substring(mergeRootPath.length()); if (path.length() == 0) { @@ -130,7 +160,7 @@ class MergingResourceProvider implements ResourceProvider { /** * {@inheritDoc} */ - public Resource getResource(ResourceResolver resolver, String path) { + public Resource getResource(final ResourceResolver resolver, final String path) { final String relativePath = getRelativePath(path); if (relativePath != null) { @@ -143,7 +173,7 @@ class MergingResourceProvider implements ResourceProvider { } while (resources.hasNext()) { - Resource resource = resources.next(); + final Resource resource = resources.next(); // check parent for hiding // SLING 3521 : if parent is not readable, nothing is hidden final Resource parent = resource.getParent(); diff --git a/src/main/java/org/apache/sling/resourcemerger/impl/MergingResourceProviderFactory.java b/src/main/java/org/apache/sling/resourcemerger/impl/MergingResourceProviderFactory.java index f2a5be1..3382fc7 100644 --- a/src/main/java/org/apache/sling/resourcemerger/impl/MergingResourceProviderFactory.java +++ b/src/main/java/org/apache/sling/resourcemerger/impl/MergingResourceProviderFactory.java @@ -31,18 +31,30 @@ class MergingResourceProviderFactory implements ResourceProviderFactory { private final MergedResourcePicker picker; - MergingResourceProviderFactory(String mergeRootPath, MergedResourcePicker picker) { + private final boolean readOnly; + + MergingResourceProviderFactory(final String mergeRootPath, + final MergedResourcePicker picker, + final boolean readOnly) { this.mergeRootPath = mergeRootPath; this.picker = picker; + this.readOnly = readOnly; } - public ResourceProvider getResourceProvider(Map<String, Object> authenticationInfo) throws LoginException { - return new MergingResourceProvider(mergeRootPath, picker); + public ResourceProvider getResourceProvider(final Map<String, Object> authenticationInfo) + throws LoginException { + if ( this.readOnly ) { + return new MergingResourceProvider(mergeRootPath, picker, this.readOnly); + } + return new CRUDMergedResourceProvider(mergeRootPath, picker); } - public ResourceProvider getAdministrativeResourceProvider(Map<String, Object> authenticationInfo) - throws LoginException { - return new MergingResourceProvider(mergeRootPath, picker); + public ResourceProvider getAdministrativeResourceProvider(final Map<String, Object> authenticationInfo) + throws LoginException { + if ( this.readOnly ) { + return new MergingResourceProvider(mergeRootPath, picker, this.readOnly); + } + return new CRUDMergedResourceProvider(mergeRootPath, picker); } } diff --git a/src/main/java/org/apache/sling/resourcemerger/spi/MergedResourcePicker.java b/src/main/java/org/apache/sling/resourcemerger/spi/MergedResourcePicker.java index 01179ee..f158470 100644 --- a/src/main/java/org/apache/sling/resourcemerger/spi/MergedResourcePicker.java +++ b/src/main/java/org/apache/sling/resourcemerger/spi/MergedResourcePicker.java @@ -41,10 +41,18 @@ public interface MergedResourcePicker { String MERGE_ROOT = "merge.root"; /** + * Service property name specifying whether the resources are read-only + * or support CRUD operations. If not specified this property defaults + * to <code>true</code>. The value of this property must be of type + * Boolean. + */ + String READ_ONLY = "merge.readOnly"; + + /** * Method invoked by the MergingResourceProvider to identify the resources to be merged for a given * relative path. The resources returned may be either resources returned from the ResourceResolver * directory or an instance of NonExistingResource. - * + * * @param resolver the ResourceResolver * @param relativePath the path relative to the merge root * @return an iterator of Resource objects 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 b888795..cded41b 100644 --- a/src/test/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderTest.java +++ b/src/test/java/org/apache/sling/resourcemerger/impl/MergedResourceProviderTest.java @@ -24,13 +24,15 @@ 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.ResourceProvider; 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; @@ -42,7 +44,7 @@ public class MergedResourceProviderTest { private ResourceResolver resolver; - private ResourceProvider provider; + private CRUDMergedResourceProvider provider; @Before public void setup() throws Exception { final MockResourceResolverFactoryOptions options = new MockResourceResolverFactoryOptions(); @@ -63,7 +65,8 @@ public class MergedResourceProviderTest { .p("d", "1") .resource(".X") .resource("/libs") - .resource("a") + .resource("deleteTest") + .resource(".a") .resource("1").p("a", "5").p("c", "2") .resource(".2").p(ResourceResolver.PROPERTY_RESOURCE_TYPE, "libs") .resource(".3").p("a", "1").p("b", "2").p("c", "3") @@ -72,7 +75,7 @@ public class MergedResourceProviderTest { .resource(".Z") .commit(); - this.provider = new MergingResourceProvider("/merged", new MergedResourceProviderFactory()); + this.provider = new CRUDMergedResourceProvider("/merged", new MergedResourceProviderFactory()); } @Test public void testHideChildren() { @@ -151,4 +154,78 @@ 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(); + } + } + + @Test public void testDeleteByHiding() throws PersistenceException { + final String path = "/merged/deleteTest"; + try { + assertNotNull(this.resolver.getResource("/libs/deleteTest")); + assertNull(this.resolver.getResource("/apps/deleteTest")); + + final Resource rsrc = this.provider.getResource(this.resolver, path); + assertNotNull(rsrc); + assertEquals(path, rsrc.getPath()); + + this.provider.delete(this.resolver, path); + + assertNull(this.provider.getResource(this.resolver, path)); + assertNotNull(this.resolver.getResource("/libs/deleteTest")); + final Resource hidingRsrc = this.resolver.getResource("/apps/deleteTest"); + assertNotNull(hidingRsrc); + final ValueMap vm = hidingRsrc.getValueMap(); + assertEquals(Boolean.TRUE, vm.get(MergedResourceConstants.PN_HIDE_RESOURCE)); + + } finally { + this.resolver.revert(); + } + } + + @Test public void testDeleteByHidingAndCreate() throws PersistenceException { + final String path = "/merged/deleteTest"; + try { + assertNotNull(this.resolver.getResource("/libs/deleteTest")); + assertNull(this.resolver.getResource("/apps/deleteTest")); + + final Resource rsrc = this.provider.getResource(this.resolver, path); + assertNotNull(rsrc); + assertEquals(path, rsrc.getPath()); + + this.provider.delete(this.resolver, path); + this.provider.create(this.resolver, path, Collections.singletonMap("foo", (Object)"bla")); + + assertNotNull(this.provider.getResource(this.resolver, path)); + assertNotNull(this.resolver.getResource("/libs/deleteTest")); + final Resource hidingRsrc = this.resolver.getResource("/apps/deleteTest"); + assertNotNull(hidingRsrc); + final ValueMap vm = hidingRsrc.getValueMap(); + assertEquals("bla", vm.get("foo")); + + } finally { + this.resolver.revert(); + } + } } diff --git a/src/test/java/org/apache/sling/resourcemerger/impl/OverridingResourceProviderTest.java b/src/test/java/org/apache/sling/resourcemerger/impl/OverridingResourceProviderTest.java index ca7c520..814338e 100644 --- a/src/test/java/org/apache/sling/resourcemerger/impl/OverridingResourceProviderTest.java +++ b/src/test/java/org/apache/sling/resourcemerger/impl/OverridingResourceProviderTest.java @@ -18,7 +18,11 @@ */ package org.apache.sling.resourcemerger.impl; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +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.Iterator; @@ -35,7 +39,7 @@ import org.junit.Before; import org.junit.Test; public class OverridingResourceProviderTest { - + private static final String SUPER_TYPE = "sling:resourceSuperType"; private ResourceResolver resolver; @@ -68,7 +72,7 @@ public class OverridingResourceProviderTest { .resource("c").p("1", "c") .commit(); - this.provider = new MergingResourceProvider("/override", new OverridingResourcePicker()); + this.provider = new MergingResourceProvider("/override", new OverridingResourcePicker(), true); } @Test -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
