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 458de997af2b6ecb2f09a099e0b0c22c5a3070cd Author: Grzegorz Grzybek <[email protected]> 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 "[email protected]" <[email protected]>.
