diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/framework/plugintool/PluginToolUtils.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/framework/plugintool/PluginToolUtils.java index 0a7411e00a..752d7ee5a1 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/framework/plugintool/PluginToolUtils.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/framework/plugintool/PluginToolUtils.java @@ -15,6 +15,8 @@ */ package ghidra.framework.plugintool; +import java.util.List; +import java.util.Objects; import java.util.function.Function; import docking.DockingWindowManager; @@ -63,11 +65,12 @@ public enum PluginToolUtils { * that case, it'll pick any compatible tool, no matter how recently it had focus. * * @param tool the front-end tool - * @param domainFile the domain file to open + * @param domainFile the domain file to open (may not be null) * @return the (possibly new) plugin tool which accepted the domain file */ public static PluginTool openInMostRecentOrLaunchedCompatibleTool(PluginTool tool, DomainFile domainFile) { + Objects.requireNonNull(domainFile); DomainFile[] data = new DomainFile[] { domainFile }; PluginTool result = inRunningToolsPreferringActive(tool, pt -> { return pt.acceptDomainFiles(data) ? pt : null; @@ -75,7 +78,7 @@ public enum PluginToolUtils { if (result != null) { return result; } - return tool.getToolServices().launchDefaultTool(domainFile); + return tool.getToolServices().launchDefaultTool(List.of(domainFile)); } /** diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/LanguageProviderPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/LanguageProviderPlugin.java index 5fd47fabea..7bac625749 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/LanguageProviderPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/processors/LanguageProviderPlugin.java @@ -17,6 +17,7 @@ package ghidra.app.plugin.core.processors; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.List; import javax.swing.SwingUtilities; @@ -316,7 +317,7 @@ public final class LanguageProviderPlugin extends Plugin implements ApplicationL try { SwingUtilities.invokeAndWait(() -> { ToolServices toolServices = tool.getToolServices(); - if (toolServices.launchDefaultTool(domainFile) == null) { + if (toolServices.launchDefaultTool(List.of(domainFile)) == null) { Msg.showError(this, tool.getToolFrame(), "Failed to Open Program", "A suitable default tool could not found!"); } diff --git a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffSaveSettingsTest.java b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffSaveSettingsTest.java index 29fe6236f2..539b9b73a9 100644 --- a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffSaveSettingsTest.java +++ b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffSaveSettingsTest.java @@ -28,7 +28,6 @@ import docking.util.image.ToolIconURL; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.app.plugin.core.progmgr.ProgramManagerPlugin; import ghidra.framework.main.FrontEndPlugin; -import ghidra.framework.plugintool.PluginTool; import ghidra.framework.project.tool.GhidraTool; import ghidra.program.database.ProgramDB; import ghidra.test.ClassicSampleX86ProgramBuilder; @@ -47,8 +46,9 @@ public class DiffSaveSettingsTest extends DiffApplyTestAdapter { private void launchTool() throws Exception { // Launch our own tool for the Diff so that we can close it and handle "Save Tool?". - runSwing(() -> tool = - (PluginTool) frontEndTool.getProject().getToolServices().launchTool("MyDiffTestTool", + runSwing(() -> tool = frontEndTool.getProject() + .getToolServices() + .launchTool("MyDiffTestTool", null)); cb = getPlugin(tool, CodeBrowserPlugin.class); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FrontEndPlugin.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FrontEndPlugin.java index 386b3c53ca..fa2c17787b 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FrontEndPlugin.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FrontEndPlugin.java @@ -1112,7 +1112,7 @@ public class FrontEndPlugin extends Plugin } } - if (toolServices.launchDefaultTool(domainFile) != null) { + if (toolServices.launchDefaultTool(List.of(domainFile)) != null) { return; } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ToolButton.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ToolButton.java index 59ce420e01..f9836554c4 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ToolButton.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ToolButton.java @@ -561,7 +561,11 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable { plugin.getActiveWorkspace().runTool(template); } else { - toolServices.launchDefaultTool(domainFiles); + PluginTool tool = toolServices.launchTool(template.getName(), domainFiles); + if (tool == null) { + Msg.showError(this, getParent(), "Failed to Launch Tool", + "Failed to launch " + template.getName() + " tool.\nSee log for details."); + } } } @@ -569,21 +573,7 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable { if (domainFiles == null) { return; } - boolean accepted = tool.acceptDomainFiles(domainFiles.toArray(DomainFile[]::new)); - if (!accepted) { - showFilesNotAcceptedMessage(domainFiles); - } - } - - private void showFilesNotAcceptedMessage(List domainFiles) { - StringBuilder buffy = new StringBuilder("Tool did not accept files: "); - for (int i = 0; i < domainFiles.size(); i++) { - buffy.append(domainFiles.get(0).getName()); - if (i != domainFiles.size() - 1) { - buffy.append(", "); - } - } - Msg.showError(this, null, "Error", buffy.toString()); + tool.acceptDomainFiles(domainFiles.toArray(DomainFile[]::new)); } private void setUpDragDrop() { diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/VersionHistoryPanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/VersionHistoryPanel.java index f3f3566d65..bf247ded2a 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/VersionHistoryPanel.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/VersionHistoryPanel.java @@ -344,10 +344,11 @@ public class VersionHistoryPanel extends JPanel implements Draggable { if (versionedObj != null) { try { if (toolName != null) { - tool.getToolServices().launchTool(toolName, versionedObj.getDomainFile()); + tool.getToolServices() + .launchTool(toolName, List.of(versionedObj.getDomainFile())); } else { - tool.getToolServices().launchDefaultTool(versionedObj.getDomainFile()); + tool.getToolServices().launchDefaultTool(List.of(versionedObj.getDomainFile())); } } finally { diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/ToolServices.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/ToolServices.java index c6b0fc750d..c85495b71c 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/ToolServices.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/ToolServices.java @@ -119,31 +119,25 @@ public interface ToolServices { public void setContentTypeToolAssociations(Set infos); /** - * Launch the default tool and open the specified domainFile. + * Launch the default {@link PluginTool tool} and open the specified domainFiles. * NOTE: running tool reuse is implementation dependent - * @param domainFile the file to open + * @param domainFiles the files to open. A null or empty list will results in an immediate + * return of a null {@link PluginTool}. Null entries are not permitted. * @return the launched tool. Null returned if a suitable default tool - * for the file content type was not found. + * for the file content type was not found or failed to launch. */ - public PluginTool launchDefaultTool(DomainFile domainFile); + public PluginTool launchDefaultTool(Collection domainFiles); /** - * Launch the default tool and open the specified domainFiles. - * NOTE: running tool reuse is implementation dependent - * @param domainFile the file to open - * @return the launched tool. Null returned if a suitable default tool - * for the file content type was not found. + * Launch the {@link PluginTool tool} with the given name and open the specified domainFiles. + * Only those domainFiles with a content type supported by the specified tool will be opened. + * NOTE: running tool reuse is implementation dependent. + * @param toolName name of the {@link ToolTemplate tool template} to launch or re-use + * @param domainFiles the files to open; may be null or empty. Null entries are not permitted. + * @return the resulting {@link PluginTool tool} or null if the specified tool was not found + * or failed to launch */ - public PluginTool launchDefaultTool(Collection domainFile); - - /** - * Launch the tool with the given name. A domainFile may be specified and will be opened - * if its content type is supported by the tool. - * @param toolName name of the tool to launch - * @param domainFile the file to open; may be null - * @return the requested tool or null if the specified tool not found. - */ - public PluginTool launchTool(String toolName, DomainFile domainFile); + public PluginTool launchTool(String toolName, Collection domainFiles); /** * Launch the default tool and open the specified Ghidra URL resource. diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/ToolServicesAdapter.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/ToolServicesAdapter.java index fcc6015aa8..13f322fdf1 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/ToolServicesAdapter.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/ToolServicesAdapter.java @@ -74,18 +74,13 @@ public class ToolServicesAdapter implements ToolServices { return null; } - @Override - public PluginTool launchDefaultTool(DomainFile domainFile) { - return null; - } - @Override public PluginTool launchDefaultTool(Collection domainFile) { return null; } @Override - public PluginTool launchTool(String toolName, DomainFile domainFile) { + public PluginTool launchTool(String toolName, Collection domainFile) { return null; } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/tool/ToolServicesImpl.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/tool/ToolServicesImpl.java index 4c56dd9da0..16d649b4c3 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/tool/ToolServicesImpl.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/tool/ToolServicesImpl.java @@ -236,14 +236,6 @@ class ToolServicesImpl implements ToolServices { return tool; } - @Override - public PluginTool launchDefaultTool(DomainFile domainFile) { - ToolTemplate template = getDefaultToolTemplate(domainFile); - return defaultLaunch(template, t -> { - return t.acceptDomainFiles(new DomainFile[] { domainFile }); - }); - } - @Override public PluginTool launchDefaultTool(Collection domainFiles) { if (CollectionUtils.isBlank(domainFiles)) { @@ -256,21 +248,17 @@ class ToolServicesImpl implements ToolServices { } @Override - public PluginTool launchTool(String toolName, DomainFile domainFile) { + public PluginTool launchTool(String toolName, Collection domainFiles) { ToolTemplate template = findToolChestToolTemplate(toolName); if (template == null) { return null; } - Workspace workspace = toolManager.getActiveWorkspace(); - PluginTool tool = workspace.runTool(template); - if (tool == null) { - return null; - } - tool.setVisible(true); - if (domainFile != null) { - tool.acceptDomainFiles(new DomainFile[] { domainFile }); - } - return tool; + return defaultLaunch(template, t -> { + if (CollectionUtils.isBlank(domainFiles)) { + return true; + } + return t.acceptDomainFiles(domainFiles.toArray(DomainFile[]::new)); + }); } @Override