You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gg...@apache.org on 2017/12/02 20:26:58 UTC
[karaf] 05/11: [KARAF-5376] Polish LocationPattern and
FeaturePattern helpers for blacklist/override matching
This is an automated email from the ASF dual-hosted git repository.
ggrzybek pushed a commit to branch KARAF-5376-overrides_v2
in repository https://gitbox.apache.org/repos/asf/karaf.git
commit 37e211b070da61762f209ff5ff2fc5115c4c5146
Author: Grzegorz Grzybek <gr...@gmail.com>
AuthorDate: Wed Nov 15 15:27:34 2017 +0100
[KARAF-5376] Polish LocationPattern and FeaturePattern helpers for blacklist/override matching
---
.../org/apache/karaf/features/FeaturePattern.java | 108 +++++++++++++
.../{internal/service => }/LocationPattern.java | 23 +--
.../model/processing/BundleReplacements.java | 4 +-
.../model/processing/FeaturesProcessing.java | 5 +-
.../karaf/features/internal/service/Blacklist.java | 176 ++++++++-------------
.../internal/service/FeaturesProcessorImpl.java | 17 +-
.../features/karaf-features-processing-1.0.0.xsd | 2 +-
.../internal/service/FeaturePatternTest.java | 73 +++++++++
.../internal/service/LocationPatternTest.java | 1 +
9 files changed, 267 insertions(+), 142 deletions(-)
diff --git a/features/core/src/main/java/org/apache/karaf/features/FeaturePattern.java b/features/core/src/main/java/org/apache/karaf/features/FeaturePattern.java
new file mode 100644
index 0000000..06db75a
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/FeaturePattern.java
@@ -0,0 +1,108 @@
+/*
+ * 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.karaf.features;
+
+import java.util.regex.Pattern;
+
+import org.apache.felix.utils.manifest.Clause;
+import org.apache.felix.utils.version.VersionCleaner;
+import org.apache.felix.utils.version.VersionRange;
+import org.osgi.framework.Version;
+
+/**
+ * <p>Helper class to compare feature identifiers that may use globs and version ranges.</p>
+ *
+ * <p>Following feature identifiers are supported:<ul>
+ * <li>name (simple name)</li>
+ * <li>name/version (Karaf feature ID syntax)</li>
+ * <li>name/version-range (Karaf feature ID syntax using version-range)</li>
+ * <li>name;range=version (OSGi manifest header with <code>range</code> <em>attribute</em>)</li>
+ * <li>name;range=version-range (OSGi manifest header with <code>range</code> <em>attribute</em>)</li>
+ * </ul></p>
+ */
+public class FeaturePattern {
+
+ public static final String RANGE = "range";
+
+ private String originalId;
+ private Pattern namePattern;
+ private String versionString;
+ private Version version;
+ private VersionRange versionRange;
+
+ public FeaturePattern(String featureId) throws IllegalArgumentException {
+ if (featureId == null) {
+ throw new IllegalArgumentException("Feature ID to match should not be null");
+ }
+ originalId = featureId;
+ String name = originalId;
+ if (name.indexOf("/") > 0) {
+ name = originalId.substring(0, originalId.indexOf("/"));
+ versionString = originalId.substring(originalId.indexOf("/") + 1);
+ } else if (name.contains(";")) {
+ Clause[] c = org.apache.felix.utils.manifest.Parser.parseClauses(new String[] { originalId });
+ name = c[0].getName();
+ versionString = c[0].getAttribute(RANGE);
+ }
+ namePattern = LocationPattern.toRegExp(name);
+
+ if (versionString != null && versionString.length() >= 1) {
+ try {
+ char first = versionString.charAt(0);
+ if (first == '[' || first == '(') {
+ // range
+ versionRange = new VersionRange(versionString, true, false);
+ } else {
+ version = new Version(VersionCleaner.clean(versionString));
+ }
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Can't parse version \"" + versionString + "\" as OSGi version object.", e);
+ }
+ } else {
+ versionRange = new VersionRange(Version.emptyVersion);
+ }
+ }
+
+ /**
+ * Returns <code>if this feature pattern</code> matches given feature/version
+ * @param featureName
+ * @param featureVersion
+ * @return
+ */
+ public boolean matches(String featureName, String featureVersion) {
+ if (featureName == null) {
+ return false;
+ }
+ boolean match = namePattern.matcher(featureName).matches();
+ if (!match) {
+ return false;
+ }
+ if (featureVersion == null) {
+ featureVersion = "0";
+ }
+ Version otherVersion = new Version(VersionCleaner.clean(featureVersion));
+ if (versionRange != null) {
+ match = versionRange.contains(otherVersion);
+ } else if (version != null) {
+ match = version.equals(otherVersion);
+ }
+ return match;
+ }
+
+}
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/LocationPattern.java b/features/core/src/main/java/org/apache/karaf/features/LocationPattern.java
similarity index 94%
rename from features/core/src/main/java/org/apache/karaf/features/internal/service/LocationPattern.java
rename to features/core/src/main/java/org/apache/karaf/features/LocationPattern.java
index 7e55b9b..20390ca 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/LocationPattern.java
+++ b/features/core/src/main/java/org/apache/karaf/features/LocationPattern.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.karaf.features.internal.service;
+package org.apache.karaf.features;
import java.net.MalformedURLException;
import java.util.regex.Matcher;
@@ -30,12 +30,15 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * <p>Helper class to compare Maven URIs that may use globs and version ranges.</p>
+ * <p>Helper class to compare Maven URIs (and falling back to other URIs) that may use globs and version ranges.</p>
+ *
* <p>Each Maven URI may contain these components: groupId, artifactId, optional version, optional type and optional
- * classifier. Concrete URIs do not use globs and use precise versions (we not consider <code>LATEST</code>
- * and <code>RELEASE</code> here).</p>
+ * classifier. Concrete URIs do not use globs and use precise versions (we do not consider <code>LATEST</code>
+ * and <code>RELEASE</code> Maven versions here).</p>
+ *
* <p>When comparing two Maven URIs, we split them to components and may use RegExps and
* {@link org.apache.felix.utils.version.VersionRange}s</p>
+ *
* <p>When pattern URI doesn't use <code>mvn:</code> scheme, plain {@link String#equals(Object)} is used or
* {@link Matcher#matches()} when pattern uses <code>*</code> glob.</p>
*/
@@ -110,7 +113,7 @@ public class LocationPattern {
* @param value
* @return
*/
- private Pattern toRegExp(String value) {
+ static Pattern toRegExp(String value) {
// TODO: escape all RegExp special chars that are valid path characters, only convert '*' into '.*'
return Pattern.compile(value
.replaceAll("\\.", "\\\\\\.")
@@ -133,10 +136,6 @@ public class LocationPattern {
// this pattern is not mvn:
return originalPattern.matcher(otherUri).matches();
}
- if (!otherUri.startsWith("mvn:")) {
- // other pattern is not mvn:
- return originalUri.equals(otherUri);
- }
LocationPattern other;
try {
@@ -145,6 +144,12 @@ public class LocationPattern {
LOG.debug("Can't parse \"" + otherUri + "\" as Maven URI. Ignoring.");
return false;
}
+
+ if (other.originalPattern != null) {
+ // other pattern is not mvn:
+ return false;
+ }
+
if (other.versionRange != null) {
LOG.warn("Matched URI can't use version ranges: " + otherUri);
return false;
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/processing/BundleReplacements.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/processing/BundleReplacements.java
index f51a8b9..ad309be 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/processing/BundleReplacements.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/processing/BundleReplacements.java
@@ -28,7 +28,7 @@ import javax.xml.bind.annotation.XmlEnumValue;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
-import org.apache.karaf.features.internal.service.LocationPattern;
+import org.apache.karaf.features.LocationPattern;
@XmlType(name = "bundleReplacements", propOrder = {
"overrideBundles"
@@ -91,7 +91,7 @@ public class BundleReplacements {
}
/**
- * Changes String for <code>originalUri</code> into {@link org.apache.karaf.features.internal.service.LocationPattern}
+ * Changes String for <code>originalUri</code> into {@link LocationPattern}
*/
public void compile() throws MalformedURLException {
originalUriPattern = new LocationPattern(originalUri);
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/processing/FeaturesProcessing.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/processing/FeaturesProcessing.java
index 142a16b..c2a0765 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/processing/FeaturesProcessing.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/processing/FeaturesProcessing.java
@@ -38,7 +38,7 @@ import org.apache.felix.utils.manifest.Parser;
import org.apache.felix.utils.version.VersionCleaner;
import org.apache.felix.utils.version.VersionRange;
import org.apache.karaf.features.internal.service.Blacklist;
-import org.apache.karaf.features.internal.service.LocationPattern;
+import org.apache.karaf.features.LocationPattern;
import org.osgi.framework.Version;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -90,6 +90,9 @@ public class FeaturesProcessing {
private Blacklist blacklist;
public FeaturesProcessing() {
+ overrideBundleDependency = new OverrideBundleDependency();
+ bundleReplacements = new BundleReplacements();
+ featureReplacements = new FeatureReplacements();
}
public List<String> getBlacklistedRepositories() {
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/Blacklist.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/Blacklist.java
index 8c6bfb9..046c4be 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/Blacklist.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/Blacklist.java
@@ -25,33 +25,27 @@ import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
+import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import java.util.Set;
-import java.util.regex.Pattern;
import org.apache.felix.utils.manifest.Clause;
import org.apache.felix.utils.manifest.Parser;
-import org.apache.felix.utils.version.VersionRange;
-import org.apache.felix.utils.version.VersionTable;
-import org.apache.karaf.features.internal.model.Bundle;
-import org.apache.karaf.features.internal.model.Conditional;
-import org.apache.karaf.features.internal.model.Feature;
+import org.apache.karaf.features.FeaturePattern;
+import org.apache.karaf.features.LocationPattern;
import org.apache.karaf.features.internal.model.Features;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Helper class to deal with blacklisted features and bundles.
+ * Helper class to deal with blacklisted features and bundles. It doesn't process JAXB model at all - it only
+ * provides information about repository/feature/bundle being blacklisted.
*/
public class Blacklist {
public static Logger LOG = LoggerFactory.getLogger(Blacklist.class);
public static final String BLACKLIST_URL = "url";
- public static final String BLACKLIST_RANGE = "range";
public static final String BLACKLIST_TYPE = "type"; // null -> "feature"
public static final String TYPE_FEATURE = "feature";
public static final String TYPE_BUNDLE = "bundle";
@@ -59,7 +53,10 @@ public class Blacklist {
private static final Logger LOGGER = LoggerFactory.getLogger(Blacklist.class);
private Clause[] clauses;
- private Map<String, LocationPattern> bundleBlacklist = new LinkedHashMap<>();
+
+ private List<LocationPattern> repositoryBlacklist = new LinkedList<>();
+ private List<FeaturePattern> featureBlacklist = new LinkedList<>();
+ private List<LocationPattern> bundleBlacklist = new LinkedList<>();
public Blacklist() {
this(Collections.emptyList());
@@ -105,11 +102,33 @@ public class Blacklist {
type = TYPE_FEATURE;
}
}
+ String location;
switch (type) {
+ case TYPE_REPOSITORY:
+ location = c.getName();
+ if (c.getAttribute(BLACKLIST_URL) != null) {
+ location = c.getAttribute(BLACKLIST_URL);
+ }
+ if (location == null) {
+ // should not happen?
+ LOG.warn("Repository blacklist URI is empty. Ignoring.");
+ } else {
+ try {
+ repositoryBlacklist.add(new LocationPattern(location));
+ } catch (MalformedURLException e) {
+ LOG.warn("Problem parsing repository blacklist URI \"" + location + "\": " + e.getMessage() + ". Ignoring.");
+ }
+ }
+ break;
case TYPE_FEATURE:
+ try {
+ featureBlacklist.add(new FeaturePattern(c.toString()));
+ } catch (IllegalArgumentException e) {
+ LOG.warn("Problem parsing blacklisted feature identifier \"" + c.toString() + "\": " + e.getMessage() + ". Ignoring.");
+ }
break;
case TYPE_BUNDLE:
- String location = c.getName();
+ location = c.getName();
if (c.getAttribute(BLACKLIST_URL) != null) {
location = c.getAttribute(BLACKLIST_URL);
}
@@ -118,74 +137,24 @@ public class Blacklist {
LOG.warn("Bundle blacklist URI is empty. Ignoring.");
} else {
try {
- bundleBlacklist.put(location, location.startsWith("mvn:") ? new LocationPattern(location) : null);
+ bundleBlacklist.add(new LocationPattern(location));
} catch (MalformedURLException e) {
- LOG.warn("Problem parsing blacklist URI \"" + location + "\": " + e.getMessage() + ". Ignoring.");
+ LOG.warn("Problem parsing bundle blacklist URI \"" + location + "\": " + e.getMessage() + ". Ignoring.");
}
}
break;
- case TYPE_REPOSITORY:
}
}
}
/**
- * TODO: set {@link Feature#setBlacklisted(boolean)} instead of removing from collection
- * @param features
+ * Checks whether features XML repository URI is blacklisted.
+ * @param uri
+ * @return
*/
- public void blacklist(Features features) {
- features.getFeature().removeIf(this::blacklist);
- }
-
- public boolean blacklist(Feature feature) {
- for (Clause clause : clauses) {
- // Check feature name
- if (clause.getName().equals(feature.getName())) {
- // Check feature version
- VersionRange range = VersionRange.ANY_VERSION;
- String vr = clause.getAttribute(BLACKLIST_RANGE);
- if (vr != null) {
- range = new VersionRange(vr, true);
- }
- if (range.contains(VersionTable.getVersion(feature.getVersion()))) {
- String type = clause.getAttribute(BLACKLIST_TYPE);
- if (type == null || TYPE_FEATURE.equals(type)) {
- return true;
- }
- }
- }
- // Check bundles
- blacklist(feature.getBundle());
- // Check conditional bundles
- for (Conditional cond : feature.getConditional()) {
- blacklist(cond.getBundle());
- }
- }
- return false;
- }
-
- private void blacklist(List<Bundle> bundles) {
- for (Iterator<Bundle> iterator = bundles.iterator(); iterator.hasNext();) {
- Bundle info = iterator.next();
- for (Clause clause : clauses) {
- String url = clause.getName();
- if (clause.getAttribute(BLACKLIST_URL) != null) {
- url = clause.getAttribute(BLACKLIST_URL);
- }
- if (info.getLocation().equals(url)) {
- String type = clause.getAttribute(BLACKLIST_TYPE);
- if (type == null || TYPE_BUNDLE.equals(type)) {
- iterator.remove();
- break;
- }
- }
- }
- }
- }
-
- public boolean isBundleBlacklisted(String uri) {
- for (Map.Entry<String, LocationPattern> clause : bundleBlacklist.entrySet()) {
- if (mavenMatches(clause.getKey(), clause.getValue(), uri)) {
+ public boolean isRepositoryBlacklisted(String uri) {
+ for (LocationPattern pattern : repositoryBlacklist) {
+ if (pattern.matches(uri)) {
return true;
}
}
@@ -193,56 +162,30 @@ public class Blacklist {
}
/**
- * Checks whether given <code>uri</code> matches Maven artifact pattern (group, artifact, optional type/classifier, version
- * range, globs).
- * @param blacklistedUri
- * @param compiledUri
- * @param uri
+ * Checks whether the feature is blacklisted according to configured rules by name
+ * (possibly with wildcards) and optional version (possibly specified as version range)
+ * @param name
+ * @param version
* @return
*/
- private boolean mavenMatches(String blacklistedUri, LocationPattern compiledUri, String uri) {
- if (compiledUri == null) {
- // non maven URI - we can't be smart
- return blacklistedUri.equals(uri);
- } else {
- return compiledUri.matches(uri);
- }
- }
-
public boolean isFeatureBlacklisted(String name, String version) {
- for (Clause clause : clauses) {
- String type = clause.getAttribute(BLACKLIST_TYPE);
- if (type != null && !TYPE_FEATURE.equals(type)) {
- continue;
- }
- if (Pattern.matches(clause.getName().replaceAll("\\*", ".*"), name)) {
- // Check feature version
- VersionRange range = VersionRange.ANY_VERSION;
- String vr = clause.getAttribute(BLACKLIST_RANGE);
- if (vr != null) {
- range = new VersionRange(vr, true);
- }
- if (range.contains(VersionTable.getVersion(version))) {
- if (type == null || TYPE_FEATURE.equals(type)) {
- return true;
- }
- }
+ for (FeaturePattern pattern : featureBlacklist) {
+ if (pattern.matches(name, version)) {
+ return true;
}
}
return false;
}
- public boolean isRepositoryBlacklisted(String uri) {
- for (Clause clause : clauses) {
- String url = clause.getName();
- if (clause.getAttribute(BLACKLIST_URL) != null) {
- url = clause.getAttribute(BLACKLIST_URL);
- }
- if (uri.equals(url)) {
- String type = clause.getAttribute(BLACKLIST_TYPE);
- if (type == null || TYPE_REPOSITORY.equals(type)) {
- return true;
- }
+ /**
+ * Checks whether the bundle URI is blacklisted according to configured rules
+ * @param uri
+ * @return
+ */
+ public boolean isBundleBlacklisted(String uri) {
+ for (LocationPattern pattern : bundleBlacklist) {
+ if (pattern.matches(uri)) {
+ return true;
}
}
return false;
@@ -262,7 +205,9 @@ public class Blacklist {
System.arraycopy(others.clauses, ours.length, this.clauses, 0, others.clauses.length);
}
if (others != null) {
- this.bundleBlacklist.putAll(others.bundleBlacklist);
+ this.repositoryBlacklist.addAll(others.repositoryBlacklist);
+ this.featureBlacklist.addAll(others.featureBlacklist);
+ this.bundleBlacklist.addAll(others.bundleBlacklist);
}
}
@@ -270,4 +215,7 @@ public class Blacklist {
return clauses;
}
+ public void blacklist(Features featuresModel) {
+ }
+
}
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesProcessorImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesProcessorImpl.java
index 03dadea..c14c559 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesProcessorImpl.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesProcessorImpl.java
@@ -29,15 +29,14 @@ import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.LocationPattern;
import org.apache.karaf.features.internal.model.Bundle;
import org.apache.karaf.features.internal.model.Conditional;
import org.apache.karaf.features.internal.model.Feature;
import org.apache.karaf.features.internal.model.Features;
import org.apache.karaf.features.internal.model.processing.BundleReplacements;
-import org.apache.karaf.features.internal.model.processing.FeatureReplacements;
import org.apache.karaf.features.internal.model.processing.FeaturesProcessing;
import org.apache.karaf.features.internal.model.processing.ObjectFactory;
-import org.apache.karaf.features.internal.model.processing.OverrideBundleDependency;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -55,7 +54,7 @@ public class FeaturesProcessorImpl implements FeaturesProcessor {
public static Logger LOG = LoggerFactory.getLogger(FeaturesProcessorImpl.class);
private static final JAXBContext FEATURES_PROCESSING_CONTEXT;
- private FeaturesProcessing processing;
+ private FeaturesProcessing processing = new FeaturesProcessing();
static {
try {
@@ -96,18 +95,6 @@ public class FeaturesProcessorImpl implements FeaturesProcessor {
}
}
- if (processing == null) {
- processing = new FeaturesProcessing();
- }
- if (processing.getBundleReplacements() == null) {
- processing.setBundleReplacements(new BundleReplacements());
- }
- if (processing.getFeatureReplacements() == null) {
- processing.setFeatureReplacements(new FeatureReplacements());
- }
- if (processing.getOverrideBundleDependency() == null) {
- processing.setOverrideBundleDependency(new OverrideBundleDependency());
- }
processing.postUnmarshall(blacklist, overrides);
}
diff --git a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-processing-1.0.0.xsd b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-processing-1.0.0.xsd
index d0e5d48..b82bf08 100644
--- a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-processing-1.0.0.xsd
+++ b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-processing-1.0.0.xsd
@@ -83,7 +83,7 @@ features, "range" manifest header attribute should be specified in "version" XML
<xs:documentation><![CDATA[Blacklisted feature name may use '*' character as glob. "version" attribute
MAY specify a version (or range) of features to blacklist, e.g.,:
* version="[1,2)" - feature with versions 1, 1.1, 1.4.3, 1.9.99, ... will be blacklisted
- * version="[2,*)" - features with all versions above 2.0.0 will be blacklisted
+ * version="[2,*)" - features with all versions above and including 2.0.0 will be blacklisted
* version="3.0" - feature with version 3.0 only will be blacklisted
]]></xs:documentation>
</xs:annotation>
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturePatternTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturePatternTest.java
new file mode 100644
index 0000000..c462b37
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturePatternTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import org.apache.karaf.features.FeaturePattern;
+import org.junit.Test;
+import org.osgi.framework.Version;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class FeaturePatternTest {
+
+ @Test
+ public void matchingFeatureIds() {
+ assertTrue(new FeaturePattern("spring").matches("spring", null));
+ assertTrue(new FeaturePattern("spring").matches("spring", "0.0.0"));
+ assertTrue(new FeaturePattern("spring").matches("spring", "1.0.0"));
+ assertFalse(new FeaturePattern("spring").matches("springish", "1.0.0"));
+ assertFalse(new FeaturePattern("commons/1").matches("commons", "0.0.0"));
+ assertFalse(new FeaturePattern("commons/1").matches("commons", null));
+ assertTrue(new FeaturePattern("commons/1").matches("commons", "1"));
+ assertFalse(new FeaturePattern("commons/1").matches("commons", "1.0.0.1"));
+ assertFalse(new FeaturePattern("space/[3,4]").matches("space", "1"));
+ assertTrue(new FeaturePattern("space/[3,4]").matches("space", "3"));
+ assertTrue(new FeaturePattern("space/[3,4]").matches("space", "3.1"));
+ assertFalse(new FeaturePattern("space/[3,4]").matches("x-space", "3.1"));
+ assertTrue(new FeaturePattern("space/[3,4]").matches("space", "4.0.0"));
+ assertFalse(new FeaturePattern("space/[3,4]").matches("space", "4.0.0.0")); // last ".0" is qualifier
+ assertFalse(new FeaturePattern("space/[3,4]").matches("space", "4.0.1"));
+ assertTrue(new FeaturePattern("special;range=1").matches("special", "1"));
+ assertTrue(new FeaturePattern("special;range=1").matches("special", "1.0"));
+ assertTrue(new FeaturePattern("special;range=1").matches("special", "1.0.0"));
+ assertFalse(new FeaturePattern("special;range=1").matches("special2", "1.0.0"));
+ assertFalse(new FeaturePattern("special;range=1").matches("special", "1.0.1"));
+ assertTrue(new FeaturePattern("universal;range=[3,4)").matches("universal", "3"));
+ assertTrue(new FeaturePattern("universal;range=[3,4)").matches("universal", "3.0"));
+ assertTrue(new FeaturePattern("universal;range=[3,4)").matches("universal", "3.0.0"));
+ assertTrue(new FeaturePattern("universal;range=[3,4)").matches("universal", "3.4.2"));
+ assertTrue(new FeaturePattern("universal;range=[3,4)").matches("universal", "3.9.9.GA"));
+ assertFalse(new FeaturePattern("universal;range=[3,4)").matches("universalis", "3.9.9.GA"));
+ assertFalse(new FeaturePattern("universal;range=[3,4)").matches("universal", "4.0.0"));
+ assertTrue(new FeaturePattern("a*").matches("alphabet", null));
+ assertTrue(new FeaturePattern("a*").matches("alphabet", "0"));
+ assertTrue(new FeaturePattern("a*").matches("alphabet", "999"));
+ assertFalse(new FeaturePattern("a*").matches("_alphabet", "999"));
+ assertTrue(new FeaturePattern("*b/[3,4)").matches("b", "3.5"));
+ assertTrue(new FeaturePattern("*b/[3,4)").matches("cb", "3.5"));
+ assertFalse(new FeaturePattern("*b/[3,4)").matches("bc", "3.5"));
+ assertFalse(new FeaturePattern("*b/[3,4)").matches("cb", "4.0.0"));
+ assertFalse(new FeaturePattern("*b/[3,4)").matches("cb", null));
+ assertFalse(new FeaturePattern("*b/[3,4)").matches("cb", "0"));
+ assertFalse(new FeaturePattern("*b/[3,4)").matches("cb", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
+ assertFalse(new FeaturePattern("*b/[3,4)").matches("cb", Version.emptyVersion.toString()));
+ }
+
+}
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/LocationPatternTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/LocationPatternTest.java
index c0a7b31..3c0a808 100644
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/LocationPatternTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/LocationPatternTest.java
@@ -20,6 +20,7 @@ package org.apache.karaf.features.internal.service;
import java.net.MalformedURLException;
+import org.apache.karaf.features.LocationPattern;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
--
To stop receiving notification emails like this one, please contact
"commits@karaf.apache.org" <co...@karaf.apache.org>.