Merge with Master
diff --git a/pom.xml b/pom.xml
index c91d51a..634ef5c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -162,5 +162,11 @@
             <version>1.1.1</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.feature.io</artifactId>
+            <version>1.0.3-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git a/src/main/java/org/apache/sling/feature/scanner/ArtifactDescriptor.java b/src/main/java/org/apache/sling/feature/scanner/ArtifactDescriptor.java
index 92fe7e2..c717356 100644
--- a/src/main/java/org/apache/sling/feature/scanner/ArtifactDescriptor.java
+++ b/src/main/java/org/apache/sling/feature/scanner/ArtifactDescriptor.java
@@ -29,6 +29,7 @@
  * descriptor is locked, it is safe to access it concurrently.
  */
 public abstract class ArtifactDescriptor extends Descriptor {
+
     protected ArtifactDescriptor(String name) {
         super(name);
     }
diff --git a/src/main/java/org/apache/sling/feature/scanner/BundleDescriptor.java b/src/main/java/org/apache/sling/feature/scanner/BundleDescriptor.java
index caa59fb..8e98bbb 100644
--- a/src/main/java/org/apache/sling/feature/scanner/BundleDescriptor.java
+++ b/src/main/java/org/apache/sling/feature/scanner/BundleDescriptor.java
@@ -29,6 +29,7 @@
  * descriptor is locked, it is safe to access it concurrently.
  */
 public abstract class BundleDescriptor extends ArtifactDescriptor implements Comparable<BundleDescriptor> {
+
     protected BundleDescriptor(String name) {
         super(name);
     }
diff --git a/src/main/java/org/apache/sling/feature/scanner/Descriptor.java b/src/main/java/org/apache/sling/feature/scanner/Descriptor.java
index 3235e6b..2dde3d8 100644
--- a/src/main/java/org/apache/sling/feature/scanner/Descriptor.java
+++ b/src/main/java/org/apache/sling/feature/scanner/Descriptor.java
@@ -20,8 +20,8 @@
 import java.util.HashSet;
 import java.util.Set;
 
+import org.apache.sling.feature.MatchingRequirement;
 import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
 
 /**
  * A descriptor holds information about requirements and capabilities.
@@ -32,6 +32,7 @@
  * descriptor is locked, it is safe to access it concurrently.
  */
 public abstract class Descriptor  {
+
     private final String name;
 
     private boolean locked;
@@ -42,7 +43,7 @@
 
     private final Set<PackageInfo> dynImports = new HashSet<>();
 
-    private final Set<Requirement> reqs = new HashSet<>();
+    private final Set<MatchingRequirement> reqs = new HashSet<>();
 
     private final Set<Capability> caps = new HashSet<>();
 
@@ -96,7 +97,7 @@
      * Return the list of requirements.
      * @return The list of requirements. The list might be empty.
      */
-    public final Set<Requirement> getRequirements() {
+    public final Set<MatchingRequirement> getRequirements() {
         return locked ? Collections.unmodifiableSet(reqs) : reqs;
     }
 
diff --git a/src/main/java/org/apache/sling/feature/scanner/FeatureDescriptor.java b/src/main/java/org/apache/sling/feature/scanner/FeatureDescriptor.java
index bc0332e..a3b4d3d 100644
--- a/src/main/java/org/apache/sling/feature/scanner/FeatureDescriptor.java
+++ b/src/main/java/org/apache/sling/feature/scanner/FeatureDescriptor.java
@@ -27,6 +27,7 @@
  * descriptor is locked, it is safe to access it concurrently.
  */
 public abstract class FeatureDescriptor extends ContainerDescriptor {
+
     private final Feature feature;
 
     protected FeatureDescriptor(Feature f) {
diff --git a/src/main/java/org/apache/sling/feature/scanner/impl/BundleDescriptorImpl.java b/src/main/java/org/apache/sling/feature/scanner/impl/BundleDescriptorImpl.java
index 4abd7ff..74cf932 100644
--- a/src/main/java/org/apache/sling/feature/scanner/impl/BundleDescriptorImpl.java
+++ b/src/main/java/org/apache/sling/feature/scanner/impl/BundleDescriptorImpl.java
@@ -21,12 +21,11 @@
 import org.apache.felix.utils.resource.ResourceBuilder;
 import org.apache.felix.utils.resource.ResourceImpl;
 import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.io.IOUtils;
 import org.apache.sling.feature.scanner.BundleDescriptor;
 import org.apache.sling.feature.scanner.PackageInfo;
 import org.osgi.framework.Constants;
-import sun.net.www.protocol.jar.JarURLConnection;
 
-import java.io.File;
 import java.io.IOException;
 import java.net.URL;
 import java.util.ArrayList;
@@ -70,7 +69,7 @@
         this.artifact = a;
         this.artifactFile = file;
         this.startLevel = startLevel;
-        try (final JarFile jarFile = ((JarURLConnection) ("jar".equals(this.artifactFile.getProtocol()) ? this.artifactFile : new URL("jar:" + this.artifactFile + "!/")).openConnection()).getJarFile()) {
+        try (final JarFile jarFile = IOUtils.getJarFileFromURL(this.artifactFile, true, null)) {
             this.manifest = jarFile.getManifest();
         }
         if ( this.manifest == null ) {
@@ -143,7 +142,8 @@
                 ResourceImpl resource = ResourceBuilder.build(null, this.manifest.getMainAttributes().entrySet().stream()
                     .collect(Collectors.toMap(entry -> entry.getKey().toString(), entry -> entry.getValue().toString())));
                 this.getCapabilities().addAll(resource.getCapabilities(null));
-                this.getRequirements().addAll(resource.getRequirements(null));
+                this.getRequirements().addAll(resource.getRequirements(null).stream()
+                        .map(entry -> new MatchingRequirementImpl(entry)).collect(Collectors.toList()));
             } catch (Exception ex) {
                 throw new IOException(ex);
             }
diff --git a/src/main/java/org/apache/sling/feature/scanner/impl/MatchingRequirementImpl.java b/src/main/java/org/apache/sling/feature/scanner/impl/MatchingRequirementImpl.java
new file mode 100644
index 0000000..d43ed31
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/scanner/impl/MatchingRequirementImpl.java
@@ -0,0 +1,50 @@
+/*
+ * 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.feature.scanner.impl;
+
+import java.util.Map;
+import java.util.Objects;
+
+import org.apache.felix.utils.resource.RequirementImpl;
+import org.apache.sling.feature.MatchingRequirement;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+class MatchingRequirementImpl extends RequirementImpl implements MatchingRequirement {
+
+    public MatchingRequirementImpl(final Requirement req) {
+        super(req.getResource(), req.getNamespace(), req.getDirectives(), req.getAttributes());
+    }
+
+    public MatchingRequirementImpl(final Resource res, final String ns, final Map<String, String> dirs,
+            final Map<String, Object> attrs) {
+        super(res, ns, dirs, attrs);
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || !(o instanceof RequirementImpl)) {
+            return false;
+        }
+        final RequirementImpl that = (RequirementImpl) o;
+        return Objects.equals(resource, that.getResource()) && Objects.equals(namespace, that.getNamespace())
+                && Objects.equals(attributes, that.getAttributes()) && Objects.equals(directives, that.getDirectives());
+    }
+}
diff --git a/src/main/java/org/apache/sling/feature/scanner/impl/RepoInitScanner.java b/src/main/java/org/apache/sling/feature/scanner/impl/RepoInitScanner.java
index c700be5..8965e5a 100644
--- a/src/main/java/org/apache/sling/feature/scanner/impl/RepoInitScanner.java
+++ b/src/main/java/org/apache/sling/feature/scanner/impl/RepoInitScanner.java
@@ -16,20 +16,20 @@
  */
 package org.apache.sling.feature.scanner.impl;
 
-import org.apache.felix.utils.resource.RequirementImpl;
-import org.apache.sling.feature.Extension;
-import org.apache.sling.feature.ExtensionType;
-import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.builder.ArtifactProvider;
-import org.apache.sling.feature.scanner.ContainerDescriptor;
-import org.apache.sling.feature.scanner.spi.ExtensionScanner;
-import org.osgi.resource.Requirement;
-
 import java.io.IOException;
 import java.util.Collections;
 
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.MatchingRequirement;
+import org.apache.sling.feature.builder.ArtifactProvider;
+import org.apache.sling.feature.scanner.ContainerDescriptor;
+import org.apache.sling.feature.scanner.spi.ExtensionScanner;
+
 public class RepoInitScanner implements ExtensionScanner {
-    private static final Requirement REQUIREMENT_REPOINIT = new RequirementImpl(null, "osgi.implementation",
+    private static final MatchingRequirement REQUIREMENT_REPOINIT = new MatchingRequirementImpl(null,
+            "osgi.implementation",
             Collections.singletonMap("filter", "(&(osgi.implementation=org.apache.sling.jcr.repoinit)(version>=1.0)(!(version>=2.0)))"),
                     null);
 
diff --git a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRequirementsCapabilitiesTest.java b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRequirementsCapabilitiesTest.java
index 9555295..ea693b9 100644
--- a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRequirementsCapabilitiesTest.java
+++ b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRequirementsCapabilitiesTest.java
@@ -16,11 +16,17 @@
  */
 package org.apache.sling.feature.analyser.task.impl;
 
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Objects;
+
 import org.apache.felix.utils.resource.CapabilityImpl;
 import org.apache.felix.utils.resource.RequirementImpl;
 import org.apache.sling.feature.Artifact;
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.MatchingRequirement;
 import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
 import org.apache.sling.feature.scanner.BundleDescriptor;
 import org.apache.sling.feature.scanner.FeatureDescriptor;
@@ -29,11 +35,7 @@
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collections;
+import org.osgi.resource.Resource;
 
 
 public class CheckRequirementsCapabilitiesTest {
@@ -53,7 +55,7 @@
         Capability cap2 = new CapabilityImpl(null,
                 "org.foo.bar", Collections.emptyMap(),
                 Collections.singletonMap("abc", "def"));
-        Requirement req = new RequirementImpl(null,
+        MatchingRequirement req = new MatchingRequirementImpl(null,
                 "org.zzz", "(&(zzz=aaa)(qqq=123))");
 
         feature.getCapabilities().addAll(Arrays.asList(cap1, cap2));
@@ -104,7 +106,7 @@
         Capability cap2 = new CapabilityImpl(null,
                 "org.foo.bar", Collections.emptyMap(),
                 Collections.singletonMap("abc", "def"));
-        Requirement req = new RequirementImpl(null,
+        MatchingRequirement req = new MatchingRequirementImpl(null,
                 "org.zzz", "(&(zzz=aaa)(qqq=123))");
 
         feature.getCapabilities().addAll(Arrays.asList(cap1, cap2));
@@ -121,4 +123,25 @@
 
         Mockito.verify(ctx).reportError(Mockito.contains("org.zzz"));
     }
+
+    private static class MatchingRequirementImpl extends RequirementImpl implements MatchingRequirement {
+
+        public MatchingRequirementImpl(Resource res, String ns, String filter) {
+            super(res, ns, filter);
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || !(o instanceof RequirementImpl)) {
+                return false;
+            }
+            final RequirementImpl that = (RequirementImpl) o;
+            return Objects.equals(resource, that.getResource()) && Objects.equals(namespace, that.getNamespace())
+                    && Objects.equals(attributes, that.getAttributes())
+                    && Objects.equals(directives, that.getDirectives());
+        }
+    }
 }