Skip to content

Commit 22d1d4f

Browse files
committed
Add feature:contains command (#2523)
The command lists features that contain a specific bundle
1 parent dcbd467 commit 22d1d4f

2 files changed

Lines changed: 100 additions & 0 deletions

File tree

features/command/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@
5454
<groupId>org.osgi</groupId>
5555
<artifactId>org.osgi.framework</artifactId>
5656
</dependency>
57+
<dependency>
58+
<!-- for ContainsBundleCommand -->
59+
<groupId>org.apache.karaf.bundle</groupId>
60+
<artifactId>org.apache.karaf.bundle.core</artifactId>
61+
</dependency>
5762
<dependency>
5863
<groupId>org.apache.karaf.features</groupId>
5964
<artifactId>org.apache.karaf.features.core</artifactId>
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package org.apache.karaf.features.command;
2+
3+
import org.apache.karaf.bundle.core.BundleService;
4+
import org.apache.karaf.features.BundleInfo;
5+
import org.apache.karaf.features.Feature;
6+
import org.apache.karaf.features.FeaturesService;
7+
import org.apache.karaf.features.command.completers.InstalledRepoNameCompleter;
8+
import org.apache.karaf.shell.api.action.Command;
9+
import org.apache.karaf.shell.api.action.Completion;
10+
import org.apache.karaf.shell.api.action.Option;
11+
import org.apache.karaf.shell.api.action.lifecycle.Reference;
12+
import org.apache.karaf.shell.api.action.lifecycle.Service;
13+
import org.apache.karaf.shell.support.CommandException;
14+
import org.osgi.framework.Bundle;
15+
16+
import java.util.Arrays;
17+
import java.util.List;
18+
import java.util.Set;
19+
import java.util.function.Predicate;
20+
import java.util.stream.Collectors;
21+
22+
@Command(scope = "feature", name = "contains", description = "Finds the features that contain a specified bundle.")
23+
@Service
24+
public class ContainsBundleCommand extends FeaturesCommandSupport {
25+
26+
@Option(name = "-b", description = "Show features containing the given bundle id", required = false, multiValued = false)
27+
Integer bundleId;
28+
29+
@Option(name = "-s", description = "Show features containing a bundle with the given symbolic name", required = false, multiValued = false)
30+
String bundleName;
31+
32+
@Option(name = "-u", description = "Show features containing a bundle with the given URL", required = false, multiValued = false)
33+
String bundleUrl;
34+
35+
@Option(name = "-i", aliases = {"--installed"}, description = "Display a list of all installed features only", required = false, multiValued = false)
36+
boolean onlyInstalled;
37+
38+
@Option(name = "--repository", description = "Only list features from that repository", required = false, multiValued = false)
39+
@Completion(InstalledRepoNameCompleter.class)
40+
String repository;
41+
42+
@Reference
43+
BundleService bundleService;
44+
45+
@Override
46+
protected void doExecute(FeaturesService featuresService) throws Exception {
47+
String bundleLocation;
48+
if (bundleId != null) {
49+
Bundle bundle = bundleService.getBundle(bundleId.toString());
50+
if (bundle == null)
51+
throw new CommandException("No bundles found with id " + bundleId);
52+
bundleLocation = bundleService.getInfo(bundle).getUpdateLocation();
53+
} else if (bundleName != null) {
54+
Bundle bundle = bundleService.selectBundles(List.of(), true).stream()
55+
.filter(b -> bundleName.equals(b.getSymbolicName()))
56+
.findAny()
57+
.orElseThrow(() -> new CommandException("No bundles found with name " + bundleName));
58+
bundleLocation = bundleService.getInfo(bundle).getUpdateLocation();
59+
} else if (bundleUrl != null) {
60+
bundleLocation = bundleUrl;
61+
} else {
62+
throw new CommandException("Either bundle id, name or URL must be specified");
63+
}
64+
65+
if (bundleLocation == null)
66+
throw new CommandException("Could not determine URL of the specified bundle");
67+
68+
Feature[] features;
69+
if (repository != null && !onlyInstalled)
70+
features = featuresService.getFeatures(repository);
71+
else
72+
features = featuresService.listFeatures();
73+
74+
Set<Feature> containingFeatures = Arrays.stream(features)
75+
.filter(f -> !onlyInstalled || featuresService.isInstalled(f))
76+
.filter(f -> f.getBundles().stream().anyMatch(byBundleLocation(bundleLocation)))
77+
.collect(Collectors.toUnmodifiableSet());
78+
79+
containingFeatures.stream()
80+
.map(f -> String.format("%s %s", f.getName(), f.getVersion()))
81+
.sorted()
82+
.forEach(System.out::println);
83+
}
84+
85+
private Predicate<BundleInfo> byBundleLocation(String bundleLocation) {
86+
return bundleInfo ->
87+
{
88+
String location = bundleInfo.getLocation();
89+
String originalLocation = bundleInfo.getOriginalLocation();
90+
return (location != null && location.startsWith(bundleLocation)) ||
91+
(originalLocation != null && originalLocation.startsWith(bundleLocation));
92+
};
93+
}
94+
95+
}

0 commit comments

Comments
 (0)