This is an automated email from the ASF dual-hosted git repository. sseifert pushed a commit to branch release/1.x in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-fsresource.git
commit 4abf59cf41b40366ceffe3e455296f822ec39db7 Author: sseifert <sseif...@pro-vision.de> AuthorDate: Mon Nov 6 17:03:26 2017 +0100 import branch for 1.x from svn --- pom.xml | 22 ++-- .../sling/fsprovider/internal/FileMonitor.java | 95 +++++++++------- .../apache/sling/fsprovider/internal/FsMode.java | 2 +- .../fsprovider/internal/FsResourceProvider.java | 125 ++++++--------------- .../internal/mapper/ContentFileResource.java | 5 +- .../fsprovider/internal/mapper/FileResource.java | 24 ++-- .../internal/mapper/FileResourceMapper.java | 11 +- .../internal/mapper/FileVaultResourceMapper.java | 5 +- .../internal/parser/ContentElementImpl.java | 2 +- .../sling/fsprovider/internal/FileMonitorTest.java | 53 +++++---- .../fsprovider/internal/FileVaultContentTest.java | 14 +-- .../internal/FileVaultFileMonitorTest.java | 59 +++++----- .../fsprovider/internal/JcrXmlContentTest.java | 15 ++- .../sling/fsprovider/internal/JsonContentTest.java | 19 ++-- .../sling/fsprovider/internal/TestUtils.java | 29 +++-- 15 files changed, 239 insertions(+), 241 deletions(-) diff --git a/pom.xml b/pom.xml index fc0b0d2..e1f065c 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ <artifactId>org.apache.sling.fsresource</artifactId> <packaging>bundle</packaging> - <version>2.1.9-SNAPSHOT</version> + <version>1.4.9-SNAPSHOT</version> <name>Apache Sling File System Resource Provider</name> <description> @@ -87,12 +87,14 @@ <dependencies> <dependency> <groupId>javax.servlet</groupId> - <artifactId>javax.servlet-api</artifactId> + <artifactId>servlet-api</artifactId> + <version>2.4</version> + <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.sling</groupId> <artifactId>org.apache.sling.api</artifactId> - <version>2.11.0</version> + <version>2.4.0</version> </dependency> <dependency> <groupId>org.apache.sling</groupId> @@ -104,8 +106,8 @@ <artifactId>osgi.core</artifactId> </dependency> <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-api</artifactId> + <groupId>org.osgi</groupId> + <artifactId>osgi.cmpn</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> @@ -157,13 +159,19 @@ <dependency> <groupId>org.apache.sling</groupId> <artifactId>org.apache.sling.testing.sling-mock</artifactId> - <version>2.2.6</version> + <version>1.9.6</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.testing.osgi-mock</artifactId> + <version>2.2.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.sling</groupId> <artifactId>org.apache.sling.testing.logging-mock</artifactId> - <version>2.0.0</version> + <version>1.0.0</version> <scope>test</scope> </dependency> <dependency> diff --git a/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java b/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java index a164d4f..88c9d6f 100644 --- a/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java +++ b/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java @@ -18,8 +18,17 @@ */ package org.apache.sling.fsprovider.internal; +import static org.apache.sling.api.SlingConstants.PROPERTY_PATH; +import static org.apache.sling.api.SlingConstants.PROPERTY_RESOURCE_TYPE; +import static org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_ADDED; +import static org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_CHANGED; +import static org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_REMOVED; + import java.io.File; import java.util.ArrayList; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Timer; @@ -27,13 +36,12 @@ import java.util.TimerTask; import org.apache.commons.lang3.StringUtils; import org.apache.jackrabbit.vault.util.PlatformNameFormat; -import org.apache.sling.api.resource.observation.ResourceChange; -import org.apache.sling.api.resource.observation.ResourceChange.ChangeType; import org.apache.sling.fsprovider.internal.mapper.ContentFile; +import org.apache.sling.fsprovider.internal.mapper.FileResource; import org.apache.sling.fsprovider.internal.parser.ContentElement; +import org.apache.sling.fsprovider.internal.parser.ContentElementImpl; import org.apache.sling.fsprovider.internal.parser.ContentFileCache; -import org.apache.sling.spi.resource.provider.ObservationReporter; -import org.apache.sling.spi.resource.provider.ObserverConfiguration; +import org.osgi.service.event.EventAdmin; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -126,8 +134,8 @@ public final class FileMonitor extends TimerTask { } synchronized ( this ) { try { - // if we don't have an observation reporter, we just skip the check - final ObservationReporter reporter = this.provider.getObservationReporter(); + // if we don't have an event admin, we just skip the check + final EventAdmin reporter = this.provider.getEventAdmin(); if ( reporter != null ) { this.check(this.root, reporter); } @@ -144,16 +152,16 @@ public final class FileMonitor extends TimerTask { /** * Check the monitorable * @param monitorable The monitorable to check - * @param reporter The ObservationReporter + * @param reporter The EventAdmin */ - private void check(final Monitorable monitorable, final ObservationReporter reporter) { + private void check(final Monitorable monitorable, final EventAdmin reporter) { log.trace("Checking {}", monitorable.file); // if the file is non existing, check if it has been readded if ( monitorable.status instanceof NonExistingStatus ) { if ( monitorable.file.exists() ) { // new file and reset status createStatus(monitorable, contentFileExtensions, contentFileCache); - sendEvents(monitorable, ChangeType.ADDED, reporter); + sendEvents(monitorable, TOPIC_RESOURCE_ADDED, reporter); final FileStatus fs = (FileStatus)monitorable.status; if ( fs instanceof DirStatus ) { final DirStatus ds = (DirStatus)fs; @@ -166,7 +174,7 @@ public final class FileMonitor extends TimerTask { // check if the file has been removed if ( !monitorable.file.exists() ) { // removed file and update status - sendEvents(monitorable, ChangeType.REMOVED, reporter); + sendEvents(monitorable, TOPIC_RESOURCE_REMOVED, reporter); monitorable.status = NonExistingStatus.SINGLETON; contentFileCache.remove(transformPath(monitorable.path)); } else { @@ -176,7 +184,7 @@ public final class FileMonitor extends TimerTask { if ( fs.lastModified < monitorable.file.lastModified() ) { fs.lastModified = monitorable.file.lastModified(); // changed - sendEvents(monitorable, ChangeType.CHANGED, reporter); + sendEvents(monitorable, TOPIC_RESOURCE_CHANGED, reporter); changed = true; contentFileCache.remove(transformPath(monitorable.path)); } @@ -196,7 +204,7 @@ public final class FileMonitor extends TimerTask { } } - private void checkDirStatusChildren(final Monitorable dirMonitorable, final ObservationReporter reporter) { + private void checkDirStatusChildren(final Monitorable dirMonitorable, final EventAdmin reporter) { final DirStatus ds = (DirStatus)dirMonitorable.status; final File[] files = dirMonitorable.file.listFiles(); if (files != null) { @@ -225,27 +233,23 @@ public final class FileMonitor extends TimerTask { /** * Send the event async via the event admin. */ - private void sendEvents(final Monitorable monitorable, final ChangeType changeType, final ObservationReporter reporter) { + private void sendEvents(final Monitorable monitorable, final String changeType, final EventAdmin reporter) { if (log.isDebugEnabled()) { log.debug("Detected change for resource {} : {}", transformPath(monitorable.path), changeType); } - List<ResourceChange> changes = null; - for (final ObserverConfiguration config : reporter.getObserverConfigurations()) { - if (config.matches(transformPath(monitorable.path))) { - if (changes == null) { - changes = collectResourceChanges(monitorable, changeType); - } - if (log.isTraceEnabled()) { - for (ResourceChange change : changes) { - log.debug("Send change for resource {}: {} to {}", change.getPath(), change.getType(), config); - } - } + List<ResourceChange> changes = collectResourceChanges(monitorable, changeType); + for (ResourceChange change : changes) { + if (log.isTraceEnabled()) { + log.debug("Send change for resource {}: {}", transformPath(change.path), change.topic); } - } - if (changes != null) { - reporter.reportChanges(changes, false); - } + final Dictionary<String, String> properties = new Hashtable<>(); + properties.put(PROPERTY_PATH, transformPath(change.path)); + if (change.resourceType != null) { + properties.put(PROPERTY_RESOURCE_TYPE, change.resourceType); + } + reporter.postEvent(new org.osgi.service.event.Event(change.topic, properties)); + } } /** @@ -262,29 +266,33 @@ public final class FileMonitor extends TimerTask { } } - private List<ResourceChange> collectResourceChanges(final Monitorable monitorable, final ChangeType changeType) { + private List<ResourceChange> collectResourceChanges(final Monitorable monitorable, final String changeType) { List<ResourceChange> changes = new ArrayList<>(); if (monitorable.status instanceof ContentFileStatus) { ContentFile contentFile = ((ContentFileStatus)monitorable.status).contentFile; - if (changeType == ChangeType.CHANGED) { + if (StringUtils.equals(changeType, TOPIC_RESOURCE_CHANGED)) { ContentElement content = contentFile.getContent(); // we cannot easily report the diff of resource changes between two content files // so we simulate a removal of the toplevel node and then add all nodes contained in the current content file again. - changes.add(buildContentResourceChange(ChangeType.REMOVED, transformPath(monitorable.path))); - addContentResourceChanges(changes, ChangeType.ADDED, content, transformPath(monitorable.path)); + changes.add(buildContentResourceChange(TOPIC_RESOURCE_REMOVED, content, transformPath(monitorable.path))); + addContentResourceChanges(changes, TOPIC_RESOURCE_ADDED, content, transformPath(monitorable.path)); } else { addContentResourceChanges(changes, changeType, contentFile.getContent(), transformPath(monitorable.path)); } } else { - changes.add(buildContentResourceChange(changeType, transformPath(monitorable.path))); + Map<String,Object> props = new HashMap<>(); + props.put("sling:resourceType", monitorable.status instanceof FileStatus ? + FileResource.RESOURCE_TYPE_FILE : FileResource.RESOURCE_TYPE_FOLDER); + ContentElement content = new ContentElementImpl(null, props); + changes.add(buildContentResourceChange(changeType, content, transformPath(monitorable.path))); } return changes; } - private void addContentResourceChanges(final List<ResourceChange> changes, final ChangeType changeType, + private void addContentResourceChanges(final List<ResourceChange> changes, final String changeType, final ContentElement content, final String path) { - changes.add(buildContentResourceChange(changeType, path)); + changes.add(buildContentResourceChange(changeType, content, path)); if (content != null) { for (Map.Entry<String,ContentElement> entry : content.getChildren().entrySet()) { String childPath = path + "/" + entry.getKey(); @@ -292,8 +300,12 @@ public final class FileMonitor extends TimerTask { } } } - private ResourceChange buildContentResourceChange(final ChangeType changeType, final String path) { - return new ResourceChange(changeType, path, false, null, null, null); + private ResourceChange buildContentResourceChange(final String changeType, final ContentElement content, final String path) { + ResourceChange change = new ResourceChange(); + change.path = path; + change.resourceType = content != null ? (String)content.getProperties().get("sling:resourceType") : null; + change.topic = changeType; + return change; } /** @@ -373,4 +385,11 @@ public final class FileMonitor extends TimerTask { private static final class NonExistingStatus { public static NonExistingStatus SINGLETON = new NonExistingStatus(); } -} \ No newline at end of file + + static class ResourceChange { + public String path; + public String resourceType; + public String topic; + } + +} diff --git a/src/main/java/org/apache/sling/fsprovider/internal/FsMode.java b/src/main/java/org/apache/sling/fsprovider/internal/FsMode.java index 722a4e5..b255bb2 100644 --- a/src/main/java/org/apache/sling/fsprovider/internal/FsMode.java +++ b/src/main/java/org/apache/sling/fsprovider/internal/FsMode.java @@ -29,7 +29,7 @@ public enum FsMode { FILES_FOLDERS, /** - * Sling-Initial-Content file system layout, supports file and folders ant content files in JSON, xml and jcr.xml format. + * Sling-Initial-Content file system layout, supports file and folders ant content files in JSON and jcr.xml format. */ INITIAL_CONTENT, diff --git a/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java b/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java index 62446d5..58babc8 100644 --- a/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java +++ b/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java @@ -27,10 +27,13 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +import javax.servlet.http.HttpServletRequest; + import org.apache.commons.collections.IteratorUtils; import org.apache.commons.collections.Predicate; import org.apache.commons.lang3.StringUtils; 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.fsprovider.internal.mapper.ContentFileResourceMapper; import org.apache.sling.fsprovider.internal.mapper.FileResourceMapper; @@ -38,17 +41,16 @@ import org.apache.sling.fsprovider.internal.mapper.FileVaultResourceMapper; import org.apache.sling.fsprovider.internal.parser.ContentFileCache; import org.apache.sling.fsprovider.internal.parser.ContentFileTypes; import org.apache.sling.jcr.contentparser.ContentType; -import org.apache.sling.spi.resource.provider.ObservationReporter; -import org.apache.sling.spi.resource.provider.ProviderContext; -import org.apache.sling.spi.resource.provider.ResolveContext; -import org.apache.sling.spi.resource.provider.ResourceContext; -import org.apache.sling.spi.resource.provider.ResourceProvider; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.ConfigurationPolicy; import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.osgi.service.event.EventAdmin; import org.osgi.service.metatype.annotations.AttributeDefinition; import org.osgi.service.metatype.annotations.Designate; import org.osgi.service.metatype.annotations.ObjectClassDefinition; @@ -73,7 +75,7 @@ import org.osgi.service.metatype.annotations.Option; Constants.SERVICE_VENDOR + "=The Apache Software Foundation" }) @Designate(ocd=FsResourceProvider.Config.class, factory=true) -public final class FsResourceProvider extends ResourceProvider<Object> { +public final class FsResourceProvider implements ResourceProvider { /** * Resource metadata property set by {@link org.apache.sling.fsprovider.internal.mapper.FileResource} @@ -96,8 +98,8 @@ public final class FsResourceProvider extends ResourceProvider<Object> { @AttributeDefinition(name = "Provider Root", description = "Location in the virtual resource tree where the " + - "file system resources are mapped in. This property must not be an empty string.") - String provider_root(); + "file system resources are mapped in. This property must not be an empty string. Only one path is supported.") + String[] provider_roots(); @AttributeDefinition(name = "File system layout", description = "File system layout mode for files, folders and content.", @@ -105,7 +107,7 @@ public final class FsResourceProvider extends ResourceProvider<Object> { @Option(value="FILES_FOLDERS", label="FILES_FOLDERS - " + "Support only files and folders (classic mode)"), @Option(value="INITIAL_CONTENT", label="INITIAL_CONTENT - " - + "Sling-Initial-Content file system layout, supports file and folders ant content files in JSON, xml and jcr.xml format"), + + "Sling-Initial-Content file system layout, supports file and folders ant content files in JSON and jcr.xml format"), @Option(value="FILEVAULT_XML", label="FILEVAULT_XML - " + "FileVault XML format (expanded content package)"), }) @@ -131,7 +133,7 @@ public final class FsResourceProvider extends ResourceProvider<Object> { int provider_cache_size() default 10000; // Internal Name hint for web console. - String webconsole_configurationFactory_nameHint() default "{provider.fs.mode}: {" + ResourceProvider.PROPERTY_ROOT + "}"; + String webconsole_configurationFactory_nameHint() default "{provider.fs.mode}: {" + ResourceProvider.ROOTS + "}"; } // The location in the resource tree where the resources are mapped @@ -149,12 +151,17 @@ public final class FsResourceProvider extends ResourceProvider<Object> { private FsResourceMapper contentFileMapper; private FileVaultResourceMapper fileVaultMapper; - // if true resources from file system are only "overlayed" to JCR resources, serving JCR as fallback within the same path - private boolean overlayParentResourceProvider; - // cache for parsed content files private ContentFileCache contentFileCache; + @Reference(cardinality=ReferenceCardinality.OPTIONAL, policy=ReferencePolicy.DYNAMIC) + private volatile EventAdmin eventAdmin; + + @Override + public Resource getResource(ResourceResolver resourceResolver, HttpServletRequest request, String path) { + return getResource(resourceResolver, path); + } + /** * Returns a resource wrapping a file system file or folder for the given * path. If the <code>path</code> is equal to the configured resource tree @@ -164,54 +171,26 @@ public final class FsResourceProvider extends ResourceProvider<Object> { * to access the file or folder. If no such file or folder exists, this * method returns <code>null</code>. */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - public Resource getResource(final ResolveContext<Object> ctx, - final String path, - final ResourceContext resourceContext, - final Resource parent) { - - ResourceResolver resolver = ctx.getResourceResolver(); + @SuppressWarnings("rawtypes") + @Override + public Resource getResource(ResourceResolver resolver, String path) { - boolean askParentResourceProvider; Resource rsrc = null; if (fsMode == FsMode.FILEVAULT_XML) { // filevault: check if path matches, if not fallback to parent resource provider if (fileVaultMapper.pathMatches(path)) { - askParentResourceProvider = false; rsrc = fileVaultMapper.getResource(resolver, path); } - else { - askParentResourceProvider = true; - } } else { // Sling-Initial-Content: mount folder/files an content files - askParentResourceProvider = this.overlayParentResourceProvider; rsrc = fileMapper.getResource(resolver, path); if (rsrc == null) { rsrc = contentFileMapper.getResource(resolver, path); } } - if (askParentResourceProvider) { - // make sure directory resources from parent resource provider have higher precedence than from this provider - // this allows properties like sling:resourceSuperType to take effect - if ( rsrc == null || rsrc.getResourceMetadata().containsKey(RESOURCE_METADATA_FILE_DIRECTORY) ) { - // get resource from shadowed provider - final ResourceProvider rp = ctx.getParentResourceProvider(); - if ( rp != null ) { - Resource resourceFromParentResourceProvider = rp.getResource((ResolveContext)ctx.getParentResolveContext(), - path, - resourceContext, parent); - if (resourceFromParentResourceProvider != null) { - rsrc = resourceFromParentResourceProvider; - } - } - } - } - return rsrc; } @@ -219,17 +198,14 @@ public final class FsResourceProvider extends ResourceProvider<Object> { * Returns an iterator of resources. */ @SuppressWarnings("unchecked") - @Override - public Iterator<Resource> listChildren(final ResolveContext<Object> ctx, final Resource parent) { - ResourceResolver resolver = ctx.getResourceResolver(); + public Iterator<Resource> listChildren(Resource parent) { + ResourceResolver resolver = parent.getResourceResolver(); List<Iterator<Resource>> allChildren = new ArrayList<>(); Iterator<Resource> children; - boolean askParentResourceProvider; if (fsMode == FsMode.FILEVAULT_XML) { // filevault: always ask provider, it checks itself if children matches the filters - askParentResourceProvider = true; children = fileVaultMapper.getChildren(resolver, parent); if (children != null) { allChildren.add(children); @@ -237,7 +213,6 @@ public final class FsResourceProvider extends ResourceProvider<Object> { } else { // Sling-Initial-Content: get all matching folders/files and content files - askParentResourceProvider = this.overlayParentResourceProvider; children = contentFileMapper.getChildren(resolver, parent); if (children != null) { allChildren.add(children); @@ -248,29 +223,6 @@ public final class FsResourceProvider extends ResourceProvider<Object> { } } - // get children from from shadowed provider - if (askParentResourceProvider) { - final ResourceProvider parentResourceProvider = ctx.getParentResourceProvider(); - if (parentResourceProvider != null) { - children = parentResourceProvider.listChildren(ctx.getParentResolveContext(), parent); - if (children != null) { - if (fsMode == FsMode.FILEVAULT_XML) { - // filevault: include all children from parent resource provider that do not match the filters - allChildren.add(IteratorUtils.filteredIterator(children, new Predicate() { - @Override - public boolean evaluate(Object object) { - Resource child = (Resource)object; - return !fileVaultMapper.pathMatches(child.getPath()); - } - })); - } - else { - allChildren.add(children); - } - } - } - } - if (allChildren.isEmpty()) { return null; } @@ -294,10 +246,11 @@ public final class FsResourceProvider extends ResourceProvider<Object> { @Activate protected void activate(BundleContext bundleContext, final Config config) { fsMode = config.provider_fs_mode(); - String providerRoot = config.provider_root(); - if (StringUtils.isBlank(providerRoot)) { - throw new IllegalArgumentException("provider.root property must be set"); + String[] providerRoots = config.provider_roots(); + if (providerRoots == null || providerRoots.length != 1 || StringUtils.isBlank(providerRoots[0])) { + throw new IllegalArgumentException("provider.roots property must be set to exactly one entry."); } + String providerRoot = config.provider_roots()[0]; String providerFileName = config.provider_file(); if (StringUtils.isBlank(providerFileName)) { @@ -306,7 +259,6 @@ public final class FsResourceProvider extends ResourceProvider<Object> { this.providerRoot = providerRoot; this.providerFile = getProviderFile(providerFileName, bundleContext); - this.overlayParentResourceProvider = false; InitialContentImportOptions options = new InitialContentImportOptions(config.provider_initial_content_import_options()); File filterXmlFile = null; @@ -319,11 +271,7 @@ public final class FsResourceProvider extends ResourceProvider<Object> { filterXmlFile = new File(config.provider_filevault_filterxml_path()); } } - else if (fsMode == FsMode.FILES_FOLDERS) { - overlayParentResourceProvider = true; - } else if (fsMode == FsMode.INITIAL_CONTENT) { - overlayParentResourceProvider = !options.isOverwrite(); if (!options.getIgnoreImportProviders().contains(ContentType.JSON.getExtension())) { contentFileSuffixes.add(ContentFileTypes.JSON_SUFFIX); } @@ -341,7 +289,7 @@ public final class FsResourceProvider extends ResourceProvider<Object> { this.fileVaultMapper = new FileVaultResourceMapper(this.providerFile, filterXmlFile, this.contentFileCache); } else { - this.fileMapper = new FileResourceMapper(this.providerRoot, this.providerFile, contentFileExtensions, this.contentFileCache); + this.fileMapper = new FileResourceMapper(this.providerRoot, this.providerFile, contentFileExtensions, this.contentFileCache, this.fsMode); this.contentFileMapper = new ContentFileResourceMapper(this.providerRoot, this.providerFile, contentFileExtensions, this.contentFileCache); } @@ -361,7 +309,6 @@ public final class FsResourceProvider extends ResourceProvider<Object> { } this.providerRoot = null; this.providerFile = null; - this.overlayParentResourceProvider = false; this.fileMapper = null; this.contentFileMapper = null; this.fileVaultMapper = null; @@ -372,6 +319,10 @@ public final class FsResourceProvider extends ResourceProvider<Object> { this.fsMode = null; } + EventAdmin getEventAdmin() { + return this.eventAdmin; + } + File getRootFile() { return this.providerFile; } @@ -409,12 +360,4 @@ public final class FsResourceProvider extends ResourceProvider<Object> { return providerFile; } - public ObservationReporter getObservationReporter() { - final ProviderContext ctx = this.getProviderContext(); - if (ctx != null) { - return ctx.getObservationReporter(); - } - return null; - } - } diff --git a/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResource.java b/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResource.java index 40549c5..f65422d 100644 --- a/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResource.java +++ b/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResource.java @@ -25,6 +25,7 @@ import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.sling.api.resource.AbstractResource; 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; import org.apache.sling.fsprovider.internal.mapper.jcr.FsNode; @@ -80,14 +81,14 @@ public final class ContentFileResource extends AbstractResource { public String getResourceSuperType() { if (resourceSuperType == null) { - resourceSuperType = getValueMap().get("sling:resourceSuperType", String.class); + resourceSuperType = ResourceUtil.getValueMap(this).get("sling:resourceSuperType", String.class); } return resourceSuperType; } public String getResourceType() { if (resourceType == null) { - ValueMap props = getValueMap(); + ValueMap props = ResourceUtil.getValueMap(this); resourceType = props.get("sling:resourceType", String.class); if (resourceType == null) { // fallback to jcr:primaryType when resource type not set diff --git a/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileResource.java b/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileResource.java index 873aba8..83516c9 100644 --- a/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileResource.java +++ b/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileResource.java @@ -41,7 +41,7 @@ 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.fsprovider.internal.ContentFileExtensions; -import org.apache.sling.fsprovider.internal.FsResourceProvider; +import org.apache.sling.fsprovider.internal.FsMode; import org.apache.sling.fsprovider.internal.mapper.jcr.FsNode; import org.apache.sling.fsprovider.internal.mapper.valuemap.ValueMapDecorator; import org.apache.sling.fsprovider.internal.parser.ContentFileCache; @@ -61,15 +61,15 @@ public final class FileResource extends AbstractResource { /** * The resource type for file system files mapped into the resource tree by - * the {@link FsResourceProvider} (value is "nt:file"). + * the {@link org.apache.sling.fsprovider.internal.FsResourceProvider} (value is "nt:file"). */ - static final String RESOURCE_TYPE_FILE = "nt:file"; + public static final String RESOURCE_TYPE_FILE = "nt:file"; /** * The resource type for file system folders mapped into the resource tree - * by the {@link FsResourceProvider} (value is "nt:folder"). + * by the {@link org.apache.sling.fsprovider.internal.FsResourceProvider} (value is "nt:folder"). */ - static final String RESOURCE_TYPE_FOLDER = "nt:folder"; + public static final String RESOURCE_TYPE_FOLDER = "nt:folder"; // the owning resource resolver private final ResourceResolver resolver; @@ -92,6 +92,7 @@ public final class FileResource extends AbstractResource { private final ContentFileExtensions contentFileExtensions; private final ContentFileCache contentFileCache; + private final FsMode fsMode; private static final Logger log = LoggerFactory.getLogger(FileResource.class); @@ -102,17 +103,19 @@ public final class FileResource extends AbstractResource { * @param resourcePath The resource path in the resource tree * @param file The wrapped file */ - FileResource(ResourceResolver resolver, String resourcePath, File file) { - this(resolver, resourcePath, file, null, null); + FileResource(ResourceResolver resolver, String resourcePath, File file, FsMode fsMode) { + this(resolver, resourcePath, file, null, null, fsMode); } FileResource(ResourceResolver resolver, String resourcePath, File file, - ContentFileExtensions contentFileExtensions, ContentFileCache contentFileCache) { + ContentFileExtensions contentFileExtensions, ContentFileCache contentFileCache, + FsMode fsMode) { this.resolver = resolver; this.resourcePath = resourcePath; this.file = file; this.contentFileExtensions = contentFileExtensions; this.contentFileCache = contentFileCache; + this.fsMode = fsMode; } /** @@ -133,8 +136,8 @@ public final class FileResource extends AbstractResource { metaData.setContentLength(file.length()); metaData.setModificationTime(file.lastModified()); metaData.setResolutionPath(resourcePath); - if ( this.file.isDirectory() ) { - metaData.put(FsResourceProvider.RESOURCE_METADATA_FILE_DIRECTORY, Boolean.TRUE); + if (fsMode == FsMode.FILES_FOLDERS && this.file.isDirectory()) { + metaData.put(ResourceMetadata.INTERNAL_CONTINUE_RESOLVING, Boolean.TRUE); } } return metaData; @@ -221,7 +224,6 @@ public final class FileResource extends AbstractResource { .build(); } - @Override public ValueMap getValueMap() { if (valueMap == null) { // this resource simulates nt:file/nt:folder behavior by returning it as resource type diff --git a/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileResourceMapper.java b/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileResourceMapper.java index e0a1429..e29b408 100644 --- a/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileResourceMapper.java +++ b/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileResourceMapper.java @@ -28,6 +28,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.fsprovider.internal.ContentFileExtensions; +import org.apache.sling.fsprovider.internal.FsMode; import org.apache.sling.fsprovider.internal.FsResourceMapper; import org.apache.sling.fsprovider.internal.parser.ContentFileCache; @@ -44,21 +45,23 @@ public final class FileResourceMapper implements FsResourceMapper { private final ContentFileExtensions contentFileExtensions; private final ContentFileCache contentFileCache; + private final FsMode fsMode; public FileResourceMapper(String providerRoot, File providerFile, - ContentFileExtensions contentFileExtensions, ContentFileCache contentFileCache) { + ContentFileExtensions contentFileExtensions, ContentFileCache contentFileCache, FsMode fsMode) { this.providerRoot = providerRoot; this.providerRootPrefix = providerRoot.concat("/"); this.providerFile = providerFile; this.contentFileExtensions = contentFileExtensions; this.contentFileCache = contentFileCache; + this.fsMode = fsMode; } @Override public Resource getResource(final ResourceResolver resolver, final String resourcePath) { File file = getFile(resourcePath); if (file != null) { - return new FileResource(resolver, resourcePath, file, contentFileExtensions, contentFileCache); + return new FileResource(resolver, resourcePath, file, contentFileExtensions, contentFileCache, fsMode); } else { return null; @@ -88,7 +91,7 @@ public final class FileResourceMapper implements FsResourceMapper { if (providerRoot.startsWith(parentPathPrefix)) { String relPath = providerRoot.substring(parentPathPrefix.length()); if (relPath.indexOf('/') < 0) { - Resource res = new FileResource(resolver, providerRoot, providerFile, contentFileExtensions, contentFileCache); + Resource res = new FileResource(resolver, providerRoot, providerFile, contentFileExtensions, contentFileCache, fsMode); return IteratorUtils.singletonIterator(res); } } @@ -119,7 +122,7 @@ public final class FileResourceMapper implements FsResourceMapper { public Object transform(Object input) { File file = (File)input; String path = parentPath + "/" + Escape.fileToResourceName(file.getName()); - return new FileResource(resolver, path, file, contentFileExtensions, contentFileCache); + return new FileResource(resolver, path, file, contentFileExtensions, contentFileCache, fsMode); } }); } diff --git a/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java b/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java index 77c5554..6665f55 100644 --- a/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java +++ b/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java @@ -38,6 +38,7 @@ import org.apache.jackrabbit.vault.util.PlatformNameFormat; 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.fsprovider.internal.FsMode; import org.apache.sling.fsprovider.internal.FsResourceMapper; import org.apache.sling.fsprovider.internal.parser.ContentElement; import org.apache.sling.fsprovider.internal.parser.ContentFileCache; @@ -71,7 +72,7 @@ public final class FileVaultResourceMapper implements FsResourceMapper { // direct file File file = getFile(resourcePath); if (file != null && file.isFile()) { - return new FileResource(resolver, resourcePath, file); + return new FileResource(resolver, resourcePath, file, FsMode.FILEVAULT_XML); } // content file @@ -82,7 +83,7 @@ public final class FileVaultResourceMapper implements FsResourceMapper { // fallback to directory resource if folder was found but nothing else if (file != null && file.isDirectory()) { - return new FileResource(resolver, resourcePath, file); + return new FileResource(resolver, resourcePath, file, FsMode.FILEVAULT_XML); } return null; diff --git a/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementImpl.java b/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementImpl.java index e7d6dd3..5205c6e 100644 --- a/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementImpl.java +++ b/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentElementImpl.java @@ -23,7 +23,7 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; -final class ContentElementImpl implements ContentElement { +public final class ContentElementImpl implements ContentElement { private final String name; private final Map<String, Object> properties; diff --git a/src/test/java/org/apache/sling/fsprovider/internal/FileMonitorTest.java b/src/test/java/org/apache/sling/fsprovider/internal/FileMonitorTest.java index d2b1143..978419b 100644 --- a/src/test/java/org/apache/sling/fsprovider/internal/FileMonitorTest.java +++ b/src/test/java/org/apache/sling/fsprovider/internal/FileMonitorTest.java @@ -18,6 +18,9 @@ */ package org.apache.sling.fsprovider.internal; +import static org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_ADDED; +import static org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_CHANGED; +import static org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_REMOVED; import static org.apache.sling.fsprovider.internal.TestUtils.assertChange; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -27,9 +30,7 @@ import java.nio.file.Files; import java.util.List; import org.apache.commons.io.FileUtils; -import org.apache.sling.api.resource.observation.ResourceChange; -import org.apache.sling.api.resource.observation.ResourceChange.ChangeType; -import org.apache.sling.api.resource.observation.ResourceChangeListener; +import org.apache.sling.fsprovider.internal.FileMonitor.ResourceChange; import org.apache.sling.fsprovider.internal.TestUtils.ResourceListener; import org.apache.sling.testing.mock.sling.ResourceResolverType; import org.apache.sling.testing.mock.sling.junit.SlingContext; @@ -37,6 +38,8 @@ import org.apache.sling.testing.mock.sling.junit.SlingContextBuilder; import org.apache.sling.testing.mock.sling.junit.SlingContextCallback; import org.junit.Rule; import org.junit.Test; +import org.osgi.service.event.EventConstants; +import org.osgi.service.event.EventHandler; /** * Test events when changing file system content (Sling-Initial-Content). @@ -66,14 +69,18 @@ public class FileMonitorTest { // mount temp. directory context.registerInjectActivateService(new FsResourceProvider(), "provider.file", tempDir.getPath(), - "provider.root", "/fs-test", + "provider.roots", "/fs-test", "provider.checkinterval", CHECK_INTERVAL, "provider.fs.mode", FsMode.INITIAL_CONTENT.name(), "provider.initial.content.import.options", "overwrite:=true;ignoreImportProviders:=jcr.xml"); // register resource change listener - context.registerService(ResourceChangeListener.class, resourceListener, - ResourceChangeListener.PATHS, new String[] { "/fs-test" }); + context.registerService(EventHandler.class, resourceListener, + EventConstants.EVENT_TOPIC, new String[] { + TOPIC_RESOURCE_ADDED, + TOPIC_RESOURCE_CHANGED, + TOPIC_RESOURCE_REMOVED + }); } }) .afterTearDown(new SlingContextCallback() { @@ -96,7 +103,7 @@ public class FileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(1, changes.size()); - assertChange(changes, "/fs-test/folder1/file1a.txt", ChangeType.CHANGED); + assertChange(changes, "/fs-test/folder1/file1a.txt", TOPIC_RESOURCE_CHANGED); } @Test @@ -110,8 +117,8 @@ public class FileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(2, changes.size()); - assertChange(changes, "/fs-test/folder1", ChangeType.CHANGED); - assertChange(changes, "/fs-test/folder1/file1c.txt", ChangeType.ADDED); + assertChange(changes, "/fs-test/folder1", TOPIC_RESOURCE_CHANGED); + assertChange(changes, "/fs-test/folder1/file1c.txt", TOPIC_RESOURCE_ADDED); } @Test @@ -125,8 +132,8 @@ public class FileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(2, changes.size()); - assertChange(changes, "/fs-test/folder1", ChangeType.CHANGED); - assertChange(changes, "/fs-test/folder1/file1a.txt", ChangeType.REMOVED); + assertChange(changes, "/fs-test/folder1", TOPIC_RESOURCE_CHANGED); + assertChange(changes, "/fs-test/folder1/file1a.txt", TOPIC_RESOURCE_REMOVED); } @Test @@ -140,8 +147,8 @@ public class FileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(2, changes.size()); - assertChange(changes, "/fs-test", ChangeType.CHANGED); - assertChange(changes, "/fs-test/folder99", ChangeType.ADDED); + assertChange(changes, "/fs-test", TOPIC_RESOURCE_CHANGED); + assertChange(changes, "/fs-test/folder99", TOPIC_RESOURCE_ADDED); } @Test @@ -155,8 +162,8 @@ public class FileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(2, changes.size()); - assertChange(changes, "/fs-test", ChangeType.CHANGED); - assertChange(changes, "/fs-test/folder1", ChangeType.REMOVED); + assertChange(changes, "/fs-test", TOPIC_RESOURCE_CHANGED); + assertChange(changes, "/fs-test/folder1", TOPIC_RESOURCE_REMOVED); } @Test @@ -169,9 +176,9 @@ public class FileMonitorTest { Thread.sleep(WAIT_INTERVAL); - assertChange(changes, "/fs-test/folder2/content", ChangeType.REMOVED); - assertChange(changes, "/fs-test/folder2/content", ChangeType.ADDED); - assertChange(changes, "/fs-test/folder2/content/jcr:content", ChangeType.ADDED); + assertChange(changes, "/fs-test/folder2/content", TOPIC_RESOURCE_REMOVED); + assertChange(changes, "/fs-test/folder2/content", TOPIC_RESOURCE_ADDED); + assertChange(changes, "/fs-test/folder2/content/jcr:content", TOPIC_RESOURCE_ADDED); } @Test @@ -185,9 +192,9 @@ public class FileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(3, changes.size()); - assertChange(changes, "/fs-test/folder1", ChangeType.CHANGED); - assertChange(changes, "/fs-test/folder1/file1c", ChangeType.ADDED); - assertChange(changes, "/fs-test/folder1/file1c/child1", ChangeType.ADDED); + assertChange(changes, "/fs-test/folder1", TOPIC_RESOURCE_CHANGED); + assertChange(changes, "/fs-test/folder1/file1c", TOPIC_RESOURCE_ADDED); + assertChange(changes, "/fs-test/folder1/file1c/child1", TOPIC_RESOURCE_ADDED); } @Test @@ -201,8 +208,8 @@ public class FileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(2, changes.size()); - assertChange(changes, "/fs-test/folder2", ChangeType.CHANGED); - assertChange(changes, "/fs-test/folder2/content", ChangeType.REMOVED); + assertChange(changes, "/fs-test/folder2", TOPIC_RESOURCE_CHANGED); + assertChange(changes, "/fs-test/folder2/content", TOPIC_RESOURCE_REMOVED); } } diff --git a/src/test/java/org/apache/sling/fsprovider/internal/FileVaultContentTest.java b/src/test/java/org/apache/sling/fsprovider/internal/FileVaultContentTest.java index 35b51d1..7eadfbc 100644 --- a/src/test/java/org/apache/sling/fsprovider/internal/FileVaultContentTest.java +++ b/src/test/java/org/apache/sling/fsprovider/internal/FileVaultContentTest.java @@ -23,7 +23,6 @@ import static org.apache.sling.fsprovider.internal.TestUtils.assertFolder; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import java.util.List; @@ -33,6 +32,7 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceUtil; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.fsprovider.internal.TestUtils.RegisterFsResourcePlugin; import org.apache.sling.hamcrest.ResourceMatchers; @@ -59,13 +59,13 @@ public class FileVaultContentTest { "provider.fs.mode", FsMode.FILEVAULT_XML.name(), "provider.file", "src/test/resources/vaultfs-test/jcr_root", "provider.filevault.filterxml.path", "src/test/resources/vaultfs-test/META-INF/vault/filter.xml", - "provider.root", "/content/dam/talk.png" + "provider.roots", "/content/dam/talk.png" )) .plugin(new RegisterFsResourcePlugin( "provider.fs.mode", FsMode.FILEVAULT_XML.name(), "provider.file", "src/test/resources/vaultfs-test/jcr_root", "provider.filevault.filterxml.path", "src/test/resources/vaultfs-test/META-INF/vault/filter.xml", - "provider.root", "/content/samples" + "provider.roots", "/content/samples" )) .build(); @@ -86,7 +86,7 @@ public class FileVaultContentTest { Resource metadata = content.getChild("metadata"); assertNotNull(metadata); - ValueMap props = metadata.getValueMap(); + ValueMap props = ResourceUtil.getValueMap(metadata); assertEquals((Integer)4, props.get("app:Bitsperpixel", Integer.class)); assertFolder(content, "renditions"); @@ -100,7 +100,7 @@ public class FileVaultContentTest { assertEquals("sling:OrderedFolder", sampleContent.getResourceType()); Resource enContent = sampleContent.getChild("en/jcr:content"); - assertArrayEquals(new String[] { "/etc/mobile/groups/responsive" }, enContent.getValueMap().get("app:deviceGroups", String[].class)); + assertArrayEquals(new String[] { "/etc/mobile/groups/responsive" }, ResourceUtil.getValueMap(enContent).get("app:deviceGroups", String[].class)); } @Test @@ -139,10 +139,6 @@ public class FileVaultContentTest { assertNotNull(sampleContent.getChild("en/conference")); assertNotNull(context.resourceResolver().getResource("/content/samples/en/conference/page2")); assertNotNull(sampleContent.getChild("en/conference/page2")); - - // hidden because overlayed by resource provider - assertNull(context.resourceResolver().getResource("/content/samples/it")); - assertNull(sampleContent.getChild("it")); // list children with mixed content Resource enResource = sampleContent.getChild("en"); diff --git a/src/test/java/org/apache/sling/fsprovider/internal/FileVaultFileMonitorTest.java b/src/test/java/org/apache/sling/fsprovider/internal/FileVaultFileMonitorTest.java index 76e0525..0475f77 100644 --- a/src/test/java/org/apache/sling/fsprovider/internal/FileVaultFileMonitorTest.java +++ b/src/test/java/org/apache/sling/fsprovider/internal/FileVaultFileMonitorTest.java @@ -18,6 +18,9 @@ */ package org.apache.sling.fsprovider.internal; +import static org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_ADDED; +import static org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_CHANGED; +import static org.apache.sling.api.SlingConstants.TOPIC_RESOURCE_REMOVED; import static org.apache.sling.fsprovider.internal.TestUtils.assertChange; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -27,9 +30,7 @@ import java.nio.file.Files; import java.util.List; import org.apache.commons.io.FileUtils; -import org.apache.sling.api.resource.observation.ResourceChange; -import org.apache.sling.api.resource.observation.ResourceChange.ChangeType; -import org.apache.sling.api.resource.observation.ResourceChangeListener; +import org.apache.sling.fsprovider.internal.FileMonitor.ResourceChange; import org.apache.sling.fsprovider.internal.TestUtils.ResourceListener; import org.apache.sling.testing.mock.sling.ResourceResolverType; import org.apache.sling.testing.mock.sling.junit.SlingContext; @@ -37,6 +38,8 @@ import org.apache.sling.testing.mock.sling.junit.SlingContextBuilder; import org.apache.sling.testing.mock.sling.junit.SlingContextCallback; import org.junit.Rule; import org.junit.Test; +import org.osgi.service.event.EventConstants; +import org.osgi.service.event.EventHandler; /** * Test events when changing file system content (FileVault XML). @@ -67,19 +70,23 @@ public class FileVaultFileMonitorTest { context.registerInjectActivateService(new FsResourceProvider(), "provider.file", tempDir.getPath() + "/jcr_root", "provider.filevault.filterxml.path", tempDir.getPath() + "/META-INF/vault/filter.xml", - "provider.root", "/content/dam/talk.png", + "provider.roots", "/content/dam/talk.png", "provider.checkinterval", CHECK_INTERVAL, "provider.fs.mode", FsMode.FILEVAULT_XML.name()); context.registerInjectActivateService(new FsResourceProvider(), "provider.file", tempDir.getPath() + "/jcr_root", "provider.filevault.filterxml.path", tempDir.getPath() + "/META-INF/vault/filter.xml", - "provider.root", "/content/samples", + "provider.roots", "/content/samples", "provider.checkinterval", CHECK_INTERVAL, "provider.fs.mode", FsMode.FILEVAULT_XML.name()); // register resource change listener - context.registerService(ResourceChangeListener.class, resourceListener, - ResourceChangeListener.PATHS, new String[] { "/content/dam/talk.png", "/content/samples" }); + context.registerService(EventHandler.class, resourceListener, + EventConstants.EVENT_TOPIC, new String[] { + TOPIC_RESOURCE_ADDED, + TOPIC_RESOURCE_CHANGED, + TOPIC_RESOURCE_REMOVED + }); } }) .afterTearDown(new SlingContextCallback() { @@ -102,7 +109,7 @@ public class FileVaultFileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(1, changes.size()); - assertChange(changes, "/content/dam/talk.png/jcr:content/renditions/web.1280.1280.png", ChangeType.CHANGED); + assertChange(changes, "/content/dam/talk.png/jcr:content/renditions/web.1280.1280.png", TOPIC_RESOURCE_CHANGED); } @Test @@ -116,8 +123,8 @@ public class FileVaultFileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(2, changes.size()); - assertChange(changes, "/content/dam/talk.png/jcr:content/renditions", ChangeType.CHANGED); - assertChange(changes, "/content/dam/talk.png/jcr:content/renditions/text.txt", ChangeType.ADDED); + assertChange(changes, "/content/dam/talk.png/jcr:content/renditions", TOPIC_RESOURCE_CHANGED); + assertChange(changes, "/content/dam/talk.png/jcr:content/renditions/text.txt", TOPIC_RESOURCE_ADDED); } @Test @@ -131,8 +138,8 @@ public class FileVaultFileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(2, changes.size()); - assertChange(changes, "/content/dam/talk.png/jcr:content/renditions", ChangeType.CHANGED); - assertChange(changes, "/content/dam/talk.png/jcr:content/renditions/web.1280.1280.png", ChangeType.REMOVED); + assertChange(changes, "/content/dam/talk.png/jcr:content/renditions", TOPIC_RESOURCE_CHANGED); + assertChange(changes, "/content/dam/talk.png/jcr:content/renditions/web.1280.1280.png", TOPIC_RESOURCE_REMOVED); } @Test @@ -146,8 +153,8 @@ public class FileVaultFileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(2, changes.size()); - assertChange(changes, "/content/dam/talk.png/jcr:content", ChangeType.CHANGED); - assertChange(changes, "/content/dam/talk.png/jcr:content/newfolder", ChangeType.ADDED); + assertChange(changes, "/content/dam/talk.png/jcr:content", TOPIC_RESOURCE_CHANGED); + assertChange(changes, "/content/dam/talk.png/jcr:content/newfolder", TOPIC_RESOURCE_ADDED); } @Test @@ -161,8 +168,8 @@ public class FileVaultFileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(2, changes.size()); - assertChange(changes, "/content/dam/talk.png/jcr:content", ChangeType.CHANGED); - assertChange(changes, "/content/dam/talk.png/jcr:content/renditions", ChangeType.REMOVED); + assertChange(changes, "/content/dam/talk.png/jcr:content", TOPIC_RESOURCE_CHANGED); + assertChange(changes, "/content/dam/talk.png/jcr:content/renditions", TOPIC_RESOURCE_REMOVED); } @Test @@ -175,9 +182,9 @@ public class FileVaultFileMonitorTest { Thread.sleep(WAIT_INTERVAL); - assertChange(changes, "/content/samples/en", ChangeType.REMOVED); - assertChange(changes, "/content/samples/en", ChangeType.ADDED); - assertChange(changes, "/content/samples/en/jcr:content", ChangeType.ADDED); + assertChange(changes, "/content/samples/en", TOPIC_RESOURCE_REMOVED); + assertChange(changes, "/content/samples/en", TOPIC_RESOURCE_ADDED); + assertChange(changes, "/content/samples/en/jcr:content", TOPIC_RESOURCE_ADDED); } @Test @@ -195,9 +202,9 @@ public class FileVaultFileMonitorTest { Thread.sleep(WAIT_INTERVAL); - assertChange(changes, "/content/samples", ChangeType.CHANGED); - assertChange(changes, "/content/samples/fr", ChangeType.ADDED); - assertChange(changes, "/content/samples/fr/jcr:content", ChangeType.ADDED); + assertChange(changes, "/content/samples", TOPIC_RESOURCE_CHANGED); + assertChange(changes, "/content/samples/fr", TOPIC_RESOURCE_ADDED); + assertChange(changes, "/content/samples/fr/jcr:content", TOPIC_RESOURCE_ADDED); } @Test @@ -211,8 +218,8 @@ public class FileVaultFileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(2, changes.size()); - assertChange(changes, "/content/samples", ChangeType.CHANGED); - assertChange(changes, "/content/samples/en", ChangeType.REMOVED); + assertChange(changes, "/content/samples", TOPIC_RESOURCE_CHANGED); + assertChange(changes, "/content/samples/en", TOPIC_RESOURCE_REMOVED); } @Test @@ -226,9 +233,9 @@ public class FileVaultFileMonitorTest { Thread.sleep(WAIT_INTERVAL); assertEquals(2, changes.size()); - assertChange(changes, "/content/samples/en", ChangeType.CHANGED); + assertChange(changes, "/content/samples/en", TOPIC_RESOURCE_CHANGED); // this second event is not fully correct, but this is a quite special case, accept it for now - assertChange(changes, "/content/samples/en", ChangeType.REMOVED); + assertChange(changes, "/content/samples/en", TOPIC_RESOURCE_REMOVED); } } diff --git a/src/test/java/org/apache/sling/fsprovider/internal/JcrXmlContentTest.java b/src/test/java/org/apache/sling/fsprovider/internal/JcrXmlContentTest.java index 1b8e2a9..45ec86f 100644 --- a/src/test/java/org/apache/sling/fsprovider/internal/JcrXmlContentTest.java +++ b/src/test/java/org/apache/sling/fsprovider/internal/JcrXmlContentTest.java @@ -34,6 +34,7 @@ import javax.jcr.Node; import javax.jcr.RepositoryException; import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceUtil; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.fsprovider.internal.TestUtils.RegisterFsResourcePlugin; import org.apache.sling.hamcrest.ResourceMatchers; @@ -41,6 +42,7 @@ import org.apache.sling.testing.mock.sling.ResourceResolverType; import org.apache.sling.testing.mock.sling.junit.SlingContext; import org.apache.sling.testing.mock.sling.junit.SlingContextBuilder; import org.junit.Before; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; @@ -97,7 +99,7 @@ public class JcrXmlContentTest { public void testContent_Root() { Resource underTest = fsroot.getChild("folder3/content"); assertNotNull(underTest); - assertEquals("app:Page", underTest.getValueMap().get("jcr:primaryType", String.class)); + assertEquals("app:Page", ResourceUtil.getValueMap(underTest).get("jcr:primaryType", String.class)); assertEquals("app:Page", underTest.getResourceType()); assertThat(underTest, ResourceMatchers.hasChildren("jcr:content")); } @@ -106,7 +108,7 @@ public class JcrXmlContentTest { public void testContent_Level1() { Resource underTest = fsroot.getChild("folder3/content/jcr:content"); assertNotNull(underTest); - assertEquals("app:PageContent", underTest.getValueMap().get("jcr:primaryType", String.class)); + assertEquals("app:PageContent", ResourceUtil.getValueMap(underTest).get("jcr:primaryType", String.class)); assertEquals("samples/sample-app/components/content/page/homepage", underTest.getResourceType()); assertThat(underTest, ResourceMatchers.hasChildren("teaserbar", "aside", "content")); } @@ -115,7 +117,7 @@ public class JcrXmlContentTest { public void testContent_Level3() { Resource underTest = fsroot.getChild("folder3/content/jcr:content/content/contentheadline"); assertNotNull(underTest); - assertEquals("nt:unstructured", underTest.getValueMap().get("jcr:primaryType", String.class)); + assertEquals("nt:unstructured", ResourceUtil.getValueMap(underTest).get("jcr:primaryType", String.class)); assertEquals("samples/sample-app/components/content/common/contentHeadline", underTest.getResourceType()); assertFalse(underTest.listChildren().hasNext()); } @@ -123,7 +125,7 @@ public class JcrXmlContentTest { @Test public void testContent_Datatypes() { Resource underTest = fsroot.getChild("folder3/content/jcr:content"); - ValueMap props = underTest.getValueMap(); + ValueMap props = ResourceUtil.getValueMap(underTest); assertEquals("en", props.get("jcr:title", String.class)); assertEquals(true, props.get("includeAside", false)); @@ -141,6 +143,7 @@ public class JcrXmlContentTest { } @Test + @Ignore // jcr overlay is always active with the old sling resource provider API public void testJcrMixedContent() throws RepositoryException { // prepare mixed JCR content Node node = root.adaptTo(Node.class); @@ -160,11 +163,11 @@ public class JcrXmlContentTest { Resource child1 = children.get(0); assertEquals("content", child1.getName()); assertEquals("app:Page", child1.getResourceType()); - assertEquals("app:Page", child1.getValueMap().get("jcr:primaryType", String.class)); + assertEquals("app:Page", ResourceUtil.getValueMap(child1).get("jcr:primaryType", String.class)); Resource child2 = children.get(1); assertEquals("folder31", child2.getName()); - assertEquals("nt:folder", child2.getValueMap().get("jcr:primaryType", String.class)); + assertEquals("nt:folder", ResourceUtil.getValueMap(child2).get("jcr:primaryType", String.class)); } } diff --git a/src/test/java/org/apache/sling/fsprovider/internal/JsonContentTest.java b/src/test/java/org/apache/sling/fsprovider/internal/JsonContentTest.java index eb4276e..02298c2 100644 --- a/src/test/java/org/apache/sling/fsprovider/internal/JsonContentTest.java +++ b/src/test/java/org/apache/sling/fsprovider/internal/JsonContentTest.java @@ -43,6 +43,7 @@ import javax.jcr.Value; import javax.jcr.nodetype.NodeType; import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceUtil; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.fsprovider.internal.TestUtils.RegisterFsResourcePlugin; import org.apache.sling.hamcrest.ResourceMatchers; @@ -51,6 +52,7 @@ import org.apache.sling.testing.mock.sling.ResourceResolverType; import org.apache.sling.testing.mock.sling.junit.SlingContext; import org.apache.sling.testing.mock.sling.junit.SlingContextBuilder; import org.junit.Before; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; @@ -108,7 +110,7 @@ public class JsonContentTest { public void testContent_Root() { Resource underTest = fsroot.getChild("folder2/content"); assertNotNull(underTest); - assertEquals("app:Page", underTest.getValueMap().get("jcr:primaryType", String.class)); + assertEquals("app:Page", ResourceUtil.getValueMap(underTest).get("jcr:primaryType", String.class)); assertEquals("app:Page", underTest.getResourceType()); assertThat(underTest, ResourceMatchers.hasChildren("jcr:content")); } @@ -117,7 +119,7 @@ public class JsonContentTest { public void testContent_Level1() { Resource underTest = fsroot.getChild("folder2/content/jcr:content"); assertNotNull(underTest); - assertEquals("app:PageContent", underTest.getValueMap().get("jcr:primaryType", String.class)); + assertEquals("app:PageContent", ResourceUtil.getValueMap(underTest).get("jcr:primaryType", String.class)); assertEquals("sample/components/homepage", underTest.getResourceType()); assertEquals("sample/components/supertype", underTest.getResourceSuperType()); assertThat(underTest, ResourceMatchers.hasChildren("par", "header", "newslist", "lead", "image", "carousel", "rightpar")); @@ -127,14 +129,14 @@ public class JsonContentTest { public void testContent_Level5() { Resource underTest = fsroot.getChild("folder2/content/jcr:content/par/image/file/jcr:content"); assertNotNull(underTest); - assertEquals("nt:resource", underTest.getValueMap().get("jcr:primaryType", String.class)); + assertEquals("nt:resource", ResourceUtil.getValueMap(underTest).get("jcr:primaryType", String.class)); assertFalse(underTest.listChildren().hasNext()); } @Test public void testContent_Datatypes() { Resource underTest = fsroot.getChild("folder2/content/toolbar/profiles/jcr:content"); - ValueMap props = underTest.getValueMap(); + ValueMap props = ResourceUtil.getValueMap(underTest); assertEquals("Profiles", props.get("jcr:title", String.class)); assertEquals(true, props.get("booleanProp", false)); @@ -149,7 +151,7 @@ public class JsonContentTest { @Test public void testContent_Datatypes_JCR() throws RepositoryException { Resource underTest = fsroot.getChild("folder2/content/toolbar/profiles/jcr:content"); - ValueMap props = underTest.getValueMap(); + ValueMap props = ResourceUtil.getValueMap(underTest); Node node = underTest.adaptTo(Node.class); assertEquals("/fs-test/folder2/content/toolbar/profiles/jcr:content", node.getPath()); @@ -236,6 +238,7 @@ public class JsonContentTest { } @Test + @Ignore // jcr overlay is always active with the old sling resource provider API public void testJcrMixedContent() throws RepositoryException { // prepare mixed JCR content Node node = root.adaptTo(Node.class); @@ -255,11 +258,11 @@ public class JsonContentTest { Resource child1 = children.get(0); assertEquals("content", child1.getName()); assertEquals("app:Page", child1.getResourceType()); - assertEquals("app:Page", child1.getValueMap().get("jcr:primaryType", String.class)); + assertEquals("app:Page", ResourceUtil.getValueMap(child1).get("jcr:primaryType", String.class)); Resource child2 = children.get(1); assertEquals("folder21", child2.getName()); - assertEquals("sling:OrderedFolder", child2.getValueMap().get("jcr:primaryType", String.class)); + assertEquals("sling:OrderedFolder", ResourceUtil.getValueMap(child2).get("jcr:primaryType", String.class)); } @Test @@ -268,7 +271,7 @@ public class JsonContentTest { assertEquals("nt:file", file21a.getResourceType()); assertEquals("/my/super/type", file21a.getResourceSuperType()); - ValueMap props = file21a.getValueMap(); + ValueMap props = ResourceUtil.getValueMap(file21a); assertEquals("nt:file", props.get("jcr:primaryType", String.class)); assertEquals("/my/super/type", props.get("sling:resourceSuperType", String.class)); assertEquals("en", props.get("jcr:language", String.class)); diff --git a/src/test/java/org/apache/sling/fsprovider/internal/TestUtils.java b/src/test/java/org/apache/sling/fsprovider/internal/TestUtils.java index 5539a40..05a5524 100644 --- a/src/test/java/org/apache/sling/fsprovider/internal/TestUtils.java +++ b/src/test/java/org/apache/sling/fsprovider/internal/TestUtils.java @@ -36,15 +36,16 @@ import java.util.Map; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingConstants; import org.apache.sling.api.resource.Resource; -import org.apache.sling.api.resource.observation.ResourceChange; -import org.apache.sling.api.resource.observation.ResourceChange.ChangeType; -import org.apache.sling.api.resource.observation.ResourceChangeListener; +import org.apache.sling.fsprovider.internal.FileMonitor.ResourceChange; import org.apache.sling.fsprovider.internal.mapper.Escape; import org.apache.sling.hamcrest.ResourceMatchers; import org.apache.sling.testing.mock.osgi.MapUtil; import org.apache.sling.testing.mock.osgi.context.AbstractContextPlugin; import org.apache.sling.testing.mock.sling.context.SlingContextImpl; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventHandler; class TestUtils { @@ -57,7 +58,7 @@ class TestUtils { public void beforeSetUp(SlingContextImpl context) throws Exception { Map<String,Object> config = new HashMap<>(); config.put("provider.file", "src/test/resources/fs-test"); - config.put("provider.root", "/fs-test"); + config.put("provider.roots", "/fs-test"); config.put("provider.checkinterval", 0); config.put("provider.fs.mode", FsMode.FILES_FOLDERS.name()); config.putAll(props); @@ -100,26 +101,30 @@ class TestUtils { } } - public static void assertChange(List<ResourceChange> changes, String path, ChangeType changeType) { + public static void assertChange(List<ResourceChange> changes, String path, String topic) { boolean found = false; for (ResourceChange change : changes) { - if (StringUtils.equals(change.getPath(), path) && change.getType() == changeType) { + if (StringUtils.equals(change.path, path) && StringUtils.equals(change.topic, topic)) { found = true; break; } } - assertTrue("Change with path=" + path + ", changeType=" + changeType + " expected", found); + assertTrue("Change with path=" + path + ", topic=" + topic + " expected", found); } - public static class ResourceListener implements ResourceChangeListener { + public static class ResourceListener implements EventHandler { private final List<ResourceChange> allChanges = new ArrayList<>(); - @Override - public void onChange(List<ResourceChange> changes) { - allChanges.addAll(changes); - } public List<ResourceChange> getChanges() { return allChanges; } + @Override + public void handleEvent(Event event) { + ResourceChange change = new ResourceChange(); + change.path = (String)event.getProperty(SlingConstants.PROPERTY_PATH); + change.resourceType = (String)event.getProperty(SlingConstants.PROPERTY_RESOURCE_TYPE); + change.topic = event.getTopic(); + allChanges.add(change); + } } } -- To stop receiving notification emails like this one, please contact "commits@sling.apache.org" <commits@sling.apache.org>.