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

cziegeler pushed a commit to branch issues/SLING-11744
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-i18n.git


The following commit(s) were added to refs/heads/issues/SLING-11744 by this 
push:
     new c07049d  SLING-11744 : Allow configuration of include and exclude 
paths for bundles
c07049d is described below

commit c07049d9124dfa73e7a249c7466699941c2afb3e
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Fri Feb 10 09:27:48 2023 +0100

    SLING-11744 : Allow configuration of include and exclude paths for bundles
---
 .../java/org/apache/sling/i18n/impl/Config.java    | 51 ++++++++++++
 .../apache/sling/i18n/impl/JcrResourceBundle.java  | 30 ++++---
 .../sling/i18n/impl/JcrResourceBundleProvider.java | 93 ++++++++--------------
 .../org/apache/sling/i18n/impl/PathFilter.java     | 56 +++++++++++++
 .../ConcurrentJcrResourceBundleLoadingTest.java    |  9 ++-
 .../i18n/impl/JcrResourceBundleProviderTest.java   | 40 ----------
 .../sling/i18n/impl/JcrResourceBundleTest.java     | 30 +++----
 .../org/apache/sling/i18n/impl/PathFilterTest.java | 46 +++++++++++
 8 files changed, 226 insertions(+), 129 deletions(-)

diff --git a/src/main/java/org/apache/sling/i18n/impl/Config.java 
b/src/main/java/org/apache/sling/i18n/impl/Config.java
new file mode 100644
index 0000000..27b3229
--- /dev/null
+++ b/src/main/java/org/apache/sling/i18n/impl/Config.java
@@ -0,0 +1,51 @@
+/*
+ * 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.i18n.impl;
+
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+
+@ObjectClassDefinition(name ="Apache Sling I18N Resource Bundle Provider",
+        description ="ResourceBundleProvider service which loads the messages 
from the repository.")
+public @interface Config {
+
+    @AttributeDefinition(name = "Default Locale",
+        description = "The default locale to assume if none can be "+
+             "resolved otherwise. This value must be in the form acceptable to 
the "+
+             "java.util.Locale class.")
+    String locale_default() default "en";
+
+    @AttributeDefinition(name = "Preload Bundles",
+            description = "Whether or not to eagerly load the resource bundles 
"+
+                "on bundle start or a cache invalidation.")
+    boolean preload_bundles() default false;
+
+    @AttributeDefinition(name = "Invalidation Delay",
+            description = "In case of dictionary change events the cached "+
+                    "resource bundle becomes invalid after the given delay (in 
ms). ")
+    long invalidation_delay() default 5000;
+    
+    @AttributeDefinition(name="Included paths",
+            description="Translations in paths starting with one of these 
values will be ignored")
+    String[] included_paths() default {"/"};
+
+    @AttributeDefinition(name="Excluded paths",
+            description="Translations in paths starting with one of these 
values will be ignored")
+    String[] excluded_paths() default {"/var/eventing"};
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/i18n/impl/JcrResourceBundle.java 
b/src/main/java/org/apache/sling/i18n/impl/JcrResourceBundle.java
index ee0fcd2..b68d49f 100644
--- a/src/main/java/org/apache/sling/i18n/impl/JcrResourceBundle.java
+++ b/src/main/java/org/apache/sling/i18n/impl/JcrResourceBundle.java
@@ -64,6 +64,8 @@ public class JcrResourceBundle extends ResourceBundle {
 
     static final String PROP_MIXINS = "jcr:mixinTypes";
 
+    static final String PROP_PATH = "jcr:path";
+
     static final String QUERY_LANGUAGE_ROOTS = 
"//element(*,mix:language)[@jcr:language]";
 
     private final Map<String, Object> resources;
@@ -75,14 +77,16 @@ public class JcrResourceBundle extends ResourceBundle {
     private final Set<String> languageRoots = new HashSet<>();
 
     JcrResourceBundle(final Locale locale, final String baseName,
-            final ResourceResolver resourceResolver, List<LocatorPaths> 
locatorPaths) {
+            final ResourceResolver resourceResolver, 
+            final List<LocatorPaths> locatorPaths,
+            final PathFilter filter) {
         this.locale = locale;
         this.baseName = baseName;
 
         log.info("Finding all dictionaries for '{}' (basename: {}) ...", 
locale, baseName == null ? "<none>" : baseName);
 
         final long start = System.currentTimeMillis();
-        final Set<String> roots = loadPotentialLanguageRoots(resourceResolver, 
locale, baseName, locatorPaths);
+        final Set<String> roots = loadPotentialLanguageRoots(resourceResolver, 
locale, baseName, locatorPaths, filter);
         this.resources = loadFully(resourceResolver, roots, 
this.languageRoots);
 
         if (log.isInfoEnabled()) {
@@ -318,7 +322,11 @@ public class JcrResourceBundle extends ResourceBundle {
         this.scanForSlingMessages(dictionaryResource, targetDictionary);
     }
 
-    private Set<String> loadPotentialLanguageRoots(ResourceResolver 
resourceResolver, Locale locale, final String baseName, 
Collection<LocatorPaths> locatorPaths) {
+    private Set<String> loadPotentialLanguageRoots(final ResourceResolver 
resourceResolver,
+            final Locale locale, 
+            final String baseName,
+            final Collection<LocatorPaths> locatorPaths,
+            final PathFilter filter) {
         final Set<String> paths = new LinkedHashSet<>();
 
         PotentialLanguageRootCheck check = new 
PotentialLanguageRootCheck(baseName, locale);
@@ -326,19 +334,21 @@ public class JcrResourceBundle extends ResourceBundle {
         // first consider resource bundles in the JCR repository
         final Iterator<Resource> bundles = 
resourceResolver.findResources(QUERY_LANGUAGE_ROOTS, "xpath");
         while (bundles.hasNext()) {
-            Resource bundle = bundles.next();
-            if (check.isResourceBundle(bundle)) {
+            final Resource bundle = bundles.next();
+            if (filter.includePath(bundle.getPath()) && 
check.isResourceBundle(bundle)) {
                 paths.add(bundle.getPath());
             }
         }
 
         if (locatorPaths != null && !locatorPaths.isEmpty()) {
             // next traverse the ancestors of all of the locator paths
-            LocatorPathsVisitor visitor = new LocatorPathsVisitor(check, 
paths);
-            for (LocatorPaths locator : locatorPaths) {
-                Resource parentResource = 
resourceResolver.getResource(locator.getPath());
-                if (parentResource != null) {
-                    visitor.accept(parentResource, locator.getTraverseDepth());
+            final LocatorPathsVisitor visitor = new LocatorPathsVisitor(check, 
paths);
+            for (final LocatorPaths locator : locatorPaths) {
+                if ( filter.includePath(locator.getPath())) {
+                    final Resource parentResource = 
resourceResolver.getResource(locator.getPath());
+                    if (parentResource != null) {
+                        visitor.accept(parentResource, 
locator.getTraverseDepth());
+                    }    
                 }
             }
         }
diff --git 
a/src/main/java/org/apache/sling/i18n/impl/JcrResourceBundleProvider.java 
b/src/main/java/org/apache/sling/i18n/impl/JcrResourceBundleProvider.java
index 04d8c21..e1bef11 100644
--- a/src/main/java/org/apache/sling/i18n/impl/JcrResourceBundleProvider.java
+++ b/src/main/java/org/apache/sling/i18n/impl/JcrResourceBundleProvider.java
@@ -20,6 +20,7 @@ package org.apache.sling.i18n.impl;
 
 import static org.apache.sling.i18n.impl.JcrResourceBundle.PROP_BASENAME;
 import static org.apache.sling.i18n.impl.JcrResourceBundle.PROP_LANGUAGE;
+import static org.apache.sling.i18n.impl.JcrResourceBundle.PROP_PATH;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -61,9 +62,7 @@ import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
 import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.metatype.annotations.AttributeDefinition;
 import org.osgi.service.metatype.annotations.Designate;
-import org.osgi.service.metatype.annotations.ObjectClassDefinition;
 import org.osgi.util.tracker.BundleTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -83,49 +82,24 @@ import org.slf4j.LoggerFactory;
             ResourceChangeListener.CHANGES + "=REMOVED",
             ResourceChangeListener.CHANGES + "=CHANGED"
     })
-@Designate(ocd = JcrResourceBundleProvider.Config.class)
+@Designate(ocd = Config.class)
 public class JcrResourceBundleProvider implements ResourceBundleProvider, 
ResourceChangeListener, ExternalResourceChangeListener {
 
+    /** default log */
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
     /**
      * A regular expression pattern matching all custom country codes.
      * @see <a 
href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#User-assigned_code_elements";>User-assigned
 code elements</a>
      */
     private static final Pattern USER_ASSIGNED_COUNTRY_CODES_PATTERN = 
Pattern.compile("aa|q[m-z]|x[a-z]|zz");
 
-    @ObjectClassDefinition(name ="Apache Sling I18N Resource Bundle Provider",
-            description ="ResourceBundleProvider service which loads the 
messages from the repository.")
-    public @interface Config {
-
-        @AttributeDefinition(name = "Default Locale",
-            description = "The default locale to assume if none can be "+
-                 "resolved otherwise. This value must be in the form 
acceptable to the "+
-                 "java.util.Locale class.")
-        String locale_default() default "en";
-
-        @AttributeDefinition(name = "Preload Bundles",
-                description = "Whether or not to eagerly load the resource 
bundles "+
-                    "on bundle start or a cache invalidation.")
-        boolean preload_bundles() default false;
-
-        @AttributeDefinition(name = "Invalidation Delay",
-                description = "In case of dictionary change events the cached 
"+
-                        "resource bundle becomes invalid after the given delay 
(in ms). ")
-        long invalidation_delay() default 5000;
-        
-        @AttributeDefinition(name="Excluded paths",
-                description="Events happening in paths starting with one of 
these values will be ignored")
-        String[] excluded_paths() default {"/var/eventing"};
-    }
-
     @Reference
     private Scheduler scheduler;
 
     /** job names of scheduled jobs for reloading individual bundles */
     private final Collection<String> scheduledJobNames = 
Collections.synchronizedList(new ArrayList<String>()) ;
 
-    /** default log */
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
     @Reference
     private ResourceResolverFactory resourceResolverFactory;
 
@@ -167,8 +141,15 @@ public class JcrResourceBundleProvider implements 
ResourceBundleProvider, Resour
 
     private BundleTracker<Set<LocatorPaths>> locatorPathsTracker;
     private List<LocatorPaths> locatorPaths = new CopyOnWriteArrayList<>();
-    
-    Config config;
+
+    /**
+     * Filter to check for allowed paths
+     */
+    private volatile PathFilter pathFilter;
+
+    private volatile boolean preloadBundles;
+
+    private volatile long invalidationDelay;
 
     /**
      * Add a set of paths to the set that are inspected to
@@ -243,7 +224,7 @@ public class JcrResourceBundleProvider implements 
ResourceBundleProvider, Resour
         try {
             for (final ResourceChange change : changes) {
                 
-                if (canIgnoreChange(change)) {
+                if (!this.pathFilter.includePath(change.getPath())) {
                     continue;
                 }
                 this.onChange(status, change);
@@ -268,17 +249,6 @@ public class JcrResourceBundleProvider implements 
ResourceBundleProvider, Resour
         }
     }
     
-    // skip if the change happens within a path configured in excludedPaths 
-    protected boolean canIgnoreChange(final ResourceChange change) {
-        for (String excludedPath: this.config.excluded_paths()) {
-            if (change.getPath().startsWith(excludedPath)) {
-                return true;
-            }
-        }
-        return false;
-    }
-    
-
     private void onChange(final ChangeStatus status, final ResourceChange 
change)
     throws LoginException {
         log.debug("onChange: Detecting change {} for path '{}'", 
change.getType(), change.getPath());
@@ -372,7 +342,7 @@ public class JcrResourceBundleProvider implements 
ResourceBundleProvider, Resour
         // defer this job
         final ScheduleOptions options;
         if (withDelay) {
-            options = scheduler.AT(new Date(System.currentTimeMillis() + 
this.config.invalidation_delay()));
+            options = scheduler.AT(new Date(System.currentTimeMillis() + 
this.invalidationDelay));
         } else {
             options = scheduler.NOW();
         }
@@ -391,7 +361,7 @@ public class JcrResourceBundleProvider implements 
ResourceBundleProvider, Resour
         final Key key = new Key(bundle.getBaseName(), bundle.getLocale());
 
         // defer this job
-        ScheduleOptions options = scheduler.AT(new 
Date(System.currentTimeMillis() + this.config.invalidation_delay()));
+        ScheduleOptions options = scheduler.AT(new 
Date(System.currentTimeMillis() + this.invalidationDelay));
         final String jobName = "ResourceBundleProvider: reload bundle with key 
" + key.toString();
         scheduledJobNames.add(jobName);
         options.name(jobName);
@@ -406,7 +376,7 @@ public class JcrResourceBundleProvider implements 
ResourceBundleProvider, Resour
 
     void reloadBundle(final Key key) {
         log.info("Reloading resource bundle for {}", key);
-        if (!this.config.preload_bundles()) {
+        if (!this.preloadBundles) {
             // remove bundle from cache
             resourceBundleCache.remove(key);
             // unregister bundle
@@ -429,7 +399,7 @@ public class JcrResourceBundleProvider implements 
ResourceBundleProvider, Resour
             reloadBundle(new Key(dependentBundle.getBaseName(), 
dependentBundle.getLocale()));
         }
 
-        if (this.config.preload_bundles()) {
+        if (this.preloadBundles) {
             // reload the bundle from the repository (will also fill cache and 
register as a service)
             getResourceBundleInternal(null, key.baseName, key.locale, true);
         }
@@ -444,27 +414,26 @@ public class JcrResourceBundleProvider implements 
ResourceBundleProvider, Resour
      */
     @Activate
     protected void activate(final BundleContext context, final Config config) 
throws LoginException {
-        
-        this.config = config;
-        final String localeString = config.locale_default();
-        this.defaultLocale = toLocale(localeString);
+        this.defaultLocale = toLocale(config.locale_default());
+        this.preloadBundles = config.preload_bundles();
+        this.invalidationDelay = config.invalidation_delay();
+        this.pathFilter = new PathFilter(config.included_paths(), 
config.excluded_paths());
         this.bundleContext = context;
 
-        locatorPathsTracker = new BundleTracker<>(this.bundleContext,
+        this.locatorPathsTracker = new BundleTracker<>(this.bundleContext,
                 Bundle.ACTIVE, new LocatorPathsTracker(this));
-        locatorPathsTracker.open();
+        this.locatorPathsTracker.open();
 
         if (this.resourceResolverFactory != null) { // this is only null 
during test execution!
             scheduleReloadBundles(false);
         }
-
     }
 
     @Deactivate
     protected void deactivate() {
-        if (locatorPathsTracker != null) {
-            locatorPathsTracker.close();
-            locatorPathsTracker = null;
+        if (this.locatorPathsTracker != null) {
+            this.locatorPathsTracker.close();
+            this.locatorPathsTracker = null;
         }
 
         clearCache();
@@ -581,7 +550,7 @@ public class JcrResourceBundleProvider implements 
ResourceBundleProvider, Resour
      *             is not available to access the resources.
      */
     private JcrResourceBundle createResourceBundle(final ResourceResolver 
resolver, final String baseName, final Locale locale) {
-        final JcrResourceBundle bundle = new JcrResourceBundle(locale, 
baseName, resolver, locatorPaths);
+        final JcrResourceBundle bundle = new JcrResourceBundle(locale, 
baseName, resolver, locatorPaths, this.pathFilter);
 
         // set parent resource bundle
         Locale parentLocale = getParentLocale(locale);
@@ -655,14 +624,14 @@ public class JcrResourceBundleProvider implements 
ResourceBundleProvider, Resour
     }
 
     private void preloadBundles() {
-        if (this.config.preload_bundles()) {
+        if (this.preloadBundles) {
             try ( final ResourceResolver resolver = createResourceResolver() ) 
{
                 final Iterator<Map<String, Object>> bundles = 
resolver.queryResources(
                     JcrResourceBundle.QUERY_LANGUAGE_ROOTS, "xpath");
                 final Set<Key> usedKeys = new HashSet<>();
                 while (bundles.hasNext()) {
                     final Map<String,Object> bundle = bundles.next();
-                    if (bundle.containsKey(PROP_LANGUAGE)) {
+                    if (bundle.containsKey(PROP_LANGUAGE) && 
this.pathFilter.includePath(bundle.get(PROP_PATH).toString())) {
                         final Locale locale = 
toLocale(bundle.get(PROP_LANGUAGE).toString());
                         String baseName = null;
                         if (bundle.containsKey(PROP_BASENAME)) {
diff --git a/src/main/java/org/apache/sling/i18n/impl/PathFilter.java 
b/src/main/java/org/apache/sling/i18n/impl/PathFilter.java
new file mode 100644
index 0000000..69220c1
--- /dev/null
+++ b/src/main/java/org/apache/sling/i18n/impl/PathFilter.java
@@ -0,0 +1,56 @@
+/*
+ * 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.i18n.impl;
+
+import org.apache.sling.api.resource.path.PathSet;
+
+public class PathFilter {
+
+    /**
+     * Included paths
+     */
+    private final PathSet includedPaths;
+
+    /**
+     * Excluded paths
+     */
+    private final PathSet excludedPaths;
+
+    public PathFilter() {
+        this(null, null);
+    }
+
+    public PathFilter(final String[] includes, final String[] excludes) {
+        this.includedPaths = includes == null ? null : 
PathSet.fromStrings(includes);
+        this.excludedPaths = excludes == null ? null : 
PathSet.fromStrings(excludes);
+    }
+
+    /**
+     * Check whether the path is in the included but not in the excluded paths
+     * @param path The path to check
+     * @return {@code true} if the path can be included
+     */
+    public boolean includePath(final String path) {
+        boolean included = this.includedPaths == null || 
this.includedPaths.matches(path) != null;
+        if (included) {
+            included = this.excludedPaths == null || 
this.excludedPaths.matches(path) == null;
+        }
+        return included;
+    }
+}
\ No newline at end of file
diff --git 
a/src/test/java/org/apache/sling/i18n/impl/ConcurrentJcrResourceBundleLoadingTest.java
 
b/src/test/java/org/apache/sling/i18n/impl/ConcurrentJcrResourceBundleLoadingTest.java
index a8784af..464fd6c 100644
--- 
a/src/test/java/org/apache/sling/i18n/impl/ConcurrentJcrResourceBundleLoadingTest.java
+++ 
b/src/test/java/org/apache/sling/i18n/impl/ConcurrentJcrResourceBundleLoadingTest.java
@@ -82,11 +82,11 @@ public class ConcurrentJcrResourceBundleLoadingTest {
     @Before
     public void setup() throws Exception {
         provider = spy(new JcrResourceBundleProvider());
-        provider.activate(PowerMockito.mock(BundleContext.class), new 
JcrResourceBundleProvider.Config() {
+        provider.activate(PowerMockito.mock(BundleContext.class), new Config() 
{
 
             @Override
             public Class<? extends Annotation> annotationType() {
-                return JcrResourceBundleProvider.Config.class;
+                return Config.class;
             }
 
             @Override
@@ -104,6 +104,11 @@ public class ConcurrentJcrResourceBundleLoadingTest {
                 return 5000;
             }
 
+            @Override
+            public String[] included_paths() {
+                return new String[] {"/"};
+            }
+
             @Override
             public String[] excluded_paths() {
                 return new String[] {"/var/eventing"};
diff --git 
a/src/test/java/org/apache/sling/i18n/impl/JcrResourceBundleProviderTest.java 
b/src/test/java/org/apache/sling/i18n/impl/JcrResourceBundleProviderTest.java
index d9a5b61..7a938fb 100644
--- 
a/src/test/java/org/apache/sling/i18n/impl/JcrResourceBundleProviderTest.java
+++ 
b/src/test/java/org/apache/sling/i18n/impl/JcrResourceBundleProviderTest.java
@@ -18,22 +18,11 @@
  */
 package org.apache.sling.i18n.impl;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.HashMap;
 import java.util.Locale;
-import java.util.Map;
-
-import org.apache.sling.api.resource.observation.ResourceChange;
-import org.apache.sling.commons.scheduler.ScheduleOptions;
-import org.apache.sling.commons.scheduler.Scheduler;
-import org.apache.sling.serviceusermapping.ServiceUserMapped;
 import org.apache.sling.testing.mock.sling.junit.SlingContext;
 import org.junit.Assert;
 import org.junit.Rule;
 import org.junit.Test;
-import org.mockito.Mockito;
 
 
 public class JcrResourceBundleProviderTest {
@@ -109,33 +98,4 @@ public class JcrResourceBundleProviderTest {
         // Lowercase Private use Country 'xa'
         Assert.assertEquals(new Locale(Locale.GERMAN.getLanguage(), "XA"), 
JcrResourceBundleProvider.toLocale("de_xa"));
     }
-    
-    @Test
-    public void testPathExclusions() {
-        JcrResourceBundleProvider sut = new JcrResourceBundleProvider();
-        Map<String,Object> props = new HashMap<>();
-        props.put("excluded.paths", new String[] {"/excluded/path"});
-        
-        Scheduler scheduler = Mockito.mock(Scheduler.class);
-        Mockito.when(scheduler.schedule(Mockito.any(), 
Mockito.any())).thenReturn(false); // is ignored
-        
Mockito.when(scheduler.AT(Mockito.any())).thenReturn(Mockito.mock(ScheduleOptions.class));
-        
Mockito.when(scheduler.NOW()).thenReturn(Mockito.mock(ScheduleOptions.class));
-        context.registerService(Scheduler.class,scheduler);
-        
-        ServiceUserMapped serviceUserMapped = 
Mockito.mock(ServiceUserMapped.class);
-        context.registerService(ServiceUserMapped.class,serviceUserMapped);
-        
-        context.registerInjectActivateService(sut, props);
-        ResourceChange c1 = Mockito.mock(ResourceChange.class);
-        Mockito.when(c1.getPath()).thenReturn("/excluded/path");
-        ResourceChange c2 = Mockito.mock(ResourceChange.class);
-        Mockito.when(c2.getPath()).thenReturn("/another/path");
-        ResourceChange c3 = Mockito.mock(ResourceChange.class);
-        Mockito.when(c3.getPath()).thenReturn("/excluded/path/node");
-        
-        assertTrue(sut.canIgnoreChange(c1));
-        assertFalse(sut.canIgnoreChange(c2));
-        assertTrue(sut.canIgnoreChange(c3));
-    }
-
 }
diff --git 
a/src/test/java/org/apache/sling/i18n/impl/JcrResourceBundleTest.java 
b/src/test/java/org/apache/sling/i18n/impl/JcrResourceBundleTest.java
index a737f86..c69cdeb 100644
--- a/src/test/java/org/apache/sling/i18n/impl/JcrResourceBundleTest.java
+++ b/src/test/java/org/apache/sling/i18n/impl/JcrResourceBundleTest.java
@@ -470,29 +470,29 @@ public class JcrResourceBundleTest extends 
RepositoryTestBase {
     // ---------------------------------------------------------------< tests >
 
     public void test_getString() {
-        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null);
+        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null, new PathFilter());
         for (Message msg : MESSAGES_DE.values()) {
             assertEquals(msg.message, bundle.getString(msg.key));
         }
 
-        bundle = new JcrResourceBundle(new Locale("en", "us"), null, resolver, 
null);
+        bundle = new JcrResourceBundle(new Locale("en", "us"), null, resolver, 
null, new PathFilter());
         for (Message msg : MESSAGES_EN_DASH_US.values()) {
             assertEquals(msg.message, bundle.getString(msg.key));
         }
 
-        bundle = new JcrResourceBundle(new Locale("en", "uk"), null, resolver, 
null);
+        bundle = new JcrResourceBundle(new Locale("en", "uk"), null, resolver, 
null, new PathFilter());
         for (Message msg : MESSAGES_EN_UNDERSCORE_UK.values()) {
             assertEquals(msg.message, bundle.getString(msg.key));
         }
 
-        bundle = new JcrResourceBundle(new Locale("en", "au"), null, resolver, 
null);
+        bundle = new JcrResourceBundle(new Locale("en", "au"), null, resolver, 
null, new PathFilter());
         for (Message msg : MESSAGES_EN_UNDERSCORE_AU.values()) {
             assertEquals(msg.message, bundle.getString(msg.key));
         }
     }
 
     public void test_getObject() {
-        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null);
+        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null, new PathFilter());
         for (Message msg : MESSAGES_DE.values()) {
             assertEquals(msg.message, (String) bundle.getObject(msg.key));
         }
@@ -500,13 +500,13 @@ public class JcrResourceBundleTest extends 
RepositoryTestBase {
 
     public void test_handle_missing_key() {
         // test if key is returned if no entry found in repo
-        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null);
+        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null, new PathFilter());
         bundle.setParent(new RootResourceBundle());
         assertEquals("missing", bundle.getString("missing"));
     }
 
     public void test_getKeys() {
-        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null);
+        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null, new PathFilter());
         Enumeration<String> keys = bundle.getKeys();
         int counter = 0;
         while (keys.hasMoreElements()) {
@@ -519,8 +519,8 @@ public class JcrResourceBundleTest extends 
RepositoryTestBase {
 
     public void test_bundle_parenting() {
         // set parent of resource bundle, test if passed through
-        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null);
-        JcrResourceBundle parentBundle = new JcrResourceBundle(new 
Locale("en"), null, resolver, null);
+        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null, new PathFilter());
+        JcrResourceBundle parentBundle = new JcrResourceBundle(new 
Locale("en"), null, resolver, null, new PathFilter());
         bundle.setParent(parentBundle);
         parentBundle.setParent(new RootResourceBundle());
 
@@ -540,7 +540,7 @@ public class JcrResourceBundleTest extends 
RepositoryTestBase {
         getSession().save();
 
         // test getString
-        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null);
+        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null, new PathFilter());
         for (Message msg : MESSAGES_DE_APPS.values()) {
             assertEquals(msg.message, bundle.getString(msg.key));
         }
@@ -571,7 +571,7 @@ public class JcrResourceBundleTest extends 
RepositoryTestBase {
         getSession().save();
 
         // test if /content dictionary is read at all
-        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null);
+        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null, new PathFilter());
         for (Message msg : MESSAGES_DE.values()) {
             assertEquals(msg.message, bundle.getString(msg.key));
         }
@@ -587,7 +587,7 @@ public class JcrResourceBundleTest extends 
RepositoryTestBase {
         getSession().save();
 
         // test if /libs (something in the search path) overlays /content 
(outside the search path)
-        bundle = new JcrResourceBundle(new Locale("de"), null, resolver, null);
+        bundle = new JcrResourceBundle(new Locale("de"), null, resolver, null, 
new PathFilter());
         for (Message msg : MESSAGES_DE_APPS.values()) {
             assertEquals(msg.message, bundle.getString(msg.key));
         }
@@ -616,13 +616,13 @@ public class JcrResourceBundleTest extends 
RepositoryTestBase {
         getSession().save();
 
         // test getString
-        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
"FOO", resolver, null);
+        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
"FOO", resolver, null, new PathFilter());
         for (Message msg : MESSAGES_DE_BASENAME.values()) {
             assertEquals(msg.message, bundle.getString(msg.key));
         }
         
         // test getString
-        bundle = new JcrResourceBundle(new Locale("de"), "BAR", resolver, 
null);
+        bundle = new JcrResourceBundle(new Locale("de"), "BAR", resolver, 
null, new PathFilter());
         for (Message msg : MESSAGES_DE_BASENAME.values()) {
             assertEquals(msg.message, bundle.getString(msg.key));
         }
@@ -661,7 +661,7 @@ public class JcrResourceBundleTest extends 
RepositoryTestBase {
         getSession().save();
 
         // test getString
-        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null);
+        JcrResourceBundle bundle = new JcrResourceBundle(new Locale("de"), 
null, resolver, null, new PathFilter());
         for (Message msg : MESSAGES_DE_APPS.values()) {
             assertEquals(msg.message, bundle.getString(msg.key));
         }
diff --git a/src/test/java/org/apache/sling/i18n/impl/PathFilterTest.java 
b/src/test/java/org/apache/sling/i18n/impl/PathFilterTest.java
new file mode 100644
index 0000000..c02f14d
--- /dev/null
+++ b/src/test/java/org/apache/sling/i18n/impl/PathFilterTest.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.i18n.impl;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class PathFilterTest {
+
+    @Test
+    public void testRootIncludeWithPathExclusions() {
+        final PathFilter filter = new PathFilter(new String[] {"/"}, new 
String[] {"/excluded/path"});
+
+        assertFalse(filter.includePath("/excluded/path"));
+        assertTrue(filter.includePath("/another/path"));
+        assertFalse(filter.includePath("/excluded/path/node"));
+    }
+
+    @Test
+    public void testIncludesAndExclusions() {
+        final PathFilter filter = new PathFilter(new String[] {"/libs", 
"/apps"}, new String[] {"/libs/foo"});
+
+        assertFalse(filter.includePath("/another/path"));
+        assertFalse(filter.includePath("/libs/foo/i18n"));
+        assertTrue(filter.includePath("/libs/app/me"));
+        assertTrue(filter.includePath("/apps/app/me"));
+    }
+}

Reply via email to