Author: sseifert
Date: Mon Mar 6 21:48:44 2017
New Revision: 1785772
URL: http://svn.apache.org/viewvc?rev=1785772&view=rev
Log:
SLING-6537 FileVault XML support
Added:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FsMode.java
(with props)
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/InitialContentImportOptions.java
(with props)
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java
(with props)
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileVaultContentTest.java
(with props)
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileVaultFileMonitorTest.java
(with props)
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/InitialContentImportOptionsTest.java
(with props)
Modified:
sling/branches/fsresource-1.1.x/pom.xml
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/ContentFileExtensions.java
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFile.java
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNode.java
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNodeIterator.java
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtil.java
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileMonitorTest.java
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/JcrXmlContentTest.java
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/JsonContentTest.java
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/TestUtils.java
sling/branches/fsresource-1.1.x/src/test/resources/vaultfs-test/META-INF/vault/filter.xml
sling/branches/fsresource-1.1.x/src/test/resources/vaultfs-test/jcr_root/content/dam/talk.png/.content.xml
Modified: sling/branches/fsresource-1.1.x/pom.xml
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/pom.xml?rev=1785772&r1=1785771&r2=1785772&view=diff
==============================================================================
--- sling/branches/fsresource-1.1.x/pom.xml (original)
+++ sling/branches/fsresource-1.1.x/pom.xml Mon Mar 6 21:48:44 2017
@@ -22,7 +22,7 @@
<parent>
<groupId>org.apache.sling</groupId>
<artifactId>sling</artifactId>
- <version>30-SNAPSHOT</version>
+ <version>30</version>
<relativePath />
</parent>
Modified:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/ContentFileExtensions.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/ContentFileExtensions.java?rev=1785772&r1=1785771&r2=1785772&view=diff
==============================================================================
---
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/ContentFileExtensions.java
(original)
+++
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/ContentFileExtensions.java
Mon Mar 6 21:48:44 2017
@@ -41,8 +41,9 @@ public final class ContentFileExtensions
* @return Content file name suffix or null if not a context file.
*/
public String getSuffix(File file) {
+ String fileName = "/" + file.getName();
for (String suffix : contentFileSuffixes) {
- if (StringUtils.endsWith(file.getName(), suffix)) {
+ if (StringUtils.endsWith(fileName, suffix)) {
return suffix;
}
}
Modified:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java?rev=1785772&r1=1785771&r2=1785772&view=diff
==============================================================================
---
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java
(original)
+++
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java
Mon Mar 6 21:48:44 2017
@@ -18,9 +18,17 @@
*/
package org.apache.sling.fsprovider.internal;
+import static org.apache.jackrabbit.vault.util.Constants.ROOT_DIR;
+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;
@@ -28,7 +36,7 @@ import java.util.Timer;
import java.util.TimerTask;
import org.apache.commons.lang3.StringUtils;
-import org.apache.sling.api.SlingConstants;
+import org.apache.jackrabbit.vault.util.PlatformNameFormat;
import org.apache.sling.fsprovider.internal.mapper.ContentFile;
import org.apache.sling.fsprovider.internal.mapper.FileResource;
import org.apache.sling.fsprovider.internal.parser.ContentFileCache;
@@ -51,7 +59,7 @@ public final class FileMonitor extends T
private final Monitorable root;
private final FsResourceProvider provider;
-
+ private final FsMode fsMode;
private final ContentFileExtensions contentFileExtensions;
private final ContentFileCache contentFileCache;
@@ -60,12 +68,19 @@ public final class FileMonitor extends T
* @param provider The resource provider.
* @param interval The interval between executions of the task, in
milliseconds.
*/
- public FileMonitor(final FsResourceProvider provider, final long interval,
+ public FileMonitor(final FsResourceProvider provider, final long interval,
FsMode fsMode,
final ContentFileExtensions contentFileExtensions, final
ContentFileCache contentFileCache) {
this.provider = provider;
+ this.fsMode = fsMode;
this.contentFileExtensions = contentFileExtensions;
this.contentFileCache = contentFileCache;
- this.root = new Monitorable(this.provider.getProviderRoot(),
this.provider.getRootFile(), null);
+
+ File rootFile = this.provider.getRootFile();
+ if (fsMode == FsMode.FILEVAULT_XML) {
+ rootFile = new File(this.provider.getRootFile(), ROOT_DIR +
PlatformNameFormat.getPlatformPath(this.provider.getProviderRoot()));
+ }
+ this.root = new Monitorable(this.provider.getProviderRoot(), rootFile,
null);
+
createStatus(this.root, contentFileExtensions, contentFileCache);
log.debug("Starting file monitor for {} with an interval of {}ms",
this.root.file, interval);
timer.schedule(this, 0, interval);
@@ -116,9 +131,9 @@ public final class FileMonitor extends T
synchronized ( this ) {
try {
// if we don't have an event admin, we just skip the check
- final EventAdmin localEA = this.provider.getEventAdmin();
- if ( localEA != null ) {
- this.check(this.root, localEA);
+ final EventAdmin reporter = this.provider.getEventAdmin();
+ if ( reporter != null ) {
+ this.check(this.root, reporter);
}
} catch (Exception e) {
// ignore this
@@ -133,22 +148,29 @@ public final class FileMonitor extends T
/**
* Check the monitorable
* @param monitorable The monitorable to check
- * @param localEA The event admin
+ * @param reporter The EventAdmin
*/
- private void check(final Monitorable monitorable, final EventAdmin
localEA) {
+ 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, SlingConstants.TOPIC_RESOURCE_ADDED,
localEA);
+ sendEvents(monitorable, TOPIC_RESOURCE_ADDED, reporter);
+ final FileStatus fs = (FileStatus)monitorable.status;
+ if ( fs instanceof DirStatus ) {
+ final DirStatus ds = (DirStatus)fs;
+ // remove monitorables for new folder and update folder
children to send events for directory contents
+ ds.children = new Monitorable[0];
+ checkDirStatusChildren(monitorable, reporter);
+ }
}
} else {
// check if the file has been removed
if ( !monitorable.file.exists() ) {
// removed file and update status
- sendEvents(monitorable, SlingConstants.TOPIC_RESOURCE_REMOVED,
localEA);
+ sendEvents(monitorable, TOPIC_RESOURCE_REMOVED, reporter);
monitorable.status = NonExistingStatus.SINGLETON;
contentFileCache.remove(monitorable.path);
} else {
@@ -158,7 +180,7 @@ public final class FileMonitor extends T
if ( fs.lastModified < monitorable.file.lastModified() ) {
fs.lastModified = monitorable.file.lastModified();
// changed
- sendEvents(monitorable,
SlingConstants.TOPIC_RESOURCE_CHANGED, localEA);
+ sendEvents(monitorable, TOPIC_RESOURCE_CHANGED, reporter);
changed = true;
contentFileCache.remove(monitorable.path);
}
@@ -166,105 +188,122 @@ public final class FileMonitor extends T
// directory
final DirStatus ds = (DirStatus)fs;
for(int i=0; i<ds.children.length; i++) {
- check(ds.children[i], localEA);
+ check(ds.children[i], reporter);
}
// if the dir changed we have to update
if ( changed ) {
// and now update
- final File[] files = monitorable.file.listFiles();
- if (files != null) {
- final Monitorable[] children = new
Monitorable[files.length];
- for (int i = 0; i < files.length; i++) {
- // search in old list
- for (int m = 0; m < ds.children.length; m++) {
- if (ds.children[m].file.equals(files[i])) {
- children[i] = ds.children[m];
- break;
- }
- }
- if (children[i] == null) {
- children[i] = new
Monitorable(monitorable.path + '/' + files[i].getName(), files[i],
-
contentFileExtensions.getSuffix(files[i]));
- children[i].status =
NonExistingStatus.SINGLETON;
- check(children[i], localEA);
- }
- }
- ds.children = children;
- } else {
- ds.children = new Monitorable[0];
- }
+ checkDirStatusChildren(monitorable, 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) {
+ final Monitorable[] children = new Monitorable[files.length];
+ for (int i = 0; i < files.length; i++) {
+ // search in old list
+ for (int m = 0; m < ds.children.length; m++) {
+ if (ds.children[m].file.equals(files[i])) {
+ children[i] = ds.children[m];
+ break;
+ }
+ }
+ if (children[i] == null) {
+ children[i] = new Monitorable(dirMonitorable.path + '/' +
files[i].getName(), files[i],
+ contentFileExtensions.getSuffix(files[i]));
+ children[i].status = NonExistingStatus.SINGLETON;
+ check(children[i], reporter);
+ }
+ }
+ ds.children = children;
+ } else {
+ ds.children = new Monitorable[0];
+ }
+ }
/**
* Send the event async via the event admin.
*/
- private void sendEvents(final Monitorable monitorable, final String topic,
final EventAdmin localEA) {
+ private void sendEvents(final Monitorable monitorable, final String
changeType, final EventAdmin reporter) {
if (log.isDebugEnabled()) {
- log.debug("Detected change for resource {} : {}",
monitorable.path, topic);
+ log.debug("Detected change for resource {} : {}",
transformPath(monitorable.path), changeType);
}
- List<ResourceChange> changes = collectResourceChanges(monitorable,
topic);
+ List<ResourceChange> changes = collectResourceChanges(monitorable,
changeType);
for (ResourceChange change : changes) {
if (log.isTraceEnabled()) {
- log.debug("Send change for resource {}: {}", change.path,
change.topic);
+ log.debug("Send change for resource {}: {}",
transformPath(change.path), change.topic);
}
- final Dictionary<String, String> properties = new
Hashtable<String, String>();
- properties.put(SlingConstants.PROPERTY_PATH, change.path);
+ final Dictionary<String, String> properties = new Hashtable<>();
+ properties.put(PROPERTY_PATH, transformPath(change.path));
if (change.resourceType != null) {
- properties.put(SlingConstants.PROPERTY_RESOURCE_TYPE,
change.resourceType);
+ properties.put(PROPERTY_RESOURCE_TYPE, change.resourceType);
}
- localEA.postEvent(new org.osgi.service.event.Event(change.topic,
properties));
+ reporter.postEvent(new org.osgi.service.event.Event(change.topic,
properties));
}
}
+ /**
+ * Transform path for resource event.
+ * @param path Path
+ * @return Transformed path
+ */
+ private String transformPath(String path) {
+ if (fsMode == FsMode.FILEVAULT_XML) {
+ return PlatformNameFormat.getRepositoryPath(path);
+ }
+ else {
+ return path;
+ }
+ }
+
@SuppressWarnings("unchecked")
- private List<ResourceChange> collectResourceChanges(final Monitorable
monitorable, final String topic) {
+ 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 (StringUtils.equals(topic,
SlingConstants.TOPIC_RESOURCE_CHANGED)) {
+ if (StringUtils.equals(changeType, TOPIC_RESOURCE_CHANGED)) {
Map<String,Object> content =
(Map<String,Object>)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(SlingConstants.TOPIC_RESOURCE_REMOVED,
content, monitorable.path));
- addContentResourceChanges(changes,
SlingConstants.TOPIC_RESOURCE_ADDED, content, monitorable.path);
+ changes.add(buildContentResourceChange(TOPIC_RESOURCE_REMOVED,
content, transformPath(monitorable.path)));
+ addContentResourceChanges(changes, TOPIC_RESOURCE_ADDED,
content, transformPath(monitorable.path));
}
else {
- addContentResourceChanges(changes, topic,
(Map<String,Object>)contentFile.getContent(), monitorable.path);
+ addContentResourceChanges(changes, changeType,
(Map<String,Object>)contentFile.getContent(), transformPath(monitorable.path));
}
}
else {
- ResourceChange change = new ResourceChange();
- change.path = monitorable.path;
- change.resourceType = monitorable.status instanceof FileStatus ?
- FileResource.RESOURCE_TYPE_FILE :
FileResource.RESOURCE_TYPE_FOLDER;
- change.topic = topic;
- changes.add(change);
+ Map<String,Object> content = new HashMap<>();
+ content.put("sling:resourceType", monitorable.status instanceof
FileStatus ?
+ FileResource.RESOURCE_TYPE_FILE :
FileResource.RESOURCE_TYPE_FOLDER);
+ changes.add(buildContentResourceChange(changeType, content,
transformPath(monitorable.path)));
}
return changes;
}
@SuppressWarnings("unchecked")
- private void addContentResourceChanges(final List<ResourceChange> changes,
final String topic,
+ private void addContentResourceChanges(final List<ResourceChange> changes,
final String changeType,
final Map<String,Object> content, final String path) {
- changes.add(buildContentResourceChange(topic, content, path));
+ changes.add(buildContentResourceChange(changeType, content, path));
if (content != null) {
for (Map.Entry<String,Object> entry : content.entrySet()) {
if (entry.getValue() instanceof Map) {
String childPath = path + "/" + entry.getKey();
- addContentResourceChanges(changes, topic,
(Map<String,Object>)entry.getValue(), childPath);
+ addContentResourceChanges(changes, changeType,
(Map<String,Object>)entry.getValue(), childPath);
}
}
}
}
- private ResourceChange buildContentResourceChange(final String topic,
final Map<String,Object> content, final String path) {
+ private ResourceChange buildContentResourceChange(final String changeType,
final Map<String,Object> content, final String path) {
ResourceChange change = new ResourceChange();
change.path = path;
change.resourceType = content != null ?
(String)content.get("sling:resourceType") : null;
- change.topic = topic;
+ change.topic = changeType;
return change;
}
@@ -351,5 +390,5 @@ public final class FileMonitor extends T
public String resourceType;
public String topic;
}
-
+
}
Added:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FsMode.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FsMode.java?rev=1785772&view=auto
==============================================================================
---
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FsMode.java
(added)
+++
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FsMode.java
Mon Mar 6 21:48:44 2017
@@ -0,0 +1,41 @@
+/*
+ * 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.fsprovider.internal;
+
+/**
+ * Different modes for Filesystem provider support and filesystem layouts.
+ */
+public enum FsMode {
+
+ /**
+ * Sling-Initial-Content filesystem layout, with full support for JSON and
jcr.xml content files.
+ */
+ INITIAL_CONTENT,
+
+ /**
+ * Sling-Initial-Content filesystem layout, support only files and folders
(classic mode).
+ */
+ INITIAL_CONTENT_FILES_FOLDERS,
+
+ /**
+ * FileVault XML format (expanded content package).
+ */
+ FILEVAULT_XML
+
+}
Propchange:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FsMode.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FsMode.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Mar 6 21:48:44 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author
Propchange:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FsMode.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java?rev=1785772&r1=1785771&r2=1785772&view=diff
==============================================================================
---
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java
(original)
+++
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java
Mon Mar 6 21:48:44 2017
@@ -18,6 +18,8 @@
*/
package org.apache.sling.fsprovider.internal;
+import static org.apache.jackrabbit.vault.util.Constants.DOT_CONTENT_XML;
+
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
@@ -35,6 +37,7 @@ import org.apache.sling.api.resource.Res
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.fsprovider.internal.mapper.ContentFileResourceMapper;
import org.apache.sling.fsprovider.internal.mapper.FileResourceMapper;
+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.osgi.framework.BundleContext;
@@ -50,6 +53,7 @@ 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;
+import org.osgi.service.metatype.annotations.Option;
/**
* The <code>FsResourceProvider</code> is a resource provider which maps
@@ -72,6 +76,11 @@ import org.osgi.service.metatype.annotat
@Designate(ocd=FsResourceProvider.Config.class, factory=true)
public final class FsResourceProvider implements ResourceProvider {
+ /**
+ * Resource metadata property set by {@link FsResource} if the underlying
file reference is a directory.
+ */
+ public static final String RESOURCE_METADATA_FILE_DIRECTORY =
":org.apache.sling.fsprovider.file.directory";
+
@ObjectClassDefinition(name = "Apache Sling File System Resource Provider",
description = "Configure an instance of the filesystem " +
"resource provider in terms of provider root and
filesystem location")
@@ -104,17 +113,25 @@ public final class FsResourceProvider im
"filesystem resources are mapped in. This property must
contain at least one non-empty string.")
String[] provider_roots();
- @AttributeDefinition(name = "Mount json",
- description = "Mount .json files as content in the resource
hierarchy.")
- boolean provider_json_content();
-
- @AttributeDefinition(name = "Mount jcr.xml",
- description = "Mount .jcr.xml files as content in the resource
hierarchy.")
- boolean provider_jcrxml_content();
+ @AttributeDefinition(name = "Filesystem layout",
+ description = "Filesystem layout mode for files, folders and
content.",
+ options={
+ @Option(value="INITIAL_CONTENT",
label="INITIAL_CONTENT - "
+ + "Sling-Initial-Content filesystem layout,
with full support for JSON and jcr.xml content files."),
+ @Option(value="INITIAL_CONTENT_FILES_FOLDERS",
label="INITIAL_CONTENT_FILES_FOLDERS - "
+ + "Sling-Initial-Content filesystem layout,
support only files and folders (classic mode)."),
+ @Option(value="FILEVAULT_XML", label="FILEVAULT_XML - "
+ + "FileVault XML format (expanded content
package)."),
+ })
+ FsMode provider_fs_mode() default FsMode.INITIAL_CONTENT;
+
+ @AttributeDefinition(name = "Init. Content Options",
+ description = "Import options for Sling-Initial-Content
filesystem layout. Supported options: overwrite, ignoreImportProviders.")
+ String provider_initial_content_import_options();
@AttributeDefinition(name = "Cache Size",
description = "Max. number of content files cached in memory.")
- int provider_cache_size() default 1000;
+ int provider_cache_size() default 10000;
/**
* Internal Name hint for web console.
@@ -132,8 +149,10 @@ public final class FsResourceProvider im
private FileMonitor monitor;
// maps filesystem to resources
+ private FsMode fsMode;
private FsResourceMapper fileMapper;
private FsResourceMapper contentFileMapper;
+ private FileVaultResourceMapper fileVaultMapper;
// cache for parsed content files
private ContentFileCache contentFileCache;
@@ -155,34 +174,56 @@ public final class FsResourceProvider im
* to access the file or folder. If no such file or folder exists, this
* method returns <code>null</code>.
*/
+ @SuppressWarnings("rawtypes")
@Override
public Resource getResource(ResourceResolver resolver, String path) {
- Resource rsrc = contentFileMapper.getResource(resolver, path);
- if (rsrc == null) {
- rsrc = fileMapper.getResource(resolver, path);
+
+ Resource rsrc = null;
+
+ if (fsMode == FsMode.FILEVAULT_XML) {
+ // filevault: check if path matches, if not fallback to parent
resource provider
+ if (fileVaultMapper.pathMatches(path)) {
+ rsrc = fileVaultMapper.getResource(resolver, path);
+ }
+ }
+ else {
+ // Sling-Initial-Content: mount folder/files an content files
+ rsrc = contentFileMapper.getResource(resolver, path);
+ if (rsrc == null) {
+ rsrc = fileMapper.getResource(resolver, path);
+ }
}
+
return rsrc;
}
-
+
/**
* Returns an iterator of resources.
*/
@SuppressWarnings("unchecked")
- @Override
public Iterator<Resource> listChildren(Resource parent) {
ResourceResolver resolver = parent.getResourceResolver();
List<Iterator<Resource>> allChildren = new ArrayList<>();
Iterator<Resource> children;
- children = contentFileMapper.getChildren(resolver, parent);
- if (children != null) {
- allChildren.add(children);
+ if (fsMode == FsMode.FILEVAULT_XML) {
+ // filevault: always ask provider, it checks itself if children
matches the filters
+ children = fileVaultMapper.getChildren(resolver, parent);
+ if (children != null) {
+ allChildren.add(children);
+ }
}
-
- children = fileMapper.getChildren(resolver, parent);
- if (children != null) {
- allChildren.add(children);
+ else {
+ // Sling-Initial-Content: get all matchind folders/files and
content files
+ children = contentFileMapper.getChildren(resolver, parent);
+ if (children != null) {
+ allChildren.add(children);
+ }
+ children = fileMapper.getChildren(resolver, parent);
+ if (children != null) {
+ allChildren.add(children);
+ }
}
if (allChildren.isEmpty()) {
@@ -207,6 +248,7 @@ public final class FsResourceProvider im
// ---------- SCR Integration
@Activate
protected void activate(BundleContext bundleContext, final Config config) {
+ fsMode = config.provider_fs_mode();
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.");
@@ -214,30 +256,42 @@ public final class FsResourceProvider im
String providerRoot = config.provider_roots()[0];
String providerFileName = config.provider_file();
- if (providerFileName == null || providerFileName.length() == 0) {
+ if (StringUtils.isBlank(providerFileName)) {
throw new IllegalArgumentException("provider.file property must be
set");
}
this.providerRoot = providerRoot;
this.providerFile = getProviderFile(providerFileName, bundleContext);
+ InitialContentImportOptions options = new
InitialContentImportOptions(config.provider_initial_content_import_options());
+
List<String> contentFileSuffixes = new ArrayList<>();
- if (config.provider_json_content()) {
- contentFileSuffixes.add(ContentFileTypes.JSON_SUFFIX);
+ if (fsMode == FsMode.FILEVAULT_XML) {
+ contentFileSuffixes.add("/" + DOT_CONTENT_XML);
}
- if (config.provider_jcrxml_content()) {
- contentFileSuffixes.add(ContentFileTypes.JCR_XML_SUFFIX);
+ else if (fsMode == FsMode.INITIAL_CONTENT) {
+ if (!options.getIgnoreImportProviders().contains("json")) {
+ contentFileSuffixes.add(ContentFileTypes.JSON_SUFFIX);
+ }
+ if (!options.getIgnoreImportProviders().contains("jcr.xml")) {
+ contentFileSuffixes.add(ContentFileTypes.JCR_XML_SUFFIX);
+ }
}
ContentFileExtensions contentFileExtensions = new
ContentFileExtensions(contentFileSuffixes);
this.contentFileCache = new
ContentFileCache(config.provider_cache_size());
- this.fileMapper = new FileResourceMapper(this.providerRoot,
this.providerFile, contentFileExtensions);
- this.contentFileMapper = new
ContentFileResourceMapper(this.providerRoot, this.providerFile,
- contentFileExtensions, this.contentFileCache);
+ if (fsMode == FsMode.FILEVAULT_XML) {
+ this.fileVaultMapper = new
FileVaultResourceMapper(this.providerFile, this.contentFileCache);
+ }
+ else {
+ this.fileMapper = new FileResourceMapper(this.providerRoot,
this.providerFile, contentFileExtensions);
+ this.contentFileMapper = new
ContentFileResourceMapper(this.providerRoot, this.providerFile,
+ contentFileExtensions, this.contentFileCache);
+ }
// start background monitor if check interval is higher than 100
- if ( config.provider_checkinterval() > 100 ) {
- this.monitor = new FileMonitor(this,
config.provider_checkinterval(),
+ if (config.provider_checkinterval() > 100) {
+ this.monitor = new FileMonitor(this,
config.provider_checkinterval(), fsMode,
contentFileExtensions, this.contentFileCache);
}
}
@@ -252,10 +306,12 @@ public final class FsResourceProvider im
this.providerFile = null;
this.fileMapper = null;
this.contentFileMapper = null;
+ this.fileVaultMapper = null;
if (this.contentFileCache != null) {
this.contentFileCache.clear();
this.contentFileCache = null;
}
+ this.fsMode = null;
}
EventAdmin getEventAdmin() {
Added:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/InitialContentImportOptions.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/InitialContentImportOptions.java?rev=1785772&view=auto
==============================================================================
---
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/InitialContentImportOptions.java
(added)
+++
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/InitialContentImportOptions.java
Mon Mar 6 21:48:44 2017
@@ -0,0 +1,76 @@
+/*
+ * 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.fsprovider.internal;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+
+class InitialContentImportOptions {
+
+ /**
+ * The overwrite directive specifying if content should be overwritten or
+ * just initially added.
+ */
+ private static final String OVERWRITE_DIRECTIVE = "overwrite";
+
+ /**
+ * The ignore content readers directive specifying whether the available
ContentReaders
+ * should be used during content loading.
+ */
+ private static final String IGNORE_CONTENT_READERS_DIRECTIVE =
"ignoreImportProviders";
+
+
+ private final boolean overwrite;
+ private final Set<String> ignoreImportProviders;
+
+ public InitialContentImportOptions(String optionsString) {
+ Map<String,String> options = parseOptions(optionsString);
+ overwrite = BooleanUtils.toBoolean(options.get(OVERWRITE_DIRECTIVE));
+ ignoreImportProviders = new
HashSet<>(Arrays.asList(StringUtils.split(StringUtils.defaultString(options.get(IGNORE_CONTENT_READERS_DIRECTIVE)))));
+ }
+
+ private static Map<String,String> parseOptions(String optionsString) {
+ Map<String,String> options = new HashMap<>();
+ String[] optionsList = StringUtils.split(optionsString, ";");
+ if (optionsList != null) {
+ for (String keyValueString : optionsList) {
+ String[] keyValue =
StringUtils.splitByWholeSeparator(keyValueString, ":=");
+ if (keyValue.length == 2) {
+ options.put(StringUtils.trim(keyValue[0]),
StringUtils.trim(keyValue[1]));
+ }
+ }
+ }
+ return options;
+ }
+
+ public boolean isOverwrite() {
+ return overwrite;
+ }
+
+ public Set<String> getIgnoreImportProviders() {
+ return ignoreImportProviders;
+ }
+
+}
Propchange:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/InitialContentImportOptions.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/InitialContentImportOptions.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Mar 6 21:48:44 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author
Propchange:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/InitialContentImportOptions.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFile.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFile.java?rev=1785772&r1=1785771&r2=1785772&view=diff
==============================================================================
---
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFile.java
(original)
+++
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFile.java
Mon Mar 6 21:48:44 2017
@@ -19,8 +19,11 @@
package org.apache.sling.fsprovider.internal.mapper;
import java.io.File;
+import java.util.Iterator;
import java.util.Map;
+import org.apache.commons.collections.IteratorUtils;
+import org.apache.commons.collections.Predicate;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.fsprovider.internal.parser.ContentFileCache;
@@ -51,19 +54,6 @@ public final class ContentFile {
}
/**
- * @param file File with content fragment
- * @param path Root path of the content file
- * @param subPath Relative path addressing content fragment inside file
- * @param contentFileCache Content file cache
- * @param content Content
- */
- public ContentFile(File file, String path, String subPath,
ContentFileCache contentFileCache, Object content) {
- this(file, path, subPath, contentFileCache);
- this.contentInitialized = true;
- this.content = content;
- }
-
- /**
* @return File with content fragment
*/
public File getFile() {
@@ -129,14 +119,47 @@ public final class ContentFile {
}
/**
+ * @return Child maps.
+ */
+ @SuppressWarnings("unchecked")
+ public Iterator<Map.Entry<String,Map<String,Object>>> getChildren() {
+ if (!isResource()) {
+ return IteratorUtils.emptyIterator();
+ }
+ return
IteratorUtils.filteredIterator(((Map)getContent()).entrySet().iterator(), new
Predicate() {
+ @Override
+ public boolean evaluate(Object object) {
+ Map.Entry<String,Object> entry =
(Map.Entry<String,Object>)object;
+ return entry.getValue() instanceof Map;
+ }
+ });
+ }
+
+ /**
* Navigate to another sub path position in content file.
- * @param newSubPath New sub path
+ * @param newSubPath New sub path related to root path of content file
* @return Content file
*/
- public ContentFile navigateTo(String newSubPath) {
+ public ContentFile navigateToAbsolute(String newSubPath) {
return new ContentFile(file, path, newSubPath, contentFileCache);
}
+ /**
+ * Navigate to another sub path position in content file.
+ * @param newSubPath New sub path relative to current sub path in content
file
+ * @return Content file
+ */
+ public ContentFile navigateToRelative(String newSubPath) {
+ String absoluteSubPath;
+ if (newSubPath == null) {
+ absoluteSubPath = this.subPath;
+ }
+ else {
+ absoluteSubPath = (this.subPath != null ? this.subPath + "/" : "")
+ newSubPath;
+ }
+ return new ContentFile(file, path, absoluteSubPath, contentFileCache);
+ }
+
@SuppressWarnings("unchecked")
private static Object getDeepContent(Object object, String subPath) {
if (object == null) {
Modified:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java?rev=1785772&r1=1785771&r2=1785772&view=diff
==============================================================================
---
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java
(original)
+++
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java
Mon Mar 6 21:48:44 2017
@@ -106,18 +106,10 @@ public final class ContentFileResourceMa
// get child resources from content fragments in content file
List<ContentFile> children = new ArrayList<>();
if (parentContentFile.hasContent() && parentContentFile.isResource()) {
- Map<String,Object> content =
(Map<String,Object>)parentContentFile.getContent();
- for (Map.Entry<String, Object> entry: content.entrySet()) {
- if (entry.getValue() instanceof Map) {
- String subPath;
- if (parentContentFile.getSubPath() == null) {
- subPath = entry.getKey();
- }
- else {
- subPath = parentContentFile.getSubPath() + "/" +
entry.getKey();
- }
- children.add(new ContentFile(parentContentFile.getFile(),
parentContentFile.getPath(), subPath, contentFileCache, entry.getValue()));
- }
+ Iterator<Map.Entry<String,Map<String,Object>>> childMaps =
parentContentFile.getChildren();
+ while (childMaps.hasNext()) {
+ Map.Entry<String,Map<String,Object>> entry = childMaps.next();
+
children.add(parentContentFile.navigateToRelative(entry.getKey()));
}
}
if (children.isEmpty()) {
Added:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java?rev=1785772&view=auto
==============================================================================
---
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java
(added)
+++
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java
Mon Mar 6 21:48:44 2017
@@ -0,0 +1,201 @@
+/*
+ * 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.fsprovider.internal.mapper;
+
+import static org.apache.jackrabbit.vault.util.Constants.DOT_CONTENT_XML;
+import static org.apache.jackrabbit.vault.util.Constants.FILTER_XML;
+import static org.apache.jackrabbit.vault.util.Constants.META_DIR;
+import static org.apache.jackrabbit.vault.util.Constants.ROOT_DIR;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.IteratorUtils;
+import org.apache.commons.collections.Transformer;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
+import org.apache.jackrabbit.vault.fs.config.ConfigurationException;
+import org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter;
+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.FsResourceMapper;
+import org.apache.sling.fsprovider.internal.parser.ContentFileCache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class FileVaultResourceMapper implements FsResourceMapper {
+
+ private static final String DOT_CONTENT_XML_SUFFIX = "/" + DOT_CONTENT_XML;
+ private static final String DOT_DIR_SUFFIX = "/.dir";
+
+ private final File providerFile;
+ private final ContentFileCache contentFileCache;
+ private final WorkspaceFilter workspaceFilter;
+
+ private static final Logger log =
LoggerFactory.getLogger(FileVaultResourceMapper.class);
+
+ public FileVaultResourceMapper(File providerFile, ContentFileCache
contentFileCache) {
+ this.providerFile = providerFile;
+ this.contentFileCache = contentFileCache;
+ this.workspaceFilter = getWorkspaceFilter();
+ }
+
+ @Override
+ public Resource getResource(final ResourceResolver resolver, final String
resourcePath) {
+
+ // direct file
+ File file = getFile(resourcePath);
+ if (file != null && file.isFile()) {
+ return new FileResource(resolver, resourcePath, file);
+ }
+
+ // content file
+ ContentFile contentFile = getContentFile(resourcePath, null);
+ if (contentFile != null) {
+ return new ContentFileResource(resolver, contentFile);
+ }
+
+ // fallback to directory resource if folder was found but nothing else
+ if (file != null && file.isDirectory()) {
+ return new FileResource(resolver, resourcePath, file);
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Iterator<Resource> getChildren(final ResourceResolver resolver,
final Resource parent) {
+ String parentPath = parent.getPath();
+
+ Set<String> childPaths = new LinkedHashSet<>();
+
+ // get children from content resource of parent
+ ContentFile parentContentFile = getContentFile(parentPath, null);
+ if (parentContentFile != null) {
+ Iterator<Map.Entry<String,Map<String,Object>>> childMaps =
parentContentFile.getChildren();
+ while (childMaps.hasNext()) {
+ Map.Entry<String,Map<String,Object>> entry = childMaps.next();
+ String childPath = parentPath + "/" + entry.getKey();
+ if (pathMatches(childPath)) {
+ childPaths.add(childPath);
+ }
+ }
+ }
+
+ // additional check for children in filesystem
+ File parentFile = getFile(parentPath);
+ if (parentFile != null && parentFile.isDirectory()) {
+ for (File childFile : parentFile.listFiles()) {
+ String childPath = parentPath + "/" +
PlatformNameFormat.getRepositoryName(childFile.getName());
+ if (pathMatches(childPath) && !childPaths.contains(childPath))
{
+ childPaths.add(childPath);
+ }
+ }
+ }
+
+ if (childPaths.isEmpty()) {
+ return null;
+ }
+ else {
+ return IteratorUtils.transformedIterator(childPaths.iterator(),
new Transformer() {
+ @Override
+ public Object transform(Object input) {
+ String path = (String)input;
+ return getResource(resolver, path);
+ }
+ });
+ }
+ }
+
+ /**
+ * @return Workspace filter or null if none found.
+ */
+ private WorkspaceFilter getWorkspaceFilter() {
+ File filter = new File(providerFile, META_DIR + "/" + FILTER_XML);
+ if (filter.exists()) {
+ try {
+ DefaultWorkspaceFilter workspaceFilter = new
DefaultWorkspaceFilter();
+ workspaceFilter.load(filter);
+ return workspaceFilter;
+ } catch (IOException | ConfigurationException ex) {
+ log.error("Unable to parse workspace filter: " +
filter.getPath(), ex);
+ }
+ }
+ else {
+ log.warn("Workspace filter not found: " + filter.getPath());
+ }
+ return null;
+ }
+
+ /**
+ * Checks if the given path matches the workspace filter.
+ * @param path Path
+ * @return true if path matches
+ */
+ public boolean pathMatches(String path) {
+ // ignore .dir folder
+ if (StringUtils.endsWith(path, DOT_DIR_SUFFIX) ||
StringUtils.endsWith(path, DOT_CONTENT_XML_SUFFIX)) {
+ return false;
+ }
+ if (workspaceFilter == null) {
+ return false;
+ }
+ else {
+ return workspaceFilter.contains(path);
+ }
+ }
+
+ private File getFile(String path) {
+ if (StringUtils.endsWith(path, DOT_CONTENT_XML_SUFFIX)) {
+ return null;
+ }
+ File file = new File(providerFile, ROOT_DIR +
PlatformNameFormat.getPlatformPath(path));
+ if (file.exists()) {
+ return file;
+ }
+ return null;
+ }
+
+ private ContentFile getContentFile(String path, String subPath) {
+ File file = new File(providerFile, ROOT_DIR +
PlatformNameFormat.getPlatformPath(path) + DOT_CONTENT_XML_SUFFIX);
+ if (file.exists()) {
+ ContentFile contentFile = new ContentFile(file, path, subPath,
contentFileCache);
+ if (contentFile.hasContent()) {
+ return contentFile;
+ }
+ }
+
+ // try to find in parent path which contains content fragment
+ String parentPath = ResourceUtil.getParent(path);
+ if (parentPath == null) {
+ return null;
+ }
+ String nextSubPath = path.substring(parentPath.length() + 1)
+ + (subPath != null ? "/" + subPath : "");
+ return getContentFile(parentPath, nextSubPath);
+ }
+
+}
Propchange:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Mar 6 21:48:44 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author
Propchange:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/FileVaultResourceMapper.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNode.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNode.java?rev=1785772&r1=1785771&r2=1785772&view=diff
==============================================================================
---
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNode.java
(original)
+++
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNode.java
Mon Mar 6 21:48:44 2017
@@ -110,22 +110,22 @@ public final class FsNode extends FsItem
else {
subPath = path.substring(contentFile.getPath().length() + 1);
}
- ContentFile referencedFile = contentFile.navigateTo(subPath);
+ ContentFile referencedFile =
contentFile.navigateToAbsolute(subPath);
if (referencedFile.hasContent()) {
return new FsNode(referencedFile, resolver);
}
}
- else {
- // node is outside content file
- Node refNode = null;
- Resource resource = resolver.getResource(path);
- if (resource != null) {
- refNode = resource.adaptTo(Node.class);
- if (refNode != null) {
- return refNode;
- }
+
+ // check if node is outside content file
+ Node refNode = null;
+ Resource resource = resolver.getResource(path);
+ if (resource != null) {
+ refNode = resource.adaptTo(Node.class);
+ if (refNode != null) {
+ return refNode;
}
}
+
throw new PathNotFoundException(relPath);
}
Modified:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNodeIterator.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNodeIterator.java?rev=1785772&r1=1785771&r2=1785772&view=diff
==============================================================================
---
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNodeIterator.java
(original)
+++
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/mapper/jcr/FsNodeIterator.java
Mon Mar 6 21:48:44 2017
@@ -63,14 +63,7 @@ class FsNodeIterator implements NodeIter
@Override
public Node nextNode() {
Map.Entry<String,Map<String,Object>> nextEntry = children.next();
- String subPath;
- if (contentFile.getSubPath() == null) {
- subPath = nextEntry.getKey();
- }
- else {
- subPath = contentFile.getSubPath() + "/" + nextEntry.getKey();
- }
- return new FsNode(contentFile.navigateTo(subPath), resolver);
+ return new FsNode(contentFile.navigateToRelative(nextEntry.getKey()),
resolver);
}
Modified:
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtil.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtil.java?rev=1785772&r1=1785771&r2=1785772&view=diff
==============================================================================
---
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtil.java
(original)
+++
sling/branches/fsresource-1.1.x/src/main/java/org/apache/sling/fsprovider/internal/parser/ContentFileParserUtil.java
Mon Mar 6 21:48:44 2017
@@ -18,6 +18,7 @@
*/
package org.apache.sling.fsprovider.internal.parser;
+import static org.apache.jackrabbit.vault.util.Constants.DOT_CONTENT_XML;
import static
org.apache.sling.fsprovider.internal.parser.ContentFileTypes.JCR_XML_SUFFIX;
import static
org.apache.sling.fsprovider.internal.parser.ContentFileTypes.JSON_SUFFIX;
@@ -62,11 +63,14 @@ class ContentFileParserUtil {
* @return Content or null if content could not be parsed.
*/
public static Map<String,Object> parse(File file) {
+ if (!file.exists()) {
+ return null;
+ }
try {
if (StringUtils.endsWith(file.getName(), JSON_SUFFIX)) {
return JSON_PARSER.parse(file);
}
- else if (StringUtils.endsWith(file.getName(), JCR_XML_SUFFIX)) {
+ else if (StringUtils.equals(file.getName(), DOT_CONTENT_XML) ||
StringUtils.endsWith(file.getName(), JCR_XML_SUFFIX)) {
return JCR_XML_PARSER.parse(file);
}
}
Modified:
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileMonitorTest.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileMonitorTest.java?rev=1785772&r1=1785771&r2=1785772&view=diff
==============================================================================
---
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileMonitorTest.java
(original)
+++
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileMonitorTest.java
Mon Mar 6 21:48:44 2017
@@ -18,35 +18,39 @@
*/
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;
import java.io.File;
import java.nio.file.Files;
-import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.sling.api.SlingConstants;
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;
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.Event;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
/**
- * Test events when changing filesystem content.
+ * Test events when changing filesystem content (Sling-Initial-Content).
*/
public class FileMonitorTest {
+ private static final int CHECK_INTERVAL = 120;
+ private static final int WAIT_INTERVAL = 250;
+
private final File tempDir;
- private final EventAdminListener eventListener = new EventAdminListener();
+ private final ResourceListener resourceListener = new ResourceListener();
public FileMonitorTest() throws Exception {
tempDir = Files.createTempDirectory(getClass().getName()).toFile();
@@ -66,15 +70,16 @@ public class FileMonitorTest {
context.registerInjectActivateService(new FsResourceProvider(),
"provider.file", tempDir.getPath(),
"provider.roots", "/fs-test",
- "provider.checkinterval", 120,
- "provider.json.content", true);
+ "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(EventHandler.class, eventListener,
+ context.registerService(EventHandler.class, resourceListener,
EventConstants.EVENT_TOPIC, new String[] {
- SlingConstants.TOPIC_RESOURCE_ADDED,
- SlingConstants.TOPIC_RESOURCE_CHANGED,
- SlingConstants.TOPIC_RESOURCE_REMOVED
+ TOPIC_RESOURCE_ADDED,
+ TOPIC_RESOURCE_CHANGED,
+ TOPIC_RESOURCE_REMOVED
});
}
})
@@ -89,150 +94,122 @@ public class FileMonitorTest {
@Test
public void testUpdateFile() throws Exception {
- List<ResourceChange> changes = eventListener.getChanges();
+ List<ResourceChange> changes = resourceListener.getChanges();
assertTrue(changes.isEmpty());
File file1a = new File(tempDir, "folder1/file1a.txt");
FileUtils.touch(file1a);
- Thread.sleep(250);
+ Thread.sleep(WAIT_INTERVAL);
assertEquals(1, changes.size());
- assertChange(changes, "/fs-test/folder1/file1a.txt",
SlingConstants.TOPIC_RESOURCE_CHANGED);
+ assertChange(changes, "/fs-test/folder1/file1a.txt",
TOPIC_RESOURCE_CHANGED);
}
@Test
public void testAddFile() throws Exception {
- List<ResourceChange> changes = eventListener.getChanges();
+ List<ResourceChange> changes = resourceListener.getChanges();
assertTrue(changes.isEmpty());
File file1c = new File(tempDir, "folder1/file1c.txt");
FileUtils.write(file1c, "newcontent");
- Thread.sleep(250);
+ Thread.sleep(WAIT_INTERVAL);
assertEquals(2, changes.size());
- assertChange(changes, "/fs-test/folder1",
SlingConstants.TOPIC_RESOURCE_CHANGED);
- assertChange(changes, "/fs-test/folder1/file1c.txt",
SlingConstants.TOPIC_RESOURCE_ADDED);
+ assertChange(changes, "/fs-test/folder1", TOPIC_RESOURCE_CHANGED);
+ assertChange(changes, "/fs-test/folder1/file1c.txt",
TOPIC_RESOURCE_ADDED);
}
@Test
public void testRemoveFile() throws Exception {
- List<ResourceChange> changes = eventListener.getChanges();
+ List<ResourceChange> changes = resourceListener.getChanges();
assertTrue(changes.isEmpty());
File file1a = new File(tempDir, "folder1/file1a.txt");
file1a.delete();
- Thread.sleep(250);
+ Thread.sleep(WAIT_INTERVAL);
assertEquals(2, changes.size());
- assertChange(changes, "/fs-test/folder1",
SlingConstants.TOPIC_RESOURCE_CHANGED);
- assertChange(changes, "/fs-test/folder1/file1a.txt",
SlingConstants.TOPIC_RESOURCE_REMOVED);
+ assertChange(changes, "/fs-test/folder1", TOPIC_RESOURCE_CHANGED);
+ assertChange(changes, "/fs-test/folder1/file1a.txt",
TOPIC_RESOURCE_REMOVED);
}
@Test
public void testAddFolder() throws Exception {
- List<ResourceChange> changes = eventListener.getChanges();
+ List<ResourceChange> changes = resourceListener.getChanges();
assertTrue(changes.isEmpty());
File folder99 = new File(tempDir, "folder99");
folder99.mkdir();
- Thread.sleep(250);
+ Thread.sleep(WAIT_INTERVAL);
assertEquals(2, changes.size());
- assertChange(changes, "/fs-test",
SlingConstants.TOPIC_RESOURCE_CHANGED);
- assertChange(changes, "/fs-test/folder99",
SlingConstants.TOPIC_RESOURCE_ADDED);
+ assertChange(changes, "/fs-test", TOPIC_RESOURCE_CHANGED);
+ assertChange(changes, "/fs-test/folder99", TOPIC_RESOURCE_ADDED);
}
@Test
public void testRemoveFolder() throws Exception {
- List<ResourceChange> changes = eventListener.getChanges();
+ List<ResourceChange> changes = resourceListener.getChanges();
assertTrue(changes.isEmpty());
File folder1 = new File(tempDir, "folder1");
FileUtils.deleteDirectory(folder1);
- Thread.sleep(250);
+ Thread.sleep(WAIT_INTERVAL);
assertEquals(2, changes.size());
- assertChange(changes, "/fs-test",
SlingConstants.TOPIC_RESOURCE_CHANGED);
- assertChange(changes, "/fs-test/folder1",
SlingConstants.TOPIC_RESOURCE_REMOVED);
+ assertChange(changes, "/fs-test", TOPIC_RESOURCE_CHANGED);
+ assertChange(changes, "/fs-test/folder1", TOPIC_RESOURCE_REMOVED);
}
@Test
- public void testUpdateJsonContent() throws Exception {
- List<ResourceChange> changes = eventListener.getChanges();
+ public void testUpdateContent() throws Exception {
+ List<ResourceChange> changes = resourceListener.getChanges();
assertTrue(changes.isEmpty());
File file1a = new File(tempDir, "folder2/content.json");
FileUtils.touch(file1a);
- Thread.sleep(250);
+ Thread.sleep(WAIT_INTERVAL);
- assertTrue(changes.size() > 1);
- assertChange(changes, "/fs-test/folder2/content",
SlingConstants.TOPIC_RESOURCE_REMOVED);
- assertChange(changes, "/fs-test/folder2/content",
SlingConstants.TOPIC_RESOURCE_ADDED);
- assertChange(changes, "/fs-test/folder2/content/jcr:content",
SlingConstants.TOPIC_RESOURCE_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
- public void testAddJsonContent() throws Exception {
- List<ResourceChange> changes = eventListener.getChanges();
+ public void testAddContent() throws Exception {
+ List<ResourceChange> changes = resourceListener.getChanges();
assertTrue(changes.isEmpty());
File file1c = new File(tempDir, "folder1/file1c.json");
FileUtils.write(file1c,
"{\"prop1\":\"value1\",\"child1\":{\"prop2\":\"value1\"}}");
- Thread.sleep(250);
+ Thread.sleep(WAIT_INTERVAL);
assertEquals(3, changes.size());
- assertChange(changes, "/fs-test/folder1",
SlingConstants.TOPIC_RESOURCE_CHANGED);
- assertChange(changes, "/fs-test/folder1/file1c",
SlingConstants.TOPIC_RESOURCE_ADDED);
- assertChange(changes, "/fs-test/folder1/file1c/child1",
SlingConstants.TOPIC_RESOURCE_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
- public void testRemoveJsonContent() throws Exception {
- List<ResourceChange> changes = eventListener.getChanges();
+ public void testRemoveContent() throws Exception {
+ List<ResourceChange> changes = resourceListener.getChanges();
assertTrue(changes.isEmpty());
File file1a = new File(tempDir, "folder2/content.json");
file1a.delete();
- Thread.sleep(250);
+ Thread.sleep(WAIT_INTERVAL);
assertEquals(2, changes.size());
- assertChange(changes, "/fs-test/folder2",
SlingConstants.TOPIC_RESOURCE_CHANGED);
- assertChange(changes, "/fs-test/folder2/content",
SlingConstants.TOPIC_RESOURCE_REMOVED);
+ assertChange(changes, "/fs-test/folder2", TOPIC_RESOURCE_CHANGED);
+ assertChange(changes, "/fs-test/folder2/content",
TOPIC_RESOURCE_REMOVED);
}
-
- private void assertChange(List<ResourceChange> changes, String path,
String topic) {
- boolean found = false;
- for (ResourceChange change : changes) {
- if (StringUtils.equals(change.path, path) &&
StringUtils.equals(change.topic, topic)) {
- found = true;
- break;
- }
- }
- assertTrue("Change with path=" + path + ", topic=" + topic, found);
- }
-
- static class EventAdminListener implements EventHandler {
- private final List<ResourceChange> allChanges = new ArrayList<>();
- 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);
- }
- }
-
}
Added:
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileVaultContentTest.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileVaultContentTest.java?rev=1785772&view=auto
==============================================================================
---
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileVaultContentTest.java
(added)
+++
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileVaultContentTest.java
Mon Mar 6 21:48:44 2017
@@ -0,0 +1,143 @@
+/*
+ * 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.fsprovider.internal;
+
+import static org.apache.sling.fsprovider.internal.TestUtils.assertFile;
+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.assertThat;
+
+import java.util.List;
+
+import javax.jcr.Node;
+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;
+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.Rule;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Test access FileFault XML files, folders and content.
+ */
+public class FileVaultContentTest {
+
+ private Resource damAsset;
+ private Resource sampleContent;
+
+ @Rule
+ public SlingContext context = new
SlingContextBuilder(ResourceResolverType.JCR_MOCK)
+ .plugin(new RegisterFsResourcePlugin(
+ "provider.fs.mode", FsMode.FILEVAULT_XML.name(),
+ "provider.file", "src/test/resources/vaultfs-test",
+ "provider.roots", "/content/dam/talk.png"
+ ))
+ .plugin(new RegisterFsResourcePlugin(
+ "provider.fs.mode", FsMode.FILEVAULT_XML.name(),
+ "provider.file", "src/test/resources/vaultfs-test",
+ "provider.roots", "/content/samples"
+ ))
+ .build();
+
+ @Before
+ public void setUp() {
+ damAsset =
context.resourceResolver().getResource("/content/dam/talk.png");
+ sampleContent =
context.resourceResolver().getResource("/content/samples");
+ }
+
+ @Test
+ public void testDamAsset() {
+ assertNotNull(damAsset);
+ assertEquals("app:Asset", damAsset.getResourceType());
+
+ Resource content = damAsset.getChild("jcr:content");
+ assertNotNull(content);
+ assertEquals("app:AssetContent", content.getResourceType());
+
+ Resource metadata = content.getChild("metadata");
+ assertNotNull(metadata);
+ ValueMap props = ResourceUtil.getValueMap(metadata);
+ assertEquals((Integer)4, props.get("app:Bitsperpixel", Integer.class));
+
+ assertFolder(content, "renditions");
+ assertFile(content, "renditions/original", null);
+ assertFile(content, "renditions/web.1280.1280.png", null);
+ }
+
+ @Test
+ public void testSampleContent() {
+ assertNotNull(sampleContent);
+ assertEquals("sling:OrderedFolder", sampleContent.getResourceType());
+
+ Resource enContent = sampleContent.getChild("en/jcr:content");
+ assertArrayEquals(new String[] { "/etc/mobile/groups/responsive" },
ResourceUtil.getValueMap(enContent).get("app:deviceGroups", String[].class));
+ }
+
+ @Test
+ public void testListChildren() {
+ Resource en = sampleContent.getChild("en");
+ List<Resource> children = ImmutableList.copyOf(en.listChildren());
+ assertEquals(2, children.size());
+
+ Resource child1 = children.get(0);
+ assertEquals("jcr:content", child1.getName());
+ assertEquals("samples/sample-app/components/content/page/homepage",
child1.getResourceType());
+
+ Resource child2 = children.get(1);
+ assertEquals("tools", child2.getName());
+ assertEquals("app:Page", child2.getResourceType());
+
+ // child3 (conference) is hidden because of filter
+ }
+
+ @Test
+ public void testJcrMixedContent() throws RepositoryException {
+ // prepare mixed JCR content
+ Node root =
context.resourceResolver().adaptTo(Session.class).getNode("/");
+ Node content = root.addNode("content", "nt:folder");
+ Node samples = content.addNode("samples", "nt:folder");
+ Node en = samples.addNode("en", "nt:folder");
+ Node conference = en.addNode("conference", "nt:folder");
+ conference.addNode("page2", "nt:folder");
+ samples.addNode("it", "nt:folder");
+
+ // pass-through because of filter
+
assertNotNull(context.resourceResolver().getResource("/content/samples/en/conference"));
+ assertNotNull(sampleContent.getChild("en/conference"));
+
assertNotNull(context.resourceResolver().getResource("/content/samples/en/conference/page2"));
+ assertNotNull(sampleContent.getChild("en/conference/page2"));
+
+ // list children with mixed content
+ Resource enResource = sampleContent.getChild("en");
+ assertThat(enResource,
ResourceMatchers.containsChildren("jcr:content", "tools", "conference"));
+ }
+
+}
Propchange:
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileVaultContentTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileVaultContentTest.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Mon Mar 6 21:48:44 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author
Propchange:
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileVaultContentTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added:
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileVaultFileMonitorTest.java
URL:
http://svn.apache.org/viewvc/sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileVaultFileMonitorTest.java?rev=1785772&view=auto
==============================================================================
---
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileVaultFileMonitorTest.java
(added)
+++
sling/branches/fsresource-1.1.x/src/test/java/org/apache/sling/fsprovider/internal/FileVaultFileMonitorTest.java
Mon Mar 6 21:48:44 2017
@@ -0,0 +1,239 @@
+/*
+ * 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.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;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+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;
+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 filesystem content (FileVault XML).
+ */
+public class FileVaultFileMonitorTest {
+
+ private static final int CHECK_INTERVAL = 120;
+ private static final int WAIT_INTERVAL = 250;
+
+ private final File tempDir;
+ private final ResourceListener resourceListener = new ResourceListener();
+
+ public FileVaultFileMonitorTest() throws Exception {
+ tempDir = Files.createTempDirectory(getClass().getName()).toFile();
+ }
+
+ @Rule
+ public SlingContext context = new
SlingContextBuilder(ResourceResolverType.JCR_MOCK)
+ .beforeSetUp(new SlingContextCallback() {
+ @Override
+ public void execute(SlingContext context) throws Exception {
+ // copy test content to temp. directory
+ tempDir.mkdirs();
+ File sourceDir = new File("src/test/resources/vaultfs-test");
+ FileUtils.copyDirectory(sourceDir, tempDir);
+
+ // mount temp. directory
+ context.registerInjectActivateService(new FsResourceProvider(),
+ "provider.file", tempDir.getPath(),
+ "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(),
+ "provider.roots", "/content/samples",
+ "provider.checkinterval", CHECK_INTERVAL,
+ "provider.fs.mode", FsMode.FILEVAULT_XML.name());
+
+ // register resource change listener
+ context.registerService(EventHandler.class, resourceListener,
+ EventConstants.EVENT_TOPIC, new String[] {
+ TOPIC_RESOURCE_ADDED,
+ TOPIC_RESOURCE_CHANGED,
+ TOPIC_RESOURCE_REMOVED
+ });
+ }
+ })
+ .afterTearDown(new SlingContextCallback() {
+ @Override
+ public void execute(SlingContext context) throws Exception {
+ // remove temp directory
+ tempDir.delete();
+ }
+ })
+ .build();
+
+ @Test
+ public void testUpdateFile() throws Exception {
+ List<ResourceChange> changes = resourceListener.getChanges();
+ assertTrue(changes.isEmpty());
+
+ File file = new File(tempDir,
"jcr_root/content/dam/talk.png/_jcr_content/renditions/web.1280.1280.png");
+ FileUtils.touch(file);
+
+ Thread.sleep(WAIT_INTERVAL);
+
+ assertEquals(1, changes.size());
+ assertChange(changes,
"/content/dam/talk.png/jcr:content/renditions/web.1280.1280.png",
TOPIC_RESOURCE_CHANGED);
+ }
+
+ @Test
+ public void testAddFile() throws Exception {
+ List<ResourceChange> changes = resourceListener.getChanges();
+ assertTrue(changes.isEmpty());
+
+ File file = new File(tempDir,
"jcr_root/content/dam/talk.png/_jcr_content/renditions/text.txt");
+ FileUtils.write(file, "newcontent");
+
+ Thread.sleep(WAIT_INTERVAL);
+
+ assertEquals(2, changes.size());
+ 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
+ public void testRemoveFile() throws Exception {
+ List<ResourceChange> changes = resourceListener.getChanges();
+ assertTrue(changes.isEmpty());
+
+ File file = new File(tempDir,
"jcr_root/content/dam/talk.png/_jcr_content/renditions/web.1280.1280.png");
+ file.delete();
+
+ Thread.sleep(WAIT_INTERVAL);
+
+ assertEquals(2, changes.size());
+ 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
+ public void testAddFolder() throws Exception {
+ List<ResourceChange> changes = resourceListener.getChanges();
+ assertTrue(changes.isEmpty());
+
+ File folder = new File(tempDir,
"jcr_root/content/dam/talk.png/_jcr_content/newfolder");
+ folder.mkdir();
+
+ Thread.sleep(WAIT_INTERVAL);
+
+ assertEquals(2, changes.size());
+ assertChange(changes, "/content/dam/talk.png/jcr:content",
TOPIC_RESOURCE_CHANGED);
+ assertChange(changes, "/content/dam/talk.png/jcr:content/newfolder",
TOPIC_RESOURCE_ADDED);
+ }
+
+ @Test
+ public void testRemoveFolder() throws Exception {
+ List<ResourceChange> changes = resourceListener.getChanges();
+ assertTrue(changes.isEmpty());
+
+ File folder = new File(tempDir,
"jcr_root/content/dam/talk.png/_jcr_content/renditions");
+ FileUtils.deleteDirectory(folder);
+
+ Thread.sleep(WAIT_INTERVAL);
+
+ assertEquals(2, changes.size());
+ assertChange(changes, "/content/dam/talk.png/jcr:content",
TOPIC_RESOURCE_CHANGED);
+ assertChange(changes, "/content/dam/talk.png/jcr:content/renditions",
TOPIC_RESOURCE_REMOVED);
+ }
+
+ @Test
+ public void testUpdateContent() throws Exception {
+ List<ResourceChange> changes = resourceListener.getChanges();
+ assertTrue(changes.isEmpty());
+
+ File file = new File(tempDir,
"jcr_root/content/samples/en/.content.xml");
+ FileUtils.touch(file);
+
+ Thread.sleep(WAIT_INTERVAL);
+
+ 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
+ public void testAddContent() throws Exception {
+ List<ResourceChange> changes = resourceListener.getChanges();
+ assertTrue(changes.isEmpty());
+
+ File file = new File(tempDir,
"jcr_root/content/samples/fr/.content.xml");
+ file.getParentFile().mkdir();
+ FileUtils.write(file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ + "<jcr:root xmlns:jcr=\"http://www.jcp.org/jcr/1.0\"
xmlns:app=\"http://sample.com/jcr/app/1.0\" "
+ + "xmlns:sling=\"http://sling.apache.org/jcr/sling/1.0\"
jcr:primaryType=\"app:Page\">\n"
+ + "<jcr:content jcr:primaryType=\"app:PageContent\"/>\n"
+ + "</jcr:root>");
+
+ Thread.sleep(WAIT_INTERVAL);
+
+ 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
+ public void testRemoveContent() throws Exception {
+ List<ResourceChange> changes = resourceListener.getChanges();
+ assertTrue(changes.isEmpty());
+
+ File file = new File(tempDir, "jcr_root/content/samples/en");
+ FileUtils.deleteDirectory(file);
+
+ Thread.sleep(WAIT_INTERVAL);
+
+ assertEquals(2, changes.size());
+ assertChange(changes, "/content/samples", TOPIC_RESOURCE_CHANGED);
+ assertChange(changes, "/content/samples/en", TOPIC_RESOURCE_REMOVED);
+ }
+
+ @Test
+ public void testRemoveContentDotXmlOnly() throws Exception {
+ List<ResourceChange> changes = resourceListener.getChanges();
+ assertTrue(changes.isEmpty());
+
+ File file = new File(tempDir,
"jcr_root/content/samples/en/.content.xml");
+ file.delete();
+
+ Thread.sleep(WAIT_INTERVAL);
+
+ assertEquals(2, changes.size());
+ 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", TOPIC_RESOURCE_REMOVED);
+ }
+
+}