[KARAF-5314] Extract addFeatures into class FeatureSelector
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/cc758635 Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/cc758635 Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/cc758635 Branch: refs/heads/karaf-4.1.x Commit: cc758635a4a20fc4f68b3ca1c8d557ae17705c3a Parents: 4e83935 Author: Christian Schneider <ch...@die-schneider.net> Authored: Sun Aug 20 12:14:31 2017 +0200 Committer: Christian Schneider <ch...@die-schneider.net> Committed: Mon Aug 21 17:31:51 2017 +0200 ---------------------------------------------------------------------- .../apache/karaf/profile/assembly/Builder.java | 105 ++----------------- .../karaf/profile/assembly/FeatureSelector.java | 94 +++++++++++++++++ 2 files changed, 100 insertions(+), 99 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/karaf/blob/cc758635/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java ---------------------------------------------------------------------- diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java index e3fc26c..1fe2848 100644 --- a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java +++ b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java @@ -39,7 +39,6 @@ import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; @@ -56,8 +55,6 @@ import org.apache.felix.resolver.ResolverImpl; import org.apache.felix.utils.manifest.Clause; import org.apache.felix.utils.properties.InterpolationHelper; import org.apache.felix.utils.properties.Properties; -import org.apache.felix.utils.version.VersionRange; -import org.apache.felix.utils.version.VersionTable; import org.apache.karaf.features.FeaturesService; import org.apache.karaf.features.Library; import org.apache.karaf.features.internal.download.DownloadCallback; @@ -90,13 +87,13 @@ import org.apache.karaf.util.maven.Parser; import org.ops4j.pax.url.mvn.MavenResolver; import org.ops4j.pax.url.mvn.MavenResolvers; import org.osgi.framework.Constants; -import org.osgi.framework.Version; import org.osgi.framework.wiring.BundleRevision; import org.osgi.resource.Resource; import org.osgi.service.resolver.Resolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static java.util.Collections.singletonList; import static java.util.jar.JarFile.MANIFEST_NAME; import static org.apache.karaf.features.internal.service.Blacklist.TYPE_REPOSITORY; import static org.apache.karaf.profile.assembly.Builder.Stage.Startup; @@ -793,13 +790,11 @@ public class Builder { for (Features repo : installedRepositories.values()) { allInstalledFeatures.addAll(repo.getFeature()); } - Set<Feature> installedFeatures = new LinkedHashSet<>(); - Map<String, Map<Version, Feature>> featuresCache = new HashMap<>(); + // Add boot features for search allInstalledFeatures.addAll(allBootFeatures); - for (String feature : installedEffective.getFeatures()) { - addFeatures(allInstalledFeatures, feature, installedFeatures, true, featuresCache); - } + FeatureSelector selector = new FeatureSelector(allInstalledFeatures); + Set<Feature> installedFeatures = selector.selectMatching(installedEffective.getFeatures()); for (Feature feature : installedFeatures) { LOGGER.info(" Feature {} is defined as an installed feature", feature.getId()); for (Bundle bundle : feature.getBundle()) { @@ -869,9 +864,8 @@ public class Builder { Downloader downloader = manager.createDownloader(); // Compute startup feature dependencies - Set<Feature> bootFeatures = new HashSet<>(); - Map<String, Map<Version, Feature>> featuresCache = new HashMap<>(); - addFeatures(allBootFeatures, generated.getName(), bootFeatures, true, featuresCache); + FeatureSelector selector = new FeatureSelector(allBootFeatures); + Set<Feature> bootFeatures = selector.selectMatching(singletonList(generated.getName())); for (Feature feature : bootFeatures) { // the feature is a startup feature, updating startup.properties file LOGGER.info(" Feature " + feature.getId() + " is defined as a boot feature"); @@ -1250,93 +1244,6 @@ public class Builder { } } - private void addFeatures(Set<Feature> allFeatures, String feature, Set<Feature> features, boolean mandatory, Map<String, Map<Version, Feature>> featuresCache) { - String name; - Version osgiVersion; - VersionRange range; - int idx = feature.indexOf('/'); - if (idx > 0) { - name = feature.substring(0, idx); - String version = feature.substring(idx + 1); - version = version.trim(); - osgiVersion = VersionTable.getVersion(version); - if (version.equals(org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION)) { - range = new VersionRange(Version.emptyVersion); - } else { - range = new VersionRange(version, true, true); - } - } else { - name = feature; - osgiVersion = Version.emptyVersion; - range = new VersionRange(Version.emptyVersion); - } - Set<Feature> set = new HashSet<>(); - boolean featurePresentInCache = false; - Optional<Map<Version, Feature>> optionalVersionFeatureMap = Optional.ofNullable(featuresCache.get(name)); - if(optionalVersionFeatureMap.isPresent()) { - Optional<Feature> cachedFeature = Optional.ofNullable(optionalVersionFeatureMap.get().get(osgiVersion)); - if(cachedFeature.isPresent()){ - set.add(cachedFeature.get()); - featurePresentInCache = true; - } - } - if(!featurePresentInCache) { - for (Feature f : allFeatures) { - if (f.getName().equals(name) && range.contains(VersionTable.getVersion(f.getVersion()))) { - set.add(f); - Map<Version, Feature> versionFeatureMap = Optional.ofNullable(featuresCache.get(name)).orElse(new HashMap<>()); - versionFeatureMap.put(osgiVersion, f); - featuresCache.put(name, versionFeatureMap); - } - } - } - if (mandatory && set.isEmpty()) { - throw new IllegalStateException("Could not find matching feature for " + feature); - } - for (Feature f : set) { - features.add(f); - for (Dependency dep : f.getFeature()) { - addFeatures(allFeatures, dep.toString(), features, !dep.isDependency() && !dep.isPrerequisite(), featuresCache); - } - } - } - - private String getFeatureSt(Dependency dep) { - String version = dep.getVersion() == null || "0.0.0".equals(dep.getVersion()) ? "" : "/" + dep.getVersion(); - return dep.getName() + version; - } - - /** - * Checks if a given feature f matches the featureRef. - * TODO Need to also check for version ranges. Currently ranges are ignored and all features matching the name - * are copied in that case. - * - * @param f - * @param featureRef - * @return - */ - private boolean matches(Feature f, Dependency featureRef) { - if (!f.getName().equals(featureRef.getName())) { - return false; - } - - final String featureRefVersion = featureRef.getVersion(); - - if (featureRefVersion == null) { - return true; - } - - if (featureRefVersion.equals("0.0.0")) { - return true; - } - - if (featureRefVersion.startsWith("[")) { - return true; - } - - return VersionUtils.versionEquals(f.getVersion(), featureRefVersion); - } - private List<String> getStaged(Stage stage, Map<String, Stage> data) { List<String> staged = new ArrayList<>(); for (String s : data.keySet()) { http://git-wip-us.apache.org/repos/asf/karaf/blob/cc758635/profile/src/main/java/org/apache/karaf/profile/assembly/FeatureSelector.java ---------------------------------------------------------------------- diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/FeatureSelector.java b/profile/src/main/java/org/apache/karaf/profile/assembly/FeatureSelector.java new file mode 100644 index 0000000..1e453d6 --- /dev/null +++ b/profile/src/main/java/org/apache/karaf/profile/assembly/FeatureSelector.java @@ -0,0 +1,94 @@ +/* + * 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.profile.assembly; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.felix.utils.version.VersionRange; +import org.apache.felix.utils.version.VersionTable; +import org.apache.karaf.features.internal.model.Dependency; +import org.apache.karaf.features.internal.model.Feature; +import org.osgi.framework.Version; + +public class FeatureSelector { + Map<String, Set<Feature>> featuresCache; + + public FeatureSelector(Set<Feature> features) { + featuresCache = new HashMap<>(); + for (Feature feature : features) { + featuresCache.computeIfAbsent(feature.getName(), fn -> new HashSet<>()) + .add(feature); + } + } + + public Set<Feature> selectMatching(List<String> features) { + Set<Feature> selected = new HashSet<>(); + for (String feature : features) { + addFeatures(feature, selected, true); + } + return selected; + } + + private void addFeatures(String feature, Set<Feature> features, boolean mandatory) { + Set<Feature> set = getMatching(feature); + if (mandatory && set.isEmpty()) { + throw new IllegalStateException("Could not find matching feature for " + feature); + } + for (Feature f : set) { + features.add(f); + for (Dependency dep : f.getFeature()) { + addFeatures(dep.toString(), features, isMandatory(dep)); + } + } + } + + private boolean isMandatory(Dependency dep) { + return !dep.isDependency() && !dep.isPrerequisite(); + } + + private Set<Feature> getMatching(String nameAndVersion) { + VersionRange range; + String name; + int idx = nameAndVersion.indexOf('/'); + if (idx > 0) { + name = nameAndVersion.substring(0, idx); + String version = nameAndVersion.substring(idx + 1); + version = version.trim(); + if (version.equals(org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION)) { + range = new VersionRange(Version.emptyVersion); + } else { + range = new VersionRange(version, true, true); + } + } else { + name = nameAndVersion; + range = new VersionRange(Version.emptyVersion); + } + Set<Feature> versionToFeatures = featuresCache.get(name); + if (versionToFeatures == null) { + return Collections.emptySet(); + } + return versionToFeatures.stream() + .filter(f -> f.getName().equals(name) && range.contains(VersionTable.getVersion(f.getVersion()))) + .collect(Collectors.toSet()); + } +}