Skip to content

Commit

Permalink
RepoView: Clipboard: Bundles with self-imports
Browse files Browse the repository at this point in the history
For debugging purposes it is useful to identify bundles containing self-imported packages.
I added this to the Repo-Browser on Right Click on a Repo / Copy to Clipboard / Bundles with Self-imports.
It outputs a simple list to the clipboard which can be pased to a texteditor for further analysis. In the future this might be refactored into more sophisticated solution but for the moment it is already useful.

Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
  • Loading branch information
chrisrueger committed Sep 12, 2024
1 parent 1a96490 commit 4314d00
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 0 deletions.
56 changes: 56 additions & 0 deletions biz.aQute.bndlib/src/aQute/bnd/osgi/resource/ResourceUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -97,6 +98,10 @@ public abstract class ResourceUtils {
private static final Converter cnv = new Converter()
.hook(Version.class, (dest, o) -> toVersion(o));

private static final String PACKAGE_FILTER_PATTERN = "osgi.wiring.package=([^)]*)";
private static final Pattern pkgFilterPattern = Pattern
.compile(PACKAGE_FILTER_PATTERN);

public interface IdentityCapability extends Capability {
public enum Type {
bundle(IdentityNamespace.TYPE_BUNDLE),
Expand Down Expand Up @@ -952,4 +957,55 @@ public static List<Capability> detectDuplicateCapabilitiesWithDifferentHashes(St

return culprits;
}

/**
* Calculates a list of package names which are exported and also imported.
* This can be handy for debugging and identify unwanted self-imports.
*
* @param r the resource
* @return a non-null list of self-import package names.
*/
public static Set<String> getSelfImportPackages(Resource r) {
List<Capability> caps = r.getCapabilities(PackageNamespace.PACKAGE_NAMESPACE);
List<Requirement> requirements = r.getRequirements(PackageNamespace.PACKAGE_NAMESPACE);

Set<String> exportedPackages = new LinkedHashSet<>();
Set<String> importedPackages = new LinkedHashSet<>();

// Populate exported packages
for (Capability cap : caps) {
String packageName = (String) cap.getAttributes()
.get(PackageNamespace.PACKAGE_NAMESPACE);
if (packageName != null) {
exportedPackages.add(packageName);
}
}

// Populate imported packages
for (Requirement req : requirements) {
String requirementPackage = getRequirementPackage(req);
if (requirementPackage != null) {
importedPackages.add(requirementPackage);
}
}

Set<String> selfImports = new LinkedHashSet<>(exportedPackages);
selfImports.retainAll(importedPackages);

return selfImports;
}

private static String getRequirementPackage(Requirement req) {

String filter = req.getDirectives()
.get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
if (filter != null) {
Matcher m = pkgFilterPattern.matcher(filter);
if (m.find()) {
return m.group(1);
}
}

return null;
}
}
32 changes: 32 additions & 0 deletions bndtools.core/src/bndtools/views/repository/RepositoriesView.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
import aQute.bnd.build.Workspace;
import aQute.bnd.exceptions.Exceptions;
import aQute.bnd.http.HttpClient;
import aQute.bnd.osgi.resource.ResourceUtils;
import aQute.bnd.service.Actionable;
import aQute.bnd.service.Refreshable;
import aQute.bnd.service.Registry;
Expand All @@ -114,6 +115,7 @@
import bndtools.model.repo.RepositoryBundleVersion;
import bndtools.model.repo.RepositoryEntry;
import bndtools.model.repo.RepositoryTreeLabelProvider;
import bndtools.model.repo.ResourceProvider;
import bndtools.model.repo.SearchableRepositoryTreeContentProvider;
import bndtools.preferences.BndPreferences;
import bndtools.preferences.WorkspaceOfflineChangeAdapter;
Expand Down Expand Up @@ -1127,6 +1129,7 @@ private void addCopyToClipboardSubMenueEntries(Actionable act, final RepositoryP

if ((act instanceof Repository) || (act instanceof RepositoryPlugin)) {
hmenu.add(createContextMenueCopyInfoRepo(act, rp, clipboard));
hmenu.add(createContextMenueCopyBundlesWithSelfImports(act, rp, clipboard));
}

}
Expand Down Expand Up @@ -1154,6 +1157,35 @@ private HierarchicalLabel<Action> createContextMenueCopyInfoRepo(Actionable act,
}));
}

private HierarchicalLabel<Action> createContextMenueCopyBundlesWithSelfImports(Actionable act, final RepositoryPlugin rp,
final Clipboard clipboard) {
return new HierarchicalLabel<Action>("Copy to clipboard :: Bundles with self-imports", (label) -> createAction(label.getLeaf(),
"Add list of bundles containing self-imported packages in their Manifest.", true, false, rp, () -> {

final StringBuilder sb = new StringBuilder();

Object[] result = contentProvider.getChildren(rp);
for (Object object : result) {
if (object instanceof ResourceProvider prov) {
org.osgi.resource.Resource r = prov.getResource();

Set<String> selfImports = ResourceUtils.getSelfImportPackages(r);
if (!selfImports.isEmpty()) {
sb.append(r.toString() + " has " + selfImports.size() + " self-import packages: "
+ selfImports + "\n");
}
}
}

if (sb.isEmpty()) {
clipboard.copy("-Empty-");
} else {
clipboard.copy(sb.toString());
}

}));
}

private HierarchicalLabel<Action> createContextMenueCopyInfoRepoBundle(Actionable act, final RepositoryPlugin rp,
final Clipboard clipboard, RepositoryBundle rb) {
return new HierarchicalLabel<Action>("Copy to clipboard :: Copy info", (label) -> createAction(label.getLeaf(),
Expand Down

0 comments on commit 4314d00

Please sign in to comment.