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

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

commit e17a9b8afd93a72f48fd6a4d47800985fce83d00
Author: Stefan Seifert <[email protected]>
AuthorDate: Wed Jul 12 16:46:23 2017 +0000

    SLING-7007 fsresource: Support URL-encoded file names
    
    git-svn-id: 
https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/fsresource@1801752
 13f79535-47bb-0310-9956-ffa450edef68
---
 .../internal/mapper/ContentFileResourceMapper.java |   2 +-
 .../sling/fsprovider/internal/mapper/Escape.java   | 104 +++++++++++++++++++++
 .../internal/mapper/FileResourceMapper.java        |   4 +-
 .../sling/fsprovider/internal/FilesFolderTest.java |   5 +-
 .../sling/fsprovider/internal/JcrMixedTest.java    |   4 +-
 .../fsprovider/internal/JcrXmlContentTest.java     |   4 +-
 .../sling/fsprovider/internal/JsonContentTest.java |  11 ++-
 .../sling/fsprovider/internal/TestUtils.java       |   4 +-
 .../fsprovider/internal/mapper/EscapeTest.java     |  46 +++++++++
 .../folder1/{file1b.txt => sling%3Afile1b.txt}     |   0
 .../{content2.json => sling%3Acontent2.json}       |   0
 11 files changed, 171 insertions(+), 13 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java
 
b/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java
index 20739d6..bbf2af6 100644
--- 
a/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java
+++ 
b/src/main/java/org/apache/sling/fsprovider/internal/mapper/ContentFileResourceMapper.java
@@ -131,7 +131,7 @@ public final class ContentFileResourceMapper implements 
FsResourceMapper {
         if (!StringUtils.startsWith(path, providerRootPrefix)) {
             return null;
         }
-        String relPath = path.substring(providerRootPrefix.length());
+        String relPath = 
Escape.resourceToFileName(path.substring(providerRootPrefix.length()));
         for (String filenameSuffix : contentFileExtensions.getSuffixes()) {
             File file = new File(providerFile, relPath + filenameSuffix);
             if (file.exists()) {
diff --git 
a/src/main/java/org/apache/sling/fsprovider/internal/mapper/Escape.java 
b/src/main/java/org/apache/sling/fsprovider/internal/mapper/Escape.java
new file mode 100644
index 0000000..b28280f
--- /dev/null
+++ b/src/main/java/org/apache/sling/fsprovider/internal/mapper/Escape.java
@@ -0,0 +1,104 @@
+/*
+ * 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 java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.BitSet;
+
+import org.apache.commons.lang3.CharEncoding;
+
+/**
+ * Manages deescaping for platform file names to resource names.
+ */
+public final class Escape {
+    
+    /**
+     * List of characters typically prohibited on unix and windows file 
systems.
+     * "/" is not included because it is neither allowed in resource nor in 
file names on any system. 
+     */
+    private static final char[] RESERVED_CHARS = {
+            '<',
+            '>',
+            ':',
+            '"',
+            '\\',
+            '|',
+            '?',
+            '*',
+            0x00
+    };
+    private static final BitSet RESERVED_CHARS_SET = new BitSet();
+    static {
+        for (int i=0; i<RESERVED_CHARS.length; i++) {
+            RESERVED_CHARS_SET.set(RESERVED_CHARS[i]);
+        }
+    }
+    
+    private Escape() {
+        // static methods only
+    }
+    
+    /**
+     * Convert file name to resource name.
+     * Applies same rules as Apache Sling JCR ContentLoader. 
+     * @param path File name or path
+     * @return Resource name or path
+     */
+    public static String fileToResourceName(String path) {
+        // check for encoded characters (%xx)
+        // has encoded characters, need to decode
+        if (path.indexOf('%') >= 0) {
+            try {
+                return URLDecoder.decode(path, "UTF-8");
+            }
+            catch (UnsupportedEncodingException ex) {
+                throw new RuntimeException("Unsupported encoding.", ex);
+            }
+        }
+        return path;
+    }
+    
+    /**
+     * Converts resource name to file name.
+     * Allows all characters, but URL-encodes characters that are in the list 
of {@link #RESERVED_CHARS}.
+     * @param name Resource name or path
+     * @return File name or path
+     */
+    public static String resourceToFileName(String path) {
+        try {
+            StringBuilder result = new StringBuilder();
+            for (int i=0; i<path.length(); i++) {
+                char c = path.charAt(i);
+                if (RESERVED_CHARS_SET.get(c)) {
+                    result.append(URLEncoder.encode(String.valueOf(c), 
CharEncoding.UTF_8));
+                }
+                else {
+                    result.append(c);
+                }
+            }
+            return result.toString();
+        }
+        catch (UnsupportedEncodingException ex) {
+            throw new RuntimeException("Unsupported encoding.", ex);
+        }
+    }
+
+}
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 ec9b650..e0a1429 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
@@ -118,7 +118,7 @@ public final class FileResourceMapper implements 
FsResourceMapper {
             @Override
             public Object transform(Object input) {
                 File file = (File)input;
-                String path = parentPath + "/" + file.getName();
+                String path = parentPath + "/" + 
Escape.fileToResourceName(file.getName());
                 return new FileResource(resolver, path, file, 
contentFileExtensions, contentFileCache);
             }
         });
@@ -137,7 +137,7 @@ public final class FileResourceMapper implements 
FsResourceMapper {
             return providerFile;
         }
         if (path.startsWith(providerRootPrefix)) {
-            String relPath = path.substring(providerRootPrefix.length());
+            String relPath = 
Escape.resourceToFileName(path.substring(providerRootPrefix.length()));
             File file = new File(providerFile, relPath);
             if (file.exists() && !contentFileExtensions.matchesSuffix(file)) {
                 return file;
diff --git 
a/src/test/java/org/apache/sling/fsprovider/internal/FilesFolderTest.java 
b/src/test/java/org/apache/sling/fsprovider/internal/FilesFolderTest.java
index c1f3470..7ebc089 100644
--- a/src/test/java/org/apache/sling/fsprovider/internal/FilesFolderTest.java
+++ b/src/test/java/org/apache/sling/fsprovider/internal/FilesFolderTest.java
@@ -63,10 +63,11 @@ public class FilesFolderTest {
     @Test
     public void testFiles() {
         assertFile(fsroot, "folder1/file1a.txt", "file1a");
-        assertFile(fsroot, "folder1/file1b.txt", "file1b");
+        assertFile(fsroot, "folder1/sling:file1b.txt", "file1b");
         assertFile(fsroot, "folder1/folder11/file11a.txt", "file11a");
         assertFile(fsroot, "folder2/content.json", null);
         assertFile(fsroot, "folder2/content/file2content.txt", "file2content");
+        assertFile(fsroot, "folder2/content/sling:content2.json", null);
         assertFile(fsroot, "folder3/content.jcr.xml", null);
     }
 
@@ -74,7 +75,7 @@ public class FilesFolderTest {
     public void testListChildren() {
         assertThat(root, ResourceMatchers.containsChildren("fs-test"));
         assertThat(fsroot, ResourceMatchers.hasChildren("folder1", "folder2", 
"folder3"));
-        assertThat(fsroot.getChild("folder1"), 
ResourceMatchers.hasChildren("folder11", "file1a.txt", "file1b.txt"));
+        assertThat(fsroot.getChild("folder1"), 
ResourceMatchers.hasChildren("folder11", "file1a.txt", "sling:file1b.txt"));
         assertThat(fsroot.getChild("folder2"), 
ResourceMatchers.hasChildren("folder21", "content.json"));
         
assertFalse(fsroot.getChild("folder1/file1a.txt").listChildren().hasNext());
     }
diff --git 
a/src/test/java/org/apache/sling/fsprovider/internal/JcrMixedTest.java 
b/src/test/java/org/apache/sling/fsprovider/internal/JcrMixedTest.java
index 9a220d9..b3e4d3b 100644
--- a/src/test/java/org/apache/sling/fsprovider/internal/JcrMixedTest.java
+++ b/src/test/java/org/apache/sling/fsprovider/internal/JcrMixedTest.java
@@ -82,7 +82,7 @@ public class JcrMixedTest {
     @Test
     public void testFiles() {
         assertFile(fsroot, "folder1/file1a.txt", "file1a");
-        assertFile(fsroot, "folder1/file1b.txt", "file1b");
+        assertFile(fsroot, "folder1/sling:file1b.txt", "file1b");
         assertFile(fsroot, "folder1/folder11/file11a.txt", "file11a");
         assertFile(fsroot, "folder2/content.json", null);
 
@@ -97,7 +97,7 @@ public class JcrMixedTest {
     public void testListChildren() {
         assertThat(root, ResourceMatchers.containsChildren("fs-test"));
         assertThat(fsroot, ResourceMatchers.hasChildren("folder1", "folder2", 
"folder99"));
-        assertThat(fsroot.getChild("folder1"), 
ResourceMatchers.hasChildren("file1a.txt", "file1b.txt", "file1c.txt"));
+        assertThat(fsroot.getChild("folder1"), 
ResourceMatchers.hasChildren("file1a.txt", "sling:file1b.txt", "file1c.txt"));
     }
 
 }
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 cece206..1b8e2a9 100644
--- a/src/test/java/org/apache/sling/fsprovider/internal/JcrXmlContentTest.java
+++ b/src/test/java/org/apache/sling/fsprovider/internal/JcrXmlContentTest.java
@@ -79,7 +79,7 @@ public class JcrXmlContentTest {
     @Test
     public void testFiles() {
         assertFile(fsroot, "folder1/file1a.txt", "file1a");
-        assertFile(fsroot, "folder1/file1b.txt", "file1b");
+        assertFile(fsroot, "folder1/sling:file1b.txt", "file1b");
         assertFile(fsroot, "folder1/folder11/file11a.txt", "file11a");
         assertFile(fsroot, "folder2/content.json", null);
         assertNull(fsroot.getChild("folder3/content.jcr.xml"));
@@ -89,7 +89,7 @@ public class JcrXmlContentTest {
     public void testListChildren() {
         assertThat(root, ResourceMatchers.containsChildren("fs-test"));
         assertThat(fsroot, ResourceMatchers.hasChildren("folder1", "folder2"));
-        assertThat(fsroot.getChild("folder1"), 
ResourceMatchers.hasChildren("folder11", "file1a.txt", "file1b.txt"));
+        assertThat(fsroot.getChild("folder1"), 
ResourceMatchers.hasChildren("folder11", "file1a.txt", "sling:file1b.txt"));
         assertThat(fsroot.getChild("folder2"), 
ResourceMatchers.hasChildren("folder21", "content"));
     }
 
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 4fb6a32..eb4276e 100644
--- a/src/test/java/org/apache/sling/fsprovider/internal/JsonContentTest.java
+++ b/src/test/java/org/apache/sling/fsprovider/internal/JsonContentTest.java
@@ -89,7 +89,7 @@ public class JsonContentTest {
     @Test
     public void testFiles() {
         assertFile(fsroot, "folder1/file1a.txt", "file1a");
-        assertFile(fsroot, "folder1/file1b.txt", "file1b");
+        assertFile(fsroot, "folder1/sling:file1b.txt", "file1b");
         assertFile(fsroot, "folder1/folder11/file11a.txt", "file11a");
         assertNull(fsroot.getChild("folder2/content.json"));
         assertFile(fsroot, "folder2/content/file2content.txt", "file2content");
@@ -100,7 +100,7 @@ public class JsonContentTest {
     public void testListChildren() {
         assertThat(root, ResourceMatchers.containsChildren("fs-test"));
         assertThat(fsroot, ResourceMatchers.hasChildren("folder1", "folder2"));
-        assertThat(fsroot.getChild("folder1"), 
ResourceMatchers.hasChildren("folder11", "file1a.txt", "file1b.txt"));
+        assertThat(fsroot.getChild("folder1"), 
ResourceMatchers.hasChildren("folder11", "file1a.txt", "sling:file1b.txt"));
         assertThat(fsroot.getChild("folder2"), 
ResourceMatchers.hasChildren("folder21", "content"));
     }
 
@@ -282,4 +282,11 @@ public class JsonContentTest {
         assertEquals("en", node.getProperty("jcr:language").getString());
     }
 
+    @Test
+    public void testContent2() throws RepositoryException {
+        Resource content2 = fsroot.getChild("folder2/content/sling:content2");
+        assertNotNull(content2);
+        assertEquals("app:Page", content2.getResourceType());
+    }
+
 }
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 edfbc68..5539a40 100644
--- a/src/test/java/org/apache/sling/fsprovider/internal/TestUtils.java
+++ b/src/test/java/org/apache/sling/fsprovider/internal/TestUtils.java
@@ -40,6 +40,7 @@ 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.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;
@@ -84,8 +85,7 @@ class TestUtils {
         assertEquals("nt:file", file.getResourceType());
         
         assertNull(file.getResourceSuperType());
-        assertEquals(file.getName(), file.adaptTo(File.class).getName());
-        assertTrue(StringUtils.contains(file.adaptTo(URL.class).toString(), 
file.getName()));
+        assertEquals(file.getName(), 
Escape.fileToResourceName(file.adaptTo(File.class).getName()));
         
         if (content != null) {
             try {
diff --git 
a/src/test/java/org/apache/sling/fsprovider/internal/mapper/EscapeTest.java 
b/src/test/java/org/apache/sling/fsprovider/internal/mapper/EscapeTest.java
new file mode 100644
index 0000000..a44bda4
--- /dev/null
+++ b/src/test/java/org/apache/sling/fsprovider/internal/mapper/EscapeTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class EscapeTest {
+
+    @Test
+    public void testFileToResourceName() {
+        assertEquals("abc", Escape.fileToResourceName("abc"));
+        assertEquals("abc.txt", Escape.fileToResourceName("abc.txt"));
+        assertEquals("xyz:abc.txt", 
Escape.fileToResourceName("xyz%3Aabc.txt"));
+        assertEquals("a<>:\"/\\|?*b", 
Escape.fileToResourceName("a%3C%3E%3A%22/%5C%7C%3F%2Ab"));
+        assertEquals("", Escape.fileToResourceName(""));
+    }
+
+    @Test
+    public void testResourceToFileName() {
+        assertEquals("abc", Escape.resourceToFileName("abc"));
+        assertEquals("abc.txt", Escape.resourceToFileName("abc.txt"));
+        assertEquals("xyz%3Aabc.txt", 
Escape.resourceToFileName("xyz:abc.txt"));
+        // URLEncoder does not encode '*'
+        assertEquals("a%3C%3E%3A%22/%5C%7C%3F*b", 
Escape.resourceToFileName("a<>:\"/\\|?*b"));
+        assertEquals("", Escape.resourceToFileName(""));
+    }
+
+}
diff --git a/src/test/resources/fs-test/folder1/file1b.txt 
b/src/test/resources/fs-test/folder1/sling%3Afile1b.txt
similarity index 100%
rename from src/test/resources/fs-test/folder1/file1b.txt
rename to src/test/resources/fs-test/folder1/sling%3Afile1b.txt
diff --git a/src/test/resources/fs-test/folder2/content/content2.json 
b/src/test/resources/fs-test/folder2/content/sling%3Acontent2.json
similarity index 100%
rename from src/test/resources/fs-test/folder2/content/content2.json
rename to src/test/resources/fs-test/folder2/content/sling%3Acontent2.json

-- 
To stop receiving notification emails like this one, please contact
"[email protected]" <[email protected]>.

Reply via email to