Support looking up properties resources via class loader and from URLs

A new framework property 'sling.feature.apiregions.location' is
introduced to identify the directory where the apiregions properties
files can be found.
The system property prefix 'apiregions.' has been changed to
'sling.feature.apiregions.resource.'
Both properties now support URLs as well as file paths. Additionally,
the 'classloader://' URL pseudo-protocol is introduced which looks up the
location provided using the classloader’s getResource().
diff --git a/pom.xml b/pom.xml
index c4c8c1c..abeb95e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -64,6 +64,7 @@
                     <excludes>
                         <exclude>*.md</exclude>
                         <exclude>src/test/resources/*</exclude>
+                        <exclude>src/test/resources/props1/*</exclude>
                     </excludes>
                 </configuration>
             </plugin>
diff --git a/src/main/java/org/apache/sling/feature/apiregions/impl/Activator.java b/src/main/java/org/apache/sling/feature/apiregions/impl/Activator.java
index 95f5cc7..8064b02 100644
--- a/src/main/java/org/apache/sling/feature/apiregions/impl/Activator.java
+++ b/src/main/java/org/apache/sling/feature/apiregions/impl/Activator.java
@@ -35,7 +35,7 @@
             return; // Component not enabled
 
         Dictionary<String, Object> props = new Hashtable<>();
-        RegionEnforcer enforcer = new RegionEnforcer(props, regions);
+        RegionEnforcer enforcer = new RegionEnforcer(context, props, regions);
         context.registerService(ResolverHookFactory.class, enforcer, props);
     }
 
diff --git a/src/main/java/org/apache/sling/feature/apiregions/impl/RegionEnforcer.java b/src/main/java/org/apache/sling/feature/apiregions/impl/RegionEnforcer.java
index cf20e0d..7ab5bca 100644
--- a/src/main/java/org/apache/sling/feature/apiregions/impl/RegionEnforcer.java
+++ b/src/main/java/org/apache/sling/feature/apiregions/impl/RegionEnforcer.java
@@ -18,15 +18,17 @@
  */
 package org.apache.sling.feature.apiregions.impl;
 
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.Version;
 import org.osgi.framework.hooks.resolver.ResolverHook;
 import org.osgi.framework.hooks.resolver.ResolverHookFactory;
 import org.osgi.framework.wiring.BundleRevision;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.AbstractMap;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -41,9 +43,13 @@
 import java.util.Set;
 
 class RegionEnforcer implements ResolverHookFactory {
-    public static String GLOBAL_REGION = "global";
+    private static final String CLASSLOADER_PSEUDO_PROTOCOL = "classloader://";
 
-    static final String PROPERTIES_FILE_PREFIX = "apiregions.";
+    public static final String GLOBAL_REGION = "global";
+
+    static final String PROPERTIES_RESOURCE_PREFIX = "sling.feature.apiregions.resource.";
+    static final String PROPERTIES_FILE_LOCATION = "sling.feature.apiregions.location";
+
     static final String IDBSNVER_FILENAME = "idbsnver.properties";
     static final String BUNDLE_FEATURE_FILENAME = "bundles.properties";
     static final String FEATURE_REGION_FILENAME = "features.properties";
@@ -55,101 +61,127 @@
     final Map<String, Set<String>> regionPackageMap;
     final Set<String> enabledRegions;
 
-    RegionEnforcer(Dictionary<String, Object> regProps, String regionsProp) throws IOException {
-        File idbsnverFile = getDataFile(IDBSNVER_FILENAME);
+    RegionEnforcer(BundleContext context, Dictionary<String, Object> regProps, String regionsProp) throws Exception {
+        URI idbsnverFile = getDataFileURI(context, IDBSNVER_FILENAME);
         bsnVerMap = populateBSNVerMap(idbsnverFile);
         if (idbsnverFile != null) {
-            regProps.put(IDBSNVER_FILENAME, idbsnverFile.getAbsolutePath());
+            // Register the location as a service property for diagnostic purposes
+            regProps.put(IDBSNVER_FILENAME, idbsnverFile.toString());
         }
 
-        File bundlesFile = getDataFile(BUNDLE_FEATURE_FILENAME);
+        URI bundlesFile = getDataFileURI(context, BUNDLE_FEATURE_FILENAME);
         bundleFeatureMap = populateBundleFeatureMap(bundlesFile);
         if (bundlesFile != null) {
-            regProps.put(BUNDLE_FEATURE_FILENAME, bundlesFile.getAbsolutePath());
+            // Register the location as a service property for diagnostic purposes
+            regProps.put(BUNDLE_FEATURE_FILENAME, bundlesFile.toString());
         }
 
-        File featuresFile = getDataFile(FEATURE_REGION_FILENAME);
+        URI featuresFile = getDataFileURI(context, FEATURE_REGION_FILENAME);
         featureRegionMap = populateFeatureRegionMap(featuresFile);
         if (featuresFile != null) {
-            regProps.put(FEATURE_REGION_FILENAME, featuresFile.getAbsolutePath());
+            // Register the location as a service property for diagnostic purposes
+            regProps.put(FEATURE_REGION_FILENAME, featuresFile.toString());
         }
 
-        File regionsFile = getDataFile(REGION_PACKAGE_FILENAME);
+        URI regionsFile = getDataFileURI(context, REGION_PACKAGE_FILENAME);
         regionPackageMap = populateRegionPackageMap(regionsFile);
         if (regionsFile != null) {
-            regProps.put(REGION_PACKAGE_FILENAME, regionsFile.getAbsolutePath());
+            // Register the location as a service property for diagnostic purposes
+            regProps.put(REGION_PACKAGE_FILENAME, regionsFile.toString());
         }
 
         enabledRegions = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(regionsProp.split(","))));
     }
 
-    private Map<Map.Entry<String, Version>, List<String>> populateBSNVerMap(File idbsnverFile) throws IOException {
-        if (idbsnverFile != null && idbsnverFile.exists()) {
-            Map<Map.Entry<String, Version>, List<String>> m = new HashMap<>();
-
-            Properties p = new Properties();
-            try (InputStream is = new FileInputStream(idbsnverFile)) {
-                p.load(is);
-            }
-
-            for (String n : p.stringPropertyNames()) {
-                String[] bsnver = p.getProperty(n).split("~");
-                Map.Entry<String, Version> key = new AbstractMap.SimpleEntry<String, Version>(bsnver[0], Version.valueOf(bsnver[1]));
-                List<String> l = m.get(key);
-                if (l == null) {
-                    l = new ArrayList<>();
-                    m.put(key, l);
-                }
-                l.add(n);
-            }
-
-            Map<Map.Entry<String, Version>, List<String>> m2 = new HashMap<>();
-
-            for (Map.Entry<Map.Entry<String, Version>, List<String>> entry : m.entrySet()) {
-                m2.put(entry.getKey(), Collections.unmodifiableList(entry.getValue()));
-            }
-
-            return Collections.unmodifiableMap(m2);
-        } else {
+    private Map<Map.Entry<String, Version>, List<String>> populateBSNVerMap(URI idbsnverFile) throws IOException {
+        if (idbsnverFile == null) {
             return Collections.emptyMap();
         }
+
+        Map<Map.Entry<String, Version>, List<String>> m = new HashMap<>();
+
+        Properties p = new Properties();
+        try (InputStream is = idbsnverFile.toURL().openStream()) {
+            p.load(is);
+        }
+
+        for (String n : p.stringPropertyNames()) {
+            String[] bsnver = p.getProperty(n).split("~");
+            Map.Entry<String, Version> key = new AbstractMap.SimpleEntry<String, Version>(bsnver[0], Version.valueOf(bsnver[1]));
+            List<String> l = m.get(key);
+            if (l == null) {
+                l = new ArrayList<>();
+                m.put(key, l);
+            }
+            l.add(n);
+        }
+
+        Map<Map.Entry<String, Version>, List<String>> m2 = new HashMap<>();
+
+        for (Map.Entry<Map.Entry<String, Version>, List<String>> entry : m.entrySet()) {
+            m2.put(entry.getKey(), Collections.unmodifiableList(entry.getValue()));
+        }
+
+        return Collections.unmodifiableMap(m2);
     }
 
-    private Map<String, Set<String>> populateBundleFeatureMap(File bundlesFile) throws IOException {
+    private Map<String, Set<String>> populateBundleFeatureMap(URI bundlesFile) throws IOException {
         return loadMap(bundlesFile);
     }
 
-    private Map<String, Set<String>> populateFeatureRegionMap(File featuresFile) throws IOException {
+    private Map<String, Set<String>> populateFeatureRegionMap(URI featuresFile) throws IOException {
         return loadMap(featuresFile);
     }
 
-    private Map<String, Set<String>> populateRegionPackageMap(File regionsFile) throws IOException {
+    private Map<String, Set<String>> populateRegionPackageMap(URI regionsFile) throws IOException {
         return loadMap(regionsFile);
     }
 
-    private Map<String, Set<String>> loadMap(File propsFile) throws IOException {
+    private Map<String, Set<String>> loadMap(URI propsFile) throws IOException {
+        if (propsFile == null) {
+            return Collections.emptyMap();
+        }
         Map<String, Set<String>> m = new HashMap<>();
 
-        if (propsFile != null && propsFile.exists()) {
-            Properties p = new Properties();
-            try (InputStream is = new FileInputStream(propsFile)) {
-                p.load(is);
-            }
+        Properties p = new Properties();
+        try (InputStream is = propsFile.toURL().openStream()) {
+            p.load(is);
+        }
 
-            for (String n : p.stringPropertyNames()) {
-                String[] features = p.getProperty(n).split(",");
-                m.put(n, Collections.unmodifiableSet(new HashSet<>(Arrays.asList(features))));
-            }
+        for (String n : p.stringPropertyNames()) {
+            String[] features = p.getProperty(n).split(",");
+            m.put(n, Collections.unmodifiableSet(new HashSet<>(Arrays.asList(features))));
         }
 
         return Collections.unmodifiableMap(m);
     }
 
-    private File getDataFile(String name) throws IOException {
-        String fn = System.getProperty(PROPERTIES_FILE_PREFIX + name);
+    private URI getDataFileURI(BundleContext ctx, String name) throws IOException, URISyntaxException {
+        String fn = ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + name);
+        if (fn == null) {
+            String loc = ctx.getProperty(PROPERTIES_FILE_LOCATION);
+            if (loc != null) {
+                fn = loc + "/" + name;
+            }
+        }
+
         if (fn == null)
             return null;
-        return new File(fn);
+
+        if (fn.contains(":")) {
+            if (fn.startsWith(CLASSLOADER_PSEUDO_PROTOCOL)) {
+                // It's using the 'classloader:' protocol looks up the location from the classloader
+                String loc = fn.substring(CLASSLOADER_PSEUDO_PROTOCOL.length());
+                if (!loc.startsWith("/"))
+                    loc = "/" + loc;
+                fn = getClass().getResource(loc).toString();
+            }
+            // It's already a URL
+            return new URI(fn);
+        } else {
+            // It's a file location
+            return new File(fn).toURI();
+        }
     }
 
     @Override
diff --git a/src/test/java/org/apache/sling/feature/apiregions/impl/ActivatorTest.java b/src/test/java/org/apache/sling/feature/apiregions/impl/ActivatorTest.java
index 20924c9..9a279fd 100644
--- a/src/test/java/org/apache/sling/feature/apiregions/impl/ActivatorTest.java
+++ b/src/test/java/org/apache/sling/feature/apiregions/impl/ActivatorTest.java
@@ -25,12 +25,13 @@
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.hooks.resolver.ResolverHookFactory;
 
+import java.io.File;
 import java.util.Dictionary;
 import java.util.Hashtable;
 import java.util.Properties;
 
 import static org.apache.sling.feature.apiregions.impl.RegionEnforcer.FEATURE_REGION_FILENAME;
-import static org.apache.sling.feature.apiregions.impl.RegionEnforcer.PROPERTIES_FILE_PREFIX;
+import static org.apache.sling.feature.apiregions.impl.RegionEnforcer.PROPERTIES_RESOURCE_PREFIX;
 
 public class ActivatorTest {
     private Properties savedProps;
@@ -50,13 +51,14 @@
     @Test
     public void testStart() throws Exception {
         String f = getClass().getResource("/features1.properties").getFile();
-        System.setProperty(PROPERTIES_FILE_PREFIX + FEATURE_REGION_FILENAME, f);
 
         Dictionary<String, Object> expectedProps = new Hashtable<>();
-        expectedProps.put(FEATURE_REGION_FILENAME, f);
+        expectedProps.put(FEATURE_REGION_FILENAME, new File(f).toURI().toString());
 
         BundleContext bc = Mockito.mock(BundleContext.class);
         Mockito.when(bc.getProperty(Activator.REGIONS_PROPERTY_NAME)).thenReturn("*");
+        Mockito.when(bc.getProperty(PROPERTIES_RESOURCE_PREFIX + FEATURE_REGION_FILENAME)).
+            thenReturn(f);
 
         Activator a = new Activator();
         a.start(bc);
diff --git a/src/test/java/org/apache/sling/feature/apiregions/impl/RegionEnforcerTest.java b/src/test/java/org/apache/sling/feature/apiregions/impl/RegionEnforcerTest.java
index 322c3f3..7fd0be6 100644
--- a/src/test/java/org/apache/sling/feature/apiregions/impl/RegionEnforcerTest.java
+++ b/src/test/java/org/apache/sling/feature/apiregions/impl/RegionEnforcerTest.java
@@ -18,44 +18,33 @@
  */
 package org.apache.sling.feature.apiregions.impl;
 
-import org.junit.After;
-import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.Version;
 
+import java.io.File;
 import java.util.AbstractMap;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Hashtable;
-import java.util.Properties;
 
 import static org.apache.sling.feature.apiregions.impl.RegionEnforcer.BUNDLE_FEATURE_FILENAME;
 import static org.apache.sling.feature.apiregions.impl.RegionEnforcer.FEATURE_REGION_FILENAME;
 import static org.apache.sling.feature.apiregions.impl.RegionEnforcer.IDBSNVER_FILENAME;
-import static org.apache.sling.feature.apiregions.impl.RegionEnforcer.PROPERTIES_FILE_PREFIX;
+import static org.apache.sling.feature.apiregions.impl.RegionEnforcer.PROPERTIES_FILE_LOCATION;
+import static org.apache.sling.feature.apiregions.impl.RegionEnforcer.PROPERTIES_RESOURCE_PREFIX;
 import static org.apache.sling.feature.apiregions.impl.RegionEnforcer.REGION_PACKAGE_FILENAME;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 public class RegionEnforcerTest {
-    private Properties savedProps;
-
-    @Before
-    public void setup() {
-        savedProps = new Properties(); // note that new Properties(props) doesn't copy
-        savedProps.putAll(System.getProperties());
-    }
-
-    @After
-    public void teardown() {
-        System.setProperties(savedProps);
-        savedProps = null;
-    }
-
     @Test
     public void testRegionEnforcerNoConfiguration() throws Exception {
-        RegionEnforcer re = new RegionEnforcer(new Hashtable<String, Object>(), "*");
+        BundleContext ctx = Mockito.mock(BundleContext.class);
+
+        RegionEnforcer re = new RegionEnforcer(ctx, new Hashtable<String, Object>(), "*");
         assertEquals(0, re.bsnVerMap.size());
         assertEquals(0, re.bundleFeatureMap.size());
         assertEquals(0, re.featureRegionMap.size());
@@ -65,25 +54,27 @@
     @Test
     public void testLoadBSNVerMap() throws Exception {
         String f = getClass().getResource("/idbsnver1.properties").getFile();
-        System.setProperty(PROPERTIES_FILE_PREFIX + IDBSNVER_FILENAME, f);
+        BundleContext ctx = Mockito.mock(BundleContext.class);
+        Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + IDBSNVER_FILENAME)).thenReturn(f);
 
         Hashtable<String, Object> props = new Hashtable<>();
-        RegionEnforcer re = new RegionEnforcer(props, "*");
+        RegionEnforcer re = new RegionEnforcer(ctx, props, "*");
         assertEquals(2, re.bsnVerMap.size());
         assertEquals(Collections.singletonList("g:b1:1"),
                 re.bsnVerMap.get(new AbstractMap.SimpleEntry<String,Version>("b1", new Version(1,0,0))));
         assertEquals(new HashSet<>(Arrays.asList("g:b2:1.2.3", "g2:b2:1.2.4")),
                 new HashSet<>(re.bsnVerMap.get(new AbstractMap.SimpleEntry<String,Version>("b2", new Version(1,2,3)))));
-        assertEquals(f, props.get(IDBSNVER_FILENAME));
+        assertEquals(new File(f).toURI().toString(), props.get(IDBSNVER_FILENAME));
     }
 
     @Test
     public void testLoadBundleFeatureMap() throws Exception {
         String f = getClass().getResource("/bundles1.properties").getFile();
-        System.setProperty(PROPERTIES_FILE_PREFIX + BUNDLE_FEATURE_FILENAME, f);
+        BundleContext ctx = Mockito.mock(BundleContext.class);
+        Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + BUNDLE_FEATURE_FILENAME)).thenReturn(f);
 
         Hashtable<String, Object> props = new Hashtable<>();
-        RegionEnforcer re = new RegionEnforcer(props, "*");
+        RegionEnforcer re = new RegionEnforcer(ctx, props, "*");
         assertEquals(3, re.bundleFeatureMap.size());
         assertEquals(Collections.singleton("org.sling:something:1.2.3:slingosgifeature:myclassifier"),
                 re.bundleFeatureMap.get("org.sling:b1:1"));
@@ -91,51 +82,54 @@
                 re.bundleFeatureMap.get("org.sling:b2:1"));
         assertEquals(new HashSet<>(Arrays.asList("some.other:feature:123", "org.sling:something:1.2.3:slingosgifeature:myclassifier")),
                 re.bundleFeatureMap.get("org.sling:b3:1"));
-        assertEquals(f, props.get(BUNDLE_FEATURE_FILENAME));
+        assertEquals(new File(f).toURI().toString(), props.get(BUNDLE_FEATURE_FILENAME));
     }
 
     @Test
     public void testLoadFeatureRegionMap() throws Exception {
         String f = getClass().getResource("/features1.properties").getFile();
-        System.setProperty(PROPERTIES_FILE_PREFIX + FEATURE_REGION_FILENAME, f);
+        BundleContext ctx = Mockito.mock(BundleContext.class);
+        Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + FEATURE_REGION_FILENAME)).thenReturn(f);
 
         Hashtable<String, Object> props = new Hashtable<>();
-        RegionEnforcer re = new RegionEnforcer(props, "*");
+        RegionEnforcer re = new RegionEnforcer(ctx, props, "*");
         assertEquals(2, re.featureRegionMap.size());
         assertEquals(Collections.singleton("global"),
                 re.featureRegionMap.get("an.other:feature:123"));
         assertEquals(new HashSet<>(Arrays.asList("global", "internal")),
                 re.featureRegionMap.get("org.sling:something:1.2.3"));
-        assertEquals(f, props.get(FEATURE_REGION_FILENAME));
+        assertEquals(new File(f).toURI().toString(), props.get(FEATURE_REGION_FILENAME));
     }
 
     @Test
     public void testLoadRegionPackageMap() throws Exception {
         String f = getClass().getResource("/regions1.properties").getFile();
-        System.setProperty(PROPERTIES_FILE_PREFIX + REGION_PACKAGE_FILENAME, f);
+        BundleContext ctx = Mockito.mock(BundleContext.class);
+        Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + REGION_PACKAGE_FILENAME)).thenReturn(f);
 
         Hashtable<String, Object> props = new Hashtable<>();
-        RegionEnforcer re = new RegionEnforcer(props, "*");
+        RegionEnforcer re = new RegionEnforcer(ctx, props, "*");
         assertEquals(2, re.regionPackageMap.size());
         assertEquals(Collections.singleton("xyz"),
                 re.regionPackageMap.get("internal"));
         assertEquals(new HashSet<>(Arrays.asList("a.b.c", "d.e.f", "test")),
                 re.regionPackageMap.get("global"));
-        assertEquals(f, props.get(REGION_PACKAGE_FILENAME));
+        assertEquals(new File(f).toURI().toString(), props.get(REGION_PACKAGE_FILENAME));
     }
 
     @Test
     public void testBegin() throws Exception {
-        System.setProperty(PROPERTIES_FILE_PREFIX + IDBSNVER_FILENAME,
-                getClass().getResource("/idbsnver1.properties").getFile());
-        System.setProperty(PROPERTIES_FILE_PREFIX + BUNDLE_FEATURE_FILENAME,
-                getClass().getResource("/bundles1.properties").getFile());
-        System.setProperty(PROPERTIES_FILE_PREFIX + FEATURE_REGION_FILENAME,
-                getClass().getResource("/features1.properties").getFile());
-        System.setProperty(PROPERTIES_FILE_PREFIX + REGION_PACKAGE_FILENAME,
-                getClass().getResource("/regions1.properties").getFile());
+        BundleContext ctx = Mockito.mock(BundleContext.class);
+        Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + IDBSNVER_FILENAME)).
+            thenReturn(getClass().getResource("/idbsnver1.properties").getFile());
+        Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + BUNDLE_FEATURE_FILENAME)).
+            thenReturn(getClass().getResource("/bundles1.properties").getFile());
+        Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + FEATURE_REGION_FILENAME)).
+            thenReturn(getClass().getResource("/features1.properties").getFile());
+        Mockito.when(ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + REGION_PACKAGE_FILENAME)).
+            thenReturn(getClass().getResource("/regions1.properties").getFile());
 
-        RegionEnforcer re = new RegionEnforcer(new Hashtable<String, Object>(), "*");
+        RegionEnforcer re = new RegionEnforcer(ctx, new Hashtable<String, Object>(), "*");
         assertTrue(re.bsnVerMap.size() > 0);
         assertTrue(re.bundleFeatureMap.size() > 0);
         assertTrue(re.featureRegionMap.size() > 0);
@@ -147,4 +141,30 @@
         assertEquals(re.featureRegionMap, hook.featureRegionMap);
         assertEquals(re.regionPackageMap, hook.regionPackageMap);
     }
+
+    @Test
+    public void testURLs() throws Exception {
+        BundleContext ctx = Mockito.mock(BundleContext.class);
+        String location = new File(getClass().getResource("/props1/idbsnver.properties").
+                getFile()).getParentFile().toURI().toString();
+        Mockito.when(ctx.getProperty(PROPERTIES_FILE_LOCATION)).thenReturn(location);
+
+        RegionEnforcer re = new RegionEnforcer(ctx, new Hashtable<String, Object>(), "*");
+        assertTrue(re.bsnVerMap.size() > 0);
+        assertTrue(re.bundleFeatureMap.size() > 0);
+        assertTrue(re.featureRegionMap.size() > 0);
+        assertTrue(re.regionPackageMap.size() > 0);
+    }
+
+    @Test
+    public void testClassloaderURLs() throws Exception {
+        BundleContext ctx = Mockito.mock(BundleContext.class);
+        Mockito.when(ctx.getProperty(PROPERTIES_FILE_LOCATION)).thenReturn("classloader://props1");
+
+        RegionEnforcer re = new RegionEnforcer(ctx, new Hashtable<String, Object>(), "*");
+        assertTrue(re.bsnVerMap.size() > 0);
+        assertTrue(re.bundleFeatureMap.size() > 0);
+        assertTrue(re.featureRegionMap.size() > 0);
+        assertTrue(re.regionPackageMap.size() > 0);
+    }
 }
diff --git a/src/test/resources/props1/bundles.properties b/src/test/resources/props1/bundles.properties
new file mode 100644
index 0000000..7497eaf
--- /dev/null
+++ b/src/test/resources/props1/bundles.properties
@@ -0,0 +1,5 @@
+#Generated at Sat Nov 03 10:58:58 GMT 2018
+#Sat Nov 03 10:58:58 GMT 2018
+org.sling\:b3\:1=some.other\:feature\:123,org.sling\:something\:1.2.3\:slingosgifeature\:myclassifier
+org.sling\:b2\:1=org.sling\:something\:1.2.3\:slingosgifeature\:myclassifier
+org.sling\:b1\:1=org.sling\:something\:1.2.3\:slingosgifeature\:myclassifier
diff --git a/src/test/resources/props1/features.properties b/src/test/resources/props1/features.properties
new file mode 100644
index 0000000..9efad8d
--- /dev/null
+++ b/src/test/resources/props1/features.properties
@@ -0,0 +1,4 @@
+#Generated at Sat Nov 03 11:10:29 GMT 2018
+#Sat Nov 03 11:10:29 GMT 2018
+an.other\:feature\:123=global
+org.sling\:something\:1.2.3=internal,global
diff --git a/src/test/resources/props1/idbsnver.properties b/src/test/resources/props1/idbsnver.properties
new file mode 100644
index 0000000..00a740d
--- /dev/null
+++ b/src/test/resources/props1/idbsnver.properties
@@ -0,0 +1,6 @@
+#Generated at Sat Nov 03 10:26:37 GMT 2018
+#Sat Nov 03 10:26:37 GMT 2018
+g\:b2\:1.2.3=b2~1.2.3
+g\:b1\:1=b1~1.0.0
+g2\:b2\:1.2.4=b2~1.2.3
+
diff --git a/src/test/resources/props1/regions.properties b/src/test/resources/props1/regions.properties
new file mode 100644
index 0000000..a4982d7
--- /dev/null
+++ b/src/test/resources/props1/regions.properties
@@ -0,0 +1,4 @@
+#Generated at Sat Nov 03 11:10:29 GMT 2018
+#Sat Nov 03 11:10:29 GMT 2018
+internal=xyz
+global=d.e.f,test,a.b.c