You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by cs...@apache.org on 2017/08/10 13:54:22 UTC
[01/10] karaf git commit: [KARAF-5298] Update storage when creating
config [Forced Update!]
Repository: karaf
Updated Branches:
refs/heads/model_features 8fbce8a34 -> cd938d501 (forced update)
[KARAF-5298] Update storage when creating config
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/ae930b39
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/ae930b39
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/ae930b39
Branch: refs/heads/model_features
Commit: ae930b3922d5db7b383ffc217386c93716bfa9e8
Parents: b65801b
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Thu Aug 10 07:39:13 2017 +0200
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Thu Aug 10 07:39:13 2017 +0200
----------------------------------------------------------------------
.../karaf/config/core/impl/ConfigRepositoryImpl.java | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/ae930b39/config/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java b/config/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
index ac4e1e2..8ee9082 100644
--- a/config/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
+++ b/config/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
@@ -63,15 +63,12 @@ public class ConfigRepositoryImpl implements ConfigRepository {
public void update(String pid, Dictionary<String, Object> properties) throws IOException {
LOGGER.trace("Update configuration {}", pid);
Configuration cfg = configAdmin.getConfiguration(pid, null);
- if (storage != null) {
- // Check, whether a file location is already provided.
- if (properties.get(FILEINSTALL_FILE_NAME) == null) {
- String cfgFileName = pid + ".cfg";
- File cfgFile = new File(storage, cfgFileName);
- properties.put(FILEINSTALL_FILE_NAME, cfgFile.getCanonicalFile().toURI().toString());
- }
- }
cfg.update(properties);
+ try {
+ updateStorage(pid, properties);
+ } catch (Exception e) {
+ LOGGER.warn("Can't update cfg file", e);
+ }
}
/* (non-Javadoc)
@@ -212,7 +209,7 @@ public class ConfigRepositoryImpl implements ConfigRepository {
}
config.update(properties);
String pid = config.getPid();
-// updateStorage(pid, properties);
+ updateStorage(pid, properties);
return pid;
} catch (IOException e) {
throw new UncheckedIOException(e);
[04/10] karaf git commit: Fix typo in config file
Posted by cs...@apache.org.
Fix typo in config file
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/f1001666
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/f1001666
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/f1001666
Branch: refs/heads/model_features
Commit: f1001666e0dcdcea6089c434ba0d0b592c464171
Parents: 94fd17e
Author: Steven Spungin <st...@spungin.tv>
Authored: Thu Aug 10 08:54:04 2017 -0400
Committer: Steven Spungin <st...@spungin.tv>
Committed: Thu Aug 10 08:54:04 2017 -0400
----------------------------------------------------------------------
.../src/main/resources/resources/etc/org.ops4j.pax.url.mvn.cfg | 2 +-
itests/src/test/resources/etc/org.ops4j.pax.url.mvn.cfg | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/f1001666/assemblies/features/base/src/main/resources/resources/etc/org.ops4j.pax.url.mvn.cfg
----------------------------------------------------------------------
diff --git a/assemblies/features/base/src/main/resources/resources/etc/org.ops4j.pax.url.mvn.cfg b/assemblies/features/base/src/main/resources/resources/etc/org.ops4j.pax.url.mvn.cfg
index fc8376b..5f1ea49 100644
--- a/assemblies/features/base/src/main/resources/resources/etc/org.ops4j.pax.url.mvn.cfg
+++ b/assemblies/features/base/src/main/resources/resources/etc/org.ops4j.pax.url.mvn.cfg
@@ -85,7 +85,7 @@ org.ops4j.pax.url.mvn.defaultRepositories=\
file:${karaf.base}/${karaf.default.repository}@id=child.system.repository@snapshots
#
-# if "defaultLocalRepoAsRemote" is set do *any* value, localRepository will be
+# if "defaultLocalRepoAsRemote" is set to *any* value, localRepository will be
# added to the list of remote repositories being searched for artifacts
#
#org.ops4j.pax.url.mvn.defaultLocalRepoAsRemote = true
http://git-wip-us.apache.org/repos/asf/karaf/blob/f1001666/itests/src/test/resources/etc/org.ops4j.pax.url.mvn.cfg
----------------------------------------------------------------------
diff --git a/itests/src/test/resources/etc/org.ops4j.pax.url.mvn.cfg b/itests/src/test/resources/etc/org.ops4j.pax.url.mvn.cfg
index 9e1b187..0fccfb5 100644
--- a/itests/src/test/resources/etc/org.ops4j.pax.url.mvn.cfg
+++ b/itests/src/test/resources/etc/org.ops4j.pax.url.mvn.cfg
@@ -86,7 +86,7 @@ org.ops4j.pax.url.mvn.defaultRepositories=\
file:${user.home}/.m2/repository@snapshots@id=local
#
-# if "defaultLocalRepoAsRemote" is set do *any* value, localRepository will be
+# if "defaultLocalRepoAsRemote" is set to *any* value, localRepository will be
# added to the list of remote repositories being searched for artifacts
#
#org.ops4j.pax.url.mvn.defaultLocalRepoAsRemote = true
[05/10] karaf git commit: Suppress test exception in log,
extract addRepositories
Posted by cs...@apache.org.
Suppress test exception in log, extract addRepositories
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/b9ae8bfd
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/b9ae8bfd
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/b9ae8bfd
Branch: refs/heads/model_features
Commit: b9ae8bfddb83c252a39b5207a1af8d5a26d068cb
Parents: f100166
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Thu Aug 10 15:53:05 2017 +0200
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Thu Aug 10 15:53:05 2017 +0200
----------------------------------------------------------------------
.../internal/service/BootFeaturesInstaller.java | 26 +++++++++++---------
.../service/BootFeaturesInstallerTest.java | 14 ++++++++---
2 files changed, 26 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/b9ae8bfd/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
index c04192c..2969df0 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
@@ -90,17 +90,7 @@ public class BootFeaturesInstaller {
protected void installBootFeatures() {
try {
- for (String repo : repositories) {
- repo = repo.trim();
- if (!repo.isEmpty()) {
- repo = separatorsToUnix(repo);
- try {
- featuresService.addRepository(URI.create(repo));
- } catch (Exception e) {
- LOGGER.error("Error installing boot feature repository " + repo, e);
- }
- }
- }
+ addRepositories();
List<Set<String>> stagedFeatures = parseBootFeatures(features);
for (Set<String> features : stagedFeatures) {
@@ -124,6 +114,20 @@ public class BootFeaturesInstaller {
}
}
+ private void addRepositories() {
+ for (String repo : repositories) {
+ repo = repo.trim();
+ if (!repo.isEmpty()) {
+ repo = separatorsToUnix(repo);
+ try {
+ featuresService.addRepository(URI.create(repo));
+ } catch (Exception e) {
+ LOGGER.error("Error installing boot feature repository " + repo, e);
+ }
+ }
+ }
+ }
+
protected List<Set<String>> parseBootFeatures(String bootFeatures) {
List<Set<String>> stages = new ArrayList<>();
StringTokenizer tokenizer = new StringTokenizer(bootFeatures, " \t\r\n,()", true);
http://git-wip-us.apache.org/repos/asf/karaf/blob/b9ae8bfd/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
index f4a3cea..ee6d553 100644
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
@@ -22,6 +22,8 @@ import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import org.apache.karaf.features.FeaturesService.Option;
import org.apache.karaf.features.TestBase;
@@ -41,6 +43,8 @@ import static org.easymock.EasyMock.verify;
public class BootFeaturesInstallerTest extends TestBase {
+ private static final String INEXISTANT_REPO = "mvn:inexistent/features/1.0/xml/features";
+
@Test
public void testParser() {
BootFeaturesInstaller installer = new BootFeaturesInstaller(null, null, new String[0], "", false);
@@ -92,15 +96,19 @@ public class BootFeaturesInstallerTest extends TestBase {
@Test
public void testStartDoesNotFailWithOneInvalidUri() throws Exception {
FeaturesServiceImpl impl = createStrictMock(FeaturesServiceImpl.class);
- impl.addRepository(URI.create("mvn:inexistent/features/1.0/xml/features"));
- expectLastCall().andThrow(new IllegalArgumentException());
+ impl.addRepository(URI.create(INEXISTANT_REPO));
+ expectLastCall().andThrow(new IllegalArgumentException("Part of the test. Can be ignored."));
impl.bootDone();
expectLastCall();
replay(impl);
- BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, new String[] { "mvn:inexistent/features/1.0/xml/features" }, "", false);
+ String[] repositories = new String[] { INEXISTANT_REPO };
+ BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, repositories, "", false);
+ Logger logger = Logger.getLogger(BootFeaturesInstaller.class.getName());
+ logger.setLevel(Level.OFF); // Switch off to suppress logging of IllegalArgumentException
bootFeatures.installBootFeatures();
+ logger.setLevel(Level.INFO);
verify(impl);
}
[08/10] karaf git commit: [KARAF-5300] Split install into add and
upgrade
Posted by cs...@apache.org.
[KARAF-5300] Split install into add and upgrade
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/5c88795d
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/5c88795d
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/5c88795d
Branch: refs/heads/model_features
Commit: 5c88795d48a63c8786b24ac771495c2b332a3997
Parents: 85b3565
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Thu Aug 10 11:23:10 2017 +0200
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Thu Aug 10 15:54:06 2017 +0200
----------------------------------------------------------------------
.../internal/service/FeaturesServiceImpl.java | 114 +++++++++----------
1 file changed, 55 insertions(+), 59 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/5c88795d/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
index e44db6e..2518a09 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -83,6 +83,8 @@ import org.osgi.service.resolver.Resolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static java.util.Collections.emptyMap;
+import static java.util.stream.Collectors.toSet;
import static org.apache.karaf.features.internal.service.StateStorage.toStringStringSetMap;
import static org.apache.karaf.features.internal.util.MapUtils.add;
import static org.apache.karaf.features.internal.util.MapUtils.copy;
@@ -786,28 +788,39 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
@Override
public void installFeatures(Set<String> featuresIn, String region, EnumSet<Option> options) throws Exception {
- Set<FeatureReq> featureReqs = new HashSet<>();
+ Set<FeatureReq> toInstall = new HashSet<>();
for (String feature : featuresIn) {
- featureReqs.add(new FeatureReq(feature));
+ toInstall.add(new FeatureReq(feature));
}
State state = copyState();
Map<String, Set<String>> requires = copy(state.requirements);
if (region == null || region.isEmpty()) {
region = ROOT_REGION;
}
- Set<String> requiredForRegion = requires.computeIfAbsent(region, k -> new HashSet<>());
- computeRequirements(options, featureReqs, requiredForRegion);
- Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
- doProvisionInThread(requires, stateChanges, state, getFeaturesById(), options);
- }
+ Set<String> requirements = requires.computeIfAbsent(region, k -> new HashSet<>());
+ Set<FeatureReq> existingFeatures = requirements.stream().map(r -> toFeatureReq(r)).collect(toSet());
+
+ Set<FeatureReq> toAdd = computeFeaturesToAdd(options, toInstall);
+ toAdd.stream().forEach(f -> requirements.add(toRequirement(f)));
+ print("Adding features: " + join(toAdd), options.contains(Option.Verbose));
+
+ if (options.contains(Option.Upgrade)) {
+ Set<FeatureReq> toRemove = computeFeaturesToRemoveOnUpdate(toAdd, existingFeatures);
+ toRemove.stream().forEach(f -> requirements.remove(toRequirement(f)));
+ if (!toRemove.isEmpty()) {
+ print("Removing features: " + join(toRemove), options.contains(Option.Verbose));
+ }
+ }
- void computeRequirements(EnumSet<Option> options, Set<FeatureReq> featureReqs,
- Set<String> requirements)
- throws Exception {
+ doProvisionInThread(requires, emptyMap(), state, getFeaturesById(), options);
+ }
+
+ private Set<FeatureReq> computeFeaturesToAdd(EnumSet<Option> options,
+ Set<FeatureReq> toInstall) throws Exception {
+ Feature[] installedFeatures = listInstalledFeatures();
Map<String, Map<String, Feature>> allFeatures = getFeatureCache();
- List<FeatureReq> featuresToAdd = new ArrayList<>();
- List<String> featuresToRemove = new ArrayList<>();
- for (FeatureReq feature : featureReqs) {
+ Set<FeatureReq> toAdd = new HashSet<>();
+ for (FeatureReq feature : toInstall) {
Pattern pattern = Pattern.compile(feature.getName());
boolean matched = false;
for (String fKey : allFeatures.keySet()) {
@@ -815,8 +828,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
if (matcher.matches()) {
Feature f = getFeatureMatching(fKey, feature.getVersionRange());
if (f != null) {
- featuresToAdd.add(new FeatureReq(f));
- Feature[] installedFeatures = listInstalledFeatures();
+ toAdd.add(new FeatureReq(f));
for (Feature installedFeature : installedFeatures) {
if (installedFeature.getName().equals(f.getName()) && installedFeature.getVersion().equals(f.getVersion())) {
LOGGER.info("The specified feature: '{}' version '{}' {}",f.getName(),f.getVersion(),f.getVersion().endsWith("SNAPSHOT") ? "has been upgraded": "is already installed");
@@ -829,29 +841,20 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
if (!matched && !options.contains(Option.NoFailOnFeatureNotFound)) {
throw new IllegalArgumentException("No matching features for " + feature);
}
- if (options.contains(Option.Upgrade)) {
- for (String existentFeatureReq : requirements) {
- FeatureReq existentFeature = getFeatureRefFromRequired(existentFeatureReq);
- if (existentFeature.getName().equals(feature.getName())
- && !featuresToAdd.contains(existentFeature)) {
- featuresToRemove.add(existentFeature.toString());
- //do not break cycle to remove all old versions of feature
- }
- }
- }
- }
- if (!featuresToRemove.isEmpty()) {
- print("Removing features: " + join(featuresToRemove), options.contains(Option.Verbose));
- for (String featureReq : featuresToRemove) {
- requirements.remove(FEATURE_OSGI_REQUIREMENT_PREFIX + featureReq);
- }
}
- List<String> featuresToDisplay = new ArrayList<>();
- for (FeatureReq feature : featuresToAdd) {
- requirements.add(FEATURE_OSGI_REQUIREMENT_PREFIX + feature.toString());
- featuresToDisplay.add(feature.toString());
- }
- print("Adding features: " + join(featuresToDisplay), options.contains(Option.Verbose));
+ return toAdd;
+ }
+
+ private Set<FeatureReq> computeFeaturesToRemoveOnUpdate(Set<FeatureReq> featuresToAdd,
+ Set<FeatureReq> existingFeatures) throws Exception {
+ Set<String> namesToAdd = featuresToAdd.stream().map(f -> f.getName()).collect(toSet());
+ return existingFeatures.stream()
+ .filter(f -> namesToAdd.contains(f.getName()) && !featuresToAdd.contains(f))
+ .collect(toSet());
+ }
+
+ private String toRequirement(FeatureReq feature) {
+ return FEATURE_OSGI_REQUIREMENT_PREFIX + feature.toString();
}
@Override
@@ -865,21 +868,20 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
if (region == null || region.isEmpty()) {
region = ROOT_REGION;
}
- Set<String> existingFeatures = required.computeIfAbsent(region, k -> new HashSet<>());
- Set<String> featuresToRemove = new HashSet<>();
+ Set<String> requiredForRegion = required.computeIfAbsent(region, k -> new HashSet<>());
+ Set<FeatureReq> featuresToRemove = new HashSet<>();
for (FeatureReq feature : featureReqs) {
Pattern pattern = Pattern.compile(feature.getName());
- List<String> toRemove = new ArrayList<>();
- for (String existingFeature : existingFeatures) {
- FeatureReq existingFeatureReq = getFeatureRefFromRequired(existingFeature);
+ List<FeatureReq> toRemove = new ArrayList<>();
+ for (String existingFeature : requiredForRegion) {
+ FeatureReq existingFeatureReq = toFeatureReq(existingFeature);
if (existingFeatureReq != null) {
Matcher matcher = pattern.matcher(existingFeatureReq.getName());
if (matcher.matches() && feature.getVersionRange().includes(existingFeatureReq.getVersionRange().getLeft())) {
- toRemove.add(existingFeature);
+ toRemove.add(existingFeatureReq);
}
}
}
- toRemove.retainAll(existingFeatures);
if (toRemove.isEmpty()) {
throw new IllegalArgumentException("Feature named '" + feature + "' is not installed");
@@ -887,15 +889,14 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
featuresToRemove.addAll(toRemove);
}
print("Removing features: " + join(featuresToRemove), options.contains(Option.Verbose));
- existingFeatures.removeAll(featuresToRemove);
- if (existingFeatures.isEmpty()) {
+ featuresToRemove.stream().forEach(f->requiredForRegion.remove(toRequirement(f)));
+ if (requiredForRegion.isEmpty()) {
required.remove(region);
}
- Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
- doProvisionInThread(required, stateChanges, state, getFeaturesById(), options);
+ doProvisionInThread(required, emptyMap(), state, getFeaturesById(), options);
}
- private FeatureReq getFeatureRefFromRequired(String featureReq) {
+ private FeatureReq toFeatureReq(String featureReq) {
if (!featureReq.startsWith(FEATURE_OSGI_REQUIREMENT_PREFIX)) {
return null;
}
@@ -914,8 +915,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
State state = copyState();
Map<String, Set<String>> required = copy(state.requirements);
add(required, requirements);
- Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
- doProvisionInThread(required, stateChanges, state, getFeaturesById(), options);
+ doProvisionInThread(required, emptyMap(), state, getFeaturesById(), options);
}
@Override
@@ -923,8 +923,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
State state = copyState();
Map<String, Set<String>> required = copy(state.requirements);
remove(required, requirements);
- Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
- doProvisionInThread(required, stateChanges, state, getFeaturesById(), options);
+ doProvisionInThread(required, emptyMap(), state, getFeaturesById(), options);
}
@Override
@@ -947,8 +946,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
saveState();
stateCopy = state.copy();
}
- Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
- doProvisionInThread(requirements, stateChanges, stateCopy, getFeaturesById(), options);
+ doProvisionInThread(requirements, emptyMap(), stateCopy, getFeaturesById(), options);
}
private <T> Set<T> diff(Set<T> s1, Set<T> s2) {
@@ -1187,9 +1185,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
installSupport.installLibraries(feature);
}
-
-
- private String join(Collection<String> list) {
- return String.join(", ", list);
+ private String join(Collection<FeatureReq> reqs) {
+ return reqs.stream().map(f->f.toString()).collect(Collectors.joining(","));
}
}
[06/10] karaf git commit: [KARAF-5300] Add documentation
Posted by cs...@apache.org.
[KARAF-5300] Add documentation
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/85b35655
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/85b35655
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/85b35655
Branch: refs/heads/model_features
Commit: 85b35655ad8c39f07270f78b291e47ad17ff41d1
Parents: b716158
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Thu Aug 10 10:33:22 2017 +0200
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Thu Aug 10 15:54:06 2017 +0200
----------------------------------------------------------------------
.../karaf/features/internal/service/FeatureReq.java | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/85b35655/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureReq.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureReq.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureReq.java
index 2e1f652..1bac816 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureReq.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureReq.java
@@ -22,6 +22,15 @@ import org.osgi.framework.VersionRange;
/**
* Requirement for a feature
+ *
+ * <p>The syntax of a requirement as a String is name[/versionRange].
+ * If no versionRange is given then a range of [0,) is assumeed which matches all versions.
+ *
+ * <p>
+ * - name: Can be a feature name or a glob like myfeat*
+ * - versionRange: version or range
+ * - version: Will specify a specific version. Like [version,version]. An exemption is 0.0.0 which matches all versions.
+ * - range: Like defined in OSGi VersionRange. Example: [1.0.0, 1.1.0)
*/
public class FeatureReq {
public static final String VERSION_SEPARATOR = "/";
@@ -57,7 +66,10 @@ public class FeatureReq {
}
private static VersionRange exactVersion(String versionRange) {
- return new VersionRange(VersionRange.LEFT_CLOSED, new Version(versionRange), new Version(versionRange), VersionRange.RIGHT_CLOSED);
+ return new VersionRange(VersionRange.LEFT_CLOSED,
+ new Version(versionRange),
+ new Version(versionRange),
+ VersionRange.RIGHT_CLOSED);
}
public FeatureReq(String name, VersionRange versionRange) {
[10/10] karaf git commit: [KARAF-5300] Use FeatureReq instead of
string for FeaturesService
Posted by cs...@apache.org.
[KARAF-5300] Use FeatureReq instead of string for FeaturesService
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/b716158c
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/b716158c
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/b716158c
Branch: refs/heads/model_features
Commit: b716158cbce69e4184e7c735e162831515f4003e
Parents: 6634b5f
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Wed Aug 9 17:39:06 2017 +0200
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Thu Aug 10 15:54:06 2017 +0200
----------------------------------------------------------------------
.../features/internal/service/FeatureReq.java | 84 +++++++
.../internal/service/FeaturesServiceImpl.java | 226 +++++++------------
.../service/FeaturesServiceImplTest.java | 46 +++-
.../karaf/features/internal/service/f09.xml | 24 ++
4 files changed, 229 insertions(+), 151 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/b716158c/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureReq.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureReq.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureReq.java
new file mode 100644
index 0000000..2e1f652
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureReq.java
@@ -0,0 +1,84 @@
+/*
+ * 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.Feature;
+import org.osgi.framework.Version;
+import org.osgi.framework.VersionRange;
+
+/**
+ * Requirement for a feature
+ */
+public class FeatureReq {
+ public static final String VERSION_SEPARATOR = "/";
+ private static Version HIGHEST = new Version(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ private static final VersionRange RANGE_ALL = new VersionRange(VersionRange.LEFT_CLOSED, Version.emptyVersion, HIGHEST, VersionRange.RIGHT_CLOSED);
+ private String name;
+ private VersionRange versionRange;
+
+ public FeatureReq(String nameAndRange) {
+ String[] parts = nameAndRange.trim().split(VERSION_SEPARATOR);
+ this.name = parts[0];
+ this.versionRange = (parts.length == 1) ? RANGE_ALL : range(parts[1]);
+ }
+
+ public FeatureReq(String name, String versionRange) {
+ this.name = name;
+ this.versionRange = range(versionRange);
+ }
+
+ private VersionRange range(String versionRange) {
+ if (versionRange == null) {
+ return RANGE_ALL;
+ }
+ versionRange = versionRange.trim();
+ if ("0.0.0".equals(versionRange)) {
+ return RANGE_ALL;
+ }
+ if (versionRange.contains(",")) {
+ return new VersionRange(versionRange);
+ } else {
+ return exactVersion(versionRange);
+ }
+ }
+
+ private static VersionRange exactVersion(String versionRange) {
+ return new VersionRange(VersionRange.LEFT_CLOSED, new Version(versionRange), new Version(versionRange), VersionRange.RIGHT_CLOSED);
+ }
+
+ public FeatureReq(String name, VersionRange versionRange) {
+ this.name = name;
+ this.versionRange = versionRange;
+ }
+
+ public FeatureReq(Feature feature) {
+ this(feature.getName(), exactVersion(feature.getVersion()));
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public VersionRange getVersionRange() {
+ return versionRange;
+ }
+
+ @Override
+ public String toString() {
+ return this.name + "/" + this.getVersionRange().toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/b716158c/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
index 6a000cd..e44db6e 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -32,7 +32,6 @@ import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -49,9 +48,7 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import org.apache.felix.utils.manifest.Clause;
import org.apache.felix.utils.version.VersionCleaner;
-import org.apache.felix.utils.version.VersionRange;
import org.apache.felix.utils.version.VersionTable;
import org.apache.karaf.features.DeploymentEvent;
import org.apache.karaf.features.DeploymentListener;
@@ -77,6 +74,7 @@ import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.Version;
+import org.osgi.framework.VersionRange;
import org.osgi.resource.Resource;
import org.osgi.resource.Wire;
import org.osgi.service.cm.Configuration;
@@ -519,22 +517,22 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
@Override
public Feature[] getFeatures(String nameOrId) throws Exception {
- String[] parts = nameOrId.split(VERSION_SEPARATOR);
- String name = parts.length > 0 ? parts[0] : nameOrId;
- String version = parts.length > 1 ? parts[1] : null;
- return getFeatures(name, version);
+ return getFeatures(new FeatureReq(nameOrId));
}
@Override
public Feature[] getFeatures(String name, String version) throws Exception {
+ return getFeatures(new FeatureReq(name, version));
+ }
+
+ private Feature[] getFeatures(FeatureReq featureReq) throws Exception {
List<Feature> features = new ArrayList<>();
- Pattern pattern = Pattern.compile(name);
+ Pattern pattern = Pattern.compile(featureReq.getName());
Map<String, Map<String, Feature>> allFeatures = getFeatureCache();
for (String featureName : allFeatures.keySet()) {
Matcher matcher = pattern.matcher(featureName);
if (matcher.matches()) {
- Map<String, Feature> versions = allFeatures.get(featureName);
- Feature matchingFeature = getFeatureMatching(versions, version);
+ Feature matchingFeature = getFeatureMatching(featureName, featureReq.getVersionRange());
if (matchingFeature != null) {
features.add(matchingFeature);
}
@@ -543,35 +541,26 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
return features.toArray(new Feature[features.size()]);
}
- private Feature getFeatureMatching(Map<String, Feature> versions, String version) {
- if (version != null) {
- version = version.trim();
- if (version.equals(org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION)) {
- version = "";
- }
- } else {
- version = "";
- }
+ private Feature getFeatureMatching(String featureName, VersionRange version) throws Exception {
+ Map<String, Map<String, Feature>> allFeatures = getFeatureCache();
+ Map<String, Feature> versions = allFeatures.get(featureName);
if (versions == null || versions.isEmpty()) {
return null;
- } else {
- Feature feature = version.isEmpty() ? null : versions.get(version);
- if (feature == null) {
- // Compute version range. If an version has been given, assume exact range
- VersionRange versionRange = version.isEmpty()
- ? new VersionRange(Version.emptyVersion)
- : new VersionRange(version, true, true);
- Version latest = Version.emptyVersion;
- for (String available : versions.keySet()) {
- Version availableVersion = VersionTable.getVersion(available);
- if (availableVersion.compareTo(latest) >= 0 && versionRange.contains(availableVersion)) {
- feature = versions.get(available);
- latest = availableVersion;
- }
- }
+ }
+ return getLatestFeature(versions, version);
+ }
+
+ private Feature getLatestFeature(Map<String, Feature> versions, VersionRange versionRange) {
+ Version latest = Version.emptyVersion;
+ Feature feature = null;
+ for (String available : versions.keySet()) {
+ Version availableVersion = VersionTable.getVersion(available);
+ if (availableVersion.compareTo(latest) >= 0 && versionRange.includes(availableVersion)) {
+ feature = versions.get(available);
+ latest = availableVersion;
}
- return feature;
}
+ return feature;
}
@Override
@@ -586,6 +575,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
/**
* Should not be called while holding a lock.
+ * @return map from feature name to map from feature version to Feature
*/
protected Map<String, Map<String, Feature>> getFeatureCache() throws Exception {
Set<String> uris;
@@ -709,7 +699,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
@Override
public boolean isRequired(Feature f) {
- String id = FEATURE_OSGI_REQUIREMENT_PREFIX + getFeatureRequirement(f);
+ String id = FEATURE_OSGI_REQUIREMENT_PREFIX + new FeatureReq(f).toString();
synchronized (lock) {
Set<String> features = state.requirements.get(ROOT_REGION);
return features != null && features.contains(id);
@@ -795,31 +785,37 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
}
@Override
- public void installFeatures(Set<String> features, String region, EnumSet<Option> options) throws Exception {
+ public void installFeatures(Set<String> featuresIn, String region, EnumSet<Option> options) throws Exception {
+ Set<FeatureReq> featureReqs = new HashSet<>();
+ for (String feature : featuresIn) {
+ featureReqs.add(new FeatureReq(feature));
+ }
State state = copyState();
- Map<String, Set<String>> required = copy(state.requirements);
+ Map<String, Set<String>> requires = copy(state.requirements);
if (region == null || region.isEmpty()) {
region = ROOT_REGION;
}
- Set<String> fl = required.computeIfAbsent(region, k -> new HashSet<>());
+ Set<String> requiredForRegion = requires.computeIfAbsent(region, k -> new HashSet<>());
+ computeRequirements(options, featureReqs, requiredForRegion);
+ Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
+ doProvisionInThread(requires, stateChanges, state, getFeaturesById(), options);
+ }
+
+ void computeRequirements(EnumSet<Option> options, Set<FeatureReq> featureReqs,
+ Set<String> requirements)
+ throws Exception {
Map<String, Map<String, Feature>> allFeatures = getFeatureCache();
- List<String> featuresToAdd = new ArrayList<>();
+ List<FeatureReq> featuresToAdd = new ArrayList<>();
List<String> featuresToRemove = new ArrayList<>();
- for (String feature : features) {
- if (!feature.contains(VERSION_SEPARATOR)) {
- feature += "/0.0.0";
- }
- String name = feature.substring(0, feature.indexOf(VERSION_SEPARATOR));
- String version = feature.substring(feature.indexOf(VERSION_SEPARATOR) + 1);
- Pattern pattern = Pattern.compile(name);
+ for (FeatureReq feature : featureReqs) {
+ Pattern pattern = Pattern.compile(feature.getName());
boolean matched = false;
for (String fKey : allFeatures.keySet()) {
Matcher matcher = pattern.matcher(fKey);
if (matcher.matches()) {
- Feature f = getFeatureMatching(allFeatures.get(fKey), version);
+ Feature f = getFeatureMatching(fKey, feature.getVersionRange());
if (f != null) {
- String req = getFeatureRequirement(f);
- featuresToAdd.add(req);
+ featuresToAdd.add(new FeatureReq(f));
Feature[] installedFeatures = listInstalledFeatures();
for (Feature installedFeature : installedFeatures) {
if (installedFeature.getName().equals(f.getName()) && installedFeature.getVersion().equals(f.getVersion())) {
@@ -834,12 +830,11 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
throw new IllegalArgumentException("No matching features for " + feature);
}
if (options.contains(Option.Upgrade)) {
- for (String existentFeatureReq : fl) {
- //remove requirement prefix feature:
- String existentFeature = existentFeatureReq.substring(FEATURE_OSGI_REQUIREMENT_PREFIX.length());
- if (existentFeature.startsWith(name + VERSION_SEPARATOR)
+ for (String existentFeatureReq : requirements) {
+ FeatureReq existentFeature = getFeatureRefFromRequired(existentFeatureReq);
+ if (existentFeature.getName().equals(feature.getName())
&& !featuresToAdd.contains(existentFeature)) {
- featuresToRemove.add(existentFeature);
+ featuresToRemove.add(existentFeature.toString());
//do not break cycle to remove all old versions of feature
}
}
@@ -848,78 +843,64 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
if (!featuresToRemove.isEmpty()) {
print("Removing features: " + join(featuresToRemove), options.contains(Option.Verbose));
for (String featureReq : featuresToRemove) {
- fl.remove(FEATURE_OSGI_REQUIREMENT_PREFIX + featureReq);
+ requirements.remove(FEATURE_OSGI_REQUIREMENT_PREFIX + featureReq);
}
}
- featuresToAdd = new ArrayList<>(new LinkedHashSet<>(featuresToAdd));
List<String> featuresToDisplay = new ArrayList<>();
- for (String feature : featuresToAdd) {
- fl.add(FEATURE_OSGI_REQUIREMENT_PREFIX + feature);
- String v = feature.substring(feature.indexOf(VERSION_SEPARATOR) + VERSION_SEPARATOR.length());
- VersionRange vr = new VersionRange(v, true);
- if (vr.isPointVersion()) {
- v = feature.substring(0, feature.indexOf(VERSION_SEPARATOR) + VERSION_SEPARATOR.length())
- + vr.getCeiling().toString();
- }
- featuresToDisplay.add(v);
+ for (FeatureReq feature : featuresToAdd) {
+ requirements.add(FEATURE_OSGI_REQUIREMENT_PREFIX + feature.toString());
+ featuresToDisplay.add(feature.toString());
}
print("Adding features: " + join(featuresToDisplay), options.contains(Option.Verbose));
- Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
- doProvisionInThread(required, stateChanges, state, getFeaturesById(), options);
}
@Override
- public void uninstallFeatures(Set<String> features, String region, EnumSet<Option> options) throws Exception {
+ public void uninstallFeatures(Set<String> featuresIn, String region, EnumSet<Option> options) throws Exception {
+ Set<FeatureReq> featureReqs = new HashSet<>();
+ for (String feature : featuresIn) {
+ featureReqs.add(new FeatureReq(feature));
+ }
State state = copyState();
Map<String, Set<String>> required = copy(state.requirements);
if (region == null || region.isEmpty()) {
region = ROOT_REGION;
}
- Set<String> fl = required.computeIfAbsent(region, k -> new HashSet<>());
- List<String> featuresToRemove = new ArrayList<>();
- for (String feature : new HashSet<>(features)) {
+ Set<String> existingFeatures = required.computeIfAbsent(region, k -> new HashSet<>());
+ Set<String> featuresToRemove = new HashSet<>();
+ for (FeatureReq feature : featureReqs) {
+ Pattern pattern = Pattern.compile(feature.getName());
List<String> toRemove = new ArrayList<>();
- feature = normalize(feature);
- if (feature.endsWith("/0.0.0")) {
- // Match only on name
- String nameSep = FEATURE_OSGI_REQUIREMENT_PREFIX + feature.substring(0, feature.indexOf(VERSION_SEPARATOR) + 1);
- for (String f : fl) {
- Pattern pattern = Pattern.compile(nameSep.substring(0, nameSep.length() - 1));
- Matcher matcher = pattern.matcher(f);
- if (matcher.matches() || normalize(f).startsWith(nameSep)) {
- toRemove.add(f);
- }
- }
- } else {
- Pattern pattern = getNameAndVersionPattern(feature);
- for (String f : fl) {
- Matcher matcher = pattern.matcher(f);
- if (matcher.matches()) {
- toRemove.add(f);
- }
- }
+ for (String existingFeature : existingFeatures) {
+ FeatureReq existingFeatureReq = getFeatureRefFromRequired(existingFeature);
+ if (existingFeatureReq != null) {
+ Matcher matcher = pattern.matcher(existingFeatureReq.getName());
+ if (matcher.matches() && feature.getVersionRange().includes(existingFeatureReq.getVersionRange().getLeft())) {
+ toRemove.add(existingFeature);
+ }
+ }
}
- toRemove.retainAll(fl);
+ toRemove.retainAll(existingFeatures);
if (toRemove.isEmpty()) {
throw new IllegalArgumentException("Feature named '" + feature + "' is not installed");
}
featuresToRemove.addAll(toRemove);
}
- featuresToRemove = new ArrayList<>(new LinkedHashSet<>(featuresToRemove));
print("Removing features: " + join(featuresToRemove), options.contains(Option.Verbose));
- fl.removeAll(featuresToRemove);
- if (fl.isEmpty()) {
+ existingFeatures.removeAll(featuresToRemove);
+ if (existingFeatures.isEmpty()) {
required.remove(region);
}
Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
doProvisionInThread(required, stateChanges, state, getFeaturesById(), options);
}
- private Pattern getNameAndVersionPattern(String feature) {
- String name = feature.substring(0, feature.indexOf(VERSION_SEPARATOR));
- String version = feature.substring(feature.indexOf(VERSION_SEPARATOR) + 1);
- return getFeaturePattern(name, version);
+ private FeatureReq getFeatureRefFromRequired(String featureReq) {
+ if (!featureReq.startsWith(FEATURE_OSGI_REQUIREMENT_PREFIX)) {
+ return null;
+ }
+ String featureReq1 = featureReq.substring(FEATURE_OSGI_REQUIREMENT_PREFIX.length());
+ return new FeatureReq(featureReq1);
}
@Override
@@ -981,27 +962,6 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
return repositories.create(uri, true, true);
}
- private Map<String, Feature> loadAllFeatures(Set<URI> uris) throws Exception {
- //the outer map's key is feature name, the inner map's key is feature version
- Map<String, Feature> map = new HashMap<>();
- // Two phase load:
- // * first load dependent repositories
- Set<URI> loaded = new HashSet<>();
- List<URI> toLoad = new ArrayList<>(uris);
- Clause[] blacklisted = repositories.getBlacklisted();
- while (!toLoad.isEmpty()) {
- URI uri = toLoad.remove(0);
- if (loaded.add(uri)) {
- Repository repo = new RepositoryImpl(uri, blacklisted);
- Collections.addAll(toLoad, repo.getRepositories());
- for (Feature f : repo.getFeatures()) {
- map.put(f.getId(), f);
- }
- }
- }
- return map;
- }
-
@Override
public Map<String, Set<String>> listRequirements() {
synchronized (lock) {
@@ -1227,31 +1187,9 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
installSupport.installLibraries(feature);
}
- private Pattern getFeaturePattern(String name, String version) {
- String req = FEATURE_OSGI_REQUIREMENT_PREFIX + getFeatureRequirement(name, version);
- req = req.replace("[", "\\[");
- req = req.replace("(", "\\(");
- req = req.replace("]", "\\]");
- req = req.replace(")", "\\)");
- return Pattern.compile(req);
- }
- private String getFeatureRequirement(Feature feature) {
- return getFeatureRequirement(feature.getName(), feature.getVersion());
- }
-
- private String getFeatureRequirement(String name, String version) {
- return name + VERSION_SEPARATOR + new VersionRange(version, true);
- }
- private String join(List<String> list) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < list.size(); i++) {
- if (i > 0) {
- sb.append(", ");
- }
- sb.append(list.get(i));
- }
- return sb.toString();
+ private String join(Collection<String> list) {
+ return String.join(", ", list);
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/b716158c/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
index a5ec75a..f5363d4 100644
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
@@ -125,7 +125,7 @@ public class FeaturesServiceImplTest extends TestBase {
impl.addRepository(URI.create("custom:cycle/a-references-b.xml"));
impl.getFeatureCache();
}
-
+
@Test
public void testRemoveRepo1() throws Exception {
final FeaturesService featureService = createTestFeatureService();
@@ -141,6 +141,29 @@ public class FeaturesServiceImplTest extends TestBase {
}
@Test
+ public void testGetFeatureWithVersion() throws Exception {
+ final FeaturesService featureService = createTestFeatureService();
+ URI repoA = URI.create("custom:f09.xml");
+ featureService.addRepository(repoA);
+ Feature feature = featureService.getFeature("test", "1.0.0");
+ assertEquals("1.0.0", feature.getVersion());
+ }
+
+ @Test
+ public void testInstallAndUpdate() throws Exception {
+ final FeaturesService featureService = createTestFeatureService();
+ URI repoA = URI.create("custom:f09.xml");
+ featureService.addRepository(repoA);
+ Feature test100 = featureService.getFeature("test", "1.0.0");
+ installFeature(featureService, test100);
+ assertInstalled(featureService, test100);
+ Feature test110 = featureService.getFeature("test", "1.1.0");
+ featureService.installFeature(test110, EnumSet.of(Option.Upgrade));
+ waitInstalled(featureService, test110);
+ assertNotInstalled(featureService, test100);
+ }
+
+ @Test
public void testRemoveRepo2() throws Exception {
final FeaturesService featureService = createTestFeatureService();
URI repoA = URI.create("custom:remove/a.xml");
@@ -175,9 +198,8 @@ public class FeaturesServiceImplTest extends TestBase {
FrameworkInfo dummyInfo = new FrameworkInfo();
expect(installSupport.getInfo()).andReturn(dummyInfo).atLeastOnce();
EasyMock.replay(installSupport);
- final FeaturesServiceImpl featureService = new FeaturesServiceImpl(new Storage(), null, null, this.resolver,
- installSupport, null, cfg);
- return featureService;
+ return new FeaturesServiceImpl(new Storage(), null, null, this.resolver,
+ installSupport, null, cfg);
}
private void assertNotInstalled(FeaturesService featureService, Feature feature) {
@@ -190,11 +212,21 @@ public class FeaturesServiceImplTest extends TestBase {
featureService.isInstalled(feature));
}
- private void installFeature(final FeaturesService featureService, Feature a1Feature)
+ private void installFeature(final FeaturesService featureService, Feature feature)
throws Exception {
- featureService.installFeature(a1Feature, EnumSet.noneOf(Option.class));
- while (!featureService.isInstalled(a1Feature)) {
+ featureService.installFeature(feature, EnumSet.noneOf(Option.class));
+ waitInstalled(featureService, feature);
+ }
+
+ private void waitInstalled(final FeaturesService featureService, Feature feature)
+ throws InterruptedException {
+ int count = 40;
+ while (!featureService.isInstalled(feature) && count > 0) {
Thread.sleep(100);
+ count --;
+ }
+ if (count == 0) {
+ throw new RuntimeException("Feature " + feature + " not installed.");
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/b716158c/features/core/src/test/resources/org/apache/karaf/features/internal/service/f09.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f09.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f09.xml
new file mode 100644
index 0000000..8a6c26a
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f09.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.2.1">
+ <feature name="test" version="1.0.0" >
+ </feature>
+ <feature name="test" version="1.1.0" >
+ </feature>
+</features>
+
[02/10] karaf git commit: [KARAF-4803] Turn off Karaf configuration
persistence manager
Posted by cs...@apache.org.
[KARAF-4803] Turn off Karaf configuration persistence manager
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/1df3ce30
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/1df3ce30
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/1df3ce30
Branch: refs/heads/model_features
Commit: 1df3ce30e564e6b13bd459c4d1df446c4ce6b69a
Parents: ae930b3
Author: Dominik Przybysz <dp...@touk.pl>
Authored: Sun Oct 23 18:42:45 2016 +0200
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Thu Aug 10 07:40:27 2017 +0200
----------------------------------------------------------------------
.../karaf/config/core/impl/osgi/Activator.java | 15 ++++++++++++++-
.../src/main/asciidoc/user-guide/configuration.adoc | 6 +++++-
2 files changed, 19 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/1df3ce30/config/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java b/config/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
index 8ea04c5..cef9527 100644
--- a/config/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
+++ b/config/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
@@ -23,9 +23,11 @@ import org.apache.karaf.util.tracker.BaseActivator;
import org.apache.karaf.util.tracker.annotation.ProvideService;
import org.apache.karaf.util.tracker.annotation.RequireService;
import org.apache.karaf.util.tracker.annotation.Services;
+import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import java.io.File;
+import java.io.IOException;
@Services(
requires = @RequireService(ConfigurationAdmin.class),
@@ -39,7 +41,9 @@ public class Activator extends BaseActivator {
return;
}
- ConfigRepository configRepository = new ConfigRepositoryImpl(configurationAdmin, new File(System.getProperty("karaf.etc")));
+ File persistenceStorage = getPersistenceStorage(configurationAdmin);
+
+ ConfigRepository configRepository = new ConfigRepositoryImpl(configurationAdmin, persistenceStorage);
register(ConfigRepository.class, configRepository);
ConfigMBeanImpl configMBean = new ConfigMBeanImpl();
@@ -47,4 +51,13 @@ public class Activator extends BaseActivator {
registerMBean(configMBean, "type=config");
}
+ private File getPersistenceStorage(ConfigurationAdmin configurationAdmin) throws IOException {
+ Configuration configuration = configurationAdmin.getConfiguration("org.apache.karaf.config");
+ if(configuration.getProperties() == null){
+ return new File(System.getProperty("karaf.etc"));
+ }
+ String storage = (String) configuration.getProperties().get("storage");
+ return storage == null || storage.trim().isEmpty() ? null : new File(storage);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1df3ce30/manual/src/main/asciidoc/user-guide/configuration.adoc
----------------------------------------------------------------------
diff --git a/manual/src/main/asciidoc/user-guide/configuration.adoc b/manual/src/main/asciidoc/user-guide/configuration.adoc
index 3217f3f..7625bf2 100644
--- a/manual/src/main/asciidoc/user-guide/configuration.adoc
+++ b/manual/src/main/asciidoc/user-guide/configuration.adoc
@@ -73,7 +73,7 @@ felix.fileinstall.log.default = jul
* `felix.fileinstall.enableConfigSave` flush back in the configuration file the changes performed directly on the
configuration service (ConfigAdmin). If `true`, any change (using `config:*` commands, MBeans, OSGi service) is
persisted back in the configuration false. Default is `true`.
-* `felix.fileinstall.dir` is the directory where Apache Karaf is looking for configuration files. Default is `${karaf.etc`}
+* `felix.fileinstall.dir` is the directory where Apache Karaf is looking for configuration files. Default is `${karaf.etc}`
meaning the value of the `KARAF_ETC` variable.
* `felix.fileinstall.filter` is the file name pattern used to load only some configuration files. Only files matching
the pattern will be loaded. Default value is `.*\\.(cfg|config)` meaning *.cfg and *.config files.
@@ -90,6 +90,10 @@ You can change the configuration at runtime by directly editing the configuratio
You can also do the same using the `config:*` commands or the ConfigMBean.
+Apache Karaf persists configuration using own persistence manager in case of when available persistence managers do not support that.
+Configuration files are placed by default in `KARAF_ETC`, but it could be overridden via variable `storage` in `etc/org.apache.karaf.config.cfg`.
+If you want to disable karaf persistence manager, set storage variable to empty string (`storage=`).
+
==== `config:*` commands
Apache Karaf provides a set of commands to manage the configuration.
[03/10] karaf git commit: [KARAF-4803] This closes #253
Posted by cs...@apache.org.
[KARAF-4803] This closes #253
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/94fd17e3
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/94fd17e3
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/94fd17e3
Branch: refs/heads/model_features
Commit: 94fd17e3d1cd54a552aa4e4b6d1ed1a7e345b688
Parents: ae930b3 1df3ce3
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Thu Aug 10 11:23:26 2017 +0200
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Thu Aug 10 11:23:26 2017 +0200
----------------------------------------------------------------------
.../karaf/config/core/impl/osgi/Activator.java | 15 ++++++++++++++-
.../src/main/asciidoc/user-guide/configuration.adoc | 6 +++++-
2 files changed, 19 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
[09/10] karaf git commit: Extract common code in test
Posted by cs...@apache.org.
Extract common code in test
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/6634b5f3
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/6634b5f3
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/6634b5f3
Branch: refs/heads/model_features
Commit: 6634b5f35620b3920a8385ef0fc63e6791a06b62
Parents: b9ae8bf
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Wed Aug 9 15:51:45 2017 +0200
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Thu Aug 10 15:54:06 2017 +0200
----------------------------------------------------------------------
.../service/FeaturesServiceImplTest.java | 62 +++++++++-----------
1 file changed, 28 insertions(+), 34 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/6634b5f3/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
index 01ad34b..a5ec75a 100644
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
@@ -73,32 +73,27 @@ public class FeaturesServiceImplTest extends TestBase {
field.setAccessible(true);
field.set(null, null);
}
+
+ @Test
+ public void testListFeatureWithoutVersion() throws Exception {
+ Feature transactionFeature = feature("transaction", "1.0.0");
+ FeaturesServiceImpl impl = featuresServiceWithFeatures(transactionFeature);
+ assertNotNull(impl.getFeatures("transaction", null));
+ assertSame(transactionFeature, impl.getFeatures("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION)[0]);
+ }
@Test
public void testGetFeature() throws Exception {
Feature transactionFeature = feature("transaction", "1.0.0");
- final Map<String, Map<String, Feature>> features = features(transactionFeature);
- FeaturesServiceConfig cfg = new FeaturesServiceConfig();
- BundleInstallSupport installSupport = EasyMock.niceMock(BundleInstallSupport.class);
- EasyMock.replay(installSupport);
- final FeaturesServiceImpl impl = new FeaturesServiceImpl(new Storage(), null, null, this.resolver, installSupport, null, cfg ) {
- protected Map<String,Map<String,Feature>> getFeatureCache() throws Exception {
- return features;
- }
- };
+ FeaturesServiceImpl impl = featuresServiceWithFeatures(transactionFeature);
assertNotNull(impl.getFeatures("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
assertSame(transactionFeature, impl.getFeatures("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION)[0]);
}
@Test
public void testGetFeatureStripVersion() throws Exception {
- FeaturesServiceConfig cfg = new FeaturesServiceConfig();
- BundleInstallSupport installSupport = EasyMock.mock(BundleInstallSupport.class);
- final FeaturesServiceImpl impl = new FeaturesServiceImpl(new Storage(), null, null, this.resolver, installSupport, null, cfg) {
- protected Map<String,Map<String,Feature>> getFeatureCache() throws Exception {
- return features(feature("transaction", "1.0.0"));
- }
- };
+ Feature transactionFeature = feature("transaction", "1.0.0");
+ FeaturesServiceImpl impl = featuresServiceWithFeatures(transactionFeature);
Feature[] features = impl.getFeatures("transaction", " 1.0.0 ");
assertEquals(1, features.length);
Feature feature = features[0];
@@ -108,29 +103,15 @@ public class FeaturesServiceImplTest extends TestBase {
@Test
public void testGetFeatureNotAvailable() throws Exception {
- FeaturesServiceConfig cfg = new FeaturesServiceConfig();
- BundleInstallSupport installSupport = EasyMock.mock(BundleInstallSupport.class);
- final FeaturesServiceImpl impl = new FeaturesServiceImpl(new Storage(), null, null, this.resolver, installSupport, null, cfg) {
- protected Map<String,Map<String,Feature>> getFeatureCache() throws Exception {
- return features(feature("transaction", "1.0.0"));
- }
- };
+ Feature transactionFeature = feature("transaction", "1.0.0");
+ FeaturesServiceImpl impl = featuresServiceWithFeatures(transactionFeature);
assertEquals(0, impl.getFeatures("activemq", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION).length);
}
@Test
public void testGetFeatureHighestAvailable() throws Exception {
- final Map<String, Map<String, Feature>> features = features(
- feature("transaction", "1.0.0"),
- feature("transaction", "2.0.0")
- );
- FeaturesServiceConfig cfg = new FeaturesServiceConfig();
- BundleInstallSupport installSupport = EasyMock.mock(BundleInstallSupport.class);
- final FeaturesServiceImpl impl = new FeaturesServiceImpl(new Storage(), null, null, this.resolver, installSupport, null, cfg) {
- protected Map<String,Map<String,Feature>> getFeatureCache() throws Exception {
- return features;
- }
- };
+ FeaturesServiceImpl impl = featuresServiceWithFeatures(feature("transaction", "1.0.0"),
+ feature("transaction", "2.0.0"));
assertNotNull(impl.getFeatures("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
assertEquals("2.0.0", impl.getFeatures("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION)[0].getVersion());
}
@@ -175,6 +156,19 @@ public class FeaturesServiceImplTest extends TestBase {
assertInstalled(featureService, b1Feature);
}
+ private FeaturesServiceImpl featuresServiceWithFeatures(Feature... staticFeatures) {
+ final Map<String, Map<String, Feature>> features = features(staticFeatures);
+ FeaturesServiceConfig cfg = new FeaturesServiceConfig();
+ BundleInstallSupport installSupport = EasyMock.niceMock(BundleInstallSupport.class);
+ EasyMock.replay(installSupport);
+ final FeaturesServiceImpl impl = new FeaturesServiceImpl(new Storage(), null, null, this.resolver, installSupport, null, cfg ) {
+ protected Map<String,Map<String,Feature>> getFeatureCache() throws Exception {
+ return features;
+ }
+ };
+ return impl;
+ }
+
private FeaturesServiceImpl createTestFeatureService() {
FeaturesServiceConfig cfg = new FeaturesServiceConfig();
BundleInstallSupport installSupport = EasyMock.niceMock(BundleInstallSupport.class);
[07/10] karaf git commit: [KARAF-5300] Reuse and extract feature
matching code
Posted by cs...@apache.org.
[KARAF-5300] Reuse and extract feature matching code
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/cd938d50
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/cd938d50
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/cd938d50
Branch: refs/heads/model_features
Commit: cd938d5017fecfc9a603b1367b12fee11c81bd29
Parents: 5c88795
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Thu Aug 10 15:30:59 2017 +0200
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Thu Aug 10 15:54:06 2017 +0200
----------------------------------------------------------------------
.../internal/service/FeaturesServiceImpl.java | 79 +++++++++++---------
1 file changed, 43 insertions(+), 36 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/cd938d50/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
index 2518a09..7b61ea8 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -519,15 +519,15 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
@Override
public Feature[] getFeatures(String nameOrId) throws Exception {
- return getFeatures(new FeatureReq(nameOrId));
+ return toArray(getFeatures(new FeatureReq(nameOrId)));
}
@Override
public Feature[] getFeatures(String name, String version) throws Exception {
- return getFeatures(new FeatureReq(name, version));
+ return toArray(getFeatures(new FeatureReq(name, version)));
}
- private Feature[] getFeatures(FeatureReq featureReq) throws Exception {
+ private Collection<Feature> getFeatures(FeatureReq featureReq) throws Exception {
List<Feature> features = new ArrayList<>();
Pattern pattern = Pattern.compile(featureReq.getName());
Map<String, Map<String, Feature>> allFeatures = getFeatureCache();
@@ -540,6 +540,10 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
}
}
}
+ return features;
+ }
+
+ private Feature[] toArray(Collection<Feature> features) {
return features.toArray(new Feature[features.size()]);
}
@@ -818,33 +822,33 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
private Set<FeatureReq> computeFeaturesToAdd(EnumSet<Option> options,
Set<FeatureReq> toInstall) throws Exception {
Feature[] installedFeatures = listInstalledFeatures();
- Map<String, Map<String, Feature>> allFeatures = getFeatureCache();
Set<FeatureReq> toAdd = new HashSet<>();
- for (FeatureReq feature : toInstall) {
- Pattern pattern = Pattern.compile(feature.getName());
- boolean matched = false;
- for (String fKey : allFeatures.keySet()) {
- Matcher matcher = pattern.matcher(fKey);
- if (matcher.matches()) {
- Feature f = getFeatureMatching(fKey, feature.getVersionRange());
- if (f != null) {
- toAdd.add(new FeatureReq(f));
- for (Feature installedFeature : installedFeatures) {
- if (installedFeature.getName().equals(f.getName()) && installedFeature.getVersion().equals(f.getVersion())) {
- LOGGER.info("The specified feature: '{}' version '{}' {}",f.getName(),f.getVersion(),f.getVersion().endsWith("SNAPSHOT") ? "has been upgraded": "is already installed");
- }
- }
- matched = true;
+ for (FeatureReq featureReq : toInstall) {
+ Collection<Feature> matching = getFeatures(featureReq);
+ for (Feature f: matching) {
+ toAdd.add(new FeatureReq(f));
+ for (Feature installedFeature : installedFeatures) {
+ if (isSameFeature(f, installedFeature)) {
+ logInstalledOrUpdated(f);
}
}
}
- if (!matched && !options.contains(Option.NoFailOnFeatureNotFound)) {
- throw new IllegalArgumentException("No matching features for " + feature);
+ if (matching.isEmpty() && !options.contains(Option.NoFailOnFeatureNotFound)) {
+ throw new IllegalArgumentException("No matching features for " + featureReq);
}
}
return toAdd;
}
+ private void logInstalledOrUpdated(Feature f) {
+ String msg = f.getVersion().endsWith("SNAPSHOT") ? "has been upgraded": "is already installed";
+ LOGGER.info("The specified feature: '{}' version '{}' {}", f.getName(), f.getVersion(), msg);
+ }
+
+ private boolean isSameFeature(Feature a, Feature b) {
+ return b.getName().equals(a.getName()) && b.getVersion().equals(a.getVersion());
+ }
+
private Set<FeatureReq> computeFeaturesToRemoveOnUpdate(Set<FeatureReq> featuresToAdd,
Set<FeatureReq> existingFeatures) throws Exception {
Set<String> namesToAdd = featuresToAdd.stream().map(f -> f.getName()).collect(toSet());
@@ -868,34 +872,37 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
if (region == null || region.isEmpty()) {
region = ROOT_REGION;
}
- Set<String> requiredForRegion = required.computeIfAbsent(region, k -> new HashSet<>());
+ Set<String> requirements = required.computeIfAbsent(region, k -> new HashSet<>());
+ Set<FeatureReq> existingFeatures = requirements.stream().map(r -> toFeatureReq(r)).collect(toSet());
Set<FeatureReq> featuresToRemove = new HashSet<>();
for (FeatureReq feature : featureReqs) {
- Pattern pattern = Pattern.compile(feature.getName());
- List<FeatureReq> toRemove = new ArrayList<>();
- for (String existingFeature : requiredForRegion) {
- FeatureReq existingFeatureReq = toFeatureReq(existingFeature);
- if (existingFeatureReq != null) {
- Matcher matcher = pattern.matcher(existingFeatureReq.getName());
- if (matcher.matches() && feature.getVersionRange().includes(existingFeatureReq.getVersionRange().getLeft())) {
- toRemove.add(existingFeatureReq);
- }
- }
- }
-
+ List<FeatureReq> toRemove = getMatching(existingFeatures, feature);
if (toRemove.isEmpty()) {
throw new IllegalArgumentException("Feature named '" + feature + "' is not installed");
}
featuresToRemove.addAll(toRemove);
}
print("Removing features: " + join(featuresToRemove), options.contains(Option.Verbose));
- featuresToRemove.stream().forEach(f->requiredForRegion.remove(toRequirement(f)));
- if (requiredForRegion.isEmpty()) {
+ featuresToRemove.stream().forEach(f -> requirements.remove(toRequirement(f)));
+ if (requirements.isEmpty()) {
required.remove(region);
}
doProvisionInThread(required, emptyMap(), state, getFeaturesById(), options);
}
+ private List<FeatureReq> getMatching(Set<FeatureReq> existingFeatures, FeatureReq feature) {
+ Pattern pattern = Pattern.compile(feature.getName());
+ List<FeatureReq> matching = new ArrayList<>();
+ for (FeatureReq existingFeatureReq : existingFeatures) {
+ Matcher matcher = pattern.matcher(existingFeatureReq.getName());
+ Version existingVersion = existingFeatureReq.getVersionRange().getLeft();
+ if (matcher.matches() && feature.getVersionRange().includes(existingVersion)) {
+ matching.add(existingFeatureReq);
+ }
+ }
+ return matching;
+ }
+
private FeatureReq toFeatureReq(String featureReq) {
if (!featureReq.startsWith(FEATURE_OSGI_REQUIREMENT_PREFIX)) {
return null;