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

nfsantos pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git


The following commit(s) were added to refs/heads/trunk by this push:
     new e9bb5933ad OAK-10590 - If includedPaths and excludedPaths are 
specified as a String instead of array of String, interpret them as a 
one-element array of Strings (#1254)
e9bb5933ad is described below

commit e9bb5933ad3db01ad4c60e9c77d1d83d9f8e4eb7
Author: Nuno Santos <nsan...@adobe.com>
AuthorDate: Thu Dec 21 17:32:14 2023 +0000

    OAK-10590 - If includedPaths and excludedPaths are specified as a String 
instead of array of String, interpret them as a one-element array of Strings 
(#1254)
---
 .../index/progress/NodeCounterMBeanEstimator.java  |   8 +-
 .../index/importer/JsonDeserializationTest.java    |   7 +-
 .../oak/composite/CompositeNodeStoreQueryTest.java |  15 +-
 .../oak/composite/blueGreen/IndexUtils.java        |   3 +-
 .../pipelined/PipelinedMongoDownloadTask.java      |   2 +-
 .../oak/plugins/index/FunctionIndexCommonTest.java |   7 +-
 .../plugins/index/search/IndexDefinitionTest.java  | 163 +++++++++++----------
 .../secondary/SecondaryStoreCacheServiceTest.java  |   2 +-
 .../jackrabbit/oak/spi/filter/PathFilter.java      |  62 ++++----
 .../jackrabbit/oak/spi/filter/PathFilterTest.java  |  92 +++++++++---
 10 files changed, 213 insertions(+), 148 deletions(-)

diff --git 
a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/progress/NodeCounterMBeanEstimator.java
 
b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/progress/NodeCounterMBeanEstimator.java
index 54927f740d..a3d4706117 100644
--- 
a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/progress/NodeCounterMBeanEstimator.java
+++ 
b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/progress/NodeCounterMBeanEstimator.java
@@ -25,6 +25,7 @@ import java.util.Set;
 import org.apache.jackrabbit.guava.common.collect.Iterables;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.plugins.index.counter.jmx.NodeCounter;
+import org.apache.jackrabbit.oak.spi.filter.PathFilter;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
@@ -86,14 +87,13 @@ public class NodeCounterMBeanEstimator implements 
NodeCountEstimator {
                 NodeState idxState = NodeStateUtils.getNode(root, indexPath);
 
                 //No include exclude specified so include all
-                if (!idxState.hasProperty(PROP_INCLUDED_PATHS)
-                        && !idxState.hasProperty(PROP_EXCLUDED_PATHS)) {
+                if (!idxState.hasProperty(PROP_INCLUDED_PATHS) && 
!idxState.hasProperty(PROP_EXCLUDED_PATHS)) {
                     includeAll = true;
                     return;
                 }
 
-                Iterables.addAll(includes, 
idxState.getStrings(PROP_INCLUDED_PATHS));
-                Iterables.addAll(excludes, 
idxState.getStrings(PROP_EXCLUDED_PATHS));
+                Iterables.addAll(includes, 
PathFilter.getStrings(idxState.getProperty(PROP_INCLUDED_PATHS), Set.of()));
+                Iterables.addAll(excludes, 
PathFilter.getStrings(idxState.getProperty(PROP_EXCLUDED_PATHS), Set.of()));
             }
 
             if (includes.isEmpty()) {
diff --git 
a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/JsonDeserializationTest.java
 
b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/JsonDeserializationTest.java
index e3715bb963..e92c071798 100644
--- 
a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/JsonDeserializationTest.java
+++ 
b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/importer/JsonDeserializationTest.java
@@ -29,6 +29,7 @@ import org.apache.jackrabbit.oak.json.BlobSerializer;
 import org.apache.jackrabbit.oak.json.JsonDeserializer;
 import org.apache.jackrabbit.oak.json.JsonSerializer;
 import org.apache.jackrabbit.oak.plugins.tree.factories.TreeFactory;
+import org.apache.jackrabbit.oak.spi.filter.PathFilter;
 import org.apache.jackrabbit.oak.spi.state.EqualsDiff;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -40,7 +41,7 @@ import static org.junit.Assert.assertTrue;
 public class JsonDeserializationTest {
 
     @Test
-    public void deserialize() throws Exception{
+    public void deserialize() {
         String json = "{\n" +
                 "    \"evaluatePathRestrictions\": true,\n" +
                 "    \"compatVersion\": 2,\n" +
@@ -86,8 +87,8 @@ public class JsonDeserializationTest {
         tree.setProperty("evaluatePathRestrictions", true);
         tree.setProperty("compatVersion", 2);
         tree.setProperty("type", "lucene");
-        tree.setProperty("includedPaths", 
Collections.singletonList("/content"), Type.STRINGS);
-        tree.setProperty("excludedPaths", 
Collections.singletonList("/jcr:system"), Type.STRINGS);
+        tree.setProperty(PathFilter.PROP_INCLUDED_PATHS, 
Collections.singletonList("/content"), Type.STRINGS);
+        tree.setProperty(PathFilter.PROP_EXCLUDED_PATHS, 
Collections.singletonList("/jcr:system"), Type.STRINGS);
         tree.setProperty("async", "async");
         tree.setProperty("jcr:primaryType", "oak:QueryIndexDefinition", 
Type.NAME);
 
diff --git 
a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreQueryTest.java
 
b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreQueryTest.java
index 4f65eab8d9..b673d64bd2 100644
--- 
a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreQueryTest.java
+++ 
b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/CompositeNodeStoreQueryTest.java
@@ -28,8 +28,8 @@ import static 
org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_COU
 import static 
org.apache.jackrabbit.oak.plugins.index.IndexUtils.createIndexDefinition;
 import static 
org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
 import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
 
 import javax.jcr.query.Query;
 
@@ -51,8 +51,8 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
-import org.apache.jackrabbit.guava.common.collect.ImmutableSet;
-import org.apache.jackrabbit.guava.common.collect.Lists;
+import java.util.List;
+import java.util.Set;
 
 /**
  * Tests indexing and queries when using the composite node store.
@@ -70,12 +70,10 @@ public class CompositeNodeStoreQueryTest extends 
CompositeNodeStoreQueryTestBase
         NodeBuilder b;
         NodeBuilder readOnlyBuilder = readOnlyStore.getRoot().builder();
         b = 
createIndexDefinition(readOnlyBuilder.child(INDEX_DEFINITIONS_NAME), "foo",
-                true, false, ImmutableSet.of("foo"), null);
-        b.setProperty("excludedPaths", "/jcr:system");
+                true, false, Set.of("foo"), null);
         NodeBuilder globalBuilder = globalStore.getRoot().builder();
         b = createIndexDefinition(globalBuilder.child(INDEX_DEFINITIONS_NAME), 
"foo",
-                true, false, ImmutableSet.of("foo"), null);
-        b.setProperty("excludedPaths", "/jcr:system");
+                true, false, Set.of("foo"), null);
         EditorHook hook = new EditorHook(
                 new IndexUpdateProvider(new 
PropertyIndexEditorProvider().with(mip)));
         readOnlyStore.merge(readOnlyBuilder, hook, CommitInfo.EMPTY);
@@ -184,8 +182,7 @@ public class CompositeNodeStoreQueryTest extends 
CompositeNodeStoreQueryTestBase
         b.setProperty(TYPE_PROPERTY_NAME, LuceneIndexConstants.TYPE_LUCENE);
         b.setProperty(FulltextIndexConstants.COMPAT_MODE, 
IndexFormatVersion.V2.getVersion());
         b.setProperty(IndexConstants.ASYNC_PROPERTY_NAME,
-                Lists.newArrayList("async", "nrt"), Type.STRINGS);
-        b.setProperty("excludedPaths", "/jcr:system");
+                List.of("async", "nrt"), Type.STRINGS);
         NodeBuilder foo = b.child(FulltextIndexConstants.INDEX_RULES)
                 .child("nt:base")
                 .child(FulltextIndexConstants.PROP_NODE)
diff --git 
a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/blueGreen/IndexUtils.java
 
b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/blueGreen/IndexUtils.java
index cc4fec24dc..2bbdcc2159 100644
--- 
a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/blueGreen/IndexUtils.java
+++ 
b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/composite/blueGreen/IndexUtils.java
@@ -70,7 +70,7 @@ public class IndexUtils {
         index.setProperty(IndexConstants.ASYNC_PROPERTY_NAME,
                 new String[] { "async", "nrt" });
         index.setProperty(FulltextIndexConstants.COST_PER_EXECUTION, cost);
-        // index.setProperty("excludedPaths", "/jcr:system");
+//        index.setProperty(PathFilter.PROP_EXCLUDED_PATHS, "/jcr:system");
         Node indexRules = index.addNode(FulltextIndexConstants.INDEX_RULES);
         Node ntBase = indexRules.addNode("nt:base");
         Node props = ntBase.addNode(FulltextIndexConstants.PROP_NODE);
@@ -99,7 +99,6 @@ public class IndexUtils {
      * @param xpath the xpath query
      * @param expectedIndex the index that is expected to be used
      * @param expectedResult the expected list of results
-     * @return the index name used
      */
     public static void assertQueryUsesIndexAndReturns(Persistence p, String 
xpath, String expectedIndex,
             String expectedResult) throws RepositoryException {
diff --git 
a/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/index/indexer/document/flatfile/pipelined/PipelinedMongoDownloadTask.java
 
b/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/index/indexer/document/flatfile/pipelined/PipelinedMongoDownloadTask.java
index 00c5c8f792..a490d5a7a9 100644
--- 
a/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/index/indexer/document/flatfile/pipelined/PipelinedMongoDownloadTask.java
+++ 
b/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/index/indexer/document/flatfile/pipelined/PipelinedMongoDownloadTask.java
@@ -404,7 +404,7 @@ public class PipelinedMongoDownloadTask implements 
Callable<PipelinedMongoDownlo
             return Set.of();
         }
 
-        // Keep only unique include paths. That is, if paths "/a/b" and 
"/a/b/c" are both in the list, keep only "/a/b"
+        // Keep only unique included paths. That is, if paths "/a/b" and 
"/a/b/c" are both in the list, keep only "/a/b"
         HashSet<String> includedPathsRoots = new HashSet<>();
         for (String path : sortedIncludedPaths) {
             if (includedPathsRoots.stream().noneMatch(ancestor -> 
PathUtils.isAncestor(ancestor, path))) {
diff --git 
a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FunctionIndexCommonTest.java
 
b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FunctionIndexCommonTest.java
index 9ee0980d46..02486a597f 100644
--- 
a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FunctionIndexCommonTest.java
+++ 
b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/FunctionIndexCommonTest.java
@@ -42,6 +42,7 @@ import org.apache.jackrabbit.oak.commons.junit.LogCustomizer;
 import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants;
 import 
org.apache.jackrabbit.oak.plugins.index.search.util.IndexDefinitionBuilder;
 import org.apache.jackrabbit.oak.query.AbstractQueryTest;
+import org.apache.jackrabbit.oak.spi.filter.PathFilter;
 import org.junit.Assert;
 import org.junit.Test;
 import org.slf4j.event.Level;
@@ -91,7 +92,7 @@ public abstract class FunctionIndexCommonTest extends 
AbstractQueryTest {
     @Test
     public void lowerCaseLocalName() throws Exception {
         Tree luceneIndex = createIndex("lowerLocalName", 
Collections.emptySet());
-        luceneIndex.setProperty("excludedPaths",
+        luceneIndex.setProperty(PathFilter.PROP_EXCLUDED_PATHS,
                 List.of("/jcr:system", "/oak:index"), Type.STRINGS);
         Tree func = luceneIndex.addChild(FulltextIndexConstants.INDEX_RULES)
                 .addChild("nt:base")
@@ -130,7 +131,7 @@ public abstract class FunctionIndexCommonTest extends 
AbstractQueryTest {
     @Test
     public void lengthName() throws Exception {
         Tree luceneIndex = createIndex("lengthName", Collections.emptySet());
-        luceneIndex.setProperty("excludedPaths",
+        luceneIndex.setProperty(PathFilter.PROP_EXCLUDED_PATHS,
                 List.of("/jcr:system", "/oak:index"), Type.STRINGS);
         Tree func = luceneIndex.addChild(FulltextIndexConstants.INDEX_RULES)
                 .addChild("nt:base")
@@ -165,7 +166,7 @@ public abstract class FunctionIndexCommonTest extends 
AbstractQueryTest {
     @Test
     public void length() throws Exception {
         Tree luceneIndex = createIndex("length", Collections.emptySet());
-        luceneIndex.setProperty("excludedPaths", List.of("/jcr:system", 
"/oak:index"), Type.STRINGS);
+        luceneIndex.setProperty(PathFilter.PROP_EXCLUDED_PATHS, 
List.of("/jcr:system", "/oak:index"), Type.STRINGS);
         Tree func = luceneIndex.addChild(FulltextIndexConstants.INDEX_RULES)
                 .addChild("nt:base")
                 .addChild(FulltextIndexConstants.PROP_NODE)
diff --git 
a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinitionTest.java
 
b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinitionTest.java
index 844f368b72..da17840564 100644
--- 
a/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinitionTest.java
+++ 
b/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinitionTest.java
@@ -21,10 +21,10 @@ package org.apache.jackrabbit.oak.plugins.index.search;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 import javax.jcr.PropertyType;
 
-import org.apache.jackrabbit.guava.common.collect.ImmutableList;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
@@ -35,12 +35,12 @@ import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.junit.Test;
 
-import static org.apache.jackrabbit.guava.common.collect.ImmutableSet.of;
 import static javax.jcr.PropertyType.TYPENAME_LONG;
 import static javax.jcr.PropertyType.TYPENAME_STRING;
 import static org.apache.jackrabbit.JcrConstants.NT_BASE;
 import static org.apache.jackrabbit.oak.InitialContentHelper.INITIAL_CONTENT;
 import static org.apache.jackrabbit.oak.api.Type.NAMES;
+import static org.apache.jackrabbit.oak.api.Type.STRING;
 import static org.apache.jackrabbit.oak.api.Type.STRINGS;
 import static 
org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
 import static 
org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.INCLUDE_PROPERTY_NAMES;
@@ -55,6 +55,7 @@ import static 
org.apache.jackrabbit.oak.plugins.index.search.util.IndexHelper.ne
 import static 
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
 import static 
org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
 import static 
org.apache.jackrabbit.oak.plugins.tree.TreeConstants.OAK_CHILD_ORDER;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.empty;
 import static org.hamcrest.Matchers.is;
@@ -62,7 +63,6 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
 public class IndexDefinitionTest {
@@ -72,13 +72,13 @@ public class IndexDefinitionTest {
     private final NodeBuilder builder = root.builder();
 
     @Test
-    public void defaultConfig() throws Exception{
+    public void defaultConfig() {
         IndexDefinition idxDefn = new IndexDefinition(root, 
builder.getNodeState(), "/foo");
         assertFalse(idxDefn.hasSyncPropertyDefinitions());
     }
 
     @Test
-    public void fullTextEnabled() throws Exception{
+    public void fullTextEnabled() {
         IndexDefinition idxDefn = new IndexDefinition(root, 
builder.getNodeState(), "/foo");
         IndexDefinition.IndexingRule rule = 
idxDefn.getApplicableIndexingRule(NT_BASE);
         assertTrue("By default fulltext is enabled", 
idxDefn.isFullTextEnabled());
@@ -91,9 +91,9 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void propertyTypes() throws Exception{
-        builder.setProperty(createProperty(INCLUDE_PROPERTY_TYPES, 
of(TYPENAME_LONG), STRINGS));
-        builder.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo" , 
"bar"), STRINGS));
+    public void propertyTypes() throws Exception {
+        builder.setProperty(createProperty(INCLUDE_PROPERTY_TYPES, 
Set.of(TYPENAME_LONG), STRINGS));
+        builder.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, 
Set.of("foo", "bar"), STRINGS));
         builder.setProperty(FulltextIndexConstants.FULL_TEXT_ENABLED, false);
         IndexDefinition idxDefn = new IndexDefinition(root, 
builder.getNodeState(), "/foo");
         IndexDefinition.IndexingRule rule = 
idxDefn.getApplicableIndexingRule(NT_BASE);
@@ -110,10 +110,18 @@ public class IndexDefinitionTest {
         assertTrue(rule.getConfig("foo").skipTokenization("foo"));
     }
 
+
+    @Test
+    public void queryPathsAsString() {
+        builder.setProperty(createProperty(IndexConstants.QUERY_PATHS, 
"/foo/bar", STRING));
+        IndexDefinition idxDefn = new IndexDefinition(root, 
builder.getNodeState(), "/foo");
+        assertEquals(new String[]{"/foo/bar"}, idxDefn.getQueryPaths());
+    }
+
     @Test
-    public void propertyDefinition() throws Exception{
+    public void propertyDefinition() {
         
builder.child(PROP_NODE).child("foo").setProperty(FulltextIndexConstants.PROP_TYPE,
 PropertyType.TYPENAME_DATE);
-        builder.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, of("foo" , 
"bar"), STRINGS));
+        builder.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, 
Set.of("foo", "bar"), STRINGS));
         IndexDefinition idxDefn = new IndexDefinition(root, 
builder.getNodeState(), "/foo");
         IndexDefinition.IndexingRule rule = 
idxDefn.getApplicableIndexingRule(NT_BASE);
 
@@ -124,7 +132,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void propertyDefinitionWithExcludes() throws Exception{
+    public void propertyDefinitionWithExcludes() {
         
builder.child(PROP_NODE).child("foo").setProperty(FulltextIndexConstants.PROP_TYPE,
 PropertyType.TYPENAME_DATE);
         IndexDefinition idxDefn = new IndexDefinition(root, 
builder.getNodeState(), "/foo");
         IndexDefinition.IndexingRule rule = 
idxDefn.getApplicableIndexingRule(NT_BASE);
@@ -135,7 +143,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void indexRuleSanity() throws Exception{
+    public void indexRuleSanity() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         
rules.child("nt:folder").setProperty(FulltextIndexConstants.FIELD_BOOST, 2.0);
         TestUtil.child(rules, "nt:folder/properties/prop1")
@@ -159,7 +167,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void indexRuleInheritance() throws Exception{
+    public void indexRuleInheritance() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         builder.setProperty(PROP_NAME, "testIndex");
         
rules.child("nt:hierarchyNode").setProperty(FulltextIndexConstants.FIELD_BOOST, 
2.0);
@@ -172,7 +180,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void indexRuleMixin() throws Exception{
+    public void indexRuleMixin() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("mix:title");
         TestUtil.child(rules, "mix:title/properties/jcr:title")
@@ -185,7 +193,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void indexRuleMixinInheritance() throws Exception{
+    public void indexRuleMixinInheritance() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("mix:mimeType");
         TestUtil.child(rules, "mix:mimeType/properties/jcr:mimeType")
@@ -201,7 +209,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void indexRuleInheritanceDisabled() throws Exception{
+    public void indexRuleInheritanceDisabled() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         builder.setProperty(PROP_NAME, "testIndex");
         rules.child("nt:hierarchyNode")
@@ -217,9 +225,9 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void indexRuleInheritanceOrdering() throws Exception{
+    public void indexRuleInheritanceOrdering() {
         NodeBuilder rules = builder.child(INDEX_RULES);
-        rules.setProperty(OAK_CHILD_ORDER, 
ImmutableList.of("nt:hierarchyNode", "nt:base"),NAMES);
+        rules.setProperty(OAK_CHILD_ORDER, List.of("nt:hierarchyNode", 
"nt:base"), NAMES);
         
rules.child("nt:hierarchyNode").setProperty(FulltextIndexConstants.FIELD_BOOST, 
2.0);
         rules.child("nt:base").setProperty(FulltextIndexConstants.FIELD_BOOST, 
3.0);
 
@@ -229,10 +237,11 @@ public class IndexDefinitionTest {
         assertEquals(2.0, getRule(defn, "nt:hierarchyNode").boost, 0);
         assertEquals(3.0, getRule(defn, "nt:query").boost, 0);
     }
+
     @Test
-    public void indexRuleInheritanceOrdering2() throws Exception{
+    public void indexRuleInheritanceOrdering2() {
         NodeBuilder rules = builder.child(INDEX_RULES);
-        rules.setProperty(OAK_CHILD_ORDER, ImmutableList.of("nt:base", 
"nt:hierarchyNode"),NAMES);
+        rules.setProperty(OAK_CHILD_ORDER, List.of("nt:base", 
"nt:hierarchyNode"), NAMES);
         
rules.child("nt:hierarchyNode").setProperty(FulltextIndexConstants.FIELD_BOOST, 
2.0);
         rules.child("nt:base").setProperty(FulltextIndexConstants.FIELD_BOOST, 
3.0);
 
@@ -245,7 +254,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void indexRuleWithPropertyRegEx() throws Exception{
+    public void indexRuleWithPropertyRegEx() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("nt:folder");
         TestUtil.child(rules, "nt:folder/properties/prop1")
@@ -269,7 +278,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void indexRuleWithPropertyRegEx2() throws Exception{
+    public void indexRuleWithPropertyRegEx2() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("nt:folder");
         TestUtil.child(rules, "nt:folder/properties/prop1")
@@ -295,7 +304,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void indexRuleWithPropertyOrdering() throws Exception{
+    public void indexRuleWithPropertyOrdering() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("nt:folder");
         TestUtil.child(rules, "nt:folder/properties/prop1")
@@ -307,7 +316,7 @@ public class IndexDefinitionTest {
                 .setProperty(FulltextIndexConstants.PROP_IS_REGEX, true)
                 .setProperty(FulltextIndexConstants.FIELD_BOOST, 4.0);
 
-        rules.child("nt:folder").child(PROP_NODE).setProperty(OAK_CHILD_ORDER, 
ImmutableList.of("prop2", "prop1"), NAMES);
+        rules.child("nt:folder").child(PROP_NODE).setProperty(OAK_CHILD_ORDER, 
List.of("prop2", "prop1"), NAMES);
 
         IndexDefinition defn = new IndexDefinition(root, 
builder.getNodeState(), "/foo");
 
@@ -323,14 +332,14 @@ public class IndexDefinitionTest {
         assertEquals(4.0f, rule1.getConfig("fooProp").boost, 0);
 
         //Order it correctly to get expected result
-        rules.child("nt:folder").child(PROP_NODE).setProperty(OAK_CHILD_ORDER, 
ImmutableList.of("prop1", "prop2"), NAMES);
+        rules.child("nt:folder").child(PROP_NODE).setProperty(OAK_CHILD_ORDER, 
List.of("prop1", "prop2"), NAMES);
         defn = new IndexDefinition(root, builder.getNodeState(), "/foo");
         rule1 = defn.getApplicableIndexingRule(asState(newNode("nt:folder")));
         assertEquals(3.0f, rule1.getConfig("fooProp").boost, 0);
     }
 
     @Test
-    public void propertyConfigCaseInsensitive() throws Exception{
+    public void propertyConfigCaseInsensitive() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("nt:folder");
         TestUtil.child(rules, "nt:folder/properties/foo")
@@ -353,7 +362,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void skipTokenization() throws Exception{
+    public void skipTokenization() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("nt:folder");
         TestUtil.child(rules, "nt:folder/properties/prop2")
@@ -369,9 +378,9 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void formatUpdate() throws Exception{
+    public void formatUpdate() {
         NodeBuilder defnb = 
newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
-                "lucene", of(TYPENAME_STRING), of("foo", "Bar"), "async");
+                "lucene", Set.of(TYPENAME_STRING), Set.of("foo", "Bar"), 
"async");
         IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), 
"/foo");
         assertTrue(defn.isOfOldFormat());
 
@@ -386,9 +395,9 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void propertyRegExAndRelativeProperty() throws Exception{
+    public void propertyRegExAndRelativeProperty() {
         NodeBuilder defnb = 
newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
-                "lucene", of(TYPENAME_STRING), of("foo"), "async");
+                "lucene", Set.of(TYPENAME_STRING), Set.of("foo"), "async");
         IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), 
"/foo");
         assertTrue(defn.isOfOldFormat());
 
@@ -401,9 +410,9 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void fulltextEnabledAndAggregate() throws Exception{
+    public void fulltextEnabledAndAggregate() {
         NodeBuilder defnb = 
newFTPropertyIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
-                "lucene", of("foo"), "async");
+                "lucene", Set.of("foo"), "async");
         IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), 
"/foo");
         assertFalse(defn.isFullTextEnabled());
 
@@ -416,9 +425,9 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void costConfig() throws Exception {
+    public void costConfig() {
         NodeBuilder defnb = 
newFTPropertyIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
-                "lucene", of("foo"), "async");
+                "lucene", Set.of("foo"), "async");
         IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), 
"/foo");
         assertEquals(1.0, defn.getCostPerEntry(), 0);
         assertEquals(1.0, defn.getCostPerExecution(), 0);
@@ -436,9 +445,9 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void fulltextCost() throws Exception{
+    public void fulltextCost() {
         NodeBuilder defnb = 
newFTPropertyIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
-                "lucene", of("foo"), "async");
+                "lucene", Set.of("foo"), "async");
         IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), 
"/foo");
         assertEquals(300, defn.getFulltextEntryCount(300));
         assertEquals(IndexDefinition.DEFAULT_ENTRY_COUNT + 100,
@@ -452,9 +461,9 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void customTikaConfig() throws Exception{
+    public void customTikaConfig() {
         NodeBuilder defnb = 
newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
-                "lucene", of(TYPENAME_STRING));
+                "lucene", Set.of(TYPENAME_STRING));
         IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), 
"/foo");
         assertFalse(defn.hasCustomTikaConfig());
 
@@ -467,13 +476,13 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void customTikaMimeTypes() throws Exception{
+    public void customTikaMimeTypes() {
         NodeBuilder defnb = 
newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
-                "lucene", of(TYPENAME_STRING));
+                "lucene", Set.of(TYPENAME_STRING));
         IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), 
"/foo");
         assertEquals("application/test", 
defn.getTikaMappedMimeType("application/test"));
 
-        NodeBuilder app =defnb.child(FulltextIndexConstants.TIKA)
+        NodeBuilder app = defnb.child(FulltextIndexConstants.TIKA)
                 .child(FulltextIndexConstants.TIKA_MIME_TYPES)
                 .child("application");
         app.child("test").setProperty(FulltextIndexConstants.TIKA_MAPPED_TYPE, 
"text/plain");
@@ -485,9 +494,9 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void maxExtractLength() throws Exception{
+    public void maxExtractLength() {
         NodeBuilder defnb = 
newFTIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo",
-                "lucene", of(TYPENAME_STRING));
+                "lucene", Set.of(TYPENAME_STRING));
         IndexDefinition defn = new IndexDefinition(root, defnb.getNodeState(), 
"/foo");
         assertEquals(-IndexDefinition.DEFAULT_MAX_EXTRACT_LENGTH * 
IndexDefinition.DEFAULT_MAX_FIELD_LENGTH,
                 defn.getMaxExtractLength());
@@ -500,13 +509,13 @@ public class IndexDefinitionTest {
     }
 
     @Test(expected = IllegalStateException.class)
-    public void nullCheckEnabledWithNtBase() throws Exception{
+    public void nullCheckEnabledWithNtBase() {
         
builder.child(PROP_NODE).child("foo").setProperty(FulltextIndexConstants.PROP_NULL_CHECK_ENABLED,
 true);
         IndexDefinition idxDefn = new IndexDefinition(root, 
builder.getNodeState(), "/foo");
     }
 
     @Test(expected = IllegalStateException.class)
-    public void nullCheckEnabledWithRegex() throws Exception{
+    public void nullCheckEnabledWithRegex() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child(TestUtil.NT_TEST);
         TestUtil.child(rules, "oak:TestNode/properties/prop2")
@@ -518,7 +527,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void nullCheckEnabledWithTestNode() throws Exception{
+    public void nullCheckEnabledWithTestNode() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         TestUtil.child(rules, "oak:TestNode/properties/prop2")
                 .setProperty(PROP_NAME, "foo")
@@ -529,7 +538,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void notNullCheckEnabledWithTestNode() throws Exception{
+    public void notNullCheckEnabledWithTestNode() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         TestUtil.child(rules, "oak:TestNode/properties/prop2")
                 .setProperty(PROP_NAME, "foo")
@@ -541,7 +550,7 @@ public class IndexDefinitionTest {
 
     //OAK-2477
     @Test
-    public void testSuggestFrequency() throws Exception {
+    public void testSuggestFrequency() {
         int suggestFreq = 40;
         //default config
         NodeBuilder indexRoot = builder;
@@ -571,7 +580,7 @@ public class IndexDefinitionTest {
 
     //OAK-2477
     @Test
-    public void testSuggestAnalyzed() throws Exception {
+    public void testSuggestAnalyzed() {
         //default config
         NodeBuilder indexRoot = builder;
         IndexDefinition idxDefn = new IndexDefinition(root, 
indexRoot.getNodeState(), "/foo");
@@ -598,7 +607,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void testSuggestEnabledOnNamedProp() throws Exception {
+    public void testSuggestEnabledOnNamedProp() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         TestUtil.child(rules, "oak:TestNode/properties/prop2")
                 .setProperty(PROP_NAME, "foo")
@@ -609,7 +618,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void testSuggestEnabledOnRegexProp() throws Exception {
+    public void testSuggestEnabledOnRegexProp() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child(TestUtil.NT_TEST);
         TestUtil.child(rules, "oak:TestNode/properties/prop2")
@@ -622,7 +631,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void testSuggestDisabled() throws Exception {
+    public void testSuggestDisabled() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         TestUtil.child(rules, "oak:TestNode/properties/prop2")
                 .setProperty(PROP_NAME, "foo");
@@ -632,7 +641,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void analyzedEnabledForBoostedField() throws Exception {
+    public void analyzedEnabledForBoostedField() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("nt:folder");
         TestUtil.child(rules, "nt:folder/properties/prop1")
@@ -659,7 +668,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void nodeFullTextIndexed_Regex() throws Exception {
+    public void nodeFullTextIndexed_Regex() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("nt:folder");
         TestUtil.child(rules, "nt:folder/properties/prop1")
@@ -681,7 +690,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void nodeFullTextIndexed_Simple() throws Exception {
+    public void nodeFullTextIndexed_Simple() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("nt:folder");
         TestUtil.child(rules, "nt:folder/properties/prop1")
@@ -702,7 +711,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void nodeFullTextIndexed_Aggregates() throws Exception {
+    public void nodeFullTextIndexed_Aggregates() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("nt:folder");
         TestUtil.child(rules, "nt:folder/properties/prop1")
@@ -721,7 +730,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void nonIndexPropShouldHaveAllOtherConfigDisabled() throws 
Exception{
+    public void nonIndexPropShouldHaveAllOtherConfigDisabled() {
         NodeBuilder rules = builder.child(INDEX_RULES);
         rules.child("nt:folder");
         TestUtil.child(rules, "nt:folder/properties/prop1")
@@ -754,38 +763,38 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void costPerEntry() throws Exception{
+    public void costPerEntry() {
         builder.setProperty(FulltextIndexConstants.COMPAT_MODE, 2);
         IndexDefinition defn = new IndexDefinition(root, 
builder.getNodeState(), "/foo");
         assertEquals(1.0, defn.getCostPerEntry(), 0.0);
     }
 
     @Test
-    public void sync() throws Exception{
+    public void sync() throws Exception {
         TestUtil.enableIndexingMode(builder, IndexingMode.SYNC);
         IndexDefinition idxDefn = new IndexDefinition(root, 
builder.getNodeState(), "/foo");
         assertTrue(idxDefn.isSyncIndexingEnabled());
     }
 
     @Test
-    public void hasPersistedIndex() throws Exception{
+    public void hasPersistedIndex() {
         assertFalse(IndexDefinition.hasPersistedIndex(builder.getNodeState()));
         builder.child(":status");
         assertTrue(IndexDefinition.hasPersistedIndex(builder.getNodeState()));
     }
 
     @Test
-    public void uniqueIdForFreshIndex() throws Exception{
+    public void uniqueIdForFreshIndex() {
         IndexDefinition defn = IndexDefinition.newBuilder(root, 
builder.getNodeState(), "/foo").build();
         assertEquals("0", defn.getUniqueId());
 
         builder.child(":status");
-        defn = IndexDefinition.newBuilder(root, 
builder.getNodeState(),"/foo").build();
+        defn = IndexDefinition.newBuilder(root, builder.getNodeState(), 
"/foo").build();
         assertNull(defn.getUniqueId());
     }
 
     @Test
-    public void nodeTypeChange() throws Exception{
+    public void nodeTypeChange() {
         IndexDefinition defn = IndexDefinition.newBuilder(root, 
builder.getNodeState(), "/foo").build();
         NodeBuilder b2 = root.builder();
         TestUtil.registerNodeType(b2, TestUtil.TEST_NODE_TYPE);
@@ -801,7 +810,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void uniqueIsSync() throws Exception{
+    public void uniqueIsSync() {
         IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
         defnb.indexRule("nt:base").property("foo").unique();
 
@@ -812,7 +821,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void syncIsProperty() throws Exception{
+    public void syncIsProperty() {
         IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
         defnb.indexRule("nt:base").property("foo").sync();
 
@@ -822,7 +831,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void syncPropertyDefinitions() throws Exception{
+    public void syncPropertyDefinitions() {
         IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
         defnb.indexRule("nt:base").property("foo").sync();
 
@@ -846,7 +855,7 @@ public class IndexDefinitionTest {
             "- * (UNDEFINED) multiple";
 
     @Test
-    public void nodeTypeIndexed() throws Exception{
+    public void nodeTypeIndexed() {
         TestUtil.registerNodeType(builder, testNodeTypeDefn);
         root = builder.getNodeState();
 
@@ -872,7 +881,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void nodeTypeIndexedSync() throws Exception{
+    public void nodeTypeIndexedSync() {
         TestUtil.registerNodeType(builder, testNodeTypeDefn);
         root = builder.getNodeState();
 
@@ -894,7 +903,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void nodeTypeIndexed_IgnoreOtherProps() throws Exception{
+    public void nodeTypeIndexed_IgnoreOtherProps() {
         TestUtil.registerNodeType(builder, testNodeTypeDefn);
         root = builder.getNodeState();
 
@@ -915,7 +924,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void nodeTypeIndexed_IgnoreAggregates() throws Exception{
+    public void nodeTypeIndexed_IgnoreAggregates() {
         TestUtil.registerNodeType(builder, testNodeTypeDefn);
         root = builder.getNodeState();
 
@@ -937,7 +946,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void nodeTypeIndex_mixin() throws Exception{
+    public void nodeTypeIndex_mixin() {
         TestUtil.registerNodeType(builder, testNodeTypeDefn);
         root = builder.getNodeState();
 
@@ -960,7 +969,7 @@ public class IndexDefinitionTest {
     }
 
     @Test
-    public void mixinAndPrimaryType() throws Exception{
+    public void mixinAndPrimaryType() {
         TestUtil.registerNodeType(builder, testNodeTypeDefn);
         root = builder.getNodeState();
 
@@ -1049,21 +1058,21 @@ public class IndexDefinitionTest {
 
     //TODO indexesAllNodesOfMatchingType - with nullCheckEnabled
 
-    private static IndexingRule getRule(IndexDefinition defn, String typeName){
+    private static IndexingRule getRule(IndexDefinition defn, String typeName) 
{
         return defn.getApplicableIndexingRule(asState(newNode(typeName)));
     }
 
-    private static NodeState asState(NodeBuilder nb){
+    private static NodeState asState(NodeBuilder nb) {
         return nb.getNodeState();
     }
 
-    private static NodeBuilder newNode(String typeName){
+    private static NodeBuilder newNode(String typeName) {
         NodeBuilder builder = EMPTY_NODE.builder();
         builder.setProperty(JcrConstants.JCR_PRIMARYTYPE, typeName, Type.NAME);
         return builder;
     }
 
-    private static NodeBuilder newNode(String typeName, String mixins){
+    private static NodeBuilder newNode(String typeName, String mixins) {
         NodeBuilder builder = EMPTY_NODE.builder();
         builder.setProperty(JcrConstants.JCR_PRIMARYTYPE, typeName);
         builder.setProperty(JcrConstants.JCR_MIXINTYPES, 
Collections.singleton(mixins), Type.NAMES);
diff --git 
a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/secondary/SecondaryStoreCacheServiceTest.java
 
b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/secondary/SecondaryStoreCacheServiceTest.java
index 925f105d8f..d3956873e6 100644
--- 
a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/secondary/SecondaryStoreCacheServiceTest.java
+++ 
b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/secondary/SecondaryStoreCacheServiceTest.java
@@ -99,7 +99,7 @@ public class SecondaryStoreCacheServiceTest {
     @Test
     public void configurePathFilter() throws Exception{
         Map<String, Object> config = new HashMap<>();
-        config.put("includedPaths", new String[] {"/a"});
+        config.put(PathFilter.PROP_INCLUDED_PATHS, new String[] {"/a"});
         MockOsgi.activate(cacheService, context.bundleContext(), config);
 
         assertEquals(PathFilter.Result.INCLUDE, 
cacheService.getPathFilter().filter("/a"));
diff --git 
a/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/spi/filter/PathFilter.java
 
b/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/spi/filter/PathFilter.java
index 71be083b24..f3d1ef6aba 100644
--- 
a/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/spi/filter/PathFilter.java
+++ 
b/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/spi/filter/PathFilter.java
@@ -21,8 +21,6 @@
 package org.apache.jackrabbit.oak.spi.filter;
 
 import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
@@ -34,7 +32,6 @@ import org.jetbrains.annotations.NotNull;
 
 import static org.apache.jackrabbit.guava.common.base.Preconditions.checkState;
 import static org.apache.jackrabbit.guava.common.collect.Sets.newHashSet;
-import static java.util.Collections.singletonList;
 import static org.apache.jackrabbit.oak.commons.PathUtils.isAncestor;
 
 /**
@@ -42,7 +39,7 @@ import static 
org.apache.jackrabbit.oak.commons.PathUtils.isAncestor;
  * or not
  */
 public class PathFilter {
-    private static final Collection<String> INCLUDE_ROOT = singletonList("/");
+    private static final Set<String> INCLUDE_ROOT = Set.of("/");
     /**
      * Multi value property name used to determine list of paths to be included
      */
@@ -73,38 +70,53 @@ public class PathFilter {
         TRAVERSE
     }
 
-    private static final PathFilter ALL = new PathFilter(INCLUDE_ROOT, 
Collections.emptyList()) {
+    private static final PathFilter ALL = new PathFilter(INCLUDE_ROOT, 
List.of()) {
         @Override
         public Result filter(@NotNull String path) {
             return Result.INCLUDE;
         }
     };
-    private final String[] includedPaths;
-    private final String[] excludedPaths;
 
     /**
      * Constructs the predicate based on given definition state. It looks for
      * multi value property with names {@link PathFilter#PROP_INCLUDED_PATHS}
      * and {@link PathFilter#PROP_EXCLUDED_PATHS}. Both the properties are
      * optional.
-     * 
+     * If the properties are defined as String instead of Strings, then they
+     * are interpreted as a single-element list.
+     *
      * @param defn nodestate representing the configuration. Generally it would
-     *            be the nodestate representing the index definition
+     *             be the nodestate representing the index definition
      * @return predicate based on the passed definition state
      */
     public static PathFilter from(@NotNull NodeBuilder defn) {
-        if (!defn.hasProperty(PROP_EXCLUDED_PATHS) &&
-                !defn.hasProperty(PROP_INCLUDED_PATHS)) {
+        if (!defn.hasProperty(PROP_EXCLUDED_PATHS) && 
!defn.hasProperty(PROP_INCLUDED_PATHS)) {
             return ALL;
         }
-        return new PathFilter(getStrings(defn, PROP_INCLUDED_PATHS,
-                INCLUDE_ROOT), getStrings(defn, PROP_EXCLUDED_PATHS,
-                Collections.emptyList()));
+        return new PathFilter(
+                getStrings(defn.getProperty(PROP_INCLUDED_PATHS), 
INCLUDE_ROOT),
+                getStrings(defn.getProperty(PROP_EXCLUDED_PATHS), Set.of())
+        );
+    }
+
+    /*
+     * Gets the value of the given property as a set of strings. This works 
both if the property is of type STRING or
+     * type STRINGS. If the type is STRING, then it is interpreted as a 
single-element list. This is the default behavior
+     * of calling {@link PropertyState#getValue(Type)} with {@link 
Type#STRINGS}.
+     */
+    public static Iterable<String> getStrings(PropertyState ps, Set<String> 
defaultValues) {
+        if (ps != null && (ps.getType() == Type.STRING || ps.getType() == 
Type.STRINGS)) {
+            return ps.getValue(Type.STRINGS);
+        }
+        return defaultValues;
     }
 
+    private final String[] includedPaths;
+    private final String[] excludedPaths;
+
     /**
      * Constructs the predicate with given included and excluded paths
-     *
+     * <p>
      * If both are empty then all paths would be considered to be included
      *
      * @param includes list of paths which should be included
@@ -116,8 +128,8 @@ public class PathFilter {
         PathUtils.unifyInExcludes(includeCopy, excludeCopy);
         checkState(!includeCopy.isEmpty(), "No valid include provided. 
Includes %s, " +
                 "Excludes %s", includes, excludes);
-        this.includedPaths = includeCopy.toArray(new 
String[includeCopy.size()]);
-        this.excludedPaths = excludeCopy.toArray(new 
String[excludeCopy.size()]);
+        this.includedPaths = includeCopy.toArray(new String[0]);
+        this.excludedPaths = excludeCopy.toArray(new String[0]);
     }
 
     /**
@@ -164,26 +176,15 @@ public class PathFilter {
                 '}';
     }
 
-    private static Iterable<String> getStrings(NodeBuilder builder, String 
propertyName, 
-            Collection<String> defaultVal) {
-        PropertyState property = builder.getProperty(propertyName);
-        if (property != null && property.getType() == Type.STRINGS) {
-            return property.getValue(Type.STRINGS);
-        } else {
-            return defaultVal;
-        }
-    }
-
     /**
      * Check whether this node and all descendants are included in this filter.
-     * 
+     *
      * @param path the path
      * @return true if this and all descendants of this path are included in 
the filter
      */
     public boolean areAllDescendantsIncluded(String path) {
         for (String excludedPath : excludedPaths) {
-            if (excludedPath.equals(path) || isAncestor(excludedPath, path) || 
-                    isAncestor(path, excludedPath)) {
+            if (excludedPath.equals(path) || isAncestor(excludedPath, path) || 
isAncestor(path, excludedPath)) {
                 return false;
             }
         }
@@ -194,5 +195,4 @@ public class PathFilter {
         }
         return false;
     }
-    
 }
diff --git 
a/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/spi/filter/PathFilterTest.java
 
b/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/spi/filter/PathFilterTest.java
index 315e93cdf9..37c62ecea0 100644
--- 
a/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/spi/filter/PathFilterTest.java
+++ 
b/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/spi/filter/PathFilterTest.java
@@ -19,13 +19,14 @@
 
 package org.apache.jackrabbit.oak.spi.filter;
 
-import java.util.Collections;
-
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.jetbrains.annotations.NotNull;
 import org.junit.Test;
 
-import static org.apache.jackrabbit.guava.common.collect.ImmutableList.of;
+import java.util.HashSet;
+import java.util.Set;
+
 import static 
org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
 import static 
org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
 import static 
org.apache.jackrabbit.oak.spi.filter.PathFilter.PROP_EXCLUDED_PATHS;
@@ -36,8 +37,8 @@ import static org.junit.Assert.fail;
 public class PathFilterTest {
 
     @Test
-    public void exclude() throws Exception {
-        PathFilter p = new PathFilter(of("/"), of("/etc"));
+    public void exclude() {
+        PathFilter p = new PathFilter(Set.of("/"), Set.of("/etc"));
         assertEquals(PathFilter.Result.INCLUDE, p.filter("/"));
         assertEquals(PathFilter.Result.INCLUDE, p.filter("/a"));
         assertEquals(PathFilter.Result.EXCLUDE, p.filter("/etc"));
@@ -45,8 +46,8 @@ public class PathFilterTest {
     }
 
     @Test
-    public void include() throws Exception {
-        PathFilter p = new PathFilter(of("/content", "/etc"), 
of("/etc/workflow/instance"));
+    public void include() {
+        PathFilter p = new PathFilter(Set.of("/content", "/etc"), 
Set.of("/etc/workflow/instance"));
         assertEquals(PathFilter.Result.TRAVERSE, p.filter("/"));
         assertEquals(PathFilter.Result.EXCLUDE, p.filter("/var"));
         assertEquals(PathFilter.Result.INCLUDE, p.filter("/content"));
@@ -61,7 +62,7 @@ public class PathFilterTest {
     }
 
     @Test
-    public void emptyConfig() throws Exception {
+    public void emptyConfig() {
         NodeBuilder root = EMPTY_NODE.builder();
         PathFilter p = PathFilter.from(root);
         assertEquals(PathFilter.Result.INCLUDE, p.filter("/"));
@@ -69,10 +70,10 @@ public class PathFilterTest {
     }
 
     @Test
-    public void config() throws Exception {
+    public void config() {
         NodeBuilder root = EMPTY_NODE.builder();
-        root.setProperty(createProperty(PROP_INCLUDED_PATHS, of("/etc"), 
Type.STRINGS));
-        root.setProperty(createProperty(PROP_EXCLUDED_PATHS, 
of("/etc/workflow"), Type.STRINGS));
+        root.setProperty(createProperty(PROP_INCLUDED_PATHS, Set.of("/etc"), 
Type.STRINGS));
+        root.setProperty(createProperty(PROP_EXCLUDED_PATHS, 
Set.of("/etc/workflow"), Type.STRINGS));
         PathFilter p = PathFilter.from(root);
         assertEquals(PathFilter.Result.TRAVERSE, p.filter("/"));
         assertEquals(PathFilter.Result.INCLUDE, p.filter("/etc"));
@@ -82,9 +83,22 @@ public class PathFilterTest {
     }
 
     @Test
-    public void configOnlyExclude() throws Exception {
+    public void configWithStringProperties() {
         NodeBuilder root = EMPTY_NODE.builder();
-        root.setProperty(createProperty(PROP_EXCLUDED_PATHS, 
of("/etc/workflow"), Type.STRINGS));
+        root.setProperty(createProperty(PROP_INCLUDED_PATHS, "/etc", 
Type.STRING));
+        root.setProperty(createProperty(PROP_EXCLUDED_PATHS, "/etc/workflow", 
Type.STRING));
+        PathFilter p = PathFilter.from(root);
+        assertEquals(PathFilter.Result.TRAVERSE, p.filter("/"));
+        assertEquals(PathFilter.Result.INCLUDE, p.filter("/etc"));
+        assertEquals(PathFilter.Result.INCLUDE, p.filter("/etc/a"));
+        assertEquals(PathFilter.Result.EXCLUDE, p.filter("/etc/workflow"));
+        assertEquals(PathFilter.Result.EXCLUDE, p.filter("/etc/workflow/1"));
+    }
+
+    @Test
+    public void configOnlyExclude() {
+        NodeBuilder root = EMPTY_NODE.builder();
+        root.setProperty(createProperty(PROP_EXCLUDED_PATHS, 
Set.of("/etc/workflow"), Type.STRINGS));
         PathFilter p = PathFilter.from(root);
         assertEquals(PathFilter.Result.INCLUDE, p.filter("/"));
         assertEquals(PathFilter.Result.INCLUDE, p.filter("/etc"));
@@ -94,26 +108,70 @@ public class PathFilterTest {
     }
 
     @Test
-    public void invalid() throws Exception {
+    public void invalid() {
         try {
-            new PathFilter(Collections.<String>emptyList(), of("/etc"));
+            new PathFilter(Set.of(), Set.of("/etc"));
             fail();
         } catch (IllegalStateException ignore) {
             // expected
         }
 
         try {
-            new PathFilter(of("/etc/workflow"), of("/etc"));
+            new PathFilter(Set.of("/etc/workflow"), Set.of("/etc"));
             fail();
         } catch (IllegalStateException ignore) {
             // expected
         }
 
         try {
-            new PathFilter(Collections.<String>emptyList(), 
Collections.<String>emptyList());
+            new PathFilter(Set.of(), Set.of());
             fail();
         } catch (IllegalStateException ignore) {
             // expected
         }
     }
+
+    @Test
+    public void getStringsLenientNodeBuilder_MultipleValues() {
+        NodeBuilder root = EMPTY_NODE.builder();
+        @NotNull NodeBuilder b1 = 
root.setProperty(createProperty("propMultiple", Set.of("/p1", "/p2"), 
Type.STRINGS));
+        assertEquals(Set.of("/p1", "/p2"), 
toSet(PathFilter.getStrings(b1.getProperty("propMultiple"), 
Set.of("default"))));
+    }
+
+    @Test
+    public void getStringsLenientNodeBuilder_SingleValueAsSet() {
+        NodeBuilder root = EMPTY_NODE.builder();
+        @NotNull NodeBuilder b1 = 
root.setProperty(createProperty("propMultiple", Set.of("/p1"), Type.STRINGS));
+        assertEquals(Set.of("/p1"), 
toSet(PathFilter.getStrings(b1.getProperty("propMultiple"), 
Set.of("default"))));
+    }
+
+    @Test
+    public void getStringsLenientNodeBuilder_SingleValueAsString() {
+        NodeBuilder root = EMPTY_NODE.builder();
+        @NotNull NodeBuilder b1 = 
root.setProperty(createProperty("propMultiple", "/p1", Type.STRING));
+        assertEquals(Set.of("/p1"), 
toSet(PathFilter.getStrings(b1.getProperty("propMultiple"), 
Set.of("default"))));
+    }
+
+    @Test
+    public void getStringsLenientNodeBuilder_NoValue() {
+        NodeBuilder root = EMPTY_NODE.builder();
+        assertEquals(Set.of("default"), 
toSet(PathFilter.getStrings(root.getProperty("propMultiple"), 
Set.of("default"))));
+    }
+
+    @Test
+    public void getStringsLenientNodeBuilder_WrongType() {
+        NodeBuilder root = EMPTY_NODE.builder();
+        @NotNull NodeBuilder b1 = 
root.setProperty(createProperty("propMultiple", 1L, Type.LONG));
+        assertEquals(Set.of("default"), 
toSet(PathFilter.getStrings(root.getProperty("propMultiple"), 
Set.of("default"))));
+    }
+
+    static private <T> Set<T> toSet(Iterable<T> iterable) {
+        HashSet<T> set = new HashSet<>();
+        for (T t : iterable) {
+            set.add(t);
+        }
+        return set;
+    }
+
+
 }

Reply via email to