From 3ea242045e520db1f1474ee5d057d73bd085c2ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Wed, 20 Aug 2025 19:11:28 +0200 Subject: [PATCH 1/4] Show target result in the resolution view Analyze target problems can be a daunting task, this now makes it possible to view the Cap+Req of a open target editor in the "OSGi Resolution View" --- .../META-INF/MANIFEST.MF | 2 + .../ui/views/resolution/ResolutionView.java | 268 ++++++++---------- .../targetdefinition/TargetCapReqLoader.java | 125 ++++++++ .../editor/targetdefinition/TargetEditor.java | 4 + 4 files changed, 244 insertions(+), 155 deletions(-) create mode 100644 ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetCapReqLoader.java diff --git a/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF index 6e1de55ab63..5ec32fabf3b 100644 --- a/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF +++ b/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF @@ -6,9 +6,11 @@ Bundle-Vendor: Eclipse.org Bundle-Version: 1.2.300.qualifier Bundle-Localization: plugin Export-Package: org.eclipse.pde.bnd.ui.autocomplete;version="1.0.0";x-friends:="org.eclipse.pde.ui", + org.eclipse.pde.bnd.ui.model.resolution, org.eclipse.pde.bnd.ui.plugins;x-internal:=true, org.eclipse.pde.bnd.ui.preferences;version="1.0.0";x-friends:="org.eclipse.pde.ui", org.eclipse.pde.bnd.ui.quickfix;version="1.0.0";x-friends:="org.eclipse.pde.ui", + org.eclipse.pde.bnd.ui.tasks, org.eclipse.pde.bnd.ui.templating;version="1.0.0";x-friends:="org.eclipse.pde.ui", org.eclipse.pde.bnd.ui.wizards;version="1.0.0";x-friends:="org.eclipse.pde.ui" Import-Package: aQute.bnd.build;version="4.5.0", diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java index f986601d615..338b4229085 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java @@ -109,7 +109,6 @@ import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IPartListener; import org.eclipse.ui.ISelectionListener; -import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; @@ -132,43 +131,42 @@ public class ResolutionView extends ViewPart implements ISelectionListener, IResourceChangeListener { - public static final String PLUGIN_ID = "bndtools.core"; + public static final String PLUGIN_ID = "bndtools.core"; - private final List ees = Arrays.asList(EE.values()); - private Display display = null; + private final List ees = Arrays.asList(EE.values()); + private Display display = null; - private Tree reqsTree = null; - private Table capsTable = null; + private Tree reqsTree = null; + private Table capsTable = null; - private TreeViewer reqsViewer; - private TableViewer capsViewer; + private TreeViewer reqsViewer; + private TableViewer capsViewer; - private Label reqsLabel; - private Label capsLabel; + private Label reqsLabel; + private Label capsLabel; - private ViewerFilter hideSelfImportsFilter; - private ViewerFilter hideOptionalRequirements; - private ViewerFilter filterShowCapsProblems; + private ViewerFilter hideSelfImportsFilter; + private ViewerFilter hideOptionalRequirements; + private ViewerFilter filterShowCapsProblems; - private boolean inputLocked = false; - private boolean outOfDate = false; - Set loaders; - private Job analysisJob; - private int currentEE = 4; + private boolean inputLocked = false; + private boolean outOfDate = false; + Set loaders; + private Job analysisJob; + private int currentEE = 4; - private final Set filteredCapabilityNamespaces; - private Set duplicateCapabilitiesWithDifferentHashes = new HashSet<>(); + private final Set filteredCapabilityNamespaces; + private Set duplicateCapabilitiesWithDifferentHashes = new HashSet<>(); private final FilterPanelPart reqsFilterPart = new FilterPanelPart(Resources.getScheduler()); private final FilterPanelPart capsFilterPart = new FilterPanelPart(Resources.getScheduler()); - private static final String SEARCHSTRING_HINT = "Enter search string (Space to separate terms; '*' for partial matches)"; + private static final String SEARCHSTRING_HINT = "Enter search string (Space to separate terms; '*' for partial matches)"; - private CapReqMapContentProvider reqsContentProvider; - private CapReqMapContentProvider capsContentProvider; + private CapReqMapContentProvider reqsContentProvider; + private CapReqMapContentProvider capsContentProvider; - private final IEventBroker eventBroker = PlatformUI.getWorkbench() - .getService(IEventBroker.class); + private final IEventBroker eventBroker = PlatformUI.getWorkbench().getService(IEventBroker.class); public ResolutionView() { filteredCapabilityNamespaces = Sets.of(IdentityNamespace.IDENTITY_NAMESPACE, HostNamespace.HOST_NAMESPACE); @@ -182,8 +180,16 @@ public void partActivated(IWorkbenchPart part) { if (outOfDate) { executeAnalysis(); } - } else if (part instanceof IEditorPart) { - IEditorInput editorInput = ((IEditorPart) part).getEditorInput(); + } else if (part instanceof IEditorPart editor) { + CapReqLoader editorLoader = Adapters.adapt(editor, CapReqLoader.class); + if (editorLoader != null) { + System.out.println("Got loader from editor!"); + setLoaders(Collections.singleton(editorLoader)); + return; + } + System.out.println("Editor is: " + editor); + IEditorInput editorInput = editor.getEditorInput(); + System.out.println("Editor input is: " + editorInput); IFile file = ResourceUtil.getFile(editorInput); if (file != null) { @@ -194,24 +200,17 @@ public void partActivated(IWorkbenchPart part) { if (loader != null) { setLoaders(Collections.singleton(loader)); - - if (getSite().getPage() - .isPartVisible(ResolutionView.this)) { - executeAnalysis(); - } else { - outOfDate = true; - } } } } + } else { + System.out.println("Activated: " + part); } } }; - - - private boolean setLoaders(Set newLoaders) { + System.out.println("Set loaders: " + newLoaders); Set oldLoaders = loaders; boolean swap = !oldLoaders.equals(newLoaders); if (swap) { @@ -220,6 +219,13 @@ private boolean setLoaders(Set newLoaders) { for (CapReqLoader l : swap ? oldLoaders : newLoaders) { IO.close(l); } + if (swap) { + if (getSite().getPage().isPartVisible(ResolutionView.this)) { + executeAnalysis(); + } else { + outOfDate = true; + } + } return swap; } @@ -272,9 +278,10 @@ public void createPartControl(Composite parent) { reqsViewer.addDoubleClickListener(event -> handleReqsViewerDoubleClickEvent(event)); reqsViewer.getControl() - .addKeyListener(createCopyToClipboardAdapter(reqsViewer, - (IStructuredSelection selection, StringBuilder clipboardContent) -> reqsCopyToClipboard(selection, - (RequirementWrapperLabelProvider) reqsViewer.getLabelProvider(), clipboardContent))); + .addKeyListener(createCopyToClipboardAdapter(reqsViewer, + (IStructuredSelection selection, StringBuilder clipboardContent) -> reqsCopyToClipboard( + selection, (RequirementWrapperLabelProvider) reqsViewer.getLabelProvider(), + clipboardContent))); Composite capsPanel = new Composite(splitPanel, SWT.NONE); capsPanel.setBackground(parent.getBackground()); @@ -323,9 +330,10 @@ public boolean select(Viewer viewer, Object parentElement, Object element) { capsViewer.addDoubleClickListener(event -> handleCapsViewerDoubleClickEvent(event)); capsViewer.getTable() - .addKeyListener(createCopyToClipboardAdapter(capsViewer, - (IStructuredSelection selection1, StringBuilder clipboardContent1) -> capsCopyToClipboard(selection1, - (CapabilityLabelProvider) capsViewer.getLabelProvider(), clipboardContent1))); + .addKeyListener(createCopyToClipboardAdapter(capsViewer, + (IStructuredSelection selection1, StringBuilder clipboardContent1) -> capsCopyToClipboard( + selection1, (CapabilityLabelProvider) capsViewer.getLabelProvider(), + clipboardContent1))); hideSelfImportsFilter = new ViewerFilter() { @@ -350,40 +358,26 @@ public boolean select(Viewer viewer, Object parentElement, Object element) { } }; + reqsViewer.addDragSupport(DND.DROP_MOVE | DND.DROP_COPY, + new Transfer[] { LocalSelectionTransfer.getTransfer() }, new LocalTransferDragListener(reqsViewer)); - reqsViewer.addDragSupport(DND.DROP_MOVE | DND.DROP_COPY, new Transfer[] { - LocalSelectionTransfer.getTransfer() - }, new LocalTransferDragListener(reqsViewer)); - - capsViewer.addDragSupport(DND.DROP_MOVE | DND.DROP_COPY, new Transfer[] { - LocalSelectionTransfer.getTransfer() - }, new LocalTransferDragListener(capsViewer)); + capsViewer.addDragSupport(DND.DROP_MOVE | DND.DROP_COPY, + new Transfer[] { LocalSelectionTransfer.getTransfer() }, new LocalTransferDragListener(capsViewer)); reqsViewer.addOpenListener(this::openEditor); fillActionBars(); - getSite().getPage() - .addPostSelectionListener(this); - getSite().getPage() - .addPartListener(partAdapter); - ResourcesPlugin.getWorkspace() - .addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); + getSite().getPage().addPostSelectionListener(this); + getSite().getPage().addPartListener(partAdapter); + ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); // Current selection & part - IWorkbenchPart activePart = getSite().getPage() - .getActivePart(); - ISelection activeSelection = getSite().getWorkbenchWindow() - .getSelectionService() - .getSelection(); + IWorkbenchPart activePart = getSite().getPage().getActivePart(); + ISelection activeSelection = getSite().getWorkbenchWindow().getSelectionService().getSelection(); selectionChanged(activePart, activeSelection); } - - - - - private void openEditor(OpenEvent event) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); for (Iterator iter = selection.iterator(); iter.hasNext();) { @@ -392,8 +386,7 @@ private void openEditor(OpenEvent event) { String className = clazz.getFQN(); IType type = null; if (!loaders.isEmpty()) { - IWorkspaceRoot wsroot = ResourcesPlugin.getWorkspace() - .getRoot(); + IWorkspaceRoot wsroot = ResourcesPlugin.getWorkspace().getRoot(); for (CapReqLoader loader : loaders) { if (loader instanceof BndBuilderCapReqLoader) { File loaderFile = ((BndBuilderCapReqLoader) loader).getFile(); @@ -407,8 +400,9 @@ private void openEditor(OpenEvent event) { } } catch (JavaModelException e1) { ErrorDialog.openError(getSite().getShell(), "Error", "", - new Status(IStatus.ERROR, PLUGIN_ID, 0, - MessageFormat.format("Error opening Java class '{0}'.", className), e1)); + new Status(IStatus.ERROR, PLUGIN_ID, 0, + MessageFormat.format("Error opening Java class '{0}'.", className), + e1)); } } } @@ -420,19 +414,18 @@ private void openEditor(OpenEvent event) { JavaUI.openInEditor(type, true, true); } } catch (PartInitException e2) { - ErrorDialog.openError(getSite().getShell(), "Error", "", new Status(IStatus.ERROR, PLUGIN_ID, - 0, MessageFormat.format("Error opening Java editor for class '{0}'.", className), e2)); + ErrorDialog.openError(getSite().getShell(), "Error", "", new Status(IStatus.ERROR, PLUGIN_ID, 0, + MessageFormat.format("Error opening Java editor for class '{0}'.", className), e2)); } catch (JavaModelException e3) { - ErrorDialog.openError(getSite().getShell(), "Error", "", new Status(IStatus.ERROR, PLUGIN_ID, - 0, MessageFormat.format("Error opening Java class '{0}'.", className), e3)); + ErrorDialog.openError(getSite().getShell(), "Error", "", new Status(IStatus.ERROR, PLUGIN_ID, 0, + MessageFormat.format("Error opening Java class '{0}'.", className), e3)); } } } } void fillActionBars() { - IToolBarManager toolBarManager = getViewSite().getActionBars() - .getToolBarManager(); + IToolBarManager toolBarManager = getViewSite().getActionBars().getToolBarManager(); // Reqs Buttons toolBarManager.add(createToggleHideSelfImportsButton()); @@ -450,10 +443,6 @@ void fillActionBars() { } - - - - private void doEEActionMenu(IToolBarManager toolBarManager) { MenuManager menuManager = new MenuManager("Java", "resolutionview.java.menu"); @@ -465,9 +454,7 @@ public void runWithEvent(Event event) { if (items != null && items.length == ees.size()) { menu.setDefaultItem(items[currentEE]); } - Point location = getViewSite().getShell() - .getDisplay() - .getCursorLocation(); + Point location = getViewSite().getShell().getDisplay().getCursorLocation(); menu.setLocation(location.x, location.y); menu.setVisible(true); } @@ -510,23 +497,21 @@ protected void setEE(int ee) { } @Override - public void setFocus() {} + public void setFocus() { + } @Override public void dispose() { - getSite().getPage() - .removeSelectionListener(this); - ResourcesPlugin.getWorkspace() - .removeResourceChangeListener(this); - getSite().getPage() - .removePartListener(partAdapter); - setLoaders(Collections. emptySet()); + getSite().getPage().removeSelectionListener(this); + ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); + getSite().getPage().removePartListener(partAdapter); + setLoaders(Collections.emptySet()); duplicateCapabilitiesWithDifferentHashes.clear(); super.dispose(); } - public void setInput(Set sourceLoaders, Map> capabilities, - Map> requirements) { + private void setInput(Set sourceLoaders, Map> capabilities, + Map> requirements) { setLoaders(sourceLoaders); sourceLoaders = loaders; if (reqsTree != null && !reqsTree.isDisposed() && capsTable != null && !capsTable.isDisposed()) { @@ -551,13 +536,10 @@ public void setInput(Set sourceLoaders, Map caps = capabilities.values() - .stream() - .flatMap(List::stream) - .toList(); + List caps = capabilities.values().stream().flatMap(List::stream).toList(); duplicateCapabilitiesWithDifferentHashes = new HashSet( - ResourceUtils.detectDuplicateCapabilitiesWithDifferentHashes("osgi.wiring.package", caps)); + ResourceUtils.detectDuplicateCapabilitiesWithDifferentHashes("osgi.wiring.package", caps)); updateCapsLabel(); @@ -566,27 +548,15 @@ public void setInput(Set sourceLoaders, Map loaders = getLoadersFromSelection((IStructuredSelection) selection); - if (setLoaders(loaders)) { - IWorkbenchPage page = getSite().getPage(); - if (page != null && page.isPartVisible(this)) { - executeAnalysis(); - } else { - outOfDate = true; - } - } - + setLoaders(getLoadersFromSelection((IStructuredSelection) selection)); } private void updateReqsLabel() { - reqsLabel.setText("Requirements: " + reqsViewer.getTree() - .getItemCount()); - reqsLabel.getParent() - .layout(); + reqsLabel.setText("Requirements: " + reqsViewer.getTree().getItemCount()); + reqsLabel.getParent().layout(); } private void updateCapsLabel() { @@ -594,8 +564,7 @@ private void updateCapsLabel() { if (!duplicateCapabilitiesWithDifferentHashes.isEmpty()) { int problemCount = 0; - TableItem[] items = capsViewer.getTable() - .getItems(); + TableItem[] items = capsViewer.getTable().getItems(); for (int i = 0; i < items.length; i++) { TableItem tableItem = items[i]; Object data = tableItem.getData(); @@ -610,11 +579,9 @@ private void updateCapsLabel() { problemAddition = " Problems: " + problemCount; } } - capsLabel.setText("Capabilities: " + capsViewer.getTable() - .getItemCount() + problemAddition); + capsLabel.setText("Capabilities: " + capsViewer.getTable().getItemCount() + problemAddition); - capsLabel.getParent() - .layout(); + capsLabel.getParent().layout(); } private Set getLoadersFromSelection(IStructuredSelection structSel) { @@ -683,7 +650,7 @@ void executeAnalysis() { if (!loaders.isEmpty()) { final AnalyseBundleResolutionJob job = new AnalyseBundleResolutionJob("importExportAnalysis", loaders, - ees.get(currentEE)); + ees.get(currentEE)); job.setSystem(true); job.addJobChangeListener(new JobChangeAdapter() { @@ -704,8 +671,8 @@ public void done(IJobChangeEvent event) { IStatus result = job.getResult(); if (result != null && result.isOK()) { if (display != null && !display.isDisposed()) { - display - .asyncExec(() -> setInput(loaders, job.getCapabilities(), job.getRequirements())); + display.asyncExec( + () -> setInput(loaders, job.getCapabilities(), job.getRequirements())); } } } @@ -722,15 +689,13 @@ public void done(IJobChangeEvent event) { @Override public void resourceChanged(IResourceChangeEvent event) { if (!loaders.isEmpty()) { - IWorkspaceRoot wsroot = ResourcesPlugin.getWorkspace() - .getRoot(); + IWorkspaceRoot wsroot = ResourcesPlugin.getWorkspace().getRoot(); for (CapReqLoader loader : loaders) { if (loader instanceof BndBuilderCapReqLoader) { File file = ((BndBuilderCapReqLoader) loader).getFile(); IFile[] wsfiles = wsroot.findFilesForLocationURI(file.toURI()); for (IFile wsfile : wsfiles) { - if (event.getDelta() - .findMember(wsfile.getFullPath()) != null) { + if (event.getDelta().findMember(wsfile.getFullPath()) != null) { executeAnalysis(); break; } @@ -749,7 +714,8 @@ public LocalTransferDragListener(Viewer viewer) { } @Override - public void dragStart(DragSourceEvent event) {} + public void dragStart(DragSourceEvent event) { + } @Override public void dragSetData(DragSourceEvent event) { @@ -760,12 +726,12 @@ public void dragSetData(DragSourceEvent event) { } @Override - public void dragFinished(DragSourceEvent event) {} + public void dragFinished(DragSourceEvent event) { + } } private void handleReqsViewerDoubleClickEvent(DoubleClickEvent event) { - if (!event.getSelection() - .isEmpty()) { + if (!event.getSelection().isEmpty()) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); final Object element = selection.getFirstElement(); @@ -780,8 +746,7 @@ private void handleReqsViewerDoubleClickEvent(DoubleClickEvent event) { } private void handleCapsViewerDoubleClickEvent(DoubleClickEvent event) { - if (!event.getSelection() - .isEmpty()) { + if (!event.getSelection().isEmpty()) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); final Object element = selection.getFirstElement(); @@ -793,13 +758,12 @@ private void handleCapsViewerDoubleClickEvent(DoubleClickEvent event) { // (&(osgi.wiring.package=my.package.foo)(version>=1.7.23)) Requirement req = CapReqBuilder.createRequirementFromCapability(cap, (name) -> { if (name.equals("bundle-symbolic-name") || name.equals("bundle-version") - || name.equals("bnd.hashes")) { + || name.equals("bnd.hashes")) { return false; } return true; - }) - .buildSyntheticRequirement(); + }).buildSyntheticRequirement(); // Open AdvanvedSearch of RepositoriesView eventBroker.post(ViewEventTopics.REPOSITORIESVIEW_OPEN_ADVANCED_SEARCH.topic(), req); } @@ -810,13 +774,13 @@ private void handleCapsViewerDoubleClickEvent(DoubleClickEvent event) { /** * Generic copy to clipboard handling via Ctrl+C or MacOS: Cmd+C * - * @param viewer the viewer - * @param clipboardContentExtractor handler to extract content from the - * selected items. + * @param viewer the viewer + * @param clipboardContentExtractor handler to extract content from the selected + * items. * @return a KeyAdapter copying content of the selected items to clipboard */ private KeyAdapter createCopyToClipboardAdapter(StructuredViewer viewer, - BiConsumer clipboardContentExtractor) { + BiConsumer clipboardContentExtractor) { return new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { @@ -830,11 +794,8 @@ public void keyPressed(KeyEvent e) { if (clipboardString.length() > 0) { Clipboard clipboard = new Clipboard(Display.getCurrent()); TextTransfer textTransfer = TextTransfer.getInstance(); - clipboard.setContents(new Object[] { - clipboardString.toString() - }, new Transfer[] { - textTransfer - }); + clipboard.setContents(new Object[] { clipboardString.toString() }, + new Transfer[] { textTransfer }); clipboard.dispose(); } } @@ -843,9 +804,8 @@ public void keyPressed(KeyEvent e) { }; } - private void reqsCopyToClipboard(IStructuredSelection selection, RequirementWrapperLabelProvider lp, - StringBuilder clipboardContent) { + StringBuilder clipboardContent) { for (Iterator iterator = selection.iterator(); iterator.hasNext();) { Object element = iterator.next(); @@ -869,10 +829,8 @@ private void reqsCopyToClipboard(IStructuredSelection selection, RequirementWrap } } - - private void capsCopyToClipboard(IStructuredSelection selection, CapabilityLabelProvider lp, - StringBuilder clipboardContent) { + StringBuilder clipboardContent) { for (Iterator iterator = selection.iterator(); iterator.hasNext();) { Object element = iterator.next(); @@ -919,7 +877,7 @@ public void runWithEvent(Event event) { if (isChecked()) { capsViewer.addFilter(filterShowCapsProblems); this.setToolTipText( - "Showing capabilities containing packages that have the same name but differ in the contained classes."); + "Showing capabilities containing packages that have the same name but differ in the contained classes."); } else { capsViewer.removeFilter(filterShowCapsProblems); this.setToolTipText(tooltipTextUnlocked); @@ -930,8 +888,7 @@ public void runWithEvent(Event event) { }; toggleShowProblemCaps.setChecked(false); toggleShowProblemCaps.setImageDescriptor(Resources.getImageDescriptor("/icons/warning_obj.svg")); - toggleShowProblemCaps - .setToolTipText(tooltipTextUnlocked); + toggleShowProblemCaps.setToolTipText(tooltipTextUnlocked); return toggleShowProblemCaps; } @@ -959,7 +916,7 @@ public void runWithEvent(Event event) { private IAction createToggleHideSelfImportsButton() { String toolTipTextShowAll = "Showing all requirements."; String toolTipTextHideSelfImports = "Hiding resolved (including self-imported) requirements.\n\n" - + "Requirements that are resolved (exported and imported) within the set of selected bundles are hidden. Click to show all requirements."; + + "Requirements that are resolved (exported and imported) within the set of selected bundles are hidden. Click to show all requirements."; IAction toggleShowSelfImports = new Action("showSelfImports", IAction.AS_CHECK_BOX) { @Override @@ -997,7 +954,8 @@ public void runWithEvent(Event event) { } }; toggleShowShowUnresolvedReqsFilter.setChecked(false); - toggleShowShowUnresolvedReqsFilter.setImageDescriptor(Resources.getImageDescriptor("/icons/excludeMode_filter.svg")); + toggleShowShowUnresolvedReqsFilter + .setImageDescriptor(Resources.getImageDescriptor("/icons/excludeMode_filter.svg")); toggleShowShowUnresolvedReqsFilter.setToolTipText(toggleShowShowUnresolvedReqsFilterUnchecked); return toggleShowShowUnresolvedReqsFilter; } diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetCapReqLoader.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetCapReqLoader.java new file mode 100644 index 00000000000..d4ad9a30718 --- /dev/null +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetCapReqLoader.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (c) 2025 Christoph Läubrich and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.pde.internal.ui.editor.targetdefinition; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.Set; +import java.util.stream.Stream; + +import org.eclipse.equinox.frameworkadmin.BundleInfo; +import org.eclipse.pde.bnd.ui.model.resolution.RequirementWrapper; +import org.eclipse.pde.bnd.ui.tasks.CapReqLoader; +import org.eclipse.pde.bnd.ui.tasks.ResourceCapReqLoader; +import org.eclipse.pde.core.target.ITargetDefinition; +import org.eclipse.pde.core.target.TargetBundle; +import org.osgi.resource.Capability; + +import aQute.bnd.osgi.Processor; +import aQute.bnd.osgi.resource.ResourceBuilder; + +class TargetCapReqLoader implements CapReqLoader { + + private ITargetDefinition target; + + public TargetCapReqLoader(ITargetDefinition target) { + this.target = target; + } + + @Override + public void close() throws IOException { + // nothing to do + } + + @Override + public String getShortLabel() { + return target.getName(); + } + + @Override + public String getLongLabel() { + return getShortLabel(); + } + + @Override + public Map> loadCapabilities() throws Exception { + if (!target.isResolved()) { + target.resolve(null); + } + TargetBundle[] bundles = target.getBundles(); + if (bundles != null) { + Map> result = new LinkedHashMap<>(); + for (TargetBundle targetBundle : bundles) { + CapReqLoader loader = toLoader(targetBundle); + if (loader != null) { + Map> toMerge = loader.loadCapabilities(); + Set>> set = toMerge.entrySet(); + for (Entry> entry : set) { + result.merge(entry.getKey(), entry.getValue(), + (a, b) -> Stream.concat(a.stream(), b.stream()).toList()); + } + } + } + return result; + } + return Map.of(); + } + + private CapReqLoader toLoader(TargetBundle targetBundle) throws IOException { + BundleInfo info = targetBundle.getBundleInfo(); + String manifest = info.getManifest(); + if (manifest != null && !manifest.isBlank()) { + ResourceBuilder builder = new ResourceBuilder(); + Properties properties = new Properties(); + try (ByteArrayInputStream stream = new ByteArrayInputStream(manifest.getBytes(StandardCharsets.UTF_8))) { + properties.load(stream); + } + builder.addManifest(new Processor(properties)); + return new ResourceCapReqLoader(builder.build()); + } + // TODO use adapter pattern instead + return null; + } + + @Override + public Map> loadRequirements() throws Exception { + if (!target.isResolved()) { + target.resolve(null); + } + TargetBundle[] bundles = target.getBundles(); + if (bundles != null) { + Map> result = new LinkedHashMap<>(); + for (TargetBundle targetBundle : bundles) { + CapReqLoader loader = toLoader(targetBundle); + if (loader != null) { + Map> toMerge = loader.loadRequirements(); + Set>> set = toMerge.entrySet(); + for (Entry> entry : set) { + result.merge(entry.getKey(), entry.getValue(), + (a, b) -> Stream.concat(a.stream(), b.stream()).toList()); + } + } + } + return result; + } + return Map.of(); + } + +} diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetEditor.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetEditor.java index 36127312f3b..c4622181b6b 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetEditor.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetEditor.java @@ -55,6 +55,7 @@ import org.eclipse.jface.text.source.ISourceViewerExtension5; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.osgi.util.NLS; +import org.eclipse.pde.bnd.ui.tasks.CapReqLoader; import org.eclipse.pde.core.target.ITargetDefinition; import org.eclipse.pde.core.target.ITargetHandle; import org.eclipse.pde.core.target.ITargetPlatformService; @@ -300,6 +301,9 @@ public T getAdapter(Class adapter) { return adapter.cast(target.getHandle()); } } + if (adapter == CapReqLoader.class) { + return adapter.cast(new TargetCapReqLoader(getTarget())); + } return super.getAdapter(adapter); } /** From db7c20488f24f9636726996cc8f9c4c1bfea254d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Thu, 21 Aug 2025 16:26:50 +0200 Subject: [PATCH 2/4] Restructure model classes for Resolution view --- .../META-INF/MANIFEST.MF | 3 +-- .../resolution}/BndBuilderCapReqLoader.java | 4 +-- .../resolution}/BndFileCapReqLoader.java | 2 +- .../resolution}/CapReqLoader.java | 4 +-- .../resolution}/JarFileCapReqLoader.java | 2 +- .../resolution}/ManifestCapReqLoader.java | 4 +-- .../resolution}/ResourceCapReqLoader.java | 4 +-- .../AnalyseBundleResolutionJob.java | 13 +++------ .../resolution/CapReqComparator.java | 23 ++++++---------- .../resolution/CapReqMapContentProvider.java | 2 +- .../resolution/CapabilityLabelProvider.java | 2 +- .../resolution/RequirementWrapper.java | 27 ++++++++----------- .../RequirementWrapperLabelProvider.java | 2 +- .../ui/views/resolution/ResolutionView.java | 24 ++++++++--------- .../editor/targetdefinition/TargetEditor.java | 2 +- 15 files changed, 48 insertions(+), 70 deletions(-) rename ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/{tasks => model/resolution}/BndBuilderCapReqLoader.java (97%) rename ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/{tasks => model/resolution}/BndFileCapReqLoader.java (98%) rename ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/{tasks => model/resolution}/CapReqLoader.java (89%) rename ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/{tasks => model/resolution}/JarFileCapReqLoader.java (96%) rename ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/{tasks => model/resolution}/ManifestCapReqLoader.java (95%) rename ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/{tasks => model/resolution}/ResourceCapReqLoader.java (97%) rename ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/{tasks => views/resolution}/AnalyseBundleResolutionJob.java (92%) rename ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/{model => views}/resolution/CapReqComparator.java (87%) rename ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/{model => views}/resolution/CapReqMapContentProvider.java (99%) rename ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/{model => views}/resolution/CapabilityLabelProvider.java (98%) rename ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/{model => views}/resolution/RequirementWrapper.java (84%) rename ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/{model => views}/resolution/RequirementWrapperLabelProvider.java (98%) diff --git a/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF index 5ec32fabf3b..fe0f58daa2f 100644 --- a/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF +++ b/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF @@ -6,11 +6,10 @@ Bundle-Vendor: Eclipse.org Bundle-Version: 1.2.300.qualifier Bundle-Localization: plugin Export-Package: org.eclipse.pde.bnd.ui.autocomplete;version="1.0.0";x-friends:="org.eclipse.pde.ui", - org.eclipse.pde.bnd.ui.model.resolution, + org.eclipse.pde.bnd.ui.model.resolution;version="1.0.0";x-friends:="org.eclipse.pde.ui", org.eclipse.pde.bnd.ui.plugins;x-internal:=true, org.eclipse.pde.bnd.ui.preferences;version="1.0.0";x-friends:="org.eclipse.pde.ui", org.eclipse.pde.bnd.ui.quickfix;version="1.0.0";x-friends:="org.eclipse.pde.ui", - org.eclipse.pde.bnd.ui.tasks, org.eclipse.pde.bnd.ui.templating;version="1.0.0";x-friends:="org.eclipse.pde.ui", org.eclipse.pde.bnd.ui.wizards;version="1.0.0";x-friends:="org.eclipse.pde.ui" Import-Package: aQute.bnd.build;version="4.5.0", diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/BndBuilderCapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndBuilderCapReqLoader.java similarity index 97% rename from ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/BndBuilderCapReqLoader.java rename to ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndBuilderCapReqLoader.java index bc57fbfc884..fda81d7b88d 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/BndBuilderCapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndBuilderCapReqLoader.java @@ -14,7 +14,7 @@ * Peter Kriens - ongoing enhancements * Christoph Rueger - ongoing enhancements *******************************************************************************/ -package org.eclipse.pde.bnd.ui.tasks; +package org.eclipse.pde.bnd.ui.model.resolution; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.mapping; @@ -29,7 +29,7 @@ import java.util.Map; import java.util.Objects; -import org.eclipse.pde.bnd.ui.model.resolution.RequirementWrapper; +import org.eclipse.pde.bnd.ui.views.resolution.RequirementWrapper; import org.osgi.framework.namespace.PackageNamespace; import org.osgi.resource.Capability; import org.osgi.resource.Requirement; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/BndFileCapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndFileCapReqLoader.java similarity index 98% rename from ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/BndFileCapReqLoader.java rename to ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndFileCapReqLoader.java index 95be244be35..2b200552b1f 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/BndFileCapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndFileCapReqLoader.java @@ -13,7 +13,7 @@ * Sean Bright - ongoing enhancements * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package org.eclipse.pde.bnd.ui.tasks; +package org.eclipse.pde.bnd.ui.model.resolution; import java.io.File; import java.io.IOException; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/CapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqLoader.java similarity index 89% rename from ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/CapReqLoader.java rename to ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqLoader.java index af9b3085ab1..49a8eba2778 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/CapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqLoader.java @@ -12,13 +12,13 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package org.eclipse.pde.bnd.ui.tasks; +package org.eclipse.pde.bnd.ui.model.resolution; import java.io.Closeable; import java.util.List; import java.util.Map; -import org.eclipse.pde.bnd.ui.model.resolution.RequirementWrapper; +import org.eclipse.pde.bnd.ui.views.resolution.RequirementWrapper; import org.osgi.resource.Capability; public interface CapReqLoader extends Closeable { diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/JarFileCapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/JarFileCapReqLoader.java similarity index 96% rename from ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/JarFileCapReqLoader.java rename to ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/JarFileCapReqLoader.java index b3ec9a09b07..834a04c0a55 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/JarFileCapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/JarFileCapReqLoader.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package org.eclipse.pde.bnd.ui.tasks; +package org.eclipse.pde.bnd.ui.model.resolution; import java.io.File; import java.io.IOException; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/ManifestCapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ManifestCapReqLoader.java similarity index 95% rename from ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/ManifestCapReqLoader.java rename to ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ManifestCapReqLoader.java index 76360a1130f..b96f250cb2f 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/ManifestCapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ManifestCapReqLoader.java @@ -11,7 +11,7 @@ * Contributors: * Christoph Läubrich - initial API and implementation *******************************************************************************/ -package org.eclipse.pde.bnd.ui.tasks; +package org.eclipse.pde.bnd.ui.model.resolution; import java.io.File; import java.io.FileInputStream; @@ -20,7 +20,7 @@ import java.util.Map; import java.util.jar.Manifest; -import org.eclipse.pde.bnd.ui.model.resolution.RequirementWrapper; +import org.eclipse.pde.bnd.ui.views.resolution.RequirementWrapper; import org.osgi.resource.Capability; import aQute.bnd.osgi.resource.ResourceBuilder; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/ResourceCapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ResourceCapReqLoader.java similarity index 97% rename from ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/ResourceCapReqLoader.java rename to ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ResourceCapReqLoader.java index 2a362471d35..50158a5b982 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/ResourceCapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ResourceCapReqLoader.java @@ -14,7 +14,7 @@ * Peter Kriens - ongoing enhancements * Christoph Rueger - ongoing enhancements *******************************************************************************/ -package org.eclipse.pde.bnd.ui.tasks; +package org.eclipse.pde.bnd.ui.model.resolution; import java.io.IOException; import java.net.URI; @@ -26,7 +26,7 @@ import java.util.Objects; import org.eclipse.pde.bnd.ui.ResourceUtils; -import org.eclipse.pde.bnd.ui.model.resolution.RequirementWrapper; +import org.eclipse.pde.bnd.ui.views.resolution.RequirementWrapper; import org.osgi.resource.Capability; import org.osgi.resource.Requirement; import org.osgi.resource.Resource; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/AnalyseBundleResolutionJob.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/AnalyseBundleResolutionJob.java similarity index 92% rename from ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/AnalyseBundleResolutionJob.java rename to ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/AnalyseBundleResolutionJob.java index a35ab4a000e..cb1310c3053 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/tasks/AnalyseBundleResolutionJob.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/AnalyseBundleResolutionJob.java @@ -16,7 +16,7 @@ * BJ Hargrave - ongoing enhancements * Sean Bright - ongoing enhancements *******************************************************************************/ -package org.eclipse.pde.bnd.ui.tasks; +package org.eclipse.pde.bnd.ui.views.resolution; import static java.util.Collections.emptyList; @@ -34,14 +34,14 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.pde.bnd.ui.model.resolution.RequirementWrapper; +import org.eclipse.pde.bnd.ui.model.resolution.CapReqLoader; import org.osgi.resource.Capability; import org.osgi.resource.Namespace; import aQute.bnd.build.model.EE; import aQute.bnd.osgi.resource.ResourceUtils; -public class AnalyseBundleResolutionJob extends Job { +class AnalyseBundleResolutionJob extends Job { private final Set loaders; @@ -76,8 +76,6 @@ private static void mergeMaps(Map> from, Map> into) @Override protected IStatus run(IProgressMonitor monitor) { try { - - // Load all the capabilities and requirements Map> allCaps = new HashMap<>(); Map> allReqs = new HashMap<>(); @@ -125,13 +123,8 @@ protected IStatus run(IProgressMonitor monitor) { } // Generate the final results - // Set resultFiles = builderMap.keySet(); - // resultFileArray = resultFiles.toArray(new File[0]); - this.requirements = allReqs; this.capabilities = allCaps; - - // showResults(resultFileArray, importResults, exportResults); return Status.OK_STATUS; } catch (RuntimeException e) { throw e; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqComparator.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqComparator.java similarity index 87% rename from ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqComparator.java rename to ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqComparator.java index a779b6503b8..f9328e8ab6a 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqComparator.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqComparator.java @@ -13,11 +13,12 @@ * BJ Hargrave - ongoing enhancements * Peter Kriens - ongoing enhancements *******************************************************************************/ -package org.eclipse.pde.bnd.ui.model.resolution; +package org.eclipse.pde.bnd.ui.views.resolution; import java.util.Collection; import java.util.Comparator; +import org.eclipse.core.runtime.Adapters; import org.eclipse.pde.bnd.ui.model.resource.R5LabelFormatter; import org.osgi.framework.Version; import org.osgi.resource.Capability; @@ -29,14 +30,10 @@ public class CapReqComparator implements Comparator { @Override public int compare(Object o1, Object o2) { - if (o1 instanceof Requirement) { - return compareReqToObj((Requirement) o1, o2); + Requirement requirement = Adapters.adapt(o1, Requirement.class); + if (requirement != null) { + return compareReqToObj(requirement, o2); } - - if (o1 instanceof RequirementWrapper) { - return compareReqToObj(((RequirementWrapper) o1).requirement, o2); - } - if (o1 instanceof Capability) { return compareCapToObj((Capability) o1, o2); } @@ -45,14 +42,10 @@ public int compare(Object o1, Object o2) { } private int compareReqToObj(Requirement r1, Object o2) { - if (o2 instanceof Requirement) { - return compareReqToReq(r1, (Requirement) o2); + Requirement requirement = Adapters.adapt(o2, Requirement.class); + if (requirement != null) { + return compareReqToReq(r1, requirement); } - - if (o2 instanceof RequirementWrapper) { - return compareReqToReq(r1, ((RequirementWrapper) o2).requirement); - } - // requirements sort before other things return -1; } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqMapContentProvider.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqMapContentProvider.java similarity index 99% rename from ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqMapContentProvider.java rename to ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqMapContentProvider.java index b81a40c09f5..ece3e0a4729 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqMapContentProvider.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqMapContentProvider.java @@ -13,7 +13,7 @@ * BJ Hargrave - ongoing enhancements * Christoph Rueger - ongoing enhancements *******************************************************************************/ -package org.eclipse.pde.bnd.ui.model.resolution; +package org.eclipse.pde.bnd.ui.views.resolution; import java.util.ArrayList; import java.util.Arrays; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapabilityLabelProvider.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapabilityLabelProvider.java similarity index 98% rename from ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapabilityLabelProvider.java rename to ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapabilityLabelProvider.java index 7d9daeec5a3..8b72cfc8287 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapabilityLabelProvider.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapabilityLabelProvider.java @@ -15,7 +15,7 @@ * Peter Kriens - ongoing enhancements * Christoph Rueger - ongoing enhancements *******************************************************************************/ -package org.eclipse.pde.bnd.ui.model.resolution; +package org.eclipse.pde.bnd.ui.views.resolution; import java.util.Map.Entry; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/RequirementWrapper.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapper.java similarity index 84% rename from ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/RequirementWrapper.java rename to ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapper.java index 0d599652b46..ba7834161b5 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/RequirementWrapper.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapper.java @@ -14,16 +14,15 @@ * Peter Kriens - ongoing enhancements * Christoph Rueger - ongoing enhancements *******************************************************************************/ -package org.eclipse.pde.bnd.ui.model.resolution; +package org.eclipse.pde.bnd.ui.views.resolution; import java.util.Collection; import java.util.Objects; +import org.eclipse.core.runtime.IAdaptable; import org.osgi.resource.Requirement; -import aQute.bnd.osgi.Constants; - -public class RequirementWrapper { +public class RequirementWrapper implements IAdaptable { public final Requirement requirement; public boolean resolved; @@ -34,18 +33,6 @@ public RequirementWrapper(Requirement requirement) { this.requirement = requirement; } - public boolean isOptional() { - - String resolution = requirement.getDirectives() - .get(Constants.RESOLUTION); - - if (resolution == null) { - return false; - } - - return Constants.OPTIONAL.equals(resolution); - } - @Override public int hashCode() { return Objects.hash(java, requirement, requirers, resolved); @@ -72,4 +59,12 @@ public String toString() { return "RequirementWrapper [resolved=" + resolved + ", java=" + java + ", requirement=" + requirement + "]"; } + @Override + public T getAdapter(Class adapter) { + if (adapter == Requirement.class) { + return adapter.cast(requirement); + } + return null; + } + } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/RequirementWrapperLabelProvider.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapperLabelProvider.java similarity index 98% rename from ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/RequirementWrapperLabelProvider.java rename to ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapperLabelProvider.java index f2499987753..bf77610b4c8 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/RequirementWrapperLabelProvider.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapperLabelProvider.java @@ -15,7 +15,7 @@ * Peter Kriens - ongoing enhancements * Christoph Rueger - ongoing enhancements *******************************************************************************/ -package org.eclipse.pde.bnd.ui.model.resolution; +package org.eclipse.pde.bnd.ui.views.resolution; import java.util.Map.Entry; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java index 338b4229085..61fbfee1ae0 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java @@ -70,17 +70,12 @@ import org.eclipse.pde.bnd.ui.Resources; import org.eclipse.pde.bnd.ui.internal.PartAdapter; import org.eclipse.pde.bnd.ui.model.repo.ResourceProvider; -import org.eclipse.pde.bnd.ui.model.resolution.CapReqMapContentProvider; -import org.eclipse.pde.bnd.ui.model.resolution.CapabilityLabelProvider; -import org.eclipse.pde.bnd.ui.model.resolution.RequirementWrapper; -import org.eclipse.pde.bnd.ui.model.resolution.RequirementWrapperLabelProvider; -import org.eclipse.pde.bnd.ui.tasks.AnalyseBundleResolutionJob; -import org.eclipse.pde.bnd.ui.tasks.BndBuilderCapReqLoader; -import org.eclipse.pde.bnd.ui.tasks.BndFileCapReqLoader; -import org.eclipse.pde.bnd.ui.tasks.CapReqLoader; -import org.eclipse.pde.bnd.ui.tasks.JarFileCapReqLoader; -import org.eclipse.pde.bnd.ui.tasks.ManifestCapReqLoader; -import org.eclipse.pde.bnd.ui.tasks.ResourceCapReqLoader; +import org.eclipse.pde.bnd.ui.model.resolution.BndBuilderCapReqLoader; +import org.eclipse.pde.bnd.ui.model.resolution.BndFileCapReqLoader; +import org.eclipse.pde.bnd.ui.model.resolution.CapReqLoader; +import org.eclipse.pde.bnd.ui.model.resolution.JarFileCapReqLoader; +import org.eclipse.pde.bnd.ui.model.resolution.ManifestCapReqLoader; +import org.eclipse.pde.bnd.ui.model.resolution.ResourceCapReqLoader; import org.eclipse.pde.bnd.ui.views.ViewEventTopics; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; @@ -114,6 +109,7 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.ResourceUtil; import org.eclipse.ui.part.ViewPart; +import org.osgi.framework.Constants; import org.osgi.framework.namespace.HostNamespace; import org.osgi.framework.namespace.IdentityNamespace; import org.osgi.resource.Capability; @@ -351,8 +347,10 @@ public boolean select(Viewer viewer, Object parentElement, Object element) { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { - if (element instanceof RequirementWrapper rw) { - return !rw.isOptional(); + Requirement requirement = Adapters.adapt(element, Requirement.class); + if (requirement != null) { + String resolution = requirement.getDirectives().get(Constants.RESOLUTION_DIRECTIVE); + return Constants.RESOLUTION_OPTIONAL.equals(resolution); } return true; } diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetEditor.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetEditor.java index c4622181b6b..34012bde144 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetEditor.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetEditor.java @@ -55,7 +55,7 @@ import org.eclipse.jface.text.source.ISourceViewerExtension5; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.osgi.util.NLS; -import org.eclipse.pde.bnd.ui.tasks.CapReqLoader; +import org.eclipse.pde.bnd.ui.model.resolution.CapReqLoader; import org.eclipse.pde.core.target.ITargetDefinition; import org.eclipse.pde.core.target.ITargetHandle; import org.eclipse.pde.core.target.ITargetPlatformService; From 99e1a5ad0596bc82228298dc22d471e2ff355993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Thu, 21 Aug 2025 17:17:00 +0200 Subject: [PATCH 3/4] Streamline usage of loaders --- .../resolution/BndBuilderCapReqLoader.java | 36 ++++----- .../pde/bnd/ui/model/resolution/CapReq.java | 25 +++++++ .../bnd/ui/model/resolution/CapReqLoader.java | 10 +-- .../resolution/ManifestCapReqLoader.java | 15 +--- .../resolution/RequirementWithChildren.java | 67 +++++++++++++++++ .../resolution/ResourceCapReqLoader.java | 22 +++--- .../AnalyseBundleResolutionJob.java | 49 ++++++------ .../resolution/CapReqMapContentProvider.java | 21 ++---- .../views/resolution/RequirementWrapper.java | 6 +- .../ui/views/resolution/ResolutionView.java | 9 ++- .../targetdefinition/TargetCapReqLoader.java | 74 ++++++++----------- 11 files changed, 192 insertions(+), 142 deletions(-) create mode 100644 ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReq.java create mode 100644 ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/RequirementWithChildren.java diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndBuilderCapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndBuilderCapReqLoader.java index fda81d7b88d..6794054e71a 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndBuilderCapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndBuilderCapReqLoader.java @@ -17,8 +17,6 @@ package org.eclipse.pde.bnd.ui.model.resolution; import static java.util.stream.Collectors.groupingBy; -import static java.util.stream.Collectors.mapping; -import static java.util.stream.Collectors.toList; import java.io.File; import java.util.ArrayList; @@ -28,8 +26,8 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; -import org.eclipse.pde.bnd.ui.views.resolution.RequirementWrapper; import org.osgi.framework.namespace.PackageNamespace; import org.osgi.resource.Capability; import org.osgi.resource.Requirement; @@ -45,8 +43,8 @@ public abstract class BndBuilderCapReqLoader implements CapReqLoader { protected final File file; - private Map> loadCapabilities; - private Map> loadRequirements; + private Map> loadCapabilities; + private Map> loadRequirements; public BndBuilderCapReqLoader(File file) { this.file = file; @@ -94,37 +92,33 @@ private void load() throws Exception { capabilities.addAll(resource.getCapabilities(null)); requirements.addAll(resource.getRequirements(null)); } - loadRequirements = requirements.stream() - .collect(groupingBy(Requirement::getNamespace, mapping(this::toRequirementWrapper, toList()))); + loadRequirements = requirements.stream().map(r -> toRequirementWrapper(r)) + .collect(groupingBy(Requirement::getNamespace, Collectors.toCollection(ArrayList::new))); loadCapabilities = capabilities.stream() - .collect(groupingBy(Capability::getNamespace, toList())); + .collect(groupingBy(Capability::getNamespace, Collectors.toCollection(ArrayList::new))); } @Override - public Map> loadCapabilities() throws Exception { + public CapReq loadCapReq() throws Exception { load(); - return loadCapabilities; + return new CapReq(loadCapabilities, loadRequirements); } - @Override - public Map> loadRequirements() throws Exception { - load(); - return loadRequirements; - } - - private RequirementWrapper toRequirementWrapper(Requirement req) { - RequirementWrapper rw = new RequirementWrapper(req); + private Requirement toRequirementWrapper(Requirement req) { if (req.getNamespace() .equals(PackageNamespace.PACKAGE_NAMESPACE)) { String pkgName = (String) req.getAttributes() .get(PackageNamespace.PACKAGE_NAMESPACE); try { - rw.requirers = findImportingClasses(pkgName); + List importingClasses = findImportingClasses(pkgName); + if (!importingClasses.isEmpty()) { + return new RequirementWithChildren(req, importingClasses); + } } catch (Exception e) { throw Exceptions.duck(e); } } - return rw; + return req; } private List findImportingClasses(String pkgName) throws Exception { @@ -172,4 +166,6 @@ public boolean equals(Object obj) { return Objects.equals(file, other.file); } + + } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReq.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReq.java new file mode 100644 index 00000000000..2ee1984621f --- /dev/null +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReq.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2025 Christoph Läubrich project and others. + * +* This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation +*******************************************************************************/ +package org.eclipse.pde.bnd.ui.model.resolution; + +import java.util.Collection; +import java.util.Map; + +import org.osgi.resource.Capability; +import org.osgi.resource.Requirement; + +public record CapReq(Map> capabilities, + Map> requirements) { + +} diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqLoader.java index 49a8eba2778..ff1a74f3de0 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqLoader.java @@ -15,20 +15,12 @@ package org.eclipse.pde.bnd.ui.model.resolution; import java.io.Closeable; -import java.util.List; -import java.util.Map; - -import org.eclipse.pde.bnd.ui.views.resolution.RequirementWrapper; -import org.osgi.resource.Capability; public interface CapReqLoader extends Closeable { String getShortLabel(); String getLongLabel(); - - Map> loadCapabilities() throws Exception; - - Map> loadRequirements() throws Exception; + CapReq loadCapReq() throws Exception; } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ManifestCapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ManifestCapReqLoader.java index b96f250cb2f..346548fd2b5 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ManifestCapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ManifestCapReqLoader.java @@ -16,13 +16,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.util.List; -import java.util.Map; import java.util.jar.Manifest; -import org.eclipse.pde.bnd.ui.views.resolution.RequirementWrapper; -import org.osgi.resource.Capability; - import aQute.bnd.osgi.resource.ResourceBuilder; /** @@ -56,14 +51,8 @@ public String getLongLabel() { } @Override - public Map> loadCapabilities() throws Exception { - loadManifest(); - return loadManifest().loadCapabilities(); - } - - @Override - public Map> loadRequirements() throws Exception { - return loadManifest().loadRequirements(); + public CapReq loadCapReq() throws Exception { + return loadManifest().loadCapReq(); } private synchronized ResourceCapReqLoader loadManifest() throws IOException { diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/RequirementWithChildren.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/RequirementWithChildren.java new file mode 100644 index 00000000000..f7cc70768ec --- /dev/null +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/RequirementWithChildren.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2025 Christoph Läubrich project and others. + * +* This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation +*******************************************************************************/ +package org.eclipse.pde.bnd.ui.model.resolution; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.osgi.resource.Requirement; +import org.osgi.resource.Resource; + +public final class RequirementWithChildren implements Requirement { + + private Requirement req; + private Collection children; + + public RequirementWithChildren(Requirement req, Collection children) { + this.req = req; + this.children = children == null ? List.of() : List.copyOf(children); + } + + @Override + public String getNamespace() { + return req.getNamespace(); + } + + @Override + public Map getDirectives() { + return req.getDirectives(); + } + + @Override + public Map getAttributes() { + return req.getAttributes(); + } + + @Override + public Resource getResource() { + return req.getResource(); + } + + @Override + public boolean equals(Object obj) { + return req.equals(obj); + } + + @Override + public int hashCode() { + return req.hashCode(); + } + + public Collection getChildren() { + return children; + } + +} \ No newline at end of file diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ResourceCapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ResourceCapReqLoader.java index 50158a5b982..39598e91297 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ResourceCapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ResourceCapReqLoader.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.net.URI; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -26,7 +27,6 @@ import java.util.Objects; import org.eclipse.pde.bnd.ui.ResourceUtils; -import org.eclipse.pde.bnd.ui.views.resolution.RequirementWrapper; import org.osgi.resource.Capability; import org.osgi.resource.Requirement; import org.osgi.resource.Resource; @@ -62,8 +62,12 @@ public String getLongLabel() { } @Override - public Map> loadCapabilities() throws Exception { - Map> result = new HashMap<>(); + public CapReq loadCapReq() throws Exception { + return new CapReq(loadCapabilities(), loadRequirements()); + } + + private Map> loadCapabilities() throws Exception { + Map> result = new HashMap<>(); List caps = new ArrayList<>(resource.getCapabilities(null)); if (resource instanceof SupportingResource sr) { @@ -73,7 +77,7 @@ public Map> loadCapabilities() throws Exception { } for (Capability cap : caps) { String ns = cap.getNamespace(); - List listForNamespace = result.get(ns); + Collection listForNamespace = result.get(ns); if (listForNamespace == null) { listForNamespace = new LinkedList<>(); result.put(ns, listForNamespace); @@ -84,9 +88,8 @@ public Map> loadCapabilities() throws Exception { return result; } - @Override - public Map> loadRequirements() throws Exception { - Map> result = new HashMap<>(); + private Map> loadRequirements() throws Exception { + Map> result = new HashMap<>(); List reqs = new ArrayList<>(resource.getRequirements(null)); if (resource instanceof SupportingResource sr) { @@ -96,13 +99,12 @@ public Map> loadRequirements() throws Exception } for (Requirement req : reqs) { String ns = req.getNamespace(); - List listForNamespace = result.get(ns); + Collection listForNamespace = result.get(ns); if (listForNamespace == null) { listForNamespace = new LinkedList<>(); result.put(ns, listForNamespace); } - RequirementWrapper wrapper = new RequirementWrapper(req); - listForNamespace.add(wrapper); + listForNamespace.add(req); } return result; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/AnalyseBundleResolutionJob.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/AnalyseBundleResolutionJob.java index cb1310c3053..edf6b446f6c 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/AnalyseBundleResolutionJob.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/AnalyseBundleResolutionJob.java @@ -20,20 +20,23 @@ import static java.util.Collections.emptyList; -import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.function.Function; import java.util.function.Predicate; +import java.util.stream.Stream; import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.pde.bnd.ui.model.resolution.CapReq; import org.eclipse.pde.bnd.ui.model.resolution.CapReqLoader; import org.osgi.resource.Capability; import org.osgi.resource.Namespace; @@ -45,8 +48,8 @@ class AnalyseBundleResolutionJob extends Job { private final Set loaders; - private Map> requirements; - private Map> capabilities; + private Map> requirements; + private Map> capabilities; private final EE ee; public AnalyseBundleResolutionJob(String name, Set loaders) { @@ -59,17 +62,19 @@ public AnalyseBundleResolutionJob(String name, Set loade this.ee = ee; } - private static void mergeMaps(Map> from, Map> into) { - for (Entry> entry : from.entrySet()) { + private static void mergeMaps(Map> from, Map> into) { + for (Entry> entry : from.entrySet()) { K key = entry.getKey(); + into.merge(key, entry.getValue(), (a, b) -> Stream.concat(a.stream(), b.stream()).distinct().toList()); + } + } - List list = into.get(key); - if (list == null) { - list = new ArrayList<>(); - into.put(key, list); - } - - list.addAll(entry.getValue()); + private static void mergeMapsWithMapping(Map> from, Map> into, + Function mapper) { + for (Entry> entry : from.entrySet()) { + K key = entry.getKey(); + into.merge(key, entry.getValue().stream().map(mapper).toList(), + (a, b) -> Stream.concat(a.stream(), b.stream()).distinct().toList()); } } @@ -77,15 +82,13 @@ private static void mergeMaps(Map> from, Map> into) protected IStatus run(IProgressMonitor monitor) { try { // Load all the capabilities and requirements - Map> allCaps = new HashMap<>(); - Map> allReqs = new HashMap<>(); + Map> allCaps = new HashMap<>(); + Map> allReqs = new HashMap<>(); for (CapReqLoader loader : loaders) { try (loader){ - Map> caps = loader.loadCapabilities(); - mergeMaps(caps, allCaps); - - Map> reqs = loader.loadRequirements(); - mergeMaps(reqs, allReqs); + CapReq loaded = loader.loadCapReq(); + mergeMaps(loaded.capabilities(), allCaps); + mergeMapsWithMapping(loaded.requirements(), allReqs, req -> new RequirementWrapper(req)); } catch (Exception e) { ILog.get().error("Error in Bnd resolution analysis.", e); } @@ -93,8 +96,8 @@ protected IStatus run(IProgressMonitor monitor) { // Check for resolved requirements for (String namespace : allReqs.keySet()) { - List rws = allReqs.getOrDefault(namespace, emptyList()); - List candidates = allCaps.getOrDefault(namespace, emptyList()); + Collection rws = allReqs.getOrDefault(namespace, emptyList()); + Collection candidates = allCaps.getOrDefault(namespace, emptyList()); List javaCandidates = ee == null ? emptyList() : ee.getResource() @@ -133,11 +136,11 @@ protected IStatus run(IProgressMonitor monitor) { } } - public Map> getRequirements() { + public Map> getRequirements() { return Collections.unmodifiableMap(requirements); } - public Map> getCapabilities() { + public Map> getCapabilities() { return Collections.unmodifiableMap(capabilities); } } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqMapContentProvider.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqMapContentProvider.java index ece3e0a4729..c0bee00c3c6 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqMapContentProvider.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqMapContentProvider.java @@ -17,7 +17,6 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Comparator; import java.util.LinkedList; import java.util.List; @@ -27,6 +26,7 @@ import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; +import org.eclipse.pde.bnd.ui.model.resolution.RequirementWithChildren; import org.osgi.framework.namespace.BundleNamespace; import org.osgi.framework.namespace.HostNamespace; import org.osgi.framework.namespace.IdentityNamespace; @@ -111,25 +111,18 @@ public Object getParent(Object object) { @Override public boolean hasChildren(Object object) { - boolean children = false; - - if (object instanceof RequirementWrapper rw) { - children = rw.requirers != null && !rw.requirers.isEmpty(); + if (object instanceof RequirementWithChildren rw) { + return !rw.getChildren().isEmpty(); } - - return children; + return false; } @Override public Object[] getChildren(Object parent) { - Object[] result = EMPTY; - if (parent instanceof RequirementWrapper) { - Collection requirers = ((RequirementWrapper) parent).requirers; - if (requirers != null) { - result = requirers.toArray(); - } + if (parent instanceof RequirementWithChildren rw) { + return rw.getChildren().toArray(); } - return result; + return EMPTY; } public void setFilter(String filterString) { diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapper.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapper.java index ba7834161b5..f9c66710e0f 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapper.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapper.java @@ -16,7 +16,6 @@ *******************************************************************************/ package org.eclipse.pde.bnd.ui.views.resolution; -import java.util.Collection; import java.util.Objects; import org.eclipse.core.runtime.IAdaptable; @@ -27,7 +26,6 @@ public class RequirementWrapper implements IAdaptable { public final Requirement requirement; public boolean resolved; public boolean java; - public Collection requirers; public RequirementWrapper(Requirement requirement) { this.requirement = requirement; @@ -35,7 +33,7 @@ public RequirementWrapper(Requirement requirement) { @Override public int hashCode() { - return Objects.hash(java, requirement, requirers, resolved); + return Objects.hash(java, requirement, resolved); } @Override @@ -51,7 +49,7 @@ public boolean equals(Object obj) { } RequirementWrapper other = (RequirementWrapper) obj; return java == other.java && Objects.equals(requirement, other.requirement) - && Objects.equals(requirers, other.requirers) && resolved == other.resolved; + && resolved == other.resolved; } @Override diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java index 61fbfee1ae0..0de396fdea9 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java @@ -19,6 +19,7 @@ import java.io.File; import java.text.MessageFormat; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; @@ -350,7 +351,7 @@ public boolean select(Viewer viewer, Object parentElement, Object element) { Requirement requirement = Adapters.adapt(element, Requirement.class); if (requirement != null) { String resolution = requirement.getDirectives().get(Constants.RESOLUTION_DIRECTIVE); - return Constants.RESOLUTION_OPTIONAL.equals(resolution); + return !Constants.RESOLUTION_OPTIONAL.equals(resolution); } return true; } @@ -508,8 +509,8 @@ public void dispose() { super.dispose(); } - private void setInput(Set sourceLoaders, Map> capabilities, - Map> requirements) { + private void setInput(Set sourceLoaders, Map> capabilities, + Map> requirements) { setLoaders(sourceLoaders); sourceLoaders = loaders; if (reqsTree != null && !reqsTree.isDisposed() && capsTable != null && !capsTable.isDisposed()) { @@ -534,7 +535,7 @@ private void setInput(Set sourceLoaders, Map caps = capabilities.values().stream().flatMap(List::stream).toList(); + List caps = capabilities.values().stream().flatMap(Collection::stream).toList(); duplicateCapabilitiesWithDifferentHashes = new HashSet( ResourceUtils.detectDuplicateCapabilitiesWithDifferentHashes("osgi.wiring.package", caps)); diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetCapReqLoader.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetCapReqLoader.java index d4ad9a30718..325ba7670af 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetCapReqLoader.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetCapReqLoader.java @@ -16,21 +16,21 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.Collection; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; -import java.util.Set; import java.util.stream.Stream; import org.eclipse.equinox.frameworkadmin.BundleInfo; -import org.eclipse.pde.bnd.ui.model.resolution.RequirementWrapper; -import org.eclipse.pde.bnd.ui.tasks.CapReqLoader; -import org.eclipse.pde.bnd.ui.tasks.ResourceCapReqLoader; +import org.eclipse.pde.bnd.ui.model.resolution.CapReq; +import org.eclipse.pde.bnd.ui.model.resolution.CapReqLoader; +import org.eclipse.pde.bnd.ui.model.resolution.ResourceCapReqLoader; import org.eclipse.pde.core.target.ITargetDefinition; import org.eclipse.pde.core.target.TargetBundle; import org.osgi.resource.Capability; +import org.osgi.resource.Requirement; import aQute.bnd.osgi.Processor; import aQute.bnd.osgi.resource.ResourceBuilder; @@ -59,33 +59,35 @@ public String getLongLabel() { } @Override - public Map> loadCapabilities() throws Exception { - if (!target.isResolved()) { - target.resolve(null); - } + public CapReq loadCapReq() throws Exception { TargetBundle[] bundles = target.getBundles(); - if (bundles != null) { - Map> result = new LinkedHashMap<>(); - for (TargetBundle targetBundle : bundles) { - CapReqLoader loader = toLoader(targetBundle); - if (loader != null) { - Map> toMerge = loader.loadCapabilities(); - Set>> set = toMerge.entrySet(); - for (Entry> entry : set) { - result.merge(entry.getKey(), entry.getValue(), - (a, b) -> Stream.concat(a.stream(), b.stream()).toList()); - } - } + if (bundles == null || bundles.length == 0) { + // TODO need a way to trigger a reload when target changes! + return new CapReq(Map.of(), Map.of()); + } + Map> capabilityResults = new LinkedHashMap<>(); + Map> requirementResults = new LinkedHashMap<>(); + for (TargetBundle targetBundle : bundles) { + if (targetBundle.isSourceBundle()) { + continue; + } + CapReqLoader loader = toLoader(targetBundle); + if (loader != null) { + CapReq result = loader.loadCapReq(); + mergeMaps(result.capabilities(), capabilityResults); + mergeMaps(result.requirements(), requirementResults); } - return result; } - return Map.of(); + return new CapReq(capabilityResults, requirementResults); } private CapReqLoader toLoader(TargetBundle targetBundle) throws IOException { BundleInfo info = targetBundle.getBundleInfo(); + // TODO check if we can get a jar as BND offers additional infos when + // loading from a jar! String manifest = info.getManifest(); if (manifest != null && !manifest.isBlank()) { + // TODO use equinox manifest reader ResourceBuilder builder = new ResourceBuilder(); Properties properties = new Properties(); try (ByteArrayInputStream stream = new ByteArrayInputStream(manifest.getBytes(StandardCharsets.UTF_8))) { @@ -94,32 +96,14 @@ private CapReqLoader toLoader(TargetBundle targetBundle) throws IOException { builder.addManifest(new Processor(properties)); return new ResourceCapReqLoader(builder.build()); } - // TODO use adapter pattern instead return null; } - @Override - public Map> loadRequirements() throws Exception { - if (!target.isResolved()) { - target.resolve(null); - } - TargetBundle[] bundles = target.getBundles(); - if (bundles != null) { - Map> result = new LinkedHashMap<>(); - for (TargetBundle targetBundle : bundles) { - CapReqLoader loader = toLoader(targetBundle); - if (loader != null) { - Map> toMerge = loader.loadRequirements(); - Set>> set = toMerge.entrySet(); - for (Entry> entry : set) { - result.merge(entry.getKey(), entry.getValue(), - (a, b) -> Stream.concat(a.stream(), b.stream()).toList()); - } - } - } - return result; + private static void mergeMaps(Map> from, Map> into) { + for (Entry> entry : from.entrySet()) { + K key = entry.getKey(); + into.merge(key, entry.getValue(), (a, b) -> Stream.concat(a.stream(), b.stream()).distinct().toList()); } - return Map.of(); } } From 70f946a87364954515847599e2182462e45ac49e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Thu, 21 Aug 2025 17:50:22 +0200 Subject: [PATCH 4/4] Show loading progress and use jars if possible for enhanced display --- .../resolution/BndBuilderCapReqLoader.java | 3 +- .../bnd/ui/model/resolution/CapReqLoader.java | 4 +- .../resolution/ManifestCapReqLoader.java | 6 +- .../resolution/ResourceCapReqLoader.java | 3 +- .../AnalyseBundleResolutionJob.java | 48 ++++++++++++-- .../resolution/CapReqMapContentProvider.java | 7 +- .../views/resolution/RequirementWrapper.java | 4 ++ .../ui/views/resolution/ResolutionView.java | 14 ++-- .../targetdefinition/TargetCapReqLoader.java | 64 +++++++++++++++---- .../editor/targetdefinition/TargetEditor.java | 2 +- 10 files changed, 120 insertions(+), 35 deletions(-) diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndBuilderCapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndBuilderCapReqLoader.java index 6794054e71a..56a565c9758 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndBuilderCapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/BndBuilderCapReqLoader.java @@ -28,6 +28,7 @@ import java.util.Objects; import java.util.stream.Collectors; +import org.eclipse.core.runtime.IProgressMonitor; import org.osgi.framework.namespace.PackageNamespace; import org.osgi.resource.Capability; import org.osgi.resource.Requirement; @@ -99,7 +100,7 @@ private void load() throws Exception { } @Override - public CapReq loadCapReq() throws Exception { + public CapReq loadCapReq(IProgressMonitor monitor) throws Exception { load(); return new CapReq(loadCapabilities, loadRequirements); } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqLoader.java index ff1a74f3de0..d0d36348d5c 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/CapReqLoader.java @@ -16,11 +16,13 @@ import java.io.Closeable; +import org.eclipse.core.runtime.IProgressMonitor; + public interface CapReqLoader extends Closeable { String getShortLabel(); String getLongLabel(); - CapReq loadCapReq() throws Exception; + CapReq loadCapReq(IProgressMonitor monitor) throws Exception; } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ManifestCapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ManifestCapReqLoader.java index 346548fd2b5..b807212bcc1 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ManifestCapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ManifestCapReqLoader.java @@ -18,6 +18,8 @@ import java.io.IOException; import java.util.jar.Manifest; +import org.eclipse.core.runtime.IProgressMonitor; + import aQute.bnd.osgi.resource.ResourceBuilder; /** @@ -51,8 +53,8 @@ public String getLongLabel() { } @Override - public CapReq loadCapReq() throws Exception { - return loadManifest().loadCapReq(); + public CapReq loadCapReq(IProgressMonitor monitor) throws Exception { + return loadManifest().loadCapReq(null); } private synchronized ResourceCapReqLoader loadManifest() throws IOException { diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ResourceCapReqLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ResourceCapReqLoader.java index 39598e91297..7386df4df6c 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ResourceCapReqLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/resolution/ResourceCapReqLoader.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Objects; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.pde.bnd.ui.ResourceUtils; import org.osgi.resource.Capability; import org.osgi.resource.Requirement; @@ -62,7 +63,7 @@ public String getLongLabel() { } @Override - public CapReq loadCapReq() throws Exception { + public CapReq loadCapReq(IProgressMonitor monitor) throws Exception { return new CapReq(loadCapabilities(), loadRequirements()); } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/AnalyseBundleResolutionJob.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/AnalyseBundleResolutionJob.java index edf6b446f6c..8cc1b894ee3 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/AnalyseBundleResolutionJob.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/AnalyseBundleResolutionJob.java @@ -27,6 +27,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; @@ -34,7 +35,9 @@ import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.ProgressMonitorWrapper; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.pde.bnd.ui.model.resolution.CapReq; import org.eclipse.pde.bnd.ui.model.resolution.CapReqLoader; @@ -46,20 +49,25 @@ class AnalyseBundleResolutionJob extends Job { - private final Set loaders; + private final Set loaders; private Map> requirements; private Map> capabilities; private final EE ee; - public AnalyseBundleResolutionJob(String name, Set loaders) { - this(name, loaders, null); + private Consumer messageConsumer; + + public AnalyseBundleResolutionJob(String name, Set loaders, + Consumer messageConsumer) { + this(name, loaders, null, messageConsumer); } - public AnalyseBundleResolutionJob(String name, Set loaders, EE ee) { + public AnalyseBundleResolutionJob(String name, Set loaders, EE ee, + Consumer messageConsumer) { super(name); this.loaders = loaders; this.ee = ee; + this.messageConsumer = messageConsumer; } private static void mergeMaps(Map> from, Map> into) { @@ -80,20 +88,48 @@ private static void mergeMapsWithMapping(Map> from, M @Override protected IStatus run(IProgressMonitor monitor) { + messageConsumer.accept("Working..."); try { // Load all the capabilities and requirements Map> allCaps = new HashMap<>(); Map> allReqs = new HashMap<>(); + SubMonitor convert = SubMonitor.convert(monitor, loaders.size()); for (CapReqLoader loader : loaders) { try (loader){ - CapReq loaded = loader.loadCapReq(); + String baseLabel = "Loading " + loader.getShortLabel() ; + messageConsumer.accept(baseLabel + "..."); + CapReq loaded = loader.loadCapReq(new ProgressMonitorWrapper(convert.split(1)) { + String task; + @Override + public void beginTask(String name, int totalWork) { + task = baseLabel + " - " + name; + messageConsumer.accept(task); + super.beginTask(name, totalWork); + } + + @Override + public void setTaskName(String name) { + task = baseLabel + " - " + name; + super.setTaskName(name); + } + + @Override + public void subTask(String name) { + if (task == null || task.isBlank()) { + messageConsumer.accept(baseLabel + " - " + name); + } else { + messageConsumer.accept(task + " (" + name + ")"); + } + super.subTask(name); + } + }); mergeMaps(loaded.capabilities(), allCaps); mergeMapsWithMapping(loaded.requirements(), allReqs, req -> new RequirementWrapper(req)); } catch (Exception e) { ILog.get().error("Error in Bnd resolution analysis.", e); } } - + messageConsumer.accept("Calculating..."); // Check for resolved requirements for (String namespace : allReqs.keySet()) { Collection rws = allReqs.getOrDefault(namespace, emptyList()); diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqMapContentProvider.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqMapContentProvider.java index c0bee00c3c6..daae80c0959 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqMapContentProvider.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/CapReqMapContentProvider.java @@ -24,6 +24,7 @@ import java.util.Map.Entry; import java.util.Set; +import org.eclipse.core.runtime.Adapters; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.pde.bnd.ui.model.resolution.RequirementWithChildren; @@ -111,7 +112,8 @@ public Object getParent(Object object) { @Override public boolean hasChildren(Object object) { - if (object instanceof RequirementWithChildren rw) { + RequirementWithChildren rw = Adapters.adapt(object, RequirementWithChildren.class); + if (rw != null) { return !rw.getChildren().isEmpty(); } return false; @@ -119,7 +121,8 @@ public boolean hasChildren(Object object) { @Override public Object[] getChildren(Object parent) { - if (parent instanceof RequirementWithChildren rw) { + RequirementWithChildren rw = Adapters.adapt(parent, RequirementWithChildren.class); + if (rw != null) { return rw.getChildren().toArray(); } return EMPTY; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapper.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapper.java index f9c66710e0f..082018bb79a 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapper.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/RequirementWrapper.java @@ -19,6 +19,7 @@ import java.util.Objects; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.pde.bnd.ui.model.resolution.RequirementWithChildren; import org.osgi.resource.Requirement; public class RequirementWrapper implements IAdaptable { @@ -62,6 +63,9 @@ public T getAdapter(Class adapter) { if (adapter == Requirement.class) { return adapter.cast(requirement); } + if (adapter == RequirementWithChildren.class && requirement instanceof RequirementWithChildren) { + return adapter.cast(requirement); + } return null; } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java index 0de396fdea9..34ad1f6c22b 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/resolution/ResolutionView.java @@ -649,20 +649,16 @@ void executeAnalysis() { if (!loaders.isEmpty()) { final AnalyseBundleResolutionJob job = new AnalyseBundleResolutionJob("importExportAnalysis", loaders, - ees.get(currentEE)); + ees.get(currentEE), msg -> { + if (display != null && !display.isDisposed()) { + display.execute(() -> setContentDescription(msg)); + } + }); job.setSystem(true); job.addJobChangeListener(new JobChangeAdapter() { @Override public void aboutToRun(IJobChangeEvent event) { - if (display != null && !display.isDisposed()) { - Runnable update = () -> setContentDescription("Working..."); - if (display.getThread() == Thread.currentThread()) { - update.run(); - } else { - display.asyncExec(update); - } - } } @Override diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetCapReqLoader.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetCapReqLoader.java index 325ba7670af..ffcf2266294 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetCapReqLoader.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/targetdefinition/TargetCapReqLoader.java @@ -14,21 +14,29 @@ package org.eclipse.pde.internal.ui.editor.targetdefinition; import java.io.ByteArrayInputStream; +import java.io.File; import java.io.IOException; +import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; -import java.util.Properties; +import java.util.Objects; import java.util.stream.Stream; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.equinox.frameworkadmin.BundleInfo; +import org.eclipse.osgi.util.ManifestElement; import org.eclipse.pde.bnd.ui.model.resolution.CapReq; import org.eclipse.pde.bnd.ui.model.resolution.CapReqLoader; +import org.eclipse.pde.bnd.ui.model.resolution.JarFileCapReqLoader; import org.eclipse.pde.bnd.ui.model.resolution.ResourceCapReqLoader; import org.eclipse.pde.core.target.ITargetDefinition; import org.eclipse.pde.core.target.TargetBundle; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IPathEditorInput; +import org.osgi.framework.BundleException; import org.osgi.resource.Capability; import org.osgi.resource.Requirement; @@ -38,9 +46,11 @@ class TargetCapReqLoader implements CapReqLoader { private ITargetDefinition target; + private IEditorInput editorInput; - public TargetCapReqLoader(ITargetDefinition target) { + public TargetCapReqLoader(ITargetDefinition target, IEditorInput editorInput) { this.target = target; + this.editorInput = editorInput; } @Override @@ -50,16 +60,19 @@ public void close() throws IOException { @Override public String getShortLabel() { - return target.getName(); + return String.format("Target Platform '%s'", target.getName()); //$NON-NLS-1$ } @Override public String getLongLabel() { + if (editorInput instanceof IPathEditorInput path) { + return String.format("%s (%s)", getShortLabel(), path.getPath()); //$NON-NLS-1$ + } return getShortLabel(); } @Override - public CapReq loadCapReq() throws Exception { + public CapReq loadCapReq(IProgressMonitor monitor) throws Exception { TargetBundle[] bundles = target.getBundles(); if (bundles == null || bundles.length == 0) { // TODO need a way to trigger a reload when target changes! @@ -67,13 +80,16 @@ public CapReq loadCapReq() throws Exception { } Map> capabilityResults = new LinkedHashMap<>(); Map> requirementResults = new LinkedHashMap<>(); - for (TargetBundle targetBundle : bundles) { + monitor.beginTask("read bundles", bundles.length); //$NON-NLS-1$ + for (int i = 0; i < bundles.length; i++) { + TargetBundle targetBundle = bundles[i]; if (targetBundle.isSourceBundle()) { continue; } + monitor.subTask((i + 1) + " / " + bundles.length); //$NON-NLS-1$ CapReqLoader loader = toLoader(targetBundle); if (loader != null) { - CapReq result = loader.loadCapReq(); + CapReq result = loader.loadCapReq(null); mergeMaps(result.capabilities(), capabilityResults); mergeMaps(result.requirements(), requirementResults); } @@ -81,19 +97,26 @@ public CapReq loadCapReq() throws Exception { return new CapReq(capabilityResults, requirementResults); } - private CapReqLoader toLoader(TargetBundle targetBundle) throws IOException { + private CapReqLoader toLoader(TargetBundle targetBundle) throws IOException, BundleException { BundleInfo info = targetBundle.getBundleInfo(); - // TODO check if we can get a jar as BND offers additional infos when - // loading from a jar! + URI location = info.getLocation(); + if (location != null && "file".equals(location.getScheme())) { //$NON-NLS-1$ + File jarFile = new File(location); + if (jarFile.isFile()) { + return new JarFileCapReqLoader(jarFile); + } + } String manifest = info.getManifest(); if (manifest != null && !manifest.isBlank()) { // TODO use equinox manifest reader ResourceBuilder builder = new ResourceBuilder(); - Properties properties = new Properties(); + Map bundleManifest; try (ByteArrayInputStream stream = new ByteArrayInputStream(manifest.getBytes(StandardCharsets.UTF_8))) { - properties.load(stream); + bundleManifest = ManifestElement.parseBundleManifest(stream); } - builder.addManifest(new Processor(properties)); + Processor processor = new Processor(); + processor.addProperties(bundleManifest); + builder.addManifest(processor); return new ResourceCapReqLoader(builder.build()); } return null; @@ -106,4 +129,21 @@ private static void mergeMaps(Map> from, Map T getAdapter(Class adapter) { } } if (adapter == CapReqLoader.class) { - return adapter.cast(new TargetCapReqLoader(getTarget())); + return adapter.cast(new TargetCapReqLoader(getTarget(), getEditorInput())); } return super.getAdapter(adapter); }