GT-3495 - Refactor tool hierarchy to remove old 'Tool'

GT-3495 - GT-3495 - Refactor tool hierarchy to rename DockingTool to
Tool
This commit is contained in:
dragonmacher 2020-01-24 18:17:48 -05:00
parent 5dc7df71b3
commit 0ff6578d2c
92 changed files with 966 additions and 1228 deletions

View file

@ -65,7 +65,7 @@ public abstract class NavigatableContextAction extends DockingAction {
} }
private NavigatableActionContext getGlobalNavigationContext(ActionContext context) { private NavigatableActionContext getGlobalNavigationContext(ActionContext context) {
DockingTool tool = getTool(context.getComponentProvider()); Tool tool = getTool(context.getComponentProvider());
if (tool == null) { if (tool == null) {
return null; return null;
@ -81,7 +81,7 @@ public abstract class NavigatableContextAction extends DockingAction {
return new NavigatableActionContext(null, defaultNavigatable); return new NavigatableActionContext(null, defaultNavigatable);
} }
private DockingTool getTool(ComponentProvider provider) { private Tool getTool(ComponentProvider provider) {
if (provider != null) { if (provider != null) {
return provider.getTool(); return provider.getTool();
} }

View file

@ -55,7 +55,7 @@ public class ListingMergePanelProvider extends ComponentProviderAdapter
} }
@Override @Override
public List<DockingActionIf> getPopupActions(DockingTool dt, ActionContext context) { public List<DockingActionIf> getPopupActions(Tool dt, ActionContext context) {
ListingPanel resultPanel = mergePanel.getResultPanel(); ListingPanel resultPanel = mergePanel.getResultPanel();
if (resultPanel != null) { if (resultPanel != null) {
return resultPanel.getHeaderActions(getName()); return resultPanel.getHeaderActions(getName());

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,16 +15,16 @@
*/ */
package ghidra.app.nav; package ghidra.app.nav;
import ghidra.framework.model.Tool;
import java.util.*; import java.util.*;
import ghidra.framework.plugintool.PluginTool;
public class NavigatableRegistry { public class NavigatableRegistry {
private static Map<Long, Navigatable> navigatableMap = new HashMap<Long, Navigatable>(); private static Map<Long, Navigatable> navigatableMap = new HashMap<Long, Navigatable>();
private static Map<Tool, List<Navigatable>> toolMap = new HashMap<Tool, List<Navigatable>>(); private static Map<PluginTool, List<Navigatable>> toolMap =
new HashMap<PluginTool, List<Navigatable>>();
public static void registerNavigatable(PluginTool tool, Navigatable navigatable) {
public static void registerNavigatable(Tool tool, Navigatable navigatable) {
navigatableMap.put(navigatable.getInstanceID(), navigatable); navigatableMap.put(navigatable.getInstanceID(), navigatable);
List<Navigatable> list = toolMap.get(tool); List<Navigatable> list = toolMap.get(tool);
if (list == null) { if (list == null) {
@ -35,7 +34,7 @@ public class NavigatableRegistry {
list.add(navigatable); list.add(navigatable);
} }
public static void unregisterNavigatable(Tool tool, Navigatable navigatable) { public static void unregisterNavigatable(PluginTool tool, Navigatable navigatable) {
navigatableMap.remove(navigatable.getInstanceID()); navigatableMap.remove(navigatable.getInstanceID());
List<Navigatable> list = toolMap.get(tool); List<Navigatable> list = toolMap.get(tool);
if (list == null) { if (list == null) {
@ -46,13 +45,15 @@ public class NavigatableRegistry {
toolMap.remove(tool); toolMap.remove(tool);
} }
} }
public static List<Navigatable> getRegisteredNavigatables(Tool tool) {
public static List<Navigatable> getRegisteredNavigatables(PluginTool tool) {
List<Navigatable> list = toolMap.get(tool); List<Navigatable> list = toolMap.get(tool);
if (list == null) { if (list == null) {
list = new ArrayList<Navigatable>(navigatableMap.values()); list = new ArrayList<Navigatable>(navigatableMap.values());
} }
return list; return list;
} }
public static Navigatable getNavigatable(long navigationID) { public static Navigatable getNavigatable(long navigationID) {
return navigatableMap.get(navigationID); return navigatableMap.get(navigationID);
} }

View file

@ -22,7 +22,7 @@ import javax.swing.Icon;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import docking.ActionContext; import docking.ActionContext;
import docking.DockingTool; import docking.Tool;
import docking.action.*; import docking.action.*;
import docking.actions.PopupActionProvider; import docking.actions.PopupActionProvider;
import docking.widgets.table.GTable; import docking.widgets.table.GTable;
@ -362,10 +362,6 @@ public class BookmarkPlugin extends ProgramPlugin
getBookmarkNavigator(bookmarkMgr.getBookmarkType(type)); getBookmarkNavigator(bookmarkMgr.getBookmarkType(type));
} }
/**
* Bookmark has been changed.
* @param bookmark
*/
private void bookmarkChanged(Bookmark bookmark) { private void bookmarkChanged(Bookmark bookmark) {
if (bookmark == null) { if (bookmark == null) {
scheduleUpdate(null); scheduleUpdate(null);
@ -378,10 +374,6 @@ public class BookmarkPlugin extends ProgramPlugin
provider.bookmarkChanged(bookmark); provider.bookmarkChanged(bookmark);
} }
/**
* Bookmark has been added.
* @param bookmark
*/
private void bookmarkAdded(Bookmark bookmark) { private void bookmarkAdded(Bookmark bookmark) {
if (bookmark == null) { if (bookmark == null) {
scheduleUpdate(null); scheduleUpdate(null);
@ -496,7 +488,7 @@ public class BookmarkPlugin extends ProgramPlugin
} }
@Override @Override
public List<DockingActionIf> getPopupActions(DockingTool tool, ActionContext context) { public List<DockingActionIf> getPopupActions(Tool activeTool, ActionContext context) {
Object contextObject = context.getContextObject(); Object contextObject = context.getContextObject();
if (!(contextObject instanceof MarkerLocation)) { if (!(contextObject instanceof MarkerLocation)) {
return null; return null;

View file

@ -952,7 +952,7 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
} }
@Override @Override
public List<DockingActionIf> getPopupActions(DockingTool dt, ActionContext context) { public List<DockingActionIf> getPopupActions(Tool dt, ActionContext context) {
if (context.getComponentProvider() == this) { if (context.getComponentProvider() == this) {
return listingPanel.getHeaderActions(getName()); return listingPanel.getHeaderActions(getName());
} }

View file

@ -27,7 +27,7 @@ import javax.swing.SwingUtilities;
import javax.swing.tree.TreePath; import javax.swing.tree.TreePath;
import docking.ActionContext; import docking.ActionContext;
import docking.DockingTool; import docking.Tool;
import docking.action.*; import docking.action.*;
import docking.actions.PopupActionProvider; import docking.actions.PopupActionProvider;
import docking.widgets.tree.GTreeNode; import docking.widgets.tree.GTreeNode;
@ -678,7 +678,7 @@ public class DataTypeManagerPlugin extends ProgramPlugin
} }
@Override @Override
public List<DockingActionIf> getPopupActions(DockingTool dockingTool, ActionContext context) { public List<DockingActionIf> getPopupActions(Tool dockingTool, ActionContext context) {
if (!(context instanceof DataTypesActionContext)) { if (!(context instanceof DataTypesActionContext)) {
return null; return null;
} }

View file

@ -22,8 +22,8 @@ import javax.swing.ComboBoxModel;
import javax.swing.JPanel; import javax.swing.JPanel;
import docking.ComponentProvider; import docking.ComponentProvider;
import docking.actions.DockingToolActions;
import docking.actions.SharedDockingActionPlaceholder; import docking.actions.SharedDockingActionPlaceholder;
import docking.actions.ToolActions;
import docking.widgets.checkbox.GCheckBox; import docking.widgets.checkbox.GCheckBox;
import docking.widgets.combobox.GhidraComboBox; import docking.widgets.combobox.GhidraComboBox;
import docking.widgets.label.GLabel; import docking.widgets.label.GLabel;
@ -163,7 +163,7 @@ public class DataTypeEditorManager
} }
private void registerAction(String name) { private void registerAction(String name) {
ToolActions toolActions = plugin.getTool().getToolActions(); DockingToolActions toolActions = plugin.getTool().getToolActions();
toolActions.registerSharedActionPlaceholder(new DtSharedActionPlaceholder(name)); toolActions.registerSharedActionPlaceholder(new DtSharedActionPlaceholder(name));
} }

View file

@ -19,7 +19,7 @@ import java.awt.event.MouseEvent;
import java.util.*; import java.util.*;
import docking.ActionContext; import docking.ActionContext;
import docking.DockingTool; import docking.Tool;
import docking.action.DockingAction; import docking.action.DockingAction;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.actions.PopupActionProvider; import docking.actions.PopupActionProvider;
@ -130,7 +130,7 @@ public class FunctionComparisonProvider extends ComponentProviderAdapter
} }
@Override @Override
public List<DockingActionIf> getPopupActions(DockingTool tool, ActionContext context) { public List<DockingActionIf> getPopupActions(Tool tool, ActionContext context) {
if (context.getComponentProvider() == this) { if (context.getComponentProvider() == this) {
ListingCodeComparisonPanel dualListingPanel = ListingCodeComparisonPanel dualListingPanel =
functionComparisonPanel.getDualListingPanel(); functionComparisonPanel.getDualListingPanel();

View file

@ -326,7 +326,7 @@ public final class LanguageProviderPlugin extends Plugin implements FrontEndable
SwingUtilities.invokeAndWait(() -> { SwingUtilities.invokeAndWait(() -> {
ToolServices toolServices = tool.getToolServices(); ToolServices toolServices = tool.getToolServices();
String defaultToolName = toolServices.getDefaultToolTemplate(file).getName(); String defaultToolName = toolServices.getDefaultToolTemplate(file).getName();
for (Tool t : toolServices.getRunningTools()) { for (PluginTool t : toolServices.getRunningTools()) {
if (t.getName().equals(defaultToolName)) { if (t.getName().equals(defaultToolName)) {
openTool = (PluginTool) t; openTool = (PluginTool) t;
break; break;

View file

@ -22,7 +22,6 @@ import docking.ActionContext;
import docking.widgets.tree.GTreeNode; import docking.widgets.tree.GTreeNode;
import ghidra.app.services.ProgramManager; import ghidra.app.services.ProgramManager;
import ghidra.formats.gfilesystem.*; import ghidra.formats.gfilesystem.*;
import ghidra.framework.model.Tool;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.util.Msg; import ghidra.util.Msg;
@ -60,7 +59,7 @@ public class FSBUtils {
} }
public static FSBRootNode getNodesRoot(FSBNode node) { public static FSBRootNode getNodesRoot(FSBNode node) {
GTreeNode tmp = (GTreeNode) node; GTreeNode tmp = node;
while (tmp != null && !(tmp instanceof FSBRootNode)) { while (tmp != null && !(tmp instanceof FSBRootNode)) {
tmp = tmp.getParent(); tmp = tmp.getParent();
} }
@ -102,13 +101,11 @@ public class FSBUtils {
public static List<PluginTool> getRunningProgramManagerTools(PluginTool tool) { public static List<PluginTool> getRunningProgramManagerTools(PluginTool tool) {
List<PluginTool> pluginTools = new ArrayList<>(); List<PluginTool> pluginTools = new ArrayList<>();
for (Tool runningTool : tool.getToolServices().getRunningTools()) { for (PluginTool runningTool : tool.getToolServices().getRunningTools()) {
if (runningTool instanceof PluginTool) { PluginTool pt = runningTool;
PluginTool pt = (PluginTool) runningTool; ProgramManager pmService = pt.getService(ProgramManager.class);
ProgramManager pmService = pt.getService(ProgramManager.class); if (pmService != null) {
if (pmService != null) { pluginTools.add(pt);
pluginTools.add(pt);
}
} }
} }
return pluginTools; return pluginTools;

View file

@ -22,6 +22,7 @@ import java.util.*;
import generic.test.AbstractGenericTest; import generic.test.AbstractGenericTest;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.store.LockException; import ghidra.framework.store.LockException;
import ghidra.program.database.ProgramDB; import ghidra.program.database.ProgramDB;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
@ -155,18 +156,18 @@ public class ProjectTestUtils {
return dir.delete(); return dir.delete();
} }
for (int i = 0; i < files.length; i++) { for (File file : files) {
if (files[i].isDirectory()) { if (file.isDirectory()) {
// use a dummy monitor as not to ruin our progress // use a dummy monitor as not to ruin our progress
if (!deleteDir(files[i])) { if (!deleteDir(file)) {
Msg.debug(ProjectTestUtils.class, "Unable to delete directory: " + files[i]); Msg.debug(ProjectTestUtils.class, "Unable to delete directory: " + file);
return false; return false;
} }
} }
else { else {
if (!files[i].delete()) { if (!file.delete()) {
if (!ignoredDeleteNames.contains(files[i].getName())) { if (!ignoredDeleteNames.contains(file.getName())) {
Msg.debug(ProjectTestUtils.class, "Unable to delete file: " + files[i]); Msg.debug(ProjectTestUtils.class, "Unable to delete file: " + file);
return false; return false;
} }
@ -186,6 +187,10 @@ public class ProjectTestUtils {
* @param folder domain folder within the specified project which the * @param folder domain folder within the specified project which the
* user has permission to write. If null, the root data folder will be used. * user has permission to write. If null, the root data folder will be used.
* @return new domain file. * @return new domain file.
* @throws InvalidNameException if the filename is invalid
* @throws CancelledException if the opening is cancelled
* @throws LanguageNotFoundException if the language cannot be found
* @throws IOException if there is an exception creating the program or domain file
*/ */
public static DomainFile createProgramFile(Project proj, String progName, Language language, public static DomainFile createProgramFile(Project proj, String progName, Language language,
CompilerSpec compilerSpec, DomainFolder folder) throws InvalidNameException, CompilerSpec compilerSpec, DomainFolder folder) throws InvalidNameException,
@ -210,8 +215,9 @@ public class ProjectTestUtils {
* @param project the project to which the tool belongs * @param project the project to which the tool belongs
* @param toolName name of the tool to get from the active workspace. * @param toolName name of the tool to get from the active workspace.
* If null, launch a new empty tool in the active workspace. * If null, launch a new empty tool in the active workspace.
* @return the tool
*/ */
public static Tool getTool(Project project, String toolName) { public static PluginTool getTool(Project project, String toolName) {
ToolManager tm = project.getToolManager(); ToolManager tm = project.getToolManager();
@ -222,7 +228,7 @@ public class ProjectTestUtils {
// use the first one for the testing // use the first one for the testing
Workspace activeWorkspace = workspaces[0]; Workspace activeWorkspace = workspaces[0];
Tool tool = null; PluginTool tool = null;
if (toolName == null) { if (toolName == null) {
// create a new empty tool // create a new empty tool
tool = activeWorkspace.createTool(); tool = activeWorkspace.createTool();
@ -244,7 +250,7 @@ public class ProjectTestUtils {
* @param tool The tool to be saved * @param tool The tool to be saved
* @return The tool template for the given tool. * @return The tool template for the given tool.
*/ */
public static ToolTemplate saveTool(Project project, Tool tool) { public static ToolTemplate saveTool(Project project, PluginTool tool) {
// save the tool to the project tool chest // save the tool to the project tool chest
ToolChest toolChest = project.getLocalToolChest(); ToolChest toolChest = project.getLocalToolChest();
ToolTemplate toolTemplate = tool.saveToolToToolTemplate(); ToolTemplate toolTemplate = tool.saveToolToToolTemplate();
@ -254,8 +260,8 @@ public class ProjectTestUtils {
/** /**
* Remove the specified tool if it exists. * Remove the specified tool if it exists.
* @param project * @param project the project
* @param toolName * @param toolName the tool name
* @return true if it existed and was removed from the local tool chest. * @return true if it existed and was removed from the local tool chest.
*/ */
public static boolean deleteTool(Project project, String toolName) { public static boolean deleteTool(Project project, String toolName) {

View file

@ -640,7 +640,7 @@ public class TestEnv {
* NOTE: This array will not contain any of the TestTools! * NOTE: This array will not contain any of the TestTools!
* @return an array of tools spawned by the Ghidra environment * @return an array of tools spawned by the Ghidra environment
*/ */
public Tool[] getGhidraCreatedTools() { public PluginTool[] getGhidraCreatedTools() {
return gp.getProject().getToolManager().getRunningTools(); return gp.getProject().getToolManager().getRunningTools();
} }

View file

@ -610,7 +610,7 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
} }
private void performLaunchKeyStrokeDialogAction() { private void performLaunchKeyStrokeDialogAction() {
ToolActions toolActions = ((AbstractDockingTool) tool).getToolActions(); ToolActions toolActions = (ToolActions) ((AbstractDockingTool) tool).getToolActions();
Action action = toolActions.getAction(KeyStroke.getKeyStroke("F4")); Action action = toolActions.getAction(KeyStroke.getKeyStroke("F4"));
assertNotNull(action); assertNotNull(action);
runSwing(() -> action.actionPerformed(new ActionEvent(this, 0, "")), false); runSwing(() -> action.actionPerformed(new ActionEvent(this, 0, "")), false);
@ -624,7 +624,7 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
private JComponent component = new JTextField("Hey!"); private JComponent component = new JTextField("Hey!");
TestActionsComponentProvider(DockingTool tool) { TestActionsComponentProvider(Tool tool) {
super(tool, PROVIDER_NAME, "Fooberry Plugin"); super(tool, PROVIDER_NAME, "Fooberry Plugin");
} }
@ -637,7 +637,7 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
private class HasDefaultKeyBindingComponentProvider extends ComponentProvider { private class HasDefaultKeyBindingComponentProvider extends ComponentProvider {
private JComponent component = new JTextField("Hey!"); private JComponent component = new JTextField("Hey!");
HasDefaultKeyBindingComponentProvider(DockingTool tool) { HasDefaultKeyBindingComponentProvider(Tool tool) {
super(tool, HasDefaultKeyBindingComponentProvider.class.getSimpleName(), super(tool, HasDefaultKeyBindingComponentProvider.class.getSimpleName(),
"Fooberry Plugin"); "Fooberry Plugin");

View file

@ -36,7 +36,7 @@ import ghidra.test.DummyTool;
public class DockingWindowManagerTest extends AbstractDockingTest { public class DockingWindowManagerTest extends AbstractDockingTest {
private DockingTool tool = new DummyTool(); private Tool tool = new DummyTool();
@Test @Test
public void testDefaultGroupWindowPosition() { public void testDefaultGroupWindowPosition() {

View file

@ -25,8 +25,8 @@ import javax.swing.*;
import org.junit.*; import org.junit.*;
import docking.*; import docking.*;
import docking.actions.DockingToolActions;
import docking.actions.KeyEntryDialog; import docking.actions.KeyEntryDialog;
import docking.actions.ToolActions;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.app.plugin.core.navigation.GoToAddressLabelPlugin; import ghidra.app.plugin.core.navigation.GoToAddressLabelPlugin;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
@ -197,7 +197,7 @@ public class KeyEntryDialogTest extends AbstractGhidraHeadedIntegrationTest {
public DockingAction getKeyBindingAction() { public DockingAction getKeyBindingAction() {
ToolActions toolActions = tool.getToolActions(); DockingToolActions toolActions = tool.getToolActions();
KeyBindingsManager kbm = KeyBindingsManager kbm =
(KeyBindingsManager) getInstanceField("keyBindingsManager", toolActions); (KeyBindingsManager) getInstanceField("keyBindingsManager", toolActions);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View file

@ -28,8 +28,7 @@ import org.junit.Test;
import docking.DockingUtils; import docking.DockingUtils;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.actions.KeyBindingUtils; import docking.actions.*;
import docking.actions.ToolActions;
public class GhidraScriptMgrPlugin1Test extends AbstractGhidraScriptMgrPluginTest { public class GhidraScriptMgrPlugin1Test extends AbstractGhidraScriptMgrPluginTest {
@ -147,7 +146,7 @@ public class GhidraScriptMgrPlugin1Test extends AbstractGhidraScriptMgrPluginTes
KeyStroke actionKs = toolAction.getKeyBinding(); KeyStroke actionKs = toolAction.getKeyBinding();
assertEquals(newKs, actionKs); assertEquals(newKs, actionKs);
ToolActions toolActions = plugin.getTool().getToolActions(); ToolActions toolActions = (ToolActions) plugin.getTool().getToolActions();
Action toolActionByKeyStroke = toolActions.getAction(newKs); Action toolActionByKeyStroke = toolActions.getAction(newKs);
assertNotNull(toolActionByKeyStroke); assertNotNull(toolActionByKeyStroke);
} }

View file

@ -15,11 +15,12 @@
*/ */
package ghidra.framework.project; package ghidra.framework.project;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.*;
import org.junit.*; import org.junit.*;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.protocol.ghidra.GhidraURL; import ghidra.framework.protocol.ghidra.GhidraURL;
import ghidra.program.database.ProgramBuilder; import ghidra.program.database.ProgramBuilder;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
@ -73,7 +74,7 @@ public class CreateDomainObjectTest extends AbstractGhidraHeadedIntegrationTest
// test 1 create a program and add it to a project // test 1 create a program and add it to a project
Program program1 = createProgram(project, "Prog1", this); Program program1 = createProgram(project, "Prog1", this);
Tool consumer2 = new DummyTool(); PluginTool consumer2 = new DummyTool();
Program program2 = null; Program program2 = null;
try { try {
// test 2 - get the object from the project and make sure it is the // test 2 - get the object from the project and make sure it is the
@ -213,7 +214,7 @@ public class CreateDomainObjectTest extends AbstractGhidraHeadedIntegrationTest
private static void createProgramReadOnly(Project proj, String progName) throws Exception { private static void createProgramReadOnly(Project proj, String progName) throws Exception {
Tool t = new DummyTool(); PluginTool t = new DummyTool();
Program p = createDefaultProgram(progName, ProgramBuilder._TOY, t); Program p = createDefaultProgram(progName, ProgramBuilder._TOY, t);
try { try {
@ -295,7 +296,7 @@ public class CreateDomainObjectTest extends AbstractGhidraHeadedIntegrationTest
DomainFolder f3 = f.createFolder("Y"); DomainFolder f3 = f.createFolder("Y");
DomainFolder f4 = f.createFolder("Z"); DomainFolder f4 = f.createFolder("Z");
Tool t = new DummyTool("Tool1"); PluginTool t = new DummyTool("Tool1");
Program p1 = null; Program p1 = null;
Program p2 = null; Program p2 = null;
@ -344,7 +345,7 @@ public class CreateDomainObjectTest extends AbstractGhidraHeadedIntegrationTest
DomainFolder f3 = f.getFolder("Y"); DomainFolder f3 = f.getFolder("Y");
DomainFolder f4 = f.getFolder("Z"); DomainFolder f4 = f.getFolder("Z");
Tool t = new DummyTool("Tool1"); PluginTool t = new DummyTool("Tool1");
if ((f.getFile("AAA") == null) || (f.getFile("BBB") == null) || if ((f.getFile("AAA") == null) || (f.getFile("BBB") == null) ||
(f2.getFile("CCC") == null) || (f3.getFile("DDD") == null) || (f2.getFile("CCC") == null) || (f3.getFile("DDD") == null) ||

View file

@ -200,9 +200,9 @@ public abstract class AbstractToolSavingTest extends AbstractGhidraHeadedIntegra
protected List<PluginTool> findOpenTools() { protected List<PluginTool> findOpenTools() {
ToolManager tm = testEnv.getProject().getToolManager(); ToolManager tm = testEnv.getProject().getToolManager();
Workspace activeWorkspace = tm.getActiveWorkspace(); Workspace activeWorkspace = tm.getActiveWorkspace();
Tool[] tools = activeWorkspace.getTools(); PluginTool[] tools = activeWorkspace.getTools();
List<PluginTool> pluginToolList = new ArrayList<>(tools.length); List<PluginTool> pluginToolList = new ArrayList<>(tools.length);
for (Tool tool : tools) { for (PluginTool tool : tools) {
pluginToolList.add((PluginTool) tool); pluginToolList.add((PluginTool) tool);
} }
return pluginToolList; return pluginToolList;

View file

@ -17,8 +17,10 @@ package ghidra.framework.project.tool;
import org.junit.*; import org.junit.*;
import generic.test.AbstractGenericTest; import generic.test.AbstractGTest;
import ghidra.framework.model.*; import ghidra.framework.model.DomainFile;
import ghidra.framework.model.Project;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.database.ProgramBuilder; import ghidra.program.database.ProgramBuilder;
import ghidra.test.*; import ghidra.test.*;
@ -30,20 +32,12 @@ import ghidra.test.*;
*/ */
public class ChangeToolDataTest extends AbstractGhidraHeadedIntegrationTest { public class ChangeToolDataTest extends AbstractGhidraHeadedIntegrationTest {
private final static String DIRECTORY_NAME = AbstractGenericTest.getTestDirectoryPath(); private final static String DIRECTORY_NAME = AbstractGTest.getTestDirectoryPath();
private final static String DATA_NAME_1 = "TestData1"; private final static String DATA_NAME_1 = "TestData1";
private final static String DATA_NAME_2 = "TestData2"; private final static String DATA_NAME_2 = "TestData2";
private Project project; private Project project;
/**
* Constructor
* @param arg0
*/
public ChangeToolDataTest() {
super();
}
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
ProjectTestUtils.deleteProject(DIRECTORY_NAME, PROJECT_NAME); ProjectTestUtils.deleteProject(DIRECTORY_NAME, PROJECT_NAME);
@ -56,8 +50,8 @@ public class ChangeToolDataTest extends AbstractGhidraHeadedIntegrationTest {
ProjectTestUtils.deleteProject(DIRECTORY_NAME, PROJECT_NAME); ProjectTestUtils.deleteProject(DIRECTORY_NAME, PROJECT_NAME);
} }
/** /*
* This doTest() routine tests the following requirements: * Tests the following requirements:
* (1) connect two running tools by one or more specified events * (1) connect two running tools by one or more specified events
* (2) disconnect one or more specified events between two connected tools * (2) disconnect one or more specified events between two connected tools
* @param args same as args to main() * @param args same as args to main()
@ -72,7 +66,7 @@ public class ChangeToolDataTest extends AbstractGhidraHeadedIntegrationTest {
// //
// setup the running tool // setup the running tool
// //
Tool runningTool = new DummyTool(); PluginTool runningTool = new DummyTool();
// //
// TEST 1: set the data for a tool running without data // TEST 1: set the data for a tool running without data

View file

@ -53,10 +53,8 @@ public class CloseToolTest extends AbstractGhidraHeadedIntegrationTest {
@After @After
public void tearDown() throws Exception { public void tearDown() throws Exception {
executeOnSwingWithoutBlocking(() -> env.dispose()); env.dispose();
closeAllWindows(); closeAllWindows();
} }
@Test @Test

View file

@ -17,8 +17,9 @@ package ghidra.framework.project.tool;
import org.junit.*; import org.junit.*;
import generic.test.AbstractGenericTest; import generic.test.AbstractGTest;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.test.*; import ghidra.test.*;
/** /**
@ -30,18 +31,10 @@ import ghidra.test.*;
public class ConnectToolsTest extends AbstractGhidraHeadedIntegrationTest { public class ConnectToolsTest extends AbstractGhidraHeadedIntegrationTest {
private final static String BAD_EVENT_NAME = "TEST_CONNECT_FOR_BAD_EVENT"; private final static String BAD_EVENT_NAME = "TEST_CONNECT_FOR_BAD_EVENT";
private final static String DIRECTORY_NAME = AbstractGenericTest.getTestDirectoryPath(); private final static String DIRECTORY_NAME = AbstractGTest.getTestDirectoryPath();
private Project project; private Project project;
/**
* Constructor
* @param arg0
*/
public ConnectToolsTest() {
super();
}
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
@ -56,16 +49,16 @@ public class ConnectToolsTest extends AbstractGhidraHeadedIntegrationTest {
} }
/** /*
* This doTest() routine tests the following requirements: * Tests the following requirements:
* (1) connect two running tools by one or more specified events * (1) connect two running tools by one or more specified events
* (2) disconnect one or more specified events between two connected tools * (2) disconnect one or more specified events between two connected tools
*/ */
@Test @Test
public void testConnectTools() throws Exception { public void testConnectTools() throws Exception {
Tool producer = new DummyTool("ProducerTool"); PluginTool producer = new DummyTool("ProducerTool");
Tool consumer = new DummyTool("ConsumerTool"); PluginTool consumer = new DummyTool("ConsumerTool");
ToolConnection tc; ToolConnection tc;
String eventName = null; String eventName = null;

View file

@ -17,8 +17,10 @@ package ghidra.framework.project.tool;
import org.junit.*; import org.junit.*;
import generic.test.AbstractGenericTest; import generic.test.AbstractGTest;
import ghidra.framework.model.*; import ghidra.framework.model.Project;
import ghidra.framework.model.ToolManager;
import ghidra.framework.plugintool.PluginTool;
import ghidra.test.AbstractGhidraHeadedIntegrationTest; import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.test.ProjectTestUtils; import ghidra.test.ProjectTestUtils;
@ -29,20 +31,10 @@ import ghidra.test.ProjectTestUtils;
*/ */
public class CreateToolTest extends AbstractGhidraHeadedIntegrationTest { public class CreateToolTest extends AbstractGhidraHeadedIntegrationTest {
private final static String DIRECTORY_NAME = AbstractGenericTest.getTestDirectoryPath(); private final static String DIRECTORY_NAME = AbstractGTest.getTestDirectoryPath();
private Project project; private Project project;
// private Workspace activeWorkspace; private PluginTool tool;
private Tool tool;
/**
* Constructor
* @param arg0
*/
public CreateToolTest() {
super();
}
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
@ -56,7 +48,7 @@ public class CreateToolTest extends AbstractGhidraHeadedIntegrationTest {
ProjectTestUtils.deleteProject(DIRECTORY_NAME, PROJECT_NAME); ProjectTestUtils.deleteProject(DIRECTORY_NAME, PROJECT_NAME);
} }
private void closeTool(final Tool theTool) { private void closeTool(final PluginTool theTool) {
executeOnSwingWithoutBlocking(new Runnable() { executeOnSwingWithoutBlocking(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -65,10 +57,10 @@ public class CreateToolTest extends AbstractGhidraHeadedIntegrationTest {
}); });
// this handles the save changes dialog and potential analysis dialogs // this handles the save changes dialog and potential analysis dialogs
closeAllWindowsAndFrames(); closeAllWindows();
} }
/** /*
* Do the test. * Do the test.
* This doTest() routine tests the following requirements: * This doTest() routine tests the following requirements:
* (1) create (launch) an empty tool in the active workspace * (1) create (launch) an empty tool in the active workspace
@ -92,7 +84,7 @@ public class CreateToolTest extends AbstractGhidraHeadedIntegrationTest {
try { try {
// verify the tool is actually running before declaring success // verify the tool is actually running before declaring success
ToolManager tm = project.getToolManager(); ToolManager tm = project.getToolManager();
Tool[] runningTools = tm.getRunningTools(); PluginTool[] runningTools = tm.getRunningTools();
for (int t = 0; !verified && t < runningTools.length; t++) { for (int t = 0; !verified && t < runningTools.length; t++) {
if (runningTools[t].equals(tool)) { if (runningTools[t].equals(tool)) {
verified = true; verified = true;

View file

@ -15,7 +15,7 @@
*/ */
package ghidra.framework.project.tool; package ghidra.framework.project.tool;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.*;
import java.io.IOException; import java.io.IOException;
@ -23,6 +23,7 @@ import org.junit.*;
import generic.test.AbstractGenericTest; import generic.test.AbstractGenericTest;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.store.LockException; import ghidra.framework.store.LockException;
import ghidra.test.AbstractGhidraHeadedIntegrationTest; import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.test.ProjectTestUtils; import ghidra.test.ProjectTestUtils;
@ -138,7 +139,7 @@ public class CreateWorkspaceTest extends AbstractGhidraHeadedIntegrationTest {
} }
}); });
Tool[] runningTools = wspaces[0].getTools(); PluginTool[] runningTools = wspaces[0].getTools();
assertEquals(1, runningTools.length); assertEquals(1, runningTools.length);
setWorkspaceActive(wspaces[1]); setWorkspaceActive(wspaces[1]);

View file

@ -17,8 +17,9 @@ package ghidra.framework.project.tool;
import org.junit.*; import org.junit.*;
import generic.test.AbstractGenericTest; import generic.test.AbstractGTest;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.test.AbstractGhidraHeadedIntegrationTest; import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.test.ProjectTestUtils; import ghidra.test.ProjectTestUtils;
@ -30,20 +31,12 @@ import ghidra.test.ProjectTestUtils;
*/ */
public class DeleteToolTest extends AbstractGhidraHeadedIntegrationTest { public class DeleteToolTest extends AbstractGhidraHeadedIntegrationTest {
private final static String PROJECT_DIRECTORY = AbstractGenericTest.getTestDirectoryPath(); private final static String PROJECT_DIRECTORY = AbstractGTest.getTestDirectoryPath();
private final static String TOOL_NAME = "TestTool"; private final static String TOOL_NAME = "TestTool";
private Tool runningTool; private PluginTool runningTool;
private Project project; private Project project;
/**
* Constructor
* @param arg0
*/
public DeleteToolTest() {
super();
}
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
ProjectTestUtils.deleteProject(PROJECT_DIRECTORY, PROJECT_NAME); ProjectTestUtils.deleteProject(PROJECT_DIRECTORY, PROJECT_NAME);
@ -56,8 +49,8 @@ public class DeleteToolTest extends AbstractGhidraHeadedIntegrationTest {
ProjectTestUtils.deleteProject(PROJECT_DIRECTORY, PROJECT_NAME); ProjectTestUtils.deleteProject(PROJECT_DIRECTORY, PROJECT_NAME);
} }
/** /*
* This doTest() routine tests the following requirements: * Tsts the following requirements:
* (1) delete a non-running tool from the user's project space * (1) delete a non-running tool from the user's project space
* (2) delete a running tool from the user's project space * (2) delete a running tool from the user's project space
* *

View file

@ -15,16 +15,13 @@
*/ */
package ghidra.framework.project.tool; package ghidra.framework.project.tool;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.*;
import java.beans.PropertyVetoException;
import javax.swing.SwingUtilities;
import org.junit.*; import org.junit.*;
import generic.test.AbstractGenericTest; import generic.test.AbstractGTest;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.test.AbstractGhidraHeadedIntegrationTest; import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.test.ProjectTestUtils; import ghidra.test.ProjectTestUtils;
@ -36,20 +33,12 @@ import ghidra.test.ProjectTestUtils;
*/ */
public class RunToolTest extends AbstractGhidraHeadedIntegrationTest { public class RunToolTest extends AbstractGhidraHeadedIntegrationTest {
private final static String DIRECTORY_NAME = AbstractGenericTest.getTestDirectoryPath(); private final static String DIRECTORY_NAME = AbstractGTest.getTestDirectoryPath();
private final static String TOOL_NAME = "TestTool"; private final static String TOOL_NAME = "TestTool";
private Project project; private Project project;
private Tool runningTool; private PluginTool runningTool;
private Tool tool; private PluginTool tool;
/**
* Constructor
* @param arg0
*/
public RunToolTest() {
super();
}
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
@ -59,7 +48,7 @@ public class RunToolTest extends AbstractGhidraHeadedIntegrationTest {
@After @After
public void tearDown() throws Exception { public void tearDown() throws Exception {
SwingUtilities.invokeAndWait(new Runnable() { runSwing(new Runnable() {
@Override @Override
public void run() { public void run() {
project.save(); project.save();
@ -69,7 +58,7 @@ public class RunToolTest extends AbstractGhidraHeadedIntegrationTest {
ProjectTestUtils.deleteProject(DIRECTORY_NAME, PROJECT_NAME); ProjectTestUtils.deleteProject(DIRECTORY_NAME, PROJECT_NAME);
} }
/** /*
* Do the test. * Do the test.
* This doTest() routine tests the following requirements: * This doTest() routine tests the following requirements:
* (1) Run Project Tool Without Data * (1) Run Project Tool Without Data
@ -84,22 +73,18 @@ public class RunToolTest extends AbstractGhidraHeadedIntegrationTest {
ProjectTestUtils.deleteTool(project, TOOL_NAME); ProjectTestUtils.deleteTool(project, TOOL_NAME);
// Create tool and save tool config // Create tool and save tool config
SwingUtilities.invokeAndWait(new Runnable() { runSwing(new Runnable() {
@Override @Override
public void run() { public void run() {
tool = ProjectTestUtils.getTool(project, null); tool = ProjectTestUtils.getTool(project, null);
try { tool.setToolName(TOOL_NAME);
tool.setToolName(TOOL_NAME);
}
catch (PropertyVetoException e) {
}
} }
}); });
try { try {
final ToolTemplate toolConfig = ProjectTestUtils.saveTool(project, tool); final ToolTemplate toolConfig = ProjectTestUtils.saveTool(project, tool);
SwingUtilities.invokeAndWait(new Runnable() { runSwing(new Runnable() {
@Override @Override
public void run() { public void run() {
tool.close(); tool.close();
@ -118,14 +103,14 @@ public class RunToolTest extends AbstractGhidraHeadedIntegrationTest {
// use the first one for the test // use the first one for the test
final Workspace activeWorkspace = workspaces[0]; final Workspace activeWorkspace = workspaces[0];
SwingUtilities.invokeAndWait(new Runnable() { runSwing(new Runnable() {
@Override @Override
public void run() { public void run() {
runningTool = activeWorkspace.runTool(toolConfig); runningTool = activeWorkspace.runTool(toolConfig);
} }
}); });
assertNotNull(runningTool); assertNotNull(runningTool);
SwingUtilities.invokeAndWait(new Runnable() { runSwing(new Runnable() {
@Override @Override
public void run() { public void run() {
runningTool.close(); runningTool.close();
@ -135,7 +120,7 @@ public class RunToolTest extends AbstractGhidraHeadedIntegrationTest {
} }
finally { finally {
// Don't leave the tool in the tool chest // Don't leave the tool in the tool chest
SwingUtilities.invokeAndWait(new Runnable() { runSwing(new Runnable() {
@Override @Override
public void run() { public void run() {
ProjectTestUtils.deleteTool(project, TOOL_NAME); ProjectTestUtils.deleteTool(project, TOOL_NAME);

View file

@ -15,12 +15,13 @@
*/ */
package ghidra.framework.project.tool; package ghidra.framework.project.tool;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.*;
import org.junit.*; import org.junit.*;
import generic.test.AbstractGenericTest; import generic.test.AbstractGTest;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.test.AbstractGhidraHeadedIntegrationTest; import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.test.ProjectTestUtils; import ghidra.test.ProjectTestUtils;
@ -29,20 +30,12 @@ import ghidra.test.ProjectTestUtils;
*/ */
public class SaveToolTest extends AbstractGhidraHeadedIntegrationTest { public class SaveToolTest extends AbstractGhidraHeadedIntegrationTest {
private final static String DIRECTORY_NAME = AbstractGenericTest.getTestDirectoryPath(); private final static String DIRECTORY_NAME = AbstractGTest.getTestDirectoryPath();
private final static String TOOL_NAME = "TestTool"; private final static String TOOL_NAME = "TestTool";
private Tool runningTool; private PluginTool runningTool;
private Project project; private Project project;
/**
* Constructor
* @param name The name of the test to run.
*/
public SaveToolTest() {
super();
}
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
ProjectTestUtils.deleteProject(DIRECTORY_NAME, PROJECT_NAME); ProjectTestUtils.deleteProject(DIRECTORY_NAME, PROJECT_NAME);
@ -55,7 +48,7 @@ public class SaveToolTest extends AbstractGhidraHeadedIntegrationTest {
ProjectTestUtils.deleteProject(DIRECTORY_NAME, PROJECT_NAME); ProjectTestUtils.deleteProject(DIRECTORY_NAME, PROJECT_NAME);
} }
/** /*
* This tests the following requirements: * This tests the following requirements:
* (1) create an empty tool in the active workspace, and * (1) create an empty tool in the active workspace, and
* (2) that duplicate project names do not throw exceptions. * (2) that duplicate project names do not throw exceptions.

View file

@ -97,7 +97,7 @@ public class FcgProvider
private ToggleDockingAction navigateIncomingToggleAction; private ToggleDockingAction navigateIncomingToggleAction;
public FcgProvider(DockingTool tool, FunctionCallGraphPlugin plugin) { public FcgProvider(Tool tool, FunctionCallGraphPlugin plugin) {
super(tool, NAME, plugin.getName()); super(tool, NAME, plugin.getName());
this.plugin = plugin; this.plugin = plugin;

View file

@ -174,7 +174,7 @@ public class VTSubToolManager implements VTControllerListener, OptionsChangeList
return newTool; return newTool;
} }
private DockingActionIf getToolAction(Tool tool, String actionName) { private DockingActionIf getToolAction(PluginTool tool, String actionName) {
Set<DockingActionIf> actions = tool.getDockingActionsByOwnerName(ToolConstants.TOOL_OWNER); Set<DockingActionIf> actions = tool.getDockingActionsByOwnerName(ToolConstants.TOOL_OWNER);
for (DockingActionIf action : actions) { for (DockingActionIf action : actions) {
if (action.getName().equals(actionName)) { if (action.getName().equals(actionName)) {

View file

@ -219,7 +219,7 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter
} }
@Override @Override
public List<DockingActionIf> getPopupActions(DockingTool tool, ActionContext context) { public List<DockingActionIf> getPopupActions(Tool tool, ActionContext context) {
if (context.getComponentProvider() == this) { if (context.getComponentProvider() == this) {
ListingCodeComparisonPanel dualListingPanel = ListingCodeComparisonPanel dualListingPanel =
functionComparisonPanel.getDualListingPanel(); functionComparisonPanel.getDualListingPanel();

View file

@ -452,7 +452,7 @@ public class VTMarkupItemsTableProvider extends ComponentProviderAdapter
} }
@Override @Override
public List<DockingActionIf> getPopupActions(DockingTool tool, ActionContext context) { public List<DockingActionIf> getPopupActions(Tool tool, ActionContext context) {
ListingCodeComparisonPanel dualListingPanel = functionComparisonPanel.getDualListingPanel(); ListingCodeComparisonPanel dualListingPanel = functionComparisonPanel.getDualListingPanel();
if (context.getComponentProvider() == this && dualListingPanel != null) { if (context.getComponentProvider() == this && dualListingPanel != null) {
ListingPanel sourcePanel = dualListingPanel.getLeftPanel(); ListingPanel sourcePanel = dualListingPanel.getLeftPanel();

View file

@ -21,16 +21,15 @@ import java.util.*;
import javax.swing.JFrame; import javax.swing.JFrame;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.actions.PopupActionProvider; import docking.actions.*;
import docking.actions.ToolActions;
import ghidra.framework.options.ToolOptions; import ghidra.framework.options.ToolOptions;
import ghidra.util.Swing; import ghidra.util.Swing;
/** /**
* A partial implementation of {@link DockingTool} that serves as a place to share common * A partial implementation of {@link Tool} that serves as a place to share common
* functionality * functionality
*/ */
public abstract class AbstractDockingTool implements DockingTool { public abstract class AbstractDockingTool implements Tool {
protected DockingWindowManager winMgr; protected DockingWindowManager winMgr;
protected ToolActions toolActions; protected ToolActions toolActions;
@ -235,7 +234,7 @@ public abstract class AbstractDockingTool implements DockingTool {
} }
@Override @Override
public ToolActions getToolActions() { public DockingToolActions getToolActions() {
return toolActions; return toolActions;
} }
} }

View file

@ -85,7 +85,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
// maps for mapping old provider names and owner to new names and/or owner // maps for mapping old provider names and owner to new names and/or owner
private static Map<String, String> oldOwnerMap = new HashMap<>(); private static Map<String, String> oldOwnerMap = new HashMap<>();
private static Map<String, String> oldNameMap = new HashMap<>(); private static Map<String, String> oldNameMap = new HashMap<>();
protected DockingTool dockingTool; protected Tool dockingTool;
private String name; private String name;
private final String owner; private final String owner;
private String title; private String title;
@ -121,7 +121,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
* the same window. * the same window.
* @param owner The owner of this provider, usually a plugin name. * @param owner The owner of this provider, usually a plugin name.
*/ */
public ComponentProvider(DockingTool tool, String name, String owner) { public ComponentProvider(Tool tool, String name, String owner) {
this(tool, name, owner, null); this(tool, name, owner, null);
} }
@ -134,7 +134,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
* @param contextType the type of context supported by this provider; may be null (see * @param contextType the type of context supported by this provider; may be null (see
* {@link #getContextType()} * {@link #getContextType()}
*/ */
public ComponentProvider(DockingTool tool, String name, String owner, Class<?> contextType) { public ComponentProvider(Tool tool, String name, String owner, Class<?> contextType) {
this.dockingTool = tool; this.dockingTool = tool;
this.name = name; this.name = name;
this.owner = owner; this.owner = owner;
@ -744,7 +744,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
return this; return this;
} }
public DockingTool getTool() { public Tool getTool() {
return dockingTool; return dockingTool;
} }

View file

@ -74,7 +74,7 @@ class DockableToolBarManager {
String owner = provider.getOwner(); String owner = provider.getOwner();
ToolBarCloseAction closeAction = new ToolBarCloseAction(owner); ToolBarCloseAction closeAction = new ToolBarCloseAction(owner);
closeButtonManager = new ToolBarItemManager(closeAction, winMgr); closeButtonManager = new ToolBarItemManager(closeAction, winMgr);
DockingTool tool = winMgr.getTool(); Tool tool = winMgr.getTool();
// we need to add this action to the tool in order to use key bindings // we need to add this action to the tool in order to use key bindings
tool.addLocalAction(provider, closeAction); tool.addLocalAction(provider, closeAction);
@ -166,7 +166,7 @@ class DockableToolBarManager {
// this will be null for non-standard use cases // this will be null for non-standard use cases
if (dockableComponent != null) { if (dockableComponent != null) {
DockingWindowManager dwm = dockableComponent.getDockingWindowManager(); DockingWindowManager dwm = dockableComponent.getDockingWindowManager();
DockingTool tool = dwm.getTool(); Tool tool = dwm.getTool();
ComponentProvider provider = dockableComponent.getComponentProvider(); ComponentProvider provider = dockableComponent.getComponentProvider();
tool.removeLocalAction(provider, closeButtonManager.getAction()); tool.removeLocalAction(provider, closeButtonManager.getAction());
} }

View file

@ -32,9 +32,9 @@ public abstract class DockingKeyBindingAction extends AbstractAction {
private DockingActionIf docakbleAction; private DockingActionIf docakbleAction;
protected final KeyStroke keyStroke; protected final KeyStroke keyStroke;
protected final DockingTool tool; protected final Tool tool;
public DockingKeyBindingAction(DockingTool tool, DockingActionIf action, KeyStroke keyStroke) { public DockingKeyBindingAction(Tool tool, DockingActionIf action, KeyStroke keyStroke) {
super(KeyBindingUtils.parseKeyStroke(keyStroke)); super(KeyBindingUtils.parseKeyStroke(keyStroke));
this.tool = tool; this.tool = tool;
this.docakbleAction = action; this.docakbleAction = action;

View file

@ -79,7 +79,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
// we use a list to maintain order // we use a list to maintain order
private static List<DockingWindowManager> instances = new ArrayList<>(); private static List<DockingWindowManager> instances = new ArrayList<>();
private DockingTool tool; private Tool tool;
private RootNode root; private RootNode root;
private PlaceholderManager placeholderManager; private PlaceholderManager placeholderManager;
@ -116,7 +116,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
* @param tool the tool * @param tool the tool
* @param images the images to use for windows in this window manager * @param images the images to use for windows in this window manager
*/ */
public DockingWindowManager(DockingTool tool, List<Image> images) { public DockingWindowManager(Tool tool, List<Image> images) {
this(tool, images, false, true, true, null); this(tool, images, false, true, true, null);
} }
@ -131,7 +131,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
* @param hasStatusBar if true a status bar will be created for the main window * @param hasStatusBar if true a status bar will be created for the main window
* @param factory the drop target factory * @param factory the drop target factory
*/ */
public DockingWindowManager(DockingTool tool, List<Image> images, boolean modal, public DockingWindowManager(Tool tool, List<Image> images, boolean modal,
boolean isDocking, boolean hasStatusBar, DropTargetFactory factory) { boolean isDocking, boolean hasStatusBar, DropTargetFactory factory) {
KeyBindingOverrideKeyEventDispatcher.install(); KeyBindingOverrideKeyEventDispatcher.install();
@ -330,7 +330,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
* Returns the tool that owns this manager * Returns the tool that owns this manager
* @return the tool * @return the tool
*/ */
public DockingTool getTool() { public Tool getTool() {
return tool; return tool;
} }

View file

@ -30,7 +30,7 @@ import ghidra.framework.plugintool.ServiceProvider;
* Generic tool interface for managing {@link ComponentProvider}s and * Generic tool interface for managing {@link ComponentProvider}s and
* {@link DockingActionIf actions} * {@link DockingActionIf actions}
*/ */
public interface DockingTool extends ServiceProvider { public interface Tool extends ServiceProvider {
/** /**
* Returns a combination of the tool name and the instance name of the form * Returns a combination of the tool name and the instance name of the form

View file

@ -17,7 +17,7 @@ package docking.action;
import java.util.List; import java.util.List;
import docking.DockingTool; import docking.Tool;
/** /**
* An interface for objects (really Components) to implement that signals they provide actions * An interface for objects (really Components) to implement that signals they provide actions
@ -29,7 +29,7 @@ import docking.DockingTool;
* actions. Further, in this example, the actions given will be inserted into the popup menu * actions. Further, in this example, the actions given will be inserted into the popup menu
* that is shown. * that is shown.
* *
* @deprecated use {@link DockingTool} * @deprecated use {@link Tool}
*/ */
// Note: this API is not likely used by forward-facing clients and can be removed in the next release // Note: this API is not likely used by forward-facing clients and can be removed in the next release
@Deprecated(since = "9.1", forRemoval = true) @Deprecated(since = "9.1", forRemoval = true)

View file

@ -38,9 +38,9 @@ public class KeyBindingsManager implements PropertyChangeListener {
// this map exists to update the MultiKeyBindingAction when the key binding changes // this map exists to update the MultiKeyBindingAction when the key binding changes
private Map<DockingActionIf, ComponentProvider> actionToProviderMap; private Map<DockingActionIf, ComponentProvider> actionToProviderMap;
private Map<KeyStroke, DockingKeyBindingAction> dockingKeyMap; private Map<KeyStroke, DockingKeyBindingAction> dockingKeyMap;
private DockingTool tool; private Tool tool;
public KeyBindingsManager(DockingTool tool) { public KeyBindingsManager(Tool tool) {
this.tool = tool; this.tool = tool;
dockingKeyMap = new HashMap<>(); dockingKeyMap = new HashMap<>();
actionToProviderMap = new HashMap<>(); actionToProviderMap = new HashMap<>();

View file

@ -40,7 +40,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
* @param action action that will be added to the list of actions bound to a keystroke * @param action action that will be added to the list of actions bound to a keystroke
* @param keyStroke the keystroke, if any, associated with the action * @param keyStroke the keystroke, if any, associated with the action
*/ */
public MultipleKeyAction(DockingTool tool, ComponentProvider provider, DockingActionIf action, public MultipleKeyAction(Tool tool, ComponentProvider provider, DockingActionIf action,
KeyStroke keyStroke) { KeyStroke keyStroke) {
super(tool, action, keyStroke); super(tool, action, keyStroke);
addAction(provider, action); addAction(provider, action);

View file

@ -21,7 +21,7 @@ import docking.*;
class ReservedKeyBindingAction extends DockingKeyBindingAction { class ReservedKeyBindingAction extends DockingKeyBindingAction {
ReservedKeyBindingAction(DockingTool tool, DockingActionIf action, KeyStroke keyStroke) { ReservedKeyBindingAction(Tool tool, DockingActionIf action, KeyStroke keyStroke) {
super(tool, action, keyStroke); super(tool, action, keyStroke);
} }

View file

@ -177,7 +177,7 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, B extends
/** /**
* Builds the action. To build and install the action in one step, use * Builds the action. To build and install the action in one step, use
* {@link #buildAndInstall(DockingTool)} or {@link #buildAndInstallLocal(ComponentProvider)}. * {@link #buildAndInstall(Tool)} or {@link #buildAndInstallLocal(ComponentProvider)}.
* *
* @return the newly build action * @return the newly build action
*/ */
@ -191,7 +191,7 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, B extends
* @see #build() * @see #build()
* @see #buildAndInstallLocal(ComponentProvider) * @see #buildAndInstallLocal(ComponentProvider)
*/ */
public T buildAndInstall(DockingTool tool) { public T buildAndInstall(Tool tool) {
T action = build(); T action = build();
tool.addAction(action); tool.addAction(action);
return action; return action;
@ -203,7 +203,7 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, B extends
* @param provider the provider to add the action to * @param provider the provider to add the action to
* @return the newly created action * @return the newly created action
* @see #build() * @see #build()
* @see #buildAndInstall(DockingTool) * @see #buildAndInstall(Tool)
*/ */
public T buildAndInstallLocal(ComponentProvider provider) { public T buildAndInstallLocal(ComponentProvider provider) {
T action = build(); T action = build();

View file

@ -91,4 +91,16 @@ public interface DockingToolActions {
* @return the actions * @return the actions
*/ */
public Set<DockingActionIf> getAllActions(); public Set<DockingActionIf> getAllActions();
/**
* Allows clients to register an action by using a placeholder. This is useful when
* an API wishes to have a central object (like a plugin) register actions for transient
* providers, that may not be loaded until needed.
*
* <p>This method may be called multiple times with the same conceptual placeholder--the
* placeholder will only be added once.
*
* @param placeholder the placeholder containing information related to the action it represents
*/
public void registerSharedActionPlaceholder(SharedDockingActionPlaceholder placeholder);
} }

View file

@ -33,7 +33,7 @@ import org.jdom.*;
import org.jdom.input.SAXBuilder; import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter; import org.jdom.output.XMLOutputter;
import docking.DockingTool; import docking.Tool;
import docking.DockingUtils; import docking.DockingUtils;
import docking.action.*; import docking.action.*;
import docking.widgets.filechooser.GhidraFileChooser; import docking.widgets.filechooser.GhidraFileChooser;
@ -465,7 +465,7 @@ public class KeyBindingUtils {
* @param tool the tool containing the actions * @param tool the tool containing the actions
* @return the actions mapped by their full name (e.g., 'Name (OwnerName)') * @return the actions mapped by their full name (e.g., 'Name (OwnerName)')
*/ */
public static Map<String, List<DockingActionIf>> getAllActionsByFullName(DockingTool tool) { public static Map<String, List<DockingActionIf>> getAllActionsByFullName(Tool tool) {
Map<String, List<DockingActionIf>> result = Map<String, List<DockingActionIf>> result =
LazyMap.lazyMap(new HashMap<>(), s -> new LinkedList<>()); LazyMap.lazyMap(new HashMap<>(), s -> new LinkedList<>());
@ -493,7 +493,7 @@ public class KeyBindingUtils {
* @param owner the action owner name * @param owner the action owner name
* @return the actions * @return the actions
*/ */
public static Set<DockingActionIf> getKeyBindingActionsForOwner(DockingTool tool, public static Set<DockingActionIf> getKeyBindingActionsForOwner(Tool tool,
String owner) { String owner) {
Map<String, DockingActionIf> deduper = new HashMap<>(); Map<String, DockingActionIf> deduper = new HashMap<>();

View file

@ -18,13 +18,13 @@ package docking.actions;
import java.util.List; import java.util.List;
import docking.ActionContext; import docking.ActionContext;
import docking.DockingTool; import docking.Tool;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
/** /**
* Provides notification when the popup action menu is displayed. This interface allows * Provides notification when the popup action menu is displayed. This interface allows
* temporary/transient actions (those not registered with the tool via * temporary/transient actions (those not registered with the tool via
* {@link DockingTool#addAction(DockingActionIf)}) to be used in the popup context menu. * {@link Tool#addAction(DockingActionIf)}) to be used in the popup context menu.
* *
* <p> * <p>
* Most clients will register actions directly with the tool. However, clients that have numerous * Most clients will register actions directly with the tool. However, clients that have numerous
@ -32,7 +32,7 @@ import docking.action.DockingActionIf;
* on demand as the popup is about to be shown, and only if their context is active. This * on demand as the popup is about to be shown, and only if their context is active. This
* mechanism can reduce the tool's action management overhead. Once you have created an * mechanism can reduce the tool's action management overhead. Once you have created an
* implementation of this class, you must register it with * implementation of this class, you must register it with
* {@link DockingTool#addPopupActionProvider(PopupActionProvider)}. * {@link Tool#addPopupActionProvider(PopupActionProvider)}.
*/ */
public interface PopupActionProvider { public interface PopupActionProvider {
@ -46,5 +46,5 @@ public interface PopupActionProvider {
* @param context the ActionContext * @param context the ActionContext
* @return list of temporary popup actions; return null if there are no popup actions * @return list of temporary popup actions; return null if there are no popup actions
*/ */
public List<DockingActionIf> getPopupActions(DockingTool tool, ActionContext context); public List<DockingActionIf> getPopupActions(Tool tool, ActionContext context);
} }

View file

@ -15,7 +15,7 @@
*/ */
package docking.actions; package docking.actions;
import docking.DockingTool; import docking.Tool;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.tool.ToolConstants; import docking.tool.ToolConstants;
import docking.widgets.table.GTable; import docking.widgets.table.GTable;
@ -33,7 +33,7 @@ public class SharedActionRegistry {
* @param tool the tool * @param tool the tool
* @param toolActions the tool action manager * @param toolActions the tool action manager
*/ */
public static void installSharedActions(DockingTool tool, ToolActions toolActions) { public static void installSharedActions(Tool tool, ToolActions toolActions) {
GTable.createSharedActions(tool, toolActions, ToolConstants.SHARED_OWNER); GTable.createSharedActions(tool, toolActions, ToolConstants.SHARED_OWNER);
} }
} }

View file

@ -55,7 +55,7 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
private Map<String, SharedStubKeyBindingAction> sharedActionMap = new HashMap<>(); private Map<String, SharedStubKeyBindingAction> sharedActionMap = new HashMap<>();
private ToolOptions keyBindingOptions; private ToolOptions keyBindingOptions;
private DockingTool dockingTool; private Tool dockingTool;
private KeyBindingsManager keyBindingsManager; private KeyBindingsManager keyBindingsManager;
/** /**
@ -64,7 +64,7 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
* @param tool tool using this ActionManager * @param tool tool using this ActionManager
* @param actionToGuiHelper the class that takes actions and maps them to GUI widgets * @param actionToGuiHelper the class that takes actions and maps them to GUI widgets
*/ */
public ToolActions(DockingTool tool, ActionToGuiHelper actionToGuiHelper) { public ToolActions(Tool tool, ActionToGuiHelper actionToGuiHelper) {
this.dockingTool = tool; this.dockingTool = tool;
this.actionGuiHelper = actionToGuiHelper; this.actionGuiHelper = actionToGuiHelper;
this.keyBindingsManager = new KeyBindingsManager(tool); this.keyBindingsManager = new KeyBindingsManager(tool);

View file

@ -1098,7 +1098,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
* @param name the name to match * @param name the name to match
* @return the matching actions; empty list if no matches * @return the matching actions; empty list if no matches
*/ */
public static Set<DockingActionIf> getActionsByName(DockingTool tool, String name) { public static Set<DockingActionIf> getActionsByName(Tool tool, String name) {
Set<DockingActionIf> result = new HashSet<>(); Set<DockingActionIf> result = new HashSet<>();
@ -1119,7 +1119,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
* @param name the owner's name to match * @param name the owner's name to match
* @return the matching actions; empty list if no matches * @return the matching actions; empty list if no matches
*/ */
public static Set<DockingActionIf> getActionsByOwner(DockingTool tool, String name) { public static Set<DockingActionIf> getActionsByOwner(Tool tool, String name) {
return tool.getDockingActionsByOwnerName(name); return tool.getDockingActionsByOwnerName(name);
} }
@ -1132,7 +1132,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
* @param name the owner's name to match * @param name the owner's name to match
* @return the matching actions; empty list if no matches * @return the matching actions; empty list if no matches
*/ */
public static Set<DockingActionIf> getActionsByOwnerAndName(DockingTool tool, String owner, public static Set<DockingActionIf> getActionsByOwnerAndName(Tool tool, String owner,
String name) { String name) {
Set<DockingActionIf> ownerActions = tool.getDockingActionsByOwnerName(owner); Set<DockingActionIf> ownerActions = tool.getDockingActionsByOwnerName(owner);
return ownerActions.stream() return ownerActions.stream()
@ -1143,7 +1143,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
/** /**
* Finds the singular tool action by the given name. If more than one action exists with * Finds the singular tool action by the given name. If more than one action exists with
* that name, then an exception is thrown. If you want more than one matching action, * that name, then an exception is thrown. If you want more than one matching action,
* the call {@link #getActionsByName(DockingTool, String)} instead. * the call {@link #getActionsByName(Tool, String)} instead.
* *
* <P>Note: more specific test case subclasses provide other methods for finding actions * <P>Note: more specific test case subclasses provide other methods for finding actions
* when you have an owner name (which is usually the plugin name). * when you have an owner name (which is usually the plugin name).
@ -1152,7 +1152,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
* @param name the name to match * @param name the name to match
* @return the matching action; null if no matching action can be found * @return the matching action; null if no matching action can be found
*/ */
public static DockingActionIf getAction(DockingTool tool, String name) { public static DockingActionIf getAction(Tool tool, String name) {
Set<DockingActionIf> actions = getActionsByName(tool, name); Set<DockingActionIf> actions = getActionsByName(tool, name);
if (actions.isEmpty()) { if (actions.isEmpty()) {
@ -1169,7 +1169,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
/** /**
* Finds the action by the given owner name and action name. * Finds the action by the given owner name and action name.
* If you do not know the owner name, then use * If you do not know the owner name, then use
* the call {@link #getActionsByName(DockingTool, String)} instead (this will not include * the call {@link #getActionsByName(Tool, String)} instead (this will not include
* reserved system actions). * reserved system actions).
* *
* <P>Note: more specific test case subclasses provide other methods for finding actions * <P>Note: more specific test case subclasses provide other methods for finding actions
@ -1180,7 +1180,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
* @param name the name to match * @param name the name to match
* @return the matching action; null if no matching action can be found * @return the matching action; null if no matching action can be found
*/ */
public static DockingActionIf getAction(DockingTool tool, String owner, String name) { public static DockingActionIf getAction(Tool tool, String owner, String name) {
Set<DockingActionIf> actions = getActionsByOwnerAndName(tool, owner, name); Set<DockingActionIf> actions = getActionsByOwnerAndName(tool, owner, name);
if (actions.isEmpty()) { if (actions.isEmpty()) {
return null; return null;
@ -1203,7 +1203,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
* @return the action * @return the action
*/ */
public static DockingActionIf getLocalAction(ComponentProvider provider, String actionName) { public static DockingActionIf getLocalAction(ComponentProvider provider, String actionName) {
DockingTool tool = provider.getTool(); Tool tool = provider.getTool();
DockingToolActions toolActions = tool.getToolActions(); DockingToolActions toolActions = tool.getToolActions();
DockingActionIf action = toolActions.getLocalAction(provider, actionName); DockingActionIf action = toolActions.getLocalAction(provider, actionName);
return action; return action;
@ -1862,7 +1862,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
* @param name the name of the provider to show * @param name the name of the provider to show
* @return the newly shown provider * @return the newly shown provider
*/ */
public ComponentProvider showProvider(DockingTool tool, String name) { public ComponentProvider showProvider(Tool tool, String name) {
ComponentProvider provider = tool.getComponentProvider(name); ComponentProvider provider = tool.getComponentProvider(name);
tool.showComponentProvider(provider, true); tool.showComponentProvider(provider, true);
return provider; return provider;
@ -1870,7 +1870,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
/** /**
* Closes the given provider. You could just call * Closes the given provider. You could just call
* {@link DockingTool#removeComponentProvider(ComponentProvider)}, but some providers have extra * {@link Tool#removeComponentProvider(ComponentProvider)}, but some providers have extra
* logic that happens when {@link ComponentProvider#closeComponent()} is called. This will * logic that happens when {@link ComponentProvider#closeComponent()} is called. This will
* likely change in the future. * likely change in the future.
* *

View file

@ -15,10 +15,10 @@
*/ */
package docking.tool.util; package docking.tool.util;
import docking.DockingTool; import docking.Tool;
/** /**
* An interface to house constants used by the {@link DockingTool} * An interface to house constants used by the {@link Tool}
*/ */
public interface DockingToolConstants { public interface DockingToolConstants {

View file

@ -1203,7 +1203,7 @@ public class GTable extends JTable {
GTableToCSV.writeCSVUsingColunns(file, GTable.this, columnList); GTableToCSV.writeCSVUsingColunns(file, GTable.this, columnList);
} }
public static void createSharedActions(DockingTool tool, ToolActions toolActions, public static void createSharedActions(Tool tool, ToolActions toolActions,
String owner) { String owner) {
String actionMenuGroup = "zzzTableGroup"; String actionMenuGroup = "zzzTableGroup";

View file

@ -54,7 +54,7 @@ public class SharedKeyBindingDockingActionTest extends AbstractDockingTest {
private SpyErrorLogger spyLogger = new SpyErrorLogger(); private SpyErrorLogger spyLogger = new SpyErrorLogger();
private DockingTool tool; private Tool tool;
@Before @Before
public void setUp() { public void setUp() {

View file

@ -26,7 +26,7 @@ import ghidra.framework.options.ToolOptions;
import ghidra.framework.plugintool.util.ServiceListener; import ghidra.framework.plugintool.util.ServiceListener;
/** /**
* A Test Double of the {@link DockingTool} that provides minimal tool functionality, such * A Test Double of the {@link Tool} that provides minimal tool functionality, such
* as the {@link DockingWindowManager} * as the {@link DockingWindowManager}
*/ */
public class FakeDockingTool extends AbstractDockingTool { public class FakeDockingTool extends AbstractDockingTool {

View file

@ -59,11 +59,11 @@ public abstract class VisualGraphComponentProvider<V extends VisualVertex,
private List<VisualGraphFeaturette<V, E, G>> subFeatures = new ArrayList<>(); private List<VisualGraphFeaturette<V, E, G>> subFeatures = new ArrayList<>();
protected VisualGraphComponentProvider(DockingTool tool, String name, String owner) { protected VisualGraphComponentProvider(Tool tool, String name, String owner) {
super(tool, name, owner); super(tool, name, owner);
} }
protected VisualGraphComponentProvider(DockingTool tool, String name, String owner, protected VisualGraphComponentProvider(Tool tool, String name, String owner,
Class<?> contextType) { Class<?> contextType) {
super(tool, name, owner, contextType); super(tool, name, owner, contextType);
} }

View file

@ -60,7 +60,7 @@ public class VgSatelliteFeaturette<V extends VisualVertex,
private ToggleDockingAction toggleSatelliteAction; private ToggleDockingAction toggleSatelliteAction;
private ToggleDockingAction dockSatelliteAction; private ToggleDockingAction dockSatelliteAction;
private DockingTool tool; private Tool tool;
private VisualGraphView<?, ?, ?> view; private VisualGraphView<?, ?, ?> view;
private String owner; private String owner;
private String providerName; private String providerName;
@ -229,7 +229,7 @@ public class VgSatelliteFeaturette<V extends VisualVertex,
private JComponent satelliteComponent; private JComponent satelliteComponent;
public VgUndockedSatelliteProvider(DockingTool tool, JComponent component, String name, public VgUndockedSatelliteProvider(Tool tool, JComponent component, String name,
String owner, String windowGroup) { String owner, String windowGroup) {
super(tool, name, owner); super(tool, name, owner);

View file

@ -185,7 +185,7 @@ public class VisualGraphComponentProviderTest extends AbstractVisualGraphTest {
} }
private void setSatelliteVisible(boolean visible) { private void setSatelliteVisible(boolean visible) {
DockingTool tool = provider.getTool(); Tool tool = provider.getTool();
String name = "Display Satellite View"; String name = "Display Satellite View";
DockingActionIf action = getAction(tool, name); DockingActionIf action = getAction(tool, name);
assertNotNull(name + " not in tool", action); assertNotNull(name + " not in tool", action);
@ -195,7 +195,7 @@ public class VisualGraphComponentProviderTest extends AbstractVisualGraphTest {
} }
private void setSatelliteDocked(boolean docked) { private void setSatelliteDocked(boolean docked) {
DockingTool tool = provider.getTool(); Tool tool = provider.getTool();
String name = "Dock Satellite View"; String name = "Dock Satellite View";
DockingActionIf action = getAction(tool, name); DockingActionIf action = getAction(tool, name);
assertNotNull(name + " not in tool", action); assertNotNull(name + " not in tool", action);
@ -216,7 +216,7 @@ public class VisualGraphComponentProviderTest extends AbstractVisualGraphTest {
private JComponent component; private JComponent component;
protected TestProvider(DockingTool tool) { protected TestProvider(Tool tool) {
super(tool, "Test VG Provider", "Test Owner"); super(tool, "Test VG Provider", "Test Owner");
component = new JPanel(); component = new JPanel();

View file

@ -33,6 +33,7 @@ import ghidra.framework.client.ClientUtil;
import ghidra.framework.client.RepositoryAdapter; import ghidra.framework.client.RepositoryAdapter;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.options.SaveState; import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.store.LockException; import ghidra.framework.store.LockException;
import ghidra.util.*; import ghidra.util.*;
import ghidra.util.exception.NotFoundException; import ghidra.util.exception.NotFoundException;
@ -274,6 +275,8 @@ class FileActionManager {
/** /**
* Opens the given project in a task that will show a dialog to block input while opening * Opens the given project in a task that will show a dialog to block input while opening
* the project in the swing thread. * the project in the swing thread.
* @param projectLocator the project locator
* @return true if the project was opened
*/ */
final boolean openProject(ProjectLocator projectLocator) { final boolean openProject(ProjectLocator projectLocator) {
OpenTaskRunnable openRunnable = new OpenTaskRunnable(projectLocator); OpenTaskRunnable openRunnable = new OpenTaskRunnable(projectLocator);
@ -285,6 +288,8 @@ class FileActionManager {
/** /**
* Open an existing project, using a file chooser to specify where the * Open an existing project, using a file chooser to specify where the
* existing project folder is stored. * existing project folder is stored.
* @param projectLocator the project locator
* @return true if the project was opened
*/ */
final boolean doOpenProject(ProjectLocator projectLocator) { final boolean doOpenProject(ProjectLocator projectLocator) {
String status = "Opened project: " + projectLocator.getName(); String status = "Opened project: " + projectLocator.getName();
@ -346,7 +351,7 @@ class FileActionManager {
/** /**
* Obtain domain objects from files and lock. If unable to lock * Obtain domain objects from files and lock. If unable to lock
* one or more of the files, none are locked and null is returned. * one or more of the files, none are locked and null is returned.
* @param files * @param files the files
* @return locked domain objects, or null if unable to lock * @return locked domain objects, or null if unable to lock
* all domain objects. * all domain objects.
*/ */
@ -414,8 +419,6 @@ class FileActionManager {
* This method will always save the FrontEndTool and project, but not the data unless * This method will always save the FrontEndTool and project, but not the data unless
* <tt>confirmClose</tt> is called. * <tt>confirmClose</tt> is called.
* *
* @param confirmClose true if the confirmation dialog should be
* displayed
* @param isExiting true if we are closing the project because * @param isExiting true if we are closing the project because
* Ghidra is exiting * Ghidra is exiting
* @return false if user cancels the close operation * @return false if user cancels the close operation
@ -428,9 +431,9 @@ class FileActionManager {
} }
// check for any changes since last saved // check for any changes since last saved
Tool[] runningTools = activeProject.getToolManager().getRunningTools(); PluginTool[] runningTools = activeProject.getToolManager().getRunningTools();
for (int i = 0; i < runningTools.length; i++) { for (PluginTool runningTool : runningTools) {
if (!runningTools[i].canClose(isExiting)) { if (!runningTool.canClose(isExiting)) {
return false; return false;
} }
} }
@ -655,7 +658,7 @@ class FileActionManager {
/** /**
* Checks the list for read-only files; if any are found, pops up * Checks the list for read-only files; if any are found, pops up
* a dialog for whether to save now or lose changes. * a dialog for whether to save now or lose changes.
* @param files list of files which correspond to modified * @param objs list of files which correspond to modified
* domain objects. * domain objects.
* @return true if there are no read only files OR if the user * @return true if there are no read only files OR if the user
* wants to lose his changes; false if the user wants to save the * wants to lose his changes; false if the user wants to save the

View file

@ -660,9 +660,9 @@ public class FrontEndPlugin extends Plugin
private ToolTemplate getUpToDateTemplate(ToolTemplate template) { private ToolTemplate getUpToDateTemplate(ToolTemplate template) {
ToolManager toolManager = activeProject.getToolManager(); ToolManager toolManager = activeProject.getToolManager();
Tool[] runningTools = toolManager.getRunningTools(); PluginTool[] runningTools = toolManager.getRunningTools();
String templateName = template.getName(); String templateName = template.getName();
for (Tool runningTool : runningTools) { for (PluginTool runningTool : runningTools) {
if (runningTool.getName().equals(templateName)) { if (runningTool.getName().equals(templateName)) {
return runningTool.getToolTemplate(true); return runningTool.getToolTemplate(true);
} }
@ -960,8 +960,8 @@ public class FrontEndPlugin extends Plugin
private boolean isToolRunning(ToolTemplate template) { private boolean isToolRunning(ToolTemplate template) {
ToolManager toolManager = activeProject.getToolManager(); ToolManager toolManager = activeProject.getToolManager();
Tool[] runningTools = toolManager.getRunningTools(); PluginTool[] runningTools = toolManager.getRunningTools();
for (Tool runningTool : runningTools) { for (PluginTool runningTool : runningTools) {
if (runningTool.getToolName().equals(template.getName())) { if (runningTool.getToolName().equals(template.getName())) {
return true; return true;
} }

View file

@ -745,8 +745,8 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
@Override @Override
public boolean canCloseDomainFile(DomainFile df) { public boolean canCloseDomainFile(DomainFile df) {
Tool[] tools = getProject().getToolManager().getRunningTools(); PluginTool[] tools = getProject().getToolManager().getRunningTools();
for (Tool tool : tools) { for (PluginTool tool : tools) {
DomainFile[] files = tool.getDomainFiles(); DomainFile[] files = tool.getDomainFiles();
for (DomainFile domainFile : files) { for (DomainFile domainFile : files) {
if (df == domainFile) { if (df == domainFile) {

View file

@ -34,6 +34,7 @@ import ghidra.app.util.GenericHelpTopics;
import ghidra.framework.client.*; import ghidra.framework.client.*;
import ghidra.framework.data.ConvertFileSystem; import ghidra.framework.data.ConvertFileSystem;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.remote.User; import ghidra.framework.remote.User;
import ghidra.framework.store.local.*; import ghidra.framework.store.local.*;
import ghidra.util.*; import ghidra.util.*;
@ -456,10 +457,10 @@ public class ProjectInfoDialog extends DialogComponentProvider {
} }
private boolean filesAreOpen() { private boolean filesAreOpen() {
Tool[] tools = project.getToolManager().getRunningTools(); PluginTool[] tools = project.getToolManager().getRunningTools();
if (tools.length > 0) { if (tools.length > 0) {
for (Tool tool : tools) { for (PluginTool tool : tools) {
if (tool.getDomainFiles().length > 0) { if (tool.getDomainFiles().length > 0) {
return true; return true;
} }

View file

@ -23,12 +23,14 @@ import java.util.Map;
import javax.swing.*; import javax.swing.*;
import docking.DockingUtils; import docking.DockingUtils;
import ghidra.framework.model.*; import ghidra.framework.model.ToolTemplate;
import ghidra.framework.model.Workspace;
import ghidra.framework.plugintool.PluginTool;
class RunningToolsPanel extends JPanel { class RunningToolsPanel extends JPanel {
private JToolBar runningToolbar; private JToolBar runningToolbar;
private FrontEndPlugin plugin; private FrontEndPlugin plugin;
private Map<Tool, ToolButton> runningTools; private Map<PluginTool, ToolButton> runningTools;
RunningToolsPanel(FrontEndPlugin plugin, Workspace ws) { RunningToolsPanel(FrontEndPlugin plugin, Workspace ws) {
super(new BorderLayout(0, 0)); super(new BorderLayout(0, 0));
@ -55,12 +57,13 @@ class RunningToolsPanel extends JPanel {
// remove the default etched border // remove the default etched border
add(runningToolbar, BorderLayout.CENTER); add(runningToolbar, BorderLayout.CENTER);
runningTools = new HashMap<Tool, ToolButton>(WorkspacePanel.TYPICAL_NUM_RUNNING_TOOLS); runningTools =
new HashMap<PluginTool, ToolButton>(WorkspacePanel.TYPICAL_NUM_RUNNING_TOOLS);
// populate the toolbar if the workspace has running tools // populate the toolbar if the workspace has running tools
if (ws != null) { if (ws != null) {
Tool[] tools = ws.getTools(); PluginTool[] tools = ws.getTools();
for (Tool element : tools) { for (PluginTool element : tools) {
addTool(element); addTool(element);
} }
} }
@ -73,7 +76,7 @@ class RunningToolsPanel extends JPanel {
return runningToolbar.getPreferredSize(); return runningToolbar.getPreferredSize();
} }
void addTool(Tool runningTool) { void addTool(PluginTool runningTool) {
ToolButton toolButton = ToolButton toolButton =
new ToolButton(plugin, runningTool, runningTool.getToolTemplate(true)); new ToolButton(plugin, runningTool, runningTool.getToolTemplate(true));
runningToolbar.add(toolButton); runningToolbar.add(toolButton);
@ -83,7 +86,7 @@ class RunningToolsPanel extends JPanel {
repaint(); repaint();
} }
void removeTool(Tool tool) { void removeTool(PluginTool tool) {
ToolButton button = runningTools.get(tool); ToolButton button = runningTools.get(tool);
if (button == null) { if (button == null) {
return; return;
@ -97,13 +100,13 @@ class RunningToolsPanel extends JPanel {
} }
// parameter not used // parameter not used
void toolNameChanged(Tool changedTool) { void toolNameChanged(PluginTool changedTool) {
} }
/** /**
* Update the tool template for the tool button. * Update the tool template for the tool button.
*/ */
void updateToolButton(Tool tool, ToolTemplate template, Icon icon) { void updateToolButton(PluginTool tool, ToolTemplate template, Icon icon) {
ToolButton button = runningTools.get(tool); ToolButton button = runningTools.get(tool);
if (button != null) { if (button != null) {

View file

@ -307,7 +307,7 @@ class ToolActionManager implements ToolChestChangeListener {
} }
// only enable if project has more than 1 running tool // only enable if project has more than 1 running tool
ToolManager tm = project.getToolManager(); ToolManager tm = project.getToolManager();
Tool[] runningTools = tm.getRunningTools(); PluginTool[] runningTools = tm.getRunningTools();
connectToolsAction.setEnabled(runningTools.length > 1); connectToolsAction.setEnabled(runningTools.length > 1);
} }

View file

@ -65,7 +65,7 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
private FrontEndPlugin plugin; private FrontEndPlugin plugin;
private ToolTemplate template; private ToolTemplate template;
private Tool associatedRunningTool; private PluginTool associatedRunningTool;
private DefaultToolChangeListener toolChangeListener; private DefaultToolChangeListener toolChangeListener;
private ToolServices toolServices; private ToolServices toolServices;
@ -83,7 +83,7 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
* Construct a tool label that represents a running tool, using the * Construct a tool label that represents a running tool, using the
* default RUNNING_TOOL icon. * default RUNNING_TOOL icon.
*/ */
ToolButton(FrontEndPlugin plugin, Tool tool, ToolTemplate template) { ToolButton(FrontEndPlugin plugin, PluginTool tool, ToolTemplate template) {
this(plugin, tool, template, tool.getIconURL()); this(plugin, tool, template, tool.getIconURL());
setHelpLocation("Run_Tool"); setHelpLocation("Run_Tool");
} }
@ -91,7 +91,7 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
/** /**
* Construct a tool label that represents a running tool. * Construct a tool label that represents a running tool.
*/ */
private ToolButton(FrontEndPlugin plugin, Tool tool, ToolTemplate template, private ToolButton(FrontEndPlugin plugin, PluginTool tool, ToolTemplate template,
ToolIconURL iconURL) { ToolIconURL iconURL) {
super(iconURL.getIcon()); super(iconURL.getIcon());
this.plugin = plugin; this.plugin = plugin;
@ -298,9 +298,9 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
private void addFromToolButton(ToolButton toolButton) { private void addFromToolButton(ToolButton toolButton) {
plugin.setToolButtonTransferable(null); plugin.setToolButtonTransferable(null);
Tool tool = null; PluginTool tool = null;
if (associatedRunningTool != null && toolButton.associatedRunningTool != null) { if (associatedRunningTool != null && toolButton.associatedRunningTool != null) {
final Tool t2 = toolButton.associatedRunningTool; final PluginTool t2 = toolButton.associatedRunningTool;
SwingUtilities.invokeLater(() -> connectTools(associatedRunningTool, t2)); SwingUtilities.invokeLater(() -> connectTools(associatedRunningTool, t2));
return; return;
} }
@ -309,14 +309,14 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
if (toolButton.associatedRunningTool == null) { if (toolButton.associatedRunningTool == null) {
tool = plugin.getActiveWorkspace().runTool(toolButton.template); tool = plugin.getActiveWorkspace().runTool(toolButton.template);
accepted = tool.acceptDomainFiles(associatedRunningTool.getDomainFiles()); accepted = tool.acceptDomainFiles(associatedRunningTool.getDomainFiles());
final Tool t = tool; final PluginTool t = tool;
SwingUtilities.invokeLater(() -> connectTools(t, associatedRunningTool)); SwingUtilities.invokeLater(() -> connectTools(t, associatedRunningTool));
} }
else { else {
tool = plugin.getActiveWorkspace().runTool(template); tool = plugin.getActiveWorkspace().runTool(template);
accepted = tool.acceptDomainFiles(toolButton.associatedRunningTool.getDomainFiles()); accepted = tool.acceptDomainFiles(toolButton.associatedRunningTool.getDomainFiles());
final Tool t = tool; final PluginTool t = tool;
final Tool t2 = toolButton.associatedRunningTool; final PluginTool t2 = toolButton.associatedRunningTool;
SwingUtilities.invokeLater(() -> connectTools(t, t2)); SwingUtilities.invokeLater(() -> connectTools(t, t2));
} }
@ -328,7 +328,7 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
/** /**
* Connect the tools in both directions. * Connect the tools in both directions.
*/ */
private void connectTools(Tool t1, Tool t2) { private void connectTools(PluginTool t1, PluginTool t2) {
ToolManager tm = plugin.getActiveProject().getToolManager(); ToolManager tm = plugin.getActiveProject().getToolManager();
ToolConnection tc = tm.getConnection(t1, t2); ToolConnection tc = tm.getConnection(t1, t2);
connectAll(tc); connectAll(tc);
@ -514,7 +514,7 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
associatedRunningTool.close(); associatedRunningTool.close();
} }
Tool getRunningTool() { PluginTool getRunningTool() {
return associatedRunningTool; return associatedRunningTool;
} }
@ -570,7 +570,7 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
Msg.debug(this, "Found root frame without a GhidraGlassPane registered!"); Msg.debug(this, "Found root frame without a GhidraGlassPane registered!");
// try to recover without animation // try to recover without animation
Tool newTool = plugin.getActiveWorkspace().runTool(template); PluginTool newTool = plugin.getActiveWorkspace().runTool(template);
openDomainFiles(newTool, domainFiles); openDomainFiles(newTool, domainFiles);
finishedCallback.run(); finishedCallback.run();
return; return;
@ -621,7 +621,7 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
try { try {
// cleanup any residual painting effects // cleanup any residual painting effects
toolGlassPane.paintImmediately(toolGlassPane.getBounds()); toolGlassPane.paintImmediately(toolGlassPane.getBounds());
Tool newTool = plugin.getActiveWorkspace().runTool(template); PluginTool newTool = plugin.getActiveWorkspace().runTool(template);
openDomainFiles(newTool, domainFiles); openDomainFiles(newTool, domainFiles);
} }
finally { finally {
@ -640,7 +640,7 @@ class ToolButton extends EmptyBorderButton implements Draggable, Droppable {
zoomRunner.run(); zoomRunner.run();
} }
private void openDomainFiles(Tool tool, DomainFile[] domainFiles) { private void openDomainFiles(PluginTool tool, DomainFile[] domainFiles) {
if (domainFiles == null) { if (domainFiles == null) {
return; return;
} }

View file

@ -23,6 +23,7 @@ import javax.swing.JPanel;
import docking.DialogComponentProvider; import docking.DialogComponentProvider;
import ghidra.app.util.GenericHelpTopics; import ghidra.app.util.GenericHelpTopics;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
/** /**
@ -39,9 +40,6 @@ class ToolConnectionDialog extends DialogComponentProvider implements WorkspaceC
private JButton connectAllButton; private JButton connectAllButton;
private JButton disconnectAllButton; private JButton disconnectAllButton;
/**
* Constructor
*/
ToolConnectionDialog(FrontEndTool tool, ToolManager toolManager) { ToolConnectionDialog(FrontEndTool tool, ToolManager toolManager) {
super("Connect Tools", false); super("Connect Tools", false);
this.frontEndTool = tool; this.frontEndTool = tool;
@ -59,9 +57,6 @@ class ToolConnectionDialog extends DialogComponentProvider implements WorkspaceC
toolManager.addWorkspaceChangeListener(this); toolManager.addWorkspaceChangeListener(this);
} }
/**
* Set the dialog to be visible according to the v param.
*/
void setVisible(boolean v) { void setVisible(boolean v) {
if (v) { if (v) {
@ -79,27 +74,16 @@ class ToolConnectionDialog extends DialogComponentProvider implements WorkspaceC
} }
} }
// WorkspaceChangedListener
/**
* Tool was added to the given workspace.
*/
@Override @Override
public void toolAdded(Workspace ws, Tool tool) { public void toolAdded(Workspace ws, PluginTool tool) {
panel.toolAdded(tool); panel.toolAdded(tool);
} }
/**
* Tool was removed from the given workspace.
*/
@Override @Override
public void toolRemoved(Workspace ws, Tool tool) { public void toolRemoved(Workspace ws, PluginTool tool) {
panel.toolRemoved(tool); panel.toolRemoved(tool);
} }
/*
* (non-Javadoc)
* @see ghidra.util.bean.GhidraDialog#okCallback()
*/
@Override @Override
protected void okCallback() { protected void okCallback() {
setVisible(false); setVisible(false);
@ -117,23 +101,15 @@ class ToolConnectionDialog extends DialogComponentProvider implements WorkspaceC
public void workspaceSetActive(Workspace ws) { public void workspaceSetActive(Workspace ws) {
} }
/**
* Property change on the workspace.
*/
@Override @Override
public void propertyChange(PropertyChangeEvent event) { public void propertyChange(PropertyChangeEvent event) {
Object eventSource = event.getSource(); Object eventSource = event.getSource();
if (eventSource instanceof Tool) { if (eventSource instanceof PluginTool) {
// tool name might have changed // tool name might have changed
updateDisplay(); updateDisplay();
} }
} }
///////////////////////////////////////////////////////////////////
/**
* Update the tool manager object.
*/
void setToolManager(ToolManager tm) { void setToolManager(ToolManager tm) {
toolManager.removeWorkspaceChangeListener(this); toolManager.removeWorkspaceChangeListener(this);
toolManager = tm; toolManager = tm;

View file

@ -27,7 +27,9 @@ import javax.swing.event.ListSelectionListener;
import docking.widgets.checkbox.GCheckBox; import docking.widgets.checkbox.GCheckBox;
import docking.widgets.label.GDLabel; import docking.widgets.label.GDLabel;
import docking.widgets.list.GListCellRenderer; import docking.widgets.list.GListCellRenderer;
import ghidra.framework.model.*; import ghidra.framework.model.ToolConnection;
import ghidra.framework.model.ToolManager;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.Msg; import ghidra.util.Msg;
/** /**
@ -41,20 +43,16 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener {
private ToolConnectionDialog toolDialog; private ToolConnectionDialog toolDialog;
private ToolManager toolManager; private ToolManager toolManager;
private JList<Tool> consumerList; // list of receiver tools private JList<PluginTool> consumerList; // list of receiver tools
private JList<Tool> producerList; // list of source (of events) private JList<PluginTool> producerList; // list of source (of events)
private JList<JCheckBox> eventList; // names of events generated by source private JList<JCheckBox> eventList; // names of events generated by source
private DefaultListModel<Tool> producerModel; private DefaultListModel<PluginTool> producerModel;
private DefaultListModel<Tool> consumerModel; private DefaultListModel<PluginTool> consumerModel;
private GCheckBox[] checkboxes; private GCheckBox[] checkboxes;
private String[] eventNames; private String[] eventNames;
private final static String msgSource = "Tool Connection"; private final static String msgSource = "Tool Connection";
/**
* Constructor
* @param myTool plugin tool associated with this connect panel
*/
ToolConnectionPanel(ToolConnectionDialog toolDialog, ToolManager toolManager) { ToolConnectionPanel(ToolConnectionDialog toolDialog, ToolManager toolManager) {
super(); super();
this.toolDialog = toolDialog; this.toolDialog = toolDialog;
@ -62,9 +60,6 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener {
initialize(); initialize();
} }
/**
* ListSelectionListener method to process selection events.
*/
@Override @Override
public void valueChanged(ListSelectionEvent e) { public void valueChanged(ListSelectionEvent e) {
toolDialog.setStatusText(""); toolDialog.setStatusText("");
@ -77,9 +72,6 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener {
processSelection(); processSelection();
} }
/**
* Set the tool manager; need to do this if another project is opened.
*/
void setToolManager(ToolManager toolManager) { void setToolManager(ToolManager toolManager) {
this.toolManager = toolManager; this.toolManager = toolManager;
updateDisplay(); updateDisplay();
@ -91,8 +83,8 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener {
* added or removed. * added or removed.
*/ */
void updateDisplay() { void updateDisplay() {
Tool producer = producerList.getSelectedValue(); PluginTool producer = producerList.getSelectedValue();
Tool consumer = consumerList.getSelectedValue(); PluginTool consumer = consumerList.getSelectedValue();
showData(); showData();
@ -138,7 +130,7 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener {
* Tool was added to the workspace; update the display. * Tool was added to the workspace; update the display.
* @param tool tool added * @param tool tool added
*/ */
void toolAdded(Tool tool) { void toolAdded(PluginTool tool) {
String[] consumedEvents = tool.getConsumedToolEventNames(); String[] consumedEvents = tool.getConsumedToolEventNames();
String[] producedEvents = tool.getToolEventNames(); String[] producedEvents = tool.getToolEventNames();
if (consumedEvents.length > 0) { if (consumedEvents.length > 0) {
@ -154,7 +146,7 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener {
* Tool was removed from a workspace; update the display. * Tool was removed from a workspace; update the display.
* @param tool tool removed * @param tool tool removed
*/ */
void toolRemoved(Tool tool) { void toolRemoved(PluginTool tool) {
int index = producerModel.indexOf(tool); int index = producerModel.indexOf(tool);
if (index >= 0) { if (index >= 0) {
producerModel.remove(index); producerModel.remove(index);
@ -167,13 +159,10 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener {
validate(); validate();
} }
/**
* Interconnect two producers and consumers
*/
void connectAll(boolean connect) { void connectAll(boolean connect) {
Tool producer = producerList.getSelectedValue(); PluginTool producer = producerList.getSelectedValue();
Tool consumer = consumerList.getSelectedValue(); PluginTool consumer = consumerList.getSelectedValue();
// clear the event list // clear the event list
eventList.setModel(new DefaultListModel<>()); eventList.setModel(new DefaultListModel<>());
@ -237,8 +226,8 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener {
GListCellRenderer.createDefaultCellTextRenderer(tool -> tool.getName())); GListCellRenderer.createDefaultCellTextRenderer(tool -> tool.getName()));
consumerList.setCellRenderer( consumerList.setCellRenderer(
GListCellRenderer.createDefaultCellTextRenderer(tool -> tool.getName())); GListCellRenderer.createDefaultCellTextRenderer(tool -> tool.getName()));
producerModel = (DefaultListModel<Tool>) producerList.getModel(); producerModel = (DefaultListModel<PluginTool>) producerList.getModel();
consumerModel = (DefaultListModel<Tool>) consumerList.getModel(); consumerModel = (DefaultListModel<PluginTool>) consumerList.getModel();
} }
private void processMouseClicked(MouseEvent e) { private void processMouseClicked(MouseEvent e) {
@ -256,8 +245,8 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener {
checkboxes[index].setSelected(!selected); checkboxes[index].setSelected(!selected);
refreshList(checkboxes); refreshList(checkboxes);
Tool producer = producerList.getSelectedValue(); PluginTool producer = producerList.getSelectedValue();
Tool consumer = consumerList.getSelectedValue(); PluginTool consumer = consumerList.getSelectedValue();
doConnect(producer, consumer, eventNames[index], !selected); doConnect(producer, consumer, eventNames[index], !selected);
int connectedCount = 0; int connectedCount = 0;
@ -270,7 +259,8 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener {
} }
} }
private void doConnect(Tool producer, Tool consumer, String eventName, boolean connect) { private void doConnect(PluginTool producer, PluginTool consumer, String eventName,
boolean connect) {
ToolConnection tc = toolManager.getConnection(producer, consumer); ToolConnection tc = toolManager.getConnection(producer, consumer);
if (tc.isConnected(eventName) == connect) { if (tc.isConnected(eventName) == connect) {
// if already connected // if already connected
@ -292,13 +282,13 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener {
private void populateConsumerList() { private void populateConsumerList() {
consumerModel.removeAllElements(); consumerModel.removeAllElements();
Tool[] tools = toolManager.getConsumerTools(); PluginTool[] tools = toolManager.getConsumerTools();
Arrays.sort(tools, (t1, t2) -> { Arrays.sort(tools, (t1, t2) -> {
return t1.getName().compareTo(t2.getName()); return t1.getName().compareTo(t2.getName());
}); });
for (Tool tool : tools) { for (PluginTool tool : tools) {
consumerModel.addElement(tool); consumerModel.addElement(tool);
} }
if (tools.length == 0) { if (tools.length == 0) {
@ -309,13 +299,13 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener {
private void populateProducerList() { private void populateProducerList() {
producerModel.removeAllElements(); producerModel.removeAllElements();
Tool[] tools = toolManager.getProducerTools(); PluginTool[] tools = toolManager.getProducerTools();
Arrays.sort(tools, (t1, t2) -> { Arrays.sort(tools, (t1, t2) -> {
return t1.getName().compareTo(t2.getName()); return t1.getName().compareTo(t2.getName());
}); });
for (Tool tool : tools) { for (PluginTool tool : tools) {
producerModel.addElement(tool); producerModel.addElement(tool);
} }
if (tools.length == 0) { if (tools.length == 0) {
@ -327,13 +317,13 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener {
// clear the event list // clear the event list
eventList.setModel(new DefaultListModel<>()); eventList.setModel(new DefaultListModel<>());
Tool producer = producerList.getSelectedValue(); PluginTool producer = producerList.getSelectedValue();
if (producer == null) { if (producer == null) {
toolDialog.setStatusText("Please select an Event Producer"); toolDialog.setStatusText("Please select an Event Producer");
return; return;
} }
Tool consumer = consumerList.getSelectedValue(); PluginTool consumer = consumerList.getSelectedValue();
if (consumer == null) { if (consumer == null) {
toolDialog.setStatusText("Please select an Event Consumer"); toolDialog.setStatusText("Please select an Event Consumer");
return; return;

View file

@ -28,6 +28,7 @@ import docking.help.HelpService;
import docking.widgets.combobox.GComboBox; import docking.widgets.combobox.GComboBox;
import docking.widgets.dialogs.InputDialog; import docking.widgets.dialogs.InputDialog;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
@ -87,7 +88,7 @@ class WorkspacePanel extends JPanel implements WorkspaceChangeListener {
* Tool was removed from the given workspace. * Tool was removed from the given workspace.
*/ */
@Override @Override
public void toolRemoved(Workspace ws, Tool tool) { public void toolRemoved(Workspace ws, PluginTool tool) {
removeTool(ws.getName(), tool); removeTool(ws.getName(), tool);
plugin.getToolActionManager().enableConnectTools(); plugin.getToolActionManager().enableConnectTools();
} }
@ -96,7 +97,7 @@ class WorkspacePanel extends JPanel implements WorkspaceChangeListener {
* Tool was added to the given workspace. * Tool was added to the given workspace.
*/ */
@Override @Override
public void toolAdded(Workspace ws, Tool tool) { public void toolAdded(Workspace ws, PluginTool tool) {
addTool(ws.getName(), tool); addTool(ws.getName(), tool);
plugin.getToolActionManager().enableConnectTools(); plugin.getToolActionManager().enableConnectTools();
} }
@ -192,13 +193,13 @@ class WorkspacePanel extends JPanel implements WorkspaceChangeListener {
// if this is a change in a tool, update the running tools panel // if this is a change in a tool, update the running tools panel
// containing the tool // containing the tool
Object eventSource = event.getSource(); Object eventSource = event.getSource();
if (eventSource instanceof Tool) { if (eventSource instanceof PluginTool) {
Tool tool = (Tool) eventSource; PluginTool tool = (PluginTool) eventSource;
ToolTemplate template = tool.getToolTemplate(true); ToolTemplate template = tool.getToolTemplate(true);
Icon icon = tool.getIconURL().getIcon(); Icon icon = tool.getIconURL().getIcon();
String workspaceName = activeWorkspace.getName(); String workspaceName = activeWorkspace.getName();
RunningToolsPanel rtp = runningToolsMap.get(workspaceName); RunningToolsPanel rtp = runningToolsMap.get(workspaceName);
if (eventPropertyName.equals(Tool.TOOL_NAME_PROPERTY)) { if (eventPropertyName.equals(PluginTool.TOOL_NAME_PROPERTY)) {
rtp.toolNameChanged(tool); rtp.toolNameChanged(tool);
} }
else { else {
@ -210,6 +211,7 @@ class WorkspacePanel extends JPanel implements WorkspaceChangeListener {
/** /**
* called whenever the active project changes or is being set for * called whenever the active project changes or is being set for
* the first time * the first time
* @param project the project
*/ */
void setActiveProject(Project project) { void setActiveProject(Project project) {
// clear state from previous project // clear state from previous project
@ -233,8 +235,8 @@ class WorkspacePanel extends JPanel implements WorkspaceChangeListener {
ToolManager toolManager = project.getToolManager(); ToolManager toolManager = project.getToolManager();
toolManager.addWorkspaceChangeListener(this); toolManager.addWorkspaceChangeListener(this);
Tool[] tools = toolManager.getRunningTools(); PluginTool[] tools = toolManager.getRunningTools();
for (Tool tool : tools) { for (PluginTool tool : tools) {
tool.addPropertyChangeListener(this); tool.addPropertyChangeListener(this);
} }
@ -247,10 +249,7 @@ class WorkspacePanel extends JPanel implements WorkspaceChangeListener {
initProjectState(activeProject); initProjectState(activeProject);
} }
/** void addTool(String workspaceName, PluginTool runningTool) {
* add a running tool to the panel
*/
void addTool(String workspaceName, Tool runningTool) {
RunningToolsPanel rtp = runningToolsMap.get(workspaceName); RunningToolsPanel rtp = runningToolsMap.get(workspaceName);
if (rtp != null) { if (rtp != null) {
rtp.addTool(runningTool); rtp.addTool(runningTool);
@ -418,8 +417,9 @@ class WorkspacePanel extends JPanel implements WorkspaceChangeListener {
} }
/** /**
* cause the specified workspace to be the active one * Cause the specified workspace to be the active one
* NOTE: this workspace must already be known to the ToolManager * NOTE: this workspace must already be known to the ToolManager
* @param ws the workspace
*/ */
void setActiveWorkspace(Workspace ws) { void setActiveWorkspace(Workspace ws) {
chooseWorkspace(ws.getName()); chooseWorkspace(ws.getName());
@ -452,7 +452,7 @@ class WorkspacePanel extends JPanel implements WorkspaceChangeListener {
setBorder(INACTIVE_BORDER); setBorder(INACTIVE_BORDER);
} }
private void removeTool(String workspaceName, Tool tool) { private void removeTool(String workspaceName, PluginTool tool) {
RunningToolsPanel rtp = runningToolsMap.get(workspaceName); RunningToolsPanel rtp = runningToolsMap.get(workspaceName);
if (rtp != null) { if (rtp != null) {
rtp.removeTool(tool); rtp.removeTool(tool);

View file

@ -24,6 +24,7 @@ import ghidra.framework.main.AppInfo;
import ghidra.framework.main.datatable.ProjectDataActionContext; import ghidra.framework.main.datatable.ProjectDataActionContext;
import ghidra.framework.main.datatable.ProjectDataContextAction; import ghidra.framework.main.datatable.ProjectDataContextAction;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.HTMLUtilities; import ghidra.util.HTMLUtilities;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
@ -58,7 +59,7 @@ public class ProjectDataOpenToolAction extends ProjectDataContextAction {
Workspace activeWorkspace = toolManager.getActiveWorkspace(); Workspace activeWorkspace = toolManager.getActiveWorkspace();
ToolTemplate template = toolChest.getToolTemplate(toolName); ToolTemplate template = toolChest.getToolTemplate(toolName);
Tool newTool = activeWorkspace.runTool(template); PluginTool newTool = activeWorkspace.runTool(template);
DomainFile[] files = fileList.toArray(new DomainFile[fileList.size()]); DomainFile[] files = fileList.toArray(new DomainFile[fileList.size()]);
newTool.acceptDomainFiles(files); newTool.acceptDomainFiles(files);

View file

@ -122,8 +122,8 @@ public abstract class VersionControlAction extends DomainFileProviderContextActi
*/ */
boolean canCloseDomainFile(DomainFile df) { boolean canCloseDomainFile(DomainFile df) {
Project project = tool.getProject(); Project project = tool.getProject();
Tool[] tools = project.getToolManager().getRunningTools(); PluginTool[] tools = project.getToolManager().getRunningTools();
for (Tool t : tools) { for (PluginTool t : tools) {
DomainFile[] files = t.getDomainFiles(); DomainFile[] files = t.getDomainFiles();
for (DomainFile domainFile : files) { for (DomainFile domainFile : files) {
if (df == domainFile) { if (df == domainFile) {

View file

@ -1,221 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.framework.model;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import org.jdom.Element;
import docking.DockingTool;
import docking.util.image.ToolIconURL;
import ghidra.framework.plugintool.PluginEvent;
/**
*
* A Tool represents a collection of Plugins that are the basic building
* blocks. The plugins cooperate with one another to achieve certain
* functionality. The tool interface defines methods called by the
* Project that manages the tools.
*/
public interface Tool extends DockingTool, ToolListener {
/**
* Name of the property for the tool name.
*/
public final static String TOOL_NAME_PROPERTY = "ToolName";
/**
* Name of the property for the tool icon.
*/
public final static String ICON_PROPERTY_NAME = "Icon";
/**
* Name of the property for the description of the tool.
*/
public final static String DESCRIPTION_PROPERTY_NAME = "Description";
/**
* Name of the property for the number of plugins the tool has.
*/
public final static String PLUGIN_COUNT_PROPERTY_NAME = "PluginCount";
/**
* Tells the tool to stop functioning and release its resources.
* The tool should dispose of all its windows and other resources.
*/
public void exit();
/**
* Can this tool be closed?
* @param isExiting true if all of Ghidra is closing, false if just this tool is closing.
* @return true if the tool is in a state that it can be closed.
*/
public boolean canClose(boolean isExiting);
/**
* Can the domain File be closed?
* <br>Note: This forces plugins to terminate any tasks they have running for the
* indicated domain object and apply any unsaved data to the domain object. If they can't do
* this or the user cancels then this returns false.
* @return false any of the plugins reports that the domain object
* should not be closed
*/
public boolean canCloseDomainFile(DomainFile domainFile);
/**
* Fire the plugin event by notifying the event manager which
* calls the listeners.
* @param event plugin event
*/
public void firePluginEvent(PluginEvent event);
/**
* Returns the name associated with the tool
*/
public String getToolName();
/**
* Sets the type name of the tool.
* @param toolName the basename to use when setting the tool's name
* @exception PropertyVetoException thrown if a VetoableChangeListener
* rejects the change
*/
public void setToolName(String toolName) throws PropertyVetoException;
/**
* Associates a unique(within the active project) name to a tool instance.
* @param instanceName unique tool instance name
*/
public void putInstanceName(String instanceName);
/**
* Returns the tool's unique name.
*/
public String getInstanceName();
/**
* Returns the names of all the possible ToolEvents that this
* tool might generate. Used by the ConnectionManager to connect
* tools together.
*/
public String[] getToolEventNames();
/**
* Returns a list of eventNames that this Tool is interested in.
*/
public String[] getConsumedToolEventNames();
/**
* When the user drags a data file onto a tool, an event will be fired
* that the tool will respond to by accepting the data.
*
* @param data the data to be used by the running tool
*/
public boolean acceptDomainFiles(DomainFile[] data);
/**
* Get the domain files that this tool currently has open.
*/
public DomainFile[] getDomainFiles();
/**
* Adds a ToolListener to be notified for any of a Tool's ToolEvents.
* The listener will be notified of any events that this tool generates.
*
* @param listener ToolListener to be added to receive all events
*/
public void addToolListener(ToolListener listener);
/**
* Removes a ToolListener from receiving any event generated by this Tool.
* The tool will still recieve specific events that it has registered for.
*
* @param listener The ToolListener to be removed from receiving all events.
*/
public void removeToolListener(ToolListener listener);
/**
* Add property change listener.
*/
public void addPropertyChangeListener(PropertyChangeListener l);
/**
* Remove property change listener.
*/
public void removePropertyChangeListener(PropertyChangeListener l);
/**
* Get the classes of the data types that this tool supports,
* i.e., what data types can be dropped onto this tool.
*/
public Class<?>[] getSupportedDataTypes();
/**
* Tells tool to write its data state from the given output stream.
* @param isTransactionState true if saving the toolstate is for a potential undo/redo
* (database transaction)
*/
public Element saveDataStateToXml(boolean isTransactionState);
/**
* Tells tool to read its data state from the given input stream.
* @param element XML data state
*/
public void restoreDataStateFromXml(Element element);
/**
* Set the icon for this tool.
* @param iconURL icon location
*/
public void setIconURL(ToolIconURL iconURL);
/**
* Get the url for the icon that this tool is using.
*/
public ToolIconURL getIconURL();
/**
* Returns a ToolTemplate for this Tool that describes the state of the tool.
* @return a ToolTemplate for this Tool that describes the state of the tool.
*/
public ToolTemplate getToolTemplate(boolean includeConfigState);
/**
* Save the tool and return its state as a ToolTemplate. Forces a complete
* regeneration of the tool template.
* @return a toolTemplate for this tool.
*/
public ToolTemplate saveToolToToolTemplate();
/**
* Saves the tool's Docking Window layout and positioning information to an XML element.
* @return the element containing the DockingWindow's layout information.
*/
public Element saveWindowingDataToXml();
/**
* Restores the tool's Docking Window layout and positioning information from an XML element.
* @param windowData the element containing the information.
*/
public void restoreWindowingDataFromXml(Element windowData);
/**
* Returns true if this tool should save its data, based upon its changed state and the state
* of Ghidra's saving method.
* @return true if this tool should save its data
*/
public boolean shouldSave();
public Element saveToXml(boolean includeConfigState);
}

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,60 +15,63 @@
*/ */
package ghidra.framework.model; package ghidra.framework.model;
import ghidra.framework.plugintool.PluginTool;
/** /**
* Represents a connection between a producer tool and a * Represents a connection between a producer tool and a
* consumer tool. * consumer tool.
*/ */
public interface ToolConnection { public interface ToolConnection {
/** /**
* Get the tool that produces an event. * Get the tool that produces an event
*/ * @return the tool
public Tool getProducer(); */
public PluginTool getProducer();
/**
* Get the tool that consumes an event.
*/
public Tool getConsumer();
/** /**
* Get the list of event names that is an intersection * Get the tool that consumes an event
* between what the producer produces and what the * @return the tool
* consumers consumes. */
* public PluginTool getConsumer();
* @return an array of event names
*/
public String[] getEvents();
/** /**
* Connect the tools for the given event name. * Get the list of event names that is an intersection
* * between what the producer produces and what the
* @param eventName name of event to connect * consumers consumes.
* *
* @throws IllegalArgumentException if eventName is not valid for this * @return an array of event names
*/
public String[] getEvents();
/**
* Connect the tools for the given event name.
*
* @param eventName name of event to connect
*
* @throws IllegalArgumentException if eventName is not valid for this
* producer/consumer pair. * producer/consumer pair.
*/ */
public void connect(String eventName); public void connect(String eventName);
/** /**
* Break the connection between the tools for the * Break the connection between the tools for the
* given event name. * given event name.
* *
* @param eventName name of event to disconnect * @param eventName name of event to disconnect
* *
* @throws IllegalArgumentException if eventName is not valid for this * @throws IllegalArgumentException if eventName is not valid for this
* producer/consumer pair. * producer/consumer pair.
*/ */
public void disconnect(String eventName); public void disconnect(String eventName);
/** /**
* Return whether the tools are connected for the * Return whether the tools are connected for the
* given event name. * given event name.
* *
* @param eventName name of event to check * @param eventName name of event to check
* @return true if the tools are connected by eventName. * @return true if the tools are connected by eventName.
*/ */
public boolean isConnected(String eventName); public boolean isConnected(String eventName);
} }

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,6 +15,7 @@
*/ */
package ghidra.framework.model; package ghidra.framework.model;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
/** /**
@ -29,106 +29,103 @@ import ghidra.util.exception.DuplicateNameException;
*/ */
public interface ToolManager { public interface ToolManager {
/** /**
* The name to use for a new unnamed workspace; used by the Ghidra * The name to use for a new unnamed workspace; used by the Ghidra
* Project Window when the user creates a new workspace. * Project Window when the user creates a new workspace.
*/ */
public final static String DEFAULT_WORKSPACE_NAME = "Workspace"; public final static String DEFAULT_WORKSPACE_NAME = "Workspace";
/**
* Property used when sending the change event when a workspace name is
* changed.
*/
public final static String WORKSPACE_NAME_PROPERTY = "WorkspaceName";
/**
* Get the connection object for the producer and consumer
* tools.
*
* @param producer tool that is producing the tool event
* @param consumer tool that is consuming the tool event
*/
public ToolConnection getConnection(Tool producer, Tool consumer);
/**
* Get a list of tools that produce at least one tool event.
*
* @return zero-length array if no tool produces any events
*/
public Tool[] getProducerTools();
/**
* Get a list of tools that consume at least one tool event.
*
* @return zero-length array if no tool consumes any events
*/
public Tool[] getConsumerTools();
/**
* Get a list running tools across all workspaces.
*
* @return zero-length array if there are no running tools.
*/
public Tool[] getRunningTools();
/**
* Create a workspace with the given name.
*
* @param name name of workspace
*
* @throws DuplicateNameException if a workspace with this
* name already exists.
*/
public Workspace createWorkspace(String name) throws DuplicateNameException;
/**
* Remove the workspace.
*
* @param ws workspace to remove
*/
public void removeWorkspace(Workspace ws);
/**
* Get list of known workspaces.
*
* @return an array of known workspaces
*/
public Workspace[] getWorkspaces();
/**
* Get the active workspace
*
* @return the active workspace
*/
public Workspace getActiveWorkspace();
/** /**
* Add the listener that will be notified when a tool is added * Property used when sending the change event when a workspace name is
* or removed. * changed.
* */
* @param listener workspace listener to add public final static String WORKSPACE_NAME_PROPERTY = "WorkspaceName";
*/
public void addWorkspaceChangeListener(WorkspaceChangeListener listener);
/** /**
* Remove the workspace listener. * Get the connection object for the producer and consumer tools
* *
* @param l workspace listener to remove * @param producer tool that is producing the tool event
*/ * @param consumer tool that is consuming the tool event
public void removeWorkspaceChangeListener(WorkspaceChangeListener l); * @return the connection
*/
public ToolConnection getConnection(PluginTool producer, PluginTool consumer);
/**
* Get a list of tools that produce at least one tool event.
*
* @return zero-length array if no tool produces any events
*/
public PluginTool[] getProducerTools();
/**
* Get a list of tools that consume at least one tool event.
*
* @return zero-length array if no tool consumes any events
*/
public PluginTool[] getConsumerTools();
/**
* Get a list running tools across all workspaces.
*
* @return zero-length array if there are no running tools.
*/
public PluginTool[] getRunningTools();
/**
* Create a workspace with the given name.
*
* @param name name of workspace
* @return the workspace
* @throws DuplicateNameException if a workspace with this name already exists
*/
public Workspace createWorkspace(String name) throws DuplicateNameException;
/**
* Remove the workspace.
*
* @param ws workspace to remove
*/
public void removeWorkspace(Workspace ws);
/**
* Get list of known workspaces.
*
* @return an array of known workspaces
*/
public Workspace[] getWorkspaces();
/**
* Get the active workspace
*
* @return the active workspace
*/
public Workspace getActiveWorkspace();
/**
* Add the listener that will be notified when a tool is added
* or removed.
*
* @param listener workspace listener to add
*/
public void addWorkspaceChangeListener(WorkspaceChangeListener listener);
/**
* Remove the workspace listener.
*
* @param l workspace listener to remove
*/
public void removeWorkspaceChangeListener(WorkspaceChangeListener l);
/** /**
* Removes all connections involving tool * Removes all connections involving tool
* @param tool tool for which to remove all connections * @param tool tool for which to remove all connections
*/ */
public void disconnectTool(Tool tool); public void disconnectTool(PluginTool tool);
/** /**
* A configuration change was made to the tool; a plugin was added * A configuration change was made to the tool; a plugin was added
* or removed. * or removed.
* @param tool tool that changed * @param tool tool that changed
*/ */
public void toolChanged(Tool tool); public void toolChanged(PluginTool tool);
} }

View file

@ -19,6 +19,7 @@ import java.io.*;
import java.util.Set; import java.util.Set;
import ghidra.framework.plugintool.PluginEvent; import ghidra.framework.plugintool.PluginEvent;
import ghidra.framework.plugintool.PluginTool;
/** /**
* Services that the Tool uses. * Services that the Tool uses.
@ -33,7 +34,7 @@ public interface ToolServices {
* *
* @param tool tool that is closing * @param tool tool that is closing
*/ */
public void closeTool(Tool tool); public void closeTool(PluginTool tool);
/** /**
* Saves the tool's configuration in the standard * Saves the tool's configuration in the standard
@ -41,7 +42,7 @@ public interface ToolServices {
* *
* @param tool tool to save. * @param tool tool to save.
*/ */
public void saveTool(Tool tool); public void saveTool(PluginTool tool);
/** /**
* Save the tool to the given location on the local file system. * Save the tool to the given location on the local file system.
@ -54,7 +55,8 @@ public interface ToolServices {
public File exportTool(ToolTemplate tool) throws FileNotFoundException, IOException; public File exportTool(ToolTemplate tool) throws FileNotFoundException, IOException;
/** /**
* Get the tool chest for the project. * Get the tool chest for the project
* @return the tool chest
*/ */
public ToolChest getToolChest(); public ToolChest getToolChest();
@ -68,7 +70,7 @@ public interface ToolServices {
* @param domainFile open this file in the found/created tool. * @param domainFile open this file in the found/created tool.
* @param event invoke this event on the found/created tool * @param event invoke this event on the found/created tool
*/ */
public void displaySimilarTool(Tool tool, DomainFile domainFile, PluginEvent event); public void displaySimilarTool(PluginTool tool, DomainFile domainFile, PluginEvent event);
/** /**
* Returns the default tool template used to open the tool. Here <b>default</b> means the * Returns the default tool template used to open the tool. Here <b>default</b> means the
@ -83,6 +85,7 @@ public interface ToolServices {
/** /**
* Returns a set of tools that can open the given domain file class. * Returns a set of tools that can open the given domain file class.
* @param domainClass The domain file class type for which to get tools * @param domainClass The domain file class type for which to get tools
* @return the tools
*/ */
public Set<ToolTemplate> getCompatibleTools(Class<? extends DomainObject> domainClass); public Set<ToolTemplate> getCompatibleTools(Class<? extends DomainObject> domainClass);
@ -90,6 +93,7 @@ public interface ToolServices {
* Returns the {@link ToolAssociationInfo associations}, which describe content * Returns the {@link ToolAssociationInfo associations}, which describe content
* types and the tools used to open them, for all content types known to the system. * types and the tools used to open them, for all content types known to the system.
* *
* @return the associations
* @see #setContentTypeToolAssociations(Set) * @see #setContentTypeToolAssociations(Set)
*/ */
public Set<ToolAssociationInfo> getContentTypeToolAssociations(); public Set<ToolAssociationInfo> getContentTypeToolAssociations();
@ -107,24 +111,27 @@ public interface ToolServices {
* Launch the default tool; if domainFile is not null, this file will * Launch the default tool; if domainFile is not null, this file will
* be opened in the tool. * be opened in the tool.
* @param domainFile the file to open; may be null * @param domainFile the file to open; may be null
* @return the tool
*/ */
public Tool launchDefaultTool(DomainFile domainFile); public PluginTool launchDefaultTool(DomainFile domainFile);
/** /**
* Launch the tool with the given name * Launch the tool with the given name
* @param toolName name of the tool to launch * @param toolName name of the tool to launch
* @param domainFile the file to open; may be null * @param domainFile the file to open; may be null
* @return the tool
*/ */
public Tool launchTool(String toolName, DomainFile domainFile); public PluginTool launchTool(String toolName, DomainFile domainFile);
/** /**
* Add a listener that will be notified when the default tool * Add a listener that will be notified when the default tool specification changes
* specification changes. * @param listener the listener
*/ */
public void addDefaultToolChangeListener(DefaultToolChangeListener listener); public void addDefaultToolChangeListener(DefaultToolChangeListener listener);
/** /**
* Remove the listener. * Remove the listener
* @param listener the listener
*/ */
public void removeDefaultToolChangeListener(DefaultToolChangeListener listener); public void removeDefaultToolChangeListener(DefaultToolChangeListener listener);
@ -132,13 +139,13 @@ public interface ToolServices {
* Return array of running tools * Return array of running tools
* @return array of Tools * @return array of Tools
*/ */
public Tool[] getRunningTools(); public PluginTool[] getRunningTools();
/** /**
* Returns true if this tool should be saved base on the state of other runnings instances of * Returns true if this tool should be saved base on the state of other running instances of
* the same tool * the same tool
* @param tool the tool to check for saving * @param tool the tool to check for saving
* @return true if the tool should be saved * @return true if the tool should be saved
*/ */
public boolean canAutoSave(Tool tool); public boolean canAutoSave(PluginTool tool);
} }

View file

@ -20,6 +20,7 @@ import javax.swing.ImageIcon;
import org.jdom.Element; import org.jdom.Element;
import docking.util.image.ToolIconURL; import docking.util.image.ToolIconURL;
import ghidra.framework.plugintool.PluginTool;
/** /**
* Configuration of a tool that knows how to create tools. * Configuration of a tool that knows how to create tools.
@ -51,7 +52,8 @@ public interface ToolTemplate {
void setName(String name); void setName(String name);
/** /**
* Get the iconURL for this tool template. * Get the iconURL for this tool template
* @return the iconURL for this tool template
*/ */
ToolIconURL getIconURL(); ToolIconURL getIconURL();
@ -88,7 +90,7 @@ public interface ToolTemplate {
* @param project the project in which the tool will be living. * @param project the project in which the tool will be living.
* @return a new tool for this template implementation. * @return a new tool for this template implementation.
*/ */
public Tool createTool(Project project); public PluginTool createTool(Project project);
/** /**
* This returns the XML element that represents the tool part of the overall XML hierarchy. * This returns the XML element that represents the tool part of the overall XML hierarchy.

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,6 +15,7 @@
*/ */
package ghidra.framework.model; package ghidra.framework.model;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
/** /**
@ -24,47 +24,49 @@ import ghidra.util.exception.DuplicateNameException;
*/ */
public interface Workspace { public interface Workspace {
/** /**
* Get the workspace name. * Get the workspace name
*/ * @return the name
public String getName(); */
public String getName();
/** /**
* Get the running tools in the workspace. * Get the running tools in the workspace.
* *
* @return list of running tools or zero-length array if there are no tools in the workspace * @return list of running tools or zero-length array if there are no tools in the workspace
*/ */
public Tool[] getTools(); public PluginTool[] getTools();
/** /**
* Launch an empty tool. * Launch an empty tool.
* @return name of empty tool that is launched. * @return name of empty tool that is launched.
*/ */
public Tool createTool(); public PluginTool createTool();
/** /**
* Run the tool specified by the tool template object. * Run the tool specified by the tool template object.
* @return launched tool that is now running. * @param template the template
*/ * @return launched tool that is now running.
public Tool runTool(ToolTemplate template); */
public PluginTool runTool(ToolTemplate template);
/** /**
* Rename this workspace. * Rename this workspace.
* *
* @param newName new workspace name * @param newName new workspace name
* *
* @throws DuplicateNameException if newName is already the * @throws DuplicateNameException if newName is already the
* name of a workspace. * name of a workspace.
*/ */
public void setName(String newName) public void setName(String newName)
throws DuplicateNameException; throws DuplicateNameException;
/** /**
* Set this workspace to be the active workspace, i.e., * Set this workspace to be the active workspace, i.e.,
* all tools become visible. * all tools become visible.
* The currently active workspace becomes inactive, and * The currently active workspace becomes inactive, and
* this workspace becomes active. * this workspace becomes active.
*/ */
public void setActive(); public void setActive();
} }

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,41 +17,43 @@ package ghidra.framework.model;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import ghidra.framework.plugintool.PluginTool;
/** /**
* Listener that is notified when a tool is added or removed from a * Listener that is notified when a tool is added or removed from a
* workspace, or when workspace properties change. * workspace, or when workspace properties change.
*/ */
public interface WorkspaceChangeListener extends PropertyChangeListener { public interface WorkspaceChangeListener extends PropertyChangeListener {
/** /**
* Notification that a tool was added to the given workspace. * Notification that a tool was added to the given workspace.
* @param ws workspace the affected workspace * @param ws workspace the affected workspace
* @param tool tool that was added * @param tool tool that was added
*/ */
public void toolAdded(Workspace ws, Tool tool); public void toolAdded(Workspace ws, PluginTool tool);
/** /**
* Notification that a tool was removed from the given workspace. * Notification that a tool was removed from the given workspace.
* @param ws workspace the affected workspace * @param ws workspace the affected workspace
* @param tool tool that was removed from the workspace * @param tool tool that was removed from the workspace
*/ */
public void toolRemoved(Workspace ws, Tool tool); public void toolRemoved(Workspace ws, PluginTool tool);
/** /**
* Notification that the given workspace was added by the ToolManager. * Notification that the given workspace was added by the ToolManager.
* @param ws workspace the affected workspace * @param ws workspace the affected workspace
*/ */
public void workspaceAdded(Workspace ws); public void workspaceAdded(Workspace ws);
/** /**
* Notification that the given workspace was removed by the ToolManager. * Notification that the given workspace was removed by the ToolManager.
* @param ws workspace the affected workspace * @param ws workspace the affected workspace
*/ */
public void workspaceRemoved(Workspace ws); public void workspaceRemoved(Workspace ws);
/** /**
* Notification that the given workspace is the current one. * Notification that the given workspace is the current one.
* @param ws workspace the affected workspace * @param ws workspace the affected workspace
*/ */
public void workspaceSetActive(Workspace ws); public void workspaceSetActive(Workspace ws);
} }

View file

@ -16,11 +16,11 @@
package ghidra.framework.plugintool; package ghidra.framework.plugintool;
import docking.ComponentProvider; import docking.ComponentProvider;
import docking.DockingTool; import docking.Tool;
/** /**
* Extends the {@link ComponentProvider} to fit into the Plugin architecture by taking in a * Extends the {@link ComponentProvider} to fit into the Plugin architecture by taking in a
* {@link PluginTool} which extends {@link DockingTool}. Most implementers will want to extend * {@link PluginTool} which extends {@link Tool}. Most implementers will want to extend
* this class instead of the ComponentProvider class because they will want to access the extra * this class instead of the ComponentProvider class because they will want to access the extra
* methods provided by PluginTool over DockingTool without having to cast the dockingTool variable. * methods provided by PluginTool over DockingTool without having to cast the dockingTool variable.
*/ */

View file

@ -73,7 +73,24 @@ import ghidra.util.task.*;
* <p>The PluginTool also manages tasks that run in the background, and options used by the plugins. * <p>The PluginTool also manages tasks that run in the background, and options used by the plugins.
* *
*/ */
public abstract class PluginTool extends AbstractDockingTool implements Tool { public abstract class PluginTool extends AbstractDockingTool {
/**
* Name of the property for the tool name.
*/
public final static String TOOL_NAME_PROPERTY = "ToolName";
/**
* Name of the property for the tool icon.
*/
public final static String ICON_PROPERTY_NAME = "Icon";
/**
* Name of the property for the description of the tool.
*/
public final static String DESCRIPTION_PROPERTY_NAME = "Description";
/**
* Name of the property for the number of plugins the tool has.
*/
public final static String PLUGIN_COUNT_PROPERTY_NAME = "PluginCount";
private static final String DOCKING_WINDOWS_ON_TOP = "Docking Windows On Top"; private static final String DOCKING_WINDOWS_ON_TOP = "Docking Windows On Top";
@ -170,6 +187,10 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
installHomeButton(); installHomeButton();
} }
protected PluginTool() {
// non-public constructor for stub subclasses
}
public abstract PluginClassManager getPluginClassManager(); public abstract PluginClassManager getPluginClassManager();
/** /**
@ -368,43 +389,36 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
winMgr.setDefaultComponent(provider); winMgr.setDefaultComponent(provider);
} }
@Override
public ToolTemplate getToolTemplate(boolean includeConfigState) { public ToolTemplate getToolTemplate(boolean includeConfigState) {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"You cannot create templates for generic tools: " + getClass().getName()); "You cannot create templates for generic tools: " + getClass().getName());
} }
@Override
public ToolTemplate saveToolToToolTemplate() { public ToolTemplate saveToolToToolTemplate() {
setConfigChanged(false); setConfigChanged(false);
optionsMgr.removeUnusedOptions(); optionsMgr.removeUnusedOptions();
return getToolTemplate(true); return getToolTemplate(true);
} }
@Override
public Element saveWindowingDataToXml() { public Element saveWindowingDataToXml() {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"You cannot persist generic tools: " + getClass().getName()); "You cannot persist generic tools: " + getClass().getName());
} }
@Override
public void restoreWindowingDataFromXml(Element windowData) { public void restoreWindowingDataFromXml(Element windowData) {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"You cannot persist generic tools: " + getClass().getName()); "You cannot persist generic tools: " + getClass().getName());
} }
@Override
public boolean acceptDomainFiles(DomainFile[] data) { public boolean acceptDomainFiles(DomainFile[] data) {
return pluginMgr.acceptData(data); return pluginMgr.acceptData(data);
} }
@Override
public void addPropertyChangeListener(PropertyChangeListener l) { public void addPropertyChangeListener(PropertyChangeListener l) {
propertyChangeMgr.addPropertyChangeListener(l); propertyChangeMgr.addPropertyChangeListener(l);
} }
@Override
public void addToolListener(ToolListener listener) { public void addToolListener(ToolListener listener) {
eventMgr.addToolListener(listener); eventMgr.addToolListener(listener);
} }
@ -417,7 +431,6 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
return eventMgr.hasToolListeners(); return eventMgr.hasToolListeners();
} }
@Override
public void exit() { public void exit() {
dispose(); dispose();
} }
@ -458,17 +471,14 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
executingTaskListeners.clear(); executingTaskListeners.clear();
} }
@Override
public void firePluginEvent(PluginEvent event) { public void firePluginEvent(PluginEvent event) {
eventMgr.fireEvent(event); eventMgr.fireEvent(event);
} }
@Override
public String[] getConsumedToolEventNames() { public String[] getConsumedToolEventNames() {
return eventMgr.getEventsConsumed(); return eventMgr.getEventsConsumed();
} }
@Override
public DomainFile[] getDomainFiles() { public DomainFile[] getDomainFiles() {
return pluginMgr.getData(); return pluginMgr.getData();
} }
@ -478,12 +488,10 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
return iconURL.getIcon(); return iconURL.getIcon();
} }
@Override
public ToolIconURL getIconURL() { public ToolIconURL getIconURL() {
return iconURL; return iconURL;
} }
@Override
public String getInstanceName() { public String getInstanceName() {
return instanceName; return instanceName;
} }
@ -493,22 +501,18 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
return fullName; return fullName;
} }
@Override
public Class<?>[] getSupportedDataTypes() { public Class<?>[] getSupportedDataTypes() {
return pluginMgr.getSupportedDataTypes(); return pluginMgr.getSupportedDataTypes();
} }
@Override
public String[] getToolEventNames() { public String[] getToolEventNames() {
return eventMgr.getEventsProduced(); return eventMgr.getEventsProduced();
} }
@Override
public String getToolName() { public String getToolName() {
return toolName; return toolName;
} }
@Override
public void putInstanceName(String newInstanceName) { public void putInstanceName(String newInstanceName) {
this.instanceName = newInstanceName; this.instanceName = newInstanceName;
if (instanceName.length() == 0) { if (instanceName.length() == 0) {
@ -520,24 +524,20 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
updateTitle(); updateTitle();
} }
@Override
public void removePropertyChangeListener(PropertyChangeListener l) { public void removePropertyChangeListener(PropertyChangeListener l) {
propertyChangeMgr.removePropertyChangeListener(l); propertyChangeMgr.removePropertyChangeListener(l);
} }
@Override
public void removeToolListener(ToolListener listener) { public void removeToolListener(ToolListener listener) {
eventMgr.removeToolListener(listener); eventMgr.removeToolListener(listener);
} }
@Override
public void restoreDataStateFromXml(Element root) { public void restoreDataStateFromXml(Element root) {
pluginMgr.restoreDataStateFromXml(root); pluginMgr.restoreDataStateFromXml(root);
setConfigChanged(false); setConfigChanged(false);
} }
@Override
public Element saveDataStateToXml(boolean savingProject) { public Element saveDataStateToXml(boolean savingProject) {
return pluginMgr.saveDataStateToXml(savingProject); return pluginMgr.saveDataStateToXml(savingProject);
} }
@ -570,7 +570,6 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
return hasErrors; return hasErrors;
} }
@Override
public Element saveToXml(boolean includeConfigState) { public Element saveToXml(boolean includeConfigState) {
Element root = new Element("TOOL"); Element root = new Element("TOOL");
@ -591,7 +590,6 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
} }
} }
@Override
public void setIconURL(ToolIconURL newIconURL) { public void setIconURL(ToolIconURL newIconURL) {
if (newIconURL == null) { if (newIconURL == null) {
throw new NullPointerException("iconURL cannot be null."); throw new NullPointerException("iconURL cannot be null.");
@ -609,7 +607,6 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
winMgr.setIcon(newValue); winMgr.setIcon(newValue);
} }
@Override
public void setToolName(String name) { public void setToolName(String name) {
String oldName = toolName; String oldName = toolName;
toolName = name; toolName = name;
@ -623,7 +620,6 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
propertyChangeMgr.firePropertyChange(TOOL_NAME_PROPERTY, oldName, toolName); propertyChangeMgr.firePropertyChange(TOOL_NAME_PROPERTY, oldName, toolName);
} }
@Override
public void processToolEvent(PluginEvent toolEvent) { public void processToolEvent(PluginEvent toolEvent) {
eventMgr.processToolEvent(toolEvent); eventMgr.processToolEvent(toolEvent);
} }
@ -718,6 +714,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
* Get the options for the given category name; if no options exist with * Get the options for the given category name; if no options exist with
* the given name, then one is created. * the given name, then one is created.
*/ */
@Override @Override
public ToolOptions getOptions(String categoryName) { public ToolOptions getOptions(String categoryName) {
return optionsMgr.getOptions(categoryName); return optionsMgr.getOptions(categoryName);
@ -894,6 +891,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
protected void addExitAction() { protected void addExitAction() {
DockingAction exitAction = new DockingAction("Exit Ghidra", ToolConstants.TOOL_OWNER) { DockingAction exitAction = new DockingAction("Exit Ghidra", ToolConstants.TOOL_OWNER) {
@Override @Override
public void actionPerformed(ActionContext context) { public void actionPerformed(ActionContext context) {
AppInfo.exitGhidra(); AppInfo.exitGhidra();
@ -918,6 +916,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
protected void addOptionsAction() { protected void addOptionsAction() {
DockingAction optionsAction = new DockingAction("Edit Options", ToolConstants.TOOL_OWNER) { DockingAction optionsAction = new DockingAction("Edit Options", ToolConstants.TOOL_OWNER) {
@Override @Override
public void actionPerformed(ActionContext context) { public void actionPerformed(ActionContext context) {
optionsMgr.editOptions(); optionsMgr.editOptions();
@ -943,6 +942,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
protected void addSaveToolAction() { protected void addSaveToolAction() {
DockingAction saveAction = new DockingAction("Save Tool", ToolConstants.TOOL_OWNER) { DockingAction saveAction = new DockingAction("Save Tool", ToolConstants.TOOL_OWNER) {
@Override @Override
public void actionPerformed(ActionContext context) { public void actionPerformed(ActionContext context) {
saveTool(); saveTool();
@ -956,6 +956,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
saveAction.setHelpLocation(new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "Save Tool")); saveAction.setHelpLocation(new HelpLocation(ToolConstants.TOOL_HELP_TOPIC, "Save Tool"));
DockingAction saveAsAction = new DockingAction("Save Tool As", ToolConstants.TOOL_OWNER) { DockingAction saveAsAction = new DockingAction("Save Tool As", ToolConstants.TOOL_OWNER) {
@Override @Override
public void actionPerformed(ActionContext context) { public void actionPerformed(ActionContext context) {
saveToolAs(); saveToolAs();
@ -983,6 +984,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
int subGroup = 1; int subGroup = 1;
DockingAction exportToolAction = DockingAction exportToolAction =
new DockingAction("Export Tool", ToolConstants.TOOL_OWNER) { new DockingAction("Export Tool", ToolConstants.TOOL_OWNER) {
@Override @Override
public void actionPerformed(ActionContext context) { public void actionPerformed(ActionContext context) {
dialogMgr.exportTool(); dialogMgr.exportTool();
@ -998,6 +1000,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
DockingAction exportDefautToolAction = DockingAction exportDefautToolAction =
new DockingAction("Export Default Tool", ToolConstants.TOOL_OWNER) { new DockingAction("Export Default Tool", ToolConstants.TOOL_OWNER) {
@Override @Override
public void actionPerformed(ActionContext e) { public void actionPerformed(ActionContext e) {
dialogMgr.exportDefaultTool(); dialogMgr.exportDefaultTool();
@ -1016,6 +1019,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
protected void addHelpActions() { protected void addHelpActions() {
DockingAction action = new DockingAction("About Ghidra", ToolConstants.TOOL_OWNER) { DockingAction action = new DockingAction("About Ghidra", ToolConstants.TOOL_OWNER) {
@Override @Override
public void actionPerformed(ActionContext context) { public void actionPerformed(ActionContext context) {
DockingWindowManager.showDialog(new AboutDialog()); DockingWindowManager.showDialog(new AboutDialog());
@ -1035,6 +1039,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
DockingAction userAgreementAction = new DockingAction("User Agreement", DockingAction userAgreementAction = new DockingAction("User Agreement",
ToolConstants.TOOL_OWNER, KeyBindingType.UNSUPPORTED) { ToolConstants.TOOL_OWNER, KeyBindingType.UNSUPPORTED) {
@Override @Override
public void actionPerformed(ActionContext context) { public void actionPerformed(ActionContext context) {
DockingWindowManager.showDialog(new UserAgreementDialog(false, false)); DockingWindowManager.showDialog(new UserAgreementDialog(false, false));
@ -1057,6 +1062,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
final ErrorReporter reporter = ErrLogDialog.getErrorReporter(); final ErrorReporter reporter = ErrLogDialog.getErrorReporter();
if (reporter != null) { if (reporter != null) {
action = new DockingAction("Report Bug", ToolConstants.TOOL_OWNER) { action = new DockingAction("Report Bug", ToolConstants.TOOL_OWNER) {
@Override @Override
public void actionPerformed(ActionContext context) { public void actionPerformed(ActionContext context) {
reporter.report(getToolFrame(), "User Bug Report", null); reporter.report(getToolFrame(), "User Bug Report", null);
@ -1077,6 +1083,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
HelpService help = Help.getHelpService(); HelpService help = Help.getHelpService();
action = new DockingAction("Contents", ToolConstants.TOOL_OWNER) { action = new DockingAction("Contents", ToolConstants.TOOL_OWNER) {
@Override @Override
public void actionPerformed(ActionContext context) { public void actionPerformed(ActionContext context) {
help.showHelp(null, false, getToolFrame()); help.showHelp(null, false, getToolFrame());
@ -1115,6 +1122,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
* <LI>notify the project tool services that this tool is going away. * <LI>notify the project tool services that this tool is going away.
* </OL> * </OL>
*/ */
@Override @Override
public void close() { public void close() {
if (canClose(false) && pluginMgr.saveData()) { if (canClose(false) && pluginMgr.saveData()) {
@ -1141,7 +1149,6 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
toolServices.closeTool(this); toolServices.closeTool(this);
} }
@Override
public boolean shouldSave() { public boolean shouldSave() {
return configChangedFlag; // ignore the window layout changes return configChangedFlag; // ignore the window layout changes
} }
@ -1185,10 +1192,11 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
* <br>Note: This forces plugins to terminate any tasks they have running and * <br>Note: This forces plugins to terminate any tasks they have running and
* apply any unsaved data to domain objects or files. If they can't do * apply any unsaved data to domain objects or files. If they can't do
* this or the user cancels then this returns false. * this or the user cancels then this returns false.
*
* @param isExiting whether the tool is exiting
* @return false if this tool has tasks in progress or can't be closed * @return false if this tool has tasks in progress or can't be closed
* since the user has unfinished/unsaved changes. * since the user has unfinished/unsaved changes.
*/ */
@Override
public boolean canClose(boolean isExiting) { public boolean canClose(boolean isExiting) {
if (taskMgr.isBusy()) { if (taskMgr.isBusy()) {
if (isExiting) { if (isExiting) {
@ -1236,7 +1244,6 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
return pluginMgr.canCloseDomainObject(domainObject); return pluginMgr.canCloseDomainObject(domainObject);
} }
@Override
public boolean canCloseDomainFile(DomainFile domainFile) { public boolean canCloseDomainFile(DomainFile domainFile) {
Object consumer = new Object(); Object consumer = new Object();
DomainObject domainObject = domainFile.getOpenedDomainObject(consumer); DomainObject domainObject = domainFile.getOpenedDomainObject(consumer);
@ -1469,6 +1476,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
//================================================================================================== //==================================================================================================
private class ToolOptionsListener implements OptionsChangeListener { private class ToolOptionsListener implements OptionsChangeListener {
@Override @Override
public void optionsChanged(ToolOptions options, String name, Object oldValue, public void optionsChanged(ToolOptions options, String name, Object oldValue,
Object newValue) { Object newValue) {
@ -1483,7 +1491,7 @@ public abstract class PluginTool extends AbstractDockingTool implements Tool {
private <T extends Throwable> void checkedRunSwingNow(CheckedRunnable<T> r, private <T extends Throwable> void checkedRunSwingNow(CheckedRunnable<T> r,
Class<T> exceptionClass) throws T { Class<T> exceptionClass) throws T {
AtomicReference<Throwable> caughtException = new AtomicReference<>(); AtomicReference<Throwable> caughtException = new AtomicReference<>();
SystemUtilities.runSwingNow(() -> { Swing.runNow(() -> {
try { try {
r.run(); r.run();
} }

View file

@ -29,7 +29,6 @@ import org.jdom.output.XMLOutputter;
import docking.framework.*; import docking.framework.*;
import ghidra.framework.*; import ghidra.framework.*;
import ghidra.framework.model.Tool;
import ghidra.framework.model.ToolServices; import ghidra.framework.model.ToolServices;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
@ -249,12 +248,12 @@ public abstract class StandAloneApplication implements GenericStandAloneApplicat
return new ToolServicesAdapter() { return new ToolServicesAdapter() {
@Override @Override
public void closeTool(Tool t) { public void closeTool(PluginTool t) {
System.exit(0); System.exit(0);
} }
@Override @Override
public void saveTool(Tool saveTool) { public void saveTool(PluginTool saveTool) {
Element toolElement = saveTool.saveToXml(true); Element toolElement = saveTool.saveToXml(true);
Element dataStateElement = saveTool.saveDataStateToXml(false); Element dataStateElement = saveTool.saveDataStateToXml(false);
Element rootElement = new Element("Root"); Element rootElement = new Element("Root");

View file

@ -27,17 +27,17 @@ public class ToolServicesAdapter implements ToolServices {
} }
@Override @Override
public boolean canAutoSave(Tool tool) { public boolean canAutoSave(PluginTool tool) {
return true; return true;
} }
@Override @Override
public void closeTool(Tool tool) { public void closeTool(PluginTool tool) {
// override // override
} }
@Override @Override
public void displaySimilarTool(Tool tool, DomainFile domainFile, PluginEvent event) { public void displaySimilarTool(PluginTool tool, DomainFile domainFile, PluginEvent event) {
// override // override
} }
@ -62,7 +62,7 @@ public class ToolServicesAdapter implements ToolServices {
} }
@Override @Override
public Tool[] getRunningTools() { public PluginTool[] getRunningTools() {
return null; return null;
} }
@ -72,12 +72,12 @@ public class ToolServicesAdapter implements ToolServices {
} }
@Override @Override
public Tool launchDefaultTool(DomainFile domainFile) { public PluginTool launchDefaultTool(DomainFile domainFile) {
return null; return null;
} }
@Override @Override
public Tool launchTool(String toolName, DomainFile domainFile) { public PluginTool launchTool(String toolName, DomainFile domainFile) {
return null; return null;
} }
@ -87,7 +87,7 @@ public class ToolServicesAdapter implements ToolServices {
} }
@Override @Override
public void saveTool(Tool tool) { public void saveTool(PluginTool tool) {
// override // override
} }

View file

@ -22,7 +22,9 @@ import javax.swing.ImageIcon;
import org.jdom.Element; import org.jdom.Element;
import docking.util.image.ToolIconURL; import docking.util.image.ToolIconURL;
import ghidra.framework.model.*; import ghidra.framework.model.Project;
import ghidra.framework.model.ToolTemplate;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.NumericUtilities; import ghidra.util.NumericUtilities;
@ -46,6 +48,7 @@ public class GhidraToolTemplate implements ToolTemplate {
/** /**
* Constructor. * Constructor.
* @param root XML element that contains the tool template data * @param root XML element that contains the tool template data
* @param path the path of the template
*/ */
public GhidraToolTemplate(Element root, String path) { public GhidraToolTemplate(Element root, String path) {
this.path = path; this.path = path;
@ -208,7 +211,7 @@ public class GhidraToolTemplate implements ToolTemplate {
} }
@Override @Override
public Tool createTool(Project project) { public PluginTool createTool(Project project) {
return new GhidraTool(project, this); return new GhidraTool(project, this);
} }
} }

View file

@ -27,18 +27,18 @@ import docking.DialogComponentProvider;
import docking.widgets.OptionDialog; import docking.widgets.OptionDialog;
import docking.widgets.button.GRadioButton; import docking.widgets.button.GRadioButton;
import docking.widgets.label.GHtmlLabel; import docking.widgets.label.GHtmlLabel;
import ghidra.framework.model.Tool; import ghidra.framework.plugintool.PluginTool;
import ghidra.util.HTMLUtilities; import ghidra.util.HTMLUtilities;
import ghidra.util.layout.VerticalLayout; import ghidra.util.layout.VerticalLayout;
public class SelectChangedToolDialog extends DialogComponentProvider { public class SelectChangedToolDialog extends DialogComponentProvider {
private final List<Tool> toolList; private final List<PluginTool> toolList;
private boolean wasCancelled; private boolean wasCancelled;
private Tool selectedTool; private PluginTool selectedTool;
public SelectChangedToolDialog(List<Tool> toolList) { public SelectChangedToolDialog(List<PluginTool> toolList) {
super("Save Tool Changes?", true, false, true, false); super("Save Tool Changes?", true, false, true, false);
this.toolList = toolList; this.toolList = toolList;
@ -87,7 +87,7 @@ public class SelectChangedToolDialog extends DialogComponentProvider {
buttonGroup.add(noneButton); buttonGroup.add(noneButton);
panel.add(noneButton); panel.add(noneButton);
for (final Tool tool : toolList) { for (final PluginTool tool : toolList) {
GRadioButton radioButton = new GRadioButton(tool.getName()); GRadioButton radioButton = new GRadioButton(tool.getName());
radioButton.addItemListener(new ItemListener() { radioButton.addItemListener(new ItemListener() {
@Override @Override
@ -119,7 +119,7 @@ public class SelectChangedToolDialog extends DialogComponentProvider {
return wasCancelled; return wasCancelled;
} }
Tool getSelectedTool() { PluginTool getSelectedTool() {
return selectedTool; return selectedTool;
} }
} }

View file

@ -19,8 +19,10 @@ import java.util.*;
import org.jdom.Element; import org.jdom.Element;
import ghidra.framework.model.*; import ghidra.framework.model.ToolConnection;
import ghidra.framework.model.ToolListener;
import ghidra.framework.plugintool.PluginEvent; import ghidra.framework.plugintool.PluginEvent;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.datastruct.StringIntHashtable; import ghidra.util.datastruct.StringIntHashtable;
import ghidra.util.exception.NoValueException; import ghidra.util.exception.NoValueException;
@ -32,146 +34,149 @@ import ghidra.util.exception.NoValueException;
*/ */
class ToolConnectionImpl implements ToolConnection, ToolListener { class ToolConnectionImpl implements ToolConnection, ToolListener {
private Tool producerTool; private PluginTool producerTool;
private Tool consumerTool; private PluginTool consumerTool;
private StringIntHashtable connectHt; // maps event -> int value 1 if private StringIntHashtable connectHt; // maps event -> int value 1 if
// tools are connected, int value 0 if tools are not connected // tools are connected, int value 0 if tools are not connected
private final static int CONNECTED = 1; private final static int CONNECTED = 1;
private final static int DISCONNECTED = 0; private final static int DISCONNECTED = 0;
private boolean listenerAdded; // set to true the first time a private boolean listenerAdded; // set to true the first time a
// connection is made for any event // connection is made for any event
private boolean changed; // flag for whether the connection was changed private boolean changed; // flag for whether the connection was changed
/** /**
* Constructor * Constructor
*/ */
ToolConnectionImpl(Tool producerTool, Tool consumerTool) { ToolConnectionImpl(PluginTool producerTool, PluginTool consumerTool) {
this.producerTool = producerTool; this.producerTool = producerTool;
this.consumerTool = consumerTool; this.consumerTool = consumerTool;
connectHt = new StringIntHashtable(); connectHt = new StringIntHashtable();
updateEventList(); updateEventList();
} }
/** /**
* Default constructor used when there is a problem restoring state * Default constructor used when there is a problem restoring state
* on the workspace; want the restore() method to still work. * on the workspace; want the restore() method to still work.
*/ */
ToolConnectionImpl() { ToolConnectionImpl() {
} }
/* /*
* @see ghidra.framework.model.ToolConnection#connect(java.lang.String) * @see ghidra.framework.model.ToolConnection#connect(java.lang.String)
*/ */
@Override @Override
public void connect(String eventName) { public void connect(String eventName) {
validateEventName(eventName); validateEventName(eventName);
connectHt.put(eventName, CONNECTED); connectHt.put(eventName, CONNECTED);
if (!listenerAdded) { if (!listenerAdded) {
producerTool.addToolListener(this); producerTool.addToolListener(this);
listenerAdded = true; listenerAdded = true;
} }
changed = true; changed = true;
} }
/* /*
* @see ghidra.framework.model.ToolConnection#isConnected(java.lang.String) * @see ghidra.framework.model.ToolConnection#isConnected(java.lang.String)
*/ */
@Override @Override
public boolean isConnected(String eventName) { public boolean isConnected(String eventName) {
if (!connectHt.contains(eventName)) { if (!connectHt.contains(eventName)) {
return false; return false;
} }
try { try {
int value = connectHt.get(eventName); int value = connectHt.get(eventName);
return (value == CONNECTED); return (value == CONNECTED);
} catch (NoValueException e) { }
return false; catch (NoValueException e) {
} return false;
}
} }
/* /*
* @see ghidra.framework.model.ToolConnection#getEvents() * @see ghidra.framework.model.ToolConnection#getEvents()
*/ */
@Override @Override
public String[] getEvents() { public String[] getEvents() {
String []keys = connectHt.getKeys(); String[] keys = connectHt.getKeys();
Arrays.sort(keys); Arrays.sort(keys);
return keys; return keys;
} }
/* /*
* @see ghidra.framework.model.ToolConnection#disconnect(java.lang.String) * @see ghidra.framework.model.ToolConnection#disconnect(java.lang.String)
*/ */
@Override @Override
public void disconnect(String eventName) { public void disconnect(String eventName) {
validateEventName(eventName); validateEventName(eventName);
connectHt.put(eventName, DISCONNECTED); connectHt.put(eventName, DISCONNECTED);
checkConnections(); checkConnections();
changed = true; changed = true;
} }
/* /*
* @see ghidra.framework.model.ToolConnection#getProducer() * @see ghidra.framework.model.ToolConnection#getProducer()
*/ */
@Override @Override
public Tool getProducer() { public PluginTool getProducer() {
return producerTool; return producerTool;
} }
/*
/*
* @see ghidra.framework.model.ToolConnection#getConsumer() * @see ghidra.framework.model.ToolConnection#getConsumer()
*/ */
@Override @Override
public Tool getConsumer() { public PluginTool getConsumer() {
return consumerTool; return consumerTool;
} }
/* /*
* @see ghidra.framework.model.ToolListener#processToolEvent(ghidra.framework.model.ToolEvent) * @see ghidra.framework.model.ToolListener#processToolEvent(ghidra.framework.model.ToolEvent)
*/ */
@Override @Override
public void processToolEvent(PluginEvent toolEvent) { public void processToolEvent(PluginEvent toolEvent) {
if (isConnected(toolEvent.getToolEventName())) { if (isConnected(toolEvent.getToolEventName())) {
consumerTool.processToolEvent(toolEvent); consumerTool.processToolEvent(toolEvent);
} }
} }
/** /**
* Saves the Tool Connection into an XML element. * Saves the Tool Connection into an XML element.
*/ */
public Element saveToXml() { public Element saveToXml() {
Element root = new Element("CONNECTION"); Element root = new Element("CONNECTION");
root.setAttribute("PRODUCER",producerTool.getName()); root.setAttribute("PRODUCER", producerTool.getName());
root.setAttribute("CONSUMER",consumerTool.getName()); root.setAttribute("CONSUMER", consumerTool.getName());
root.setAttribute("LISTENER_ADDED",""+listenerAdded); root.setAttribute("LISTENER_ADDED", "" + listenerAdded);
String [] keys = connectHt.getKeys(); String[] keys = connectHt.getKeys();
for (int i = 0 ; i < keys.length ; ++i) { for (String key : keys) {
Element elem = new Element("EVENT"); Element elem = new Element("EVENT");
elem.setAttribute("NAME", keys[i]); elem.setAttribute("NAME", key);
int val = DISCONNECTED; int val = DISCONNECTED;
try { try {
val = connectHt.get(keys[i]); val = connectHt.get(key);
}
catch (NoValueException nve) {
} }
catch (NoValueException nve) {}
elem.setAttribute("CONNECTED", (val == CONNECTED ? "true" : "false")); elem.setAttribute("CONNECTED", (val == CONNECTED ? "true" : "false"));
root.addContent(elem); root.addContent(elem);
} }
changed = false; changed = false;
return root; return root;
} }
/** /**
* restores the ToolConnection from an XML element * restores the ToolConnection from an XML element
* *
* @param root XML element to restore ToolConnection from. * @param root XML element to restore ToolConnection from.
*/ */
public void restoreFromXml(Element root) { public void restoreFromXml(Element root) {
listenerAdded = false; listenerAdded = false;
Iterator<?> iter = root.getChildren("EVENT").iterator(); Iterator<?> iter = root.getChildren("EVENT").iterator();
@ -181,144 +186,144 @@ class ToolConnectionImpl implements ToolConnection, ToolListener {
String state = elem.getAttributeValue("CONNECTED"); String state = elem.getAttributeValue("CONNECTED");
boolean connected = (state != null && state.equalsIgnoreCase("true")); boolean connected = (state != null && state.equalsIgnoreCase("true"));
connectHt.put(name, (connected ? CONNECTED : DISCONNECTED)); connectHt.put(name, (connected ? CONNECTED : DISCONNECTED));
if (connected && !listenerAdded) { if (connected && !listenerAdded) {
producerTool.addToolListener(this); producerTool.addToolListener(this);
listenerAdded = true; listenerAdded = true;
} }
} }
} }
/** /**
* Returns a hash code value for the object. This method is * Returns a hash code value for the object. This method is
* supported for the benefit of hashtables such as those provided by * supported for the benefit of hashtables such as those provided by
* <code>java.util.Hashtable</code>. * <code>java.util.Hashtable</code>.
*/ */
@Override @Override
public int hashCode() { public int hashCode() {
return producerTool.getName().hashCode() + return producerTool.getName().hashCode() +
consumerTool.getName().hashCode(); consumerTool.getName().hashCode();
} }
/** /**
* Indicates whether some other object is "equal to" this one. * Indicates whether some other object is "equal to" this one.
*/ */
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == null) { if (obj == null) {
return false; return false;
} }
if (obj == this) { if (obj == this) {
return true; return true;
} }
if (getClass() != obj.getClass()) { if (getClass() != obj.getClass()) {
return false; return false;
} }
ToolConnectionImpl tc = (ToolConnectionImpl)obj; ToolConnectionImpl tc = (ToolConnectionImpl) obj;
return producerTool.getName().equals(tc.producerTool.getName()) && return producerTool.getName().equals(tc.producerTool.getName()) &&
consumerTool.getName().equals(tc.consumerTool.getName()); consumerTool.getName().equals(tc.consumerTool.getName());
} }
/** /**
* Returns a string representation of the object. In general, the * Returns a string representation of the object. In general, the
* <code>toString</code> method returns a string that * <code>toString</code> method returns a string that
* "textually represents" this object. The result should * "textually represents" this object. The result should
* be a concise but informative representation that is easy for a * be a concise but informative representation that is easy for a
* person to read. * person to read.
*/ */
@Override @Override
public String toString() { public String toString() {
return "Producer=" + producerTool.getName() + return "Producer=" + producerTool.getName() +
", Consumer=" + consumerTool.getName(); ", Consumer=" + consumerTool.getName();
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// ** package methods // ** package methods
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
/** /**
* Return true if the connection changed. * Return true if the connection changed.
*/ */
boolean hasChanged() { boolean hasChanged() {
return changed; return changed;
} }
/** /**
* Update the events that are consumed and produced, as the tool * Update the events that are consumed and produced, as the tool
* may have added or removed plugins. * may have added or removed plugins.
*/ */
void updateEventList() { void updateEventList() {
String[] producerEvents = producerTool.getToolEventNames(); String[] producerEvents = producerTool.getToolEventNames();
String[] consumedEvents = consumerTool.getConsumedToolEventNames(); String[] consumedEvents = consumerTool.getConsumedToolEventNames();
List<String> pList = Arrays.asList(producerEvents); List<String> pList = Arrays.asList(producerEvents);
List<String> cList = Arrays.asList(consumedEvents); List<String> cList = Arrays.asList(consumedEvents);
ArrayList<String> producerList = new ArrayList<>(pList); ArrayList<String> producerList = new ArrayList<>(pList);
ArrayList<String> consumerList = new ArrayList<>(cList); ArrayList<String> consumerList = new ArrayList<>(cList);
// get the intersection of the lists // get the intersection of the lists
producerList.retainAll(consumerList); producerList.retainAll(consumerList);
consumerList.retainAll(producerList); consumerList.retainAll(producerList);
for (int i=0; i<producerList.size(); i++) { for (int i = 0; i < producerList.size(); i++) {
String event = producerList.get(i); String event = producerList.get(i);
if (!connectHt.contains(event)) { if (!connectHt.contains(event)) {
connectHt.put(event, DISCONNECTED); connectHt.put(event, DISCONNECTED);
} }
} }
String[] keys = connectHt.getKeys(); String[] keys = connectHt.getKeys();
for (int i=0; i<keys.length; i++) { for (String key : keys) {
if (!producerList.contains(keys[i])) { if (!producerList.contains(key)) {
connectHt.remove(keys[i]); connectHt.remove(key);
} }
} }
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// ** private methods // ** private methods
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
/** /**
* Verify that the given event name is produced by the * Verify that the given event name is produced by the
* producer tool and is consumed by the consumer tool. * producer tool and is consumed by the consumer tool.
* *
* @throws IllegalArgumentException if the event is not in the * @throws IllegalArgumentException if the event is not in the
* list of events for this producer/consumer pair. * list of events for this producer/consumer pair.
*/ */
private void validateEventName(String eventName) { private void validateEventName(String eventName) {
if (!connectHt.contains(eventName)) { if (!connectHt.contains(eventName)) {
throw new IllegalArgumentException("Event name " + eventName + throw new IllegalArgumentException("Event name " + eventName +
" is not valid for producer " + " is not valid for producer " +
producerTool.getName() + ", consumer " + producerTool.getName() + ", consumer " +
consumerTool.getName()); consumerTool.getName());
} }
} }
/** /**
* Check the connections; if there are none, then remove the * Check the connections; if there are none, then remove the
* consumer tool as a listener on the producer tool; called * consumer tool as a listener on the producer tool; called
* when a disconnect is made. * when a disconnect is made.
*/ */
private void checkConnections() { private void checkConnections() {
String [] eventNames = connectHt.getKeys(); String[] eventNames = connectHt.getKeys();
boolean connectionFound = false; boolean connectionFound = false;
for (int i=0; i<eventNames.length; i++) { for (String eventName : eventNames) {
try { try {
int value = connectHt.get(eventNames[i]); int value = connectHt.get(eventName);
if (value == CONNECTED) { if (value == CONNECTED) {
connectionFound = true; connectionFound = true;
break; break;
} }
} }
catch(NoValueException e) { catch (NoValueException e) {
Msg.showError(this, null, "Error", "Event name not in table: " + e.getMessage()); Msg.showError(this, null, "Error", "Event name not in table: " + e.getMessage());
} }
} }
if (!connectionFound) { if (!connectionFound) {
producerTool.removeToolListener(this); producerTool.removeToolListener(this);
listenerAdded = false; listenerAdded = false;
} }
} }
} }

View file

@ -15,7 +15,8 @@
*/ */
package ghidra.framework.project.tool; package ghidra.framework.project.tool;
import java.beans.*; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.*; import java.util.*;
import org.jdom.Element; import org.jdom.Element;
@ -24,6 +25,7 @@ import docking.ComponentProvider;
import ghidra.framework.main.AppInfo; import ghidra.framework.main.AppInfo;
import ghidra.framework.main.FrontEndTool; import ghidra.framework.main.FrontEndTool;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
@ -56,7 +58,7 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
private Map<String, ToolConnectionImpl> connectMap; private Map<String, ToolConnectionImpl> connectMap;
// map generic tool names to list of tools // map generic tool names to list of tools
private Map<String, List<Tool>> namesMap; private Map<String, List<PluginTool>> namesMap;
/** /**
* keep a handle to the active workspace to make inactive when another * keep a handle to the active workspace to make inactive when another
@ -90,8 +92,8 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
* @param toolName the name of the tool being registers * @param toolName the name of the tool being registers
* @param tool the tool being registered * @param tool the tool being registered
*/ */
private void registerTool(String toolName, Tool tool) { private void registerTool(String toolName, PluginTool tool) {
List<Tool> list = namesMap.get(toolName); List<PluginTool> list = namesMap.get(toolName);
if (list == null) { if (list == null) {
list = new ArrayList<>(5); list = new ArrayList<>(5);
namesMap.put(toolName, list); namesMap.put(toolName, list);
@ -109,8 +111,8 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
tool.addPropertyChangeListener(this); tool.addPropertyChangeListener(this);
} }
private void deregisterTool(String toolName, Tool tool) { private void deregisterTool(String toolName, PluginTool tool) {
List<Tool> list = namesMap.get(toolName); List<PluginTool> list = namesMap.get(toolName);
SystemUtilities.assertTrue(list != null, "Attempted to remove tool that's not there"); SystemUtilities.assertTrue(list != null, "Attempted to remove tool that's not there");
list.remove(tool); list.remove(tool);
if (list.size() == 0) { if (list.size() == 0) {
@ -126,45 +128,45 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
} }
@Override @Override
public Tool[] getConsumerTools() { public PluginTool[] getConsumerTools() {
ArrayList<Tool> consumers = new ArrayList<>(TYPICAL_NUM_TOOLS); ArrayList<PluginTool> consumers = new ArrayList<>(TYPICAL_NUM_TOOLS);
Tool[] runningTools = getRunningTools(); PluginTool[] runningTools = getRunningTools();
for (Tool tool : runningTools) { for (PluginTool tool : runningTools) {
if (tool.getConsumedToolEventNames().length > 0) { if (tool.getConsumedToolEventNames().length > 0) {
consumers.add(tool); consumers.add(tool);
} }
} }
Tool[] tools = new Tool[consumers.size()]; PluginTool[] tools = new PluginTool[consumers.size()];
consumers.toArray(tools); consumers.toArray(tools);
return tools; return tools;
} }
@Override @Override
public Tool[] getProducerTools() { public PluginTool[] getProducerTools() {
ArrayList<Tool> producers = new ArrayList<>(TYPICAL_NUM_TOOLS); ArrayList<PluginTool> producers = new ArrayList<>(TYPICAL_NUM_TOOLS);
Tool[] runningTools = getRunningTools(); PluginTool[] runningTools = getRunningTools();
for (Tool tool : runningTools) { for (PluginTool tool : runningTools) {
if (tool.getToolEventNames().length > 0) { if (tool.getToolEventNames().length > 0) {
producers.add(tool); producers.add(tool);
} }
} }
Tool[] tools = new Tool[producers.size()]; PluginTool[] tools = new PluginTool[producers.size()];
return producers.toArray(tools); return producers.toArray(tools);
} }
@Override @Override
public Tool[] getRunningTools() { public PluginTool[] getRunningTools() {
Workspace[] wsList = new Workspace[workspaces.size()]; Workspace[] wsList = new Workspace[workspaces.size()];
workspaces.toArray(wsList); workspaces.toArray(wsList);
ArrayList<Tool> runningTools = new ArrayList<>(TYPICAL_NUM_TOOLS); ArrayList<PluginTool> runningTools = new ArrayList<>(TYPICAL_NUM_TOOLS);
for (Workspace element : wsList) { for (Workspace element : wsList) {
Tool[] tools = element.getTools(); PluginTool[] tools = element.getTools();
for (Tool tool : tools) { for (PluginTool tool : tools) {
runningTools.add(tool); runningTools.add(tool);
} }
} }
Tool[] tools = new Tool[runningTools.size()]; PluginTool[] tools = new PluginTool[runningTools.size()];
runningTools.toArray(tools); runningTools.toArray(tools);
return tools; return tools;
@ -174,7 +176,7 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
* @see ghidra.framework.model.ToolManager#getConnection(ghidra.framework.model.Tool, ghidra.framework.model.Tool) * @see ghidra.framework.model.ToolManager#getConnection(ghidra.framework.model.Tool, ghidra.framework.model.Tool)
*/ */
@Override @Override
public ToolConnection getConnection(Tool producer, Tool consumer) { public ToolConnection getConnection(PluginTool producer, PluginTool consumer) {
String key = getKey(producer, consumer); String key = getKey(producer, consumer);
ToolConnectionImpl tc = connectMap.get(key); ToolConnectionImpl tc = connectMap.get(key);
if (tc == null) { if (tc == null) {
@ -229,8 +231,8 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
// first close all the tools running in the workspace // first close all the tools running in the workspace
// and if any of the tools don't close, don't remove the workspace // and if any of the tools don't close, don't remove the workspace
Tool[] runningTools = ws.getTools(); PluginTool[] runningTools = ws.getTools();
for (Tool runningTool : runningTools) { for (PluginTool runningTool : runningTools) {
// if data has changed in the tool, the frontEnd will take care // if data has changed in the tool, the frontEnd will take care
// of asking/confirming saving tool // of asking/confirming saving tool
runningTool.close(); runningTool.close();
@ -310,7 +312,7 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
public void restoreFromXml(Element root) { public void restoreFromXml(Element root) {
inRestoreMode = true; inRestoreMode = true;
try { try {
HashMap<String, Tool> toolMap = new HashMap<>(); HashMap<String, PluginTool> toolMap = new HashMap<>();
String activeWSName = root.getAttributeValue("ACTIVE_WORKSPACE"); String activeWSName = root.getAttributeValue("ACTIVE_WORKSPACE");
Workspace makeMeActive = null; Workspace makeMeActive = null;
@ -325,8 +327,8 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
if (ws.getName().equals(activeWSName)) { if (ws.getName().equals(activeWSName)) {
makeMeActive = ws; makeMeActive = ws;
} }
Tool[] tools = ws.getTools(); PluginTool[] tools = ws.getTools();
for (Tool tool : tools) { for (PluginTool tool : tools) {
toolMap.put(tool.getName(), tool); toolMap.put(tool.getName(), tool);
} }
} }
@ -340,8 +342,8 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
String producerName = elem.getAttributeValue("PRODUCER"); String producerName = elem.getAttributeValue("PRODUCER");
String consumerName = elem.getAttributeValue("CONSUMER"); String consumerName = elem.getAttributeValue("CONSUMER");
// get the tools // get the tools
Tool producer = toolMap.get(producerName); PluginTool producer = toolMap.get(producerName);
Tool consumer = toolMap.get(consumerName); PluginTool consumer = toolMap.get(consumerName);
if (producer != null && consumer != null) { if (producer != null && consumer != null) {
ToolConnectionImpl tc = new ToolConnectionImpl(producer, consumer); ToolConnectionImpl tc = new ToolConnectionImpl(producer, consumer);
tc.restoreFromXml(elem); tc.restoreFromXml(elem);
@ -393,9 +395,9 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
public boolean saveSessionTools() { public boolean saveSessionTools() {
Set<String> keySet = namesMap.keySet(); Set<String> keySet = namesMap.keySet();
for (String toolName : keySet) { for (String toolName : keySet) {
List<Tool> tools = namesMap.get(toolName); List<PluginTool> tools = namesMap.get(toolName);
if (tools.size() == 1) { if (tools.size() == 1) {
Tool tool = tools.get(0); PluginTool tool = tools.get(0);
if (tool.shouldSave()) { if (tool.shouldSave()) {
toolServices.saveTool(tool); toolServices.saveTool(tool);
} }
@ -410,9 +412,9 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
return true; return true;
} }
private boolean saveToolSet(List<Tool> tools) { private boolean saveToolSet(List<PluginTool> tools) {
List<Tool> changedTools = new ArrayList<>(); List<PluginTool> changedTools = new ArrayList<>();
for (Tool tool : tools) { for (PluginTool tool : tools) {
if (tool.hasConfigChanged()) { if (tool.hasConfigChanged()) {
changedTools.add(tool); changedTools.add(tool);
} }
@ -422,7 +424,7 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
} }
if (changedTools.size() == 1) { if (changedTools.size() == 1) {
Tool changedTool = changedTools.get(0); PluginTool changedTool = changedTools.get(0);
if (changedTool.shouldSave()) { if (changedTool.shouldSave()) {
toolServices.saveTool(changedTool); toolServices.saveTool(changedTool);
} }
@ -436,7 +438,7 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
return false; return false;
} }
Tool tool = dialog.getSelectedTool(); PluginTool tool = dialog.getSelectedTool();
if (tool != null) { if (tool != null) {
toolServices.saveTool(tool); toolServices.saveTool(tool);
} }
@ -467,15 +469,15 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
Tool tool = (Tool) evt.getSource(); PluginTool tool = (PluginTool) evt.getSource();
String propertyName = evt.getPropertyName(); String propertyName = evt.getPropertyName();
if (propertyName.equals(Tool.PLUGIN_COUNT_PROPERTY_NAME)) { if (propertyName.equals(PluginTool.PLUGIN_COUNT_PROPERTY_NAME)) {
updateConnections(evt); updateConnections(evt);
} }
if (!propertyName.equals(Tool.TOOL_NAME_PROPERTY)) { if (!propertyName.equals(PluginTool.TOOL_NAME_PROPERTY)) {
return; return;
} }
@ -524,7 +526,7 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
} }
@Override @Override
public void toolChanged(Tool tool) { public void toolChanged(PluginTool tool) {
updateConnectMap(tool); updateConnectMap(tool);
} }
@ -536,13 +538,13 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
* @param toolName the name of the tool * @param toolName the name of the tool
* @return the tool * @return the tool
*/ */
public Tool getTool(String toolName) { public PluginTool getTool(String toolName) {
ToolTemplate template = toolServices.getToolChest().getToolTemplate(toolName); ToolTemplate template = toolServices.getToolChest().getToolTemplate(toolName);
if (template == null) { if (template == null) {
return null; return null;
} }
Tool tool = template.createTool(project); PluginTool tool = template.createTool(project);
if (tool != null) { if (tool != null) {
registerTool(toolName, tool); registerTool(toolName, tool);
} }
@ -558,13 +560,13 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
* *
* @param tool tool to be closed. * @param tool tool to be closed.
*/ */
void closeTool(Tool tool) { void closeTool(PluginTool tool) {
// find the workspace running the tool // find the workspace running the tool
for (int i = 0; i < workspaces.size(); i++) { for (int i = 0; i < workspaces.size(); i++) {
WorkspaceImpl ws = (WorkspaceImpl) workspaces.get(i); WorkspaceImpl ws = (WorkspaceImpl) workspaces.get(i);
Tool[] tools = ws.getTools(); PluginTool[] tools = ws.getTools();
for (Tool tool2 : tools) { for (PluginTool tool2 : tools) {
if (tool == tool2) { if (tool == tool2) {
ws.closeRunningTool(tool); ws.closeRunningTool(tool);
return; return;
@ -655,8 +657,8 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
/* /*
* Get a tool from the template; set the instance name. * Get a tool from the template; set the instance name.
*/ */
Tool getTool(Workspace ws, ToolTemplate template) { PluginTool getTool(Workspace ws, ToolTemplate template) {
Tool tool = template.createTool(project); PluginTool tool = template.createTool(project);
if (tool != null) { if (tool != null) {
registerTool(tool.getToolName(), tool); registerTool(tool.getToolName(), tool);
} }
@ -666,7 +668,7 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
/* /*
* Called by the workspace when a tool is removed. * Called by the workspace when a tool is removed.
*/ */
void toolRemoved(Workspace ws, Tool tool) { void toolRemoved(Workspace ws, PluginTool tool) {
deregisterTool(tool.getToolName(), tool); deregisterTool(tool.getToolName(), tool);
disconnectTool(tool); disconnectTool(tool);
@ -680,13 +682,13 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
* Generate an instance name in the form * Generate an instance name in the form
* of a one-up number. * of a one-up number.
*/ */
private String generateInstanceName(String toolName, Tool tool) { private String generateInstanceName(String toolName, PluginTool tool) {
List<Tool> list = namesMap.get(toolName); List<PluginTool> list = namesMap.get(toolName);
if (list.size() <= 1) { if (list.size() <= 1) {
return ""; return "";
} }
Tool lastTool = list.get(list.size() - 2); // the last one is the one we just added above PluginTool lastTool = list.get(list.size() - 2); // the last one is the one we just added above
String instanceName = lastTool.getInstanceName(); String instanceName = lastTool.getInstanceName();
if (instanceName.length() == 0) { if (instanceName.length() == 0) {
return "2"; return "2";
@ -696,8 +698,8 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
return "" + (n + 1); return "" + (n + 1);
} }
Tool createEmptyTool() { PluginTool createEmptyTool() {
Tool tool = new GhidraTool(project, "Untitled"); PluginTool tool = new GhidraTool(project, "Untitled");
addNewTool(tool, "Untitled"); addNewTool(tool, "Untitled");
return tool; return tool;
} }
@ -706,18 +708,12 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
* Add the tool to the table, add us as a listener for property * Add the tool to the table, add us as a listener for property
* changes on the tool. * changes on the tool.
*/ */
private void addNewTool(Tool tool, String toolName) { private void addNewTool(PluginTool tool, String toolName) {
try { tool.setToolName(toolName);
tool.setToolName(toolName); registerTool(toolName, tool);
registerTool(toolName, tool);
}
catch (PropertyVetoException e) {
// shouldn't happen
Msg.showError(this, null, "Error Setting Tool Name", "Set tool name was vetoed", e);
}
} }
void fireToolAddedEvent(Workspace ws, Tool tool) { void fireToolAddedEvent(Workspace ws, PluginTool tool) {
for (int i = 0; i < changeListeners.size(); i++) { for (int i = 0; i < changeListeners.size(); i++) {
WorkspaceChangeListener l = changeListeners.get(i); WorkspaceChangeListener l = changeListeners.get(i);
l.toolAdded(ws, tool); l.toolAdded(ws, tool);
@ -725,13 +721,13 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
} }
@Override @Override
public void disconnectTool(Tool tool) { public void disconnectTool(PluginTool tool) {
Iterator<String> keys = connectMap.keySet().iterator(); Iterator<String> keys = connectMap.keySet().iterator();
while (keys.hasNext()) { while (keys.hasNext()) {
String key = keys.next(); String key = keys.next();
ToolConnection tc = connectMap.get(key); ToolConnection tc = connectMap.get(key);
Tool producer = tc.getProducer(); PluginTool producer = tc.getProducer();
Tool consumer = tc.getConsumer(); PluginTool consumer = tc.getConsumer();
if (producer == tool || consumer == tool) { if (producer == tool || consumer == tool) {
keys.remove(); keys.remove();
producer.removeToolListener((ToolConnectionImpl) tc); producer.removeToolListener((ToolConnectionImpl) tc);
@ -739,15 +735,15 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
} }
} }
private void updateConnectMap(Tool tool) { private void updateConnectMap(PluginTool tool) {
Iterator<String> keys = connectMap.keySet().iterator(); Iterator<String> keys = connectMap.keySet().iterator();
Map<String, ToolConnectionImpl> map = new HashMap<>(); Map<String, ToolConnectionImpl> map = new HashMap<>();
while (keys.hasNext()) { while (keys.hasNext()) {
String key = keys.next(); String key = keys.next();
ToolConnectionImpl tc = connectMap.get(key); ToolConnectionImpl tc = connectMap.get(key);
Tool producer = tc.getProducer(); PluginTool producer = tc.getProducer();
Tool consumer = tc.getConsumer(); PluginTool consumer = tc.getConsumer();
if (producer == tool || consumer == tool) { if (producer == tool || consumer == tool) {
String newkey = getKey(producer, consumer); String newkey = getKey(producer, consumer);
tc.updateEventList(); tc.updateEventList();
@ -767,13 +763,13 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
* @param consumer tool consuming an event * @param consumer tool consuming an event
* *
*/ */
private String getKey(Tool producer, Tool consumer) { private String getKey(PluginTool producer, PluginTool consumer) {
return producer.getName() + "+" + consumer.getName(); return producer.getName() + "+" + consumer.getName();
} }
private void updateConnections(PropertyChangeEvent ev) { private void updateConnections(PropertyChangeEvent ev) {
Tool tool = (Tool) ev.getSource(); PluginTool tool = (PluginTool) ev.getSource();
updateConnectMap(tool); updateConnectMap(tool);
// notify listeners of tool change // notify listeners of tool change
@ -809,7 +805,7 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
return name; return name;
} }
public boolean canAutoSave(Tool tool) { public boolean canAutoSave(PluginTool tool) {
ToolSaveStatus status = toolStatusMap.get(tool.getToolName()); ToolSaveStatus status = toolStatusMap.get(tool.getToolName());
if (status == ToolSaveStatus.ASK_SAVE_MODE) { if (status == ToolSaveStatus.ASK_SAVE_MODE) {
return false; return false;
@ -829,7 +825,7 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
return (status == ToolSaveStatus.AUTO_SAVE_MODE); return (status == ToolSaveStatus.AUTO_SAVE_MODE);
} }
public void toolSaved(Tool tool, boolean toolChanged) { public void toolSaved(PluginTool tool, boolean toolChanged) {
String toolName = tool.getToolName(); String toolName = tool.getToolName();
if (getToolInstanceCount(tool) == 1) { if (getToolInstanceCount(tool) == 1) {
// saving with only one instance open resets the status // saving with only one instance open resets the status
@ -841,8 +837,8 @@ public class ToolManagerImpl implements ToolManager, PropertyChangeListener {
} }
} }
private int getToolInstanceCount(Tool tool) { private int getToolInstanceCount(PluginTool tool) {
List<Tool> list = namesMap.get(tool.getToolName()); List<PluginTool> list = namesMap.get(tool.getToolName());
if (list == null) { if (list == null) {
return 0; return 0;
} }

View file

@ -60,7 +60,7 @@ class ToolServicesImpl implements ToolServices {
} }
@Override @Override
public void closeTool(Tool tool) { public void closeTool(PluginTool tool) {
toolManager.closeTool(tool); toolManager.closeTool(tool);
} }
@ -150,7 +150,7 @@ class ToolServicesImpl implements ToolServices {
} }
@Override @Override
public void saveTool(Tool tool) { public void saveTool(PluginTool tool) {
boolean toolChanged = tool.hasConfigChanged(); boolean toolChanged = tool.hasConfigChanged();
ToolTemplate template = tool.saveToolToToolTemplate(); ToolTemplate template = tool.saveToolToToolTemplate();
toolManager.toolSaved(tool, toolChanged); toolManager.toolSaved(tool, toolChanged);
@ -164,10 +164,10 @@ class ToolServicesImpl implements ToolServices {
} }
@Override @Override
public void displaySimilarTool(Tool tool, DomainFile domainFile, PluginEvent event) { public void displaySimilarTool(PluginTool tool, DomainFile domainFile, PluginEvent event) {
Tool[] similarTools = getSameNamedRunningTools(tool); PluginTool[] similarTools = getSameNamedRunningTools(tool);
Tool matchingTool = findToolUsingFile(similarTools, domainFile); PluginTool matchingTool = findToolUsingFile(similarTools, domainFile);
if (matchingTool != null) { if (matchingTool != null) {
// Bring the matching tool forward. // Bring the matching tool forward.
matchingTool.toFront(); matchingTool.toFront();
@ -185,11 +185,11 @@ class ToolServicesImpl implements ToolServices {
} }
@Override @Override
public Tool launchDefaultTool(DomainFile domainFile) { public PluginTool launchDefaultTool(DomainFile domainFile) {
ToolTemplate template = getDefaultToolTemplate(domainFile); ToolTemplate template = getDefaultToolTemplate(domainFile);
if (template != null) { if (template != null) {
Workspace workspace = toolManager.getActiveWorkspace(); Workspace workspace = toolManager.getActiveWorkspace();
Tool tool = workspace.runTool(template); PluginTool tool = workspace.runTool(template);
tool.setVisible(true); tool.setVisible(true);
if (domainFile != null) { if (domainFile != null) {
tool.acceptDomainFiles(new DomainFile[] { domainFile }); tool.acceptDomainFiles(new DomainFile[] { domainFile });
@ -200,11 +200,11 @@ class ToolServicesImpl implements ToolServices {
} }
@Override @Override
public Tool launchTool(String toolName, DomainFile domainFile) { public PluginTool launchTool(String toolName, DomainFile domainFile) {
ToolTemplate template = findToolChestToolTemplate(toolName); ToolTemplate template = findToolChestToolTemplate(toolName);
if (template != null) { if (template != null) {
Workspace workspace = toolManager.getActiveWorkspace(); Workspace workspace = toolManager.getActiveWorkspace();
Tool tool = workspace.runTool(template); PluginTool tool = workspace.runTool(template);
tool.setVisible(true); tool.setVisible(true);
if (domainFile != null) { if (domainFile != null) {
tool.acceptDomainFiles(new DomainFile[] { domainFile }); tool.acceptDomainFiles(new DomainFile[] { domainFile });
@ -451,20 +451,20 @@ class ToolServicesImpl implements ToolServices {
* *
* @return array of tools that are running and named the same as this one. * @return array of tools that are running and named the same as this one.
*/ */
private Tool[] getSameNamedRunningTools(Tool tool) { private PluginTool[] getSameNamedRunningTools(PluginTool tool) {
String toolName = tool.getToolName(); String toolName = tool.getToolName();
Tool[] tools = toolManager.getRunningTools(); PluginTool[] tools = toolManager.getRunningTools();
List<Tool> toolList = new ArrayList<>(tools.length); List<PluginTool> toolList = new ArrayList<>(tools.length);
for (Tool element : tools) { for (PluginTool element : tools) {
if (toolName.equals(element.getToolName())) { if (toolName.equals(element.getToolName())) {
toolList.add(element); toolList.add(element);
} }
} }
return toolList.toArray(new Tool[toolList.size()]); return toolList.toArray(new PluginTool[toolList.size()]);
} }
@Override @Override
public Tool[] getRunningTools() { public PluginTool[] getRunningTools() {
return toolManager.getRunningTools(); return toolManager.getRunningTools();
} }
@ -476,8 +476,8 @@ class ToolServicesImpl implements ToolServices {
* *
* @return first tool found to be using the domainFile * @return first tool found to be using the domainFile
*/ */
private Tool findToolUsingFile(Tool[] tools, DomainFile domainFile) { private PluginTool findToolUsingFile(PluginTool[] tools, DomainFile domainFile) {
Tool matchingTool = null; PluginTool matchingTool = null;
for (int toolNum = 0; (toolNum < tools.length) && (matchingTool == null); toolNum++) { for (int toolNum = 0; (toolNum < tools.length) && (matchingTool == null); toolNum++) {
PluginTool pTool = (PluginTool) tools[toolNum]; PluginTool pTool = (PluginTool) tools[toolNum];
// Is this tool the same as the type we are in. // Is this tool the same as the type we are in.
@ -493,7 +493,7 @@ class ToolServicesImpl implements ToolServices {
} }
@Override @Override
public boolean canAutoSave(Tool tool) { public boolean canAutoSave(PluginTool tool) {
return toolManager.canAutoSave(tool); return toolManager.canAutoSave(tool);
} }
} }

View file

@ -19,7 +19,9 @@ import java.util.*;
import org.jdom.Element; import org.jdom.Element;
import ghidra.framework.model.*; import ghidra.framework.model.ToolTemplate;
import ghidra.framework.model.Workspace;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
/** /**
@ -33,7 +35,7 @@ class WorkspaceImpl implements Workspace {
private String name; private String name;
private ToolManagerImpl toolManager; private ToolManagerImpl toolManager;
private Set<Tool> runningTools = new HashSet<Tool>(TYPICAL_NUM_RUNNING_TOOLS); private Set<PluginTool> runningTools = new HashSet<PluginTool>(TYPICAL_NUM_RUNNING_TOOLS);
private boolean isActive; private boolean isActive;
WorkspaceImpl(String name, ToolManagerImpl toolManager) { WorkspaceImpl(String name, ToolManagerImpl toolManager) {
@ -47,16 +49,16 @@ class WorkspaceImpl implements Workspace {
} }
@Override @Override
public Tool[] getTools() { public PluginTool[] getTools() {
Tool[] tools = new Tool[runningTools.size()]; PluginTool[] tools = new PluginTool[runningTools.size()];
runningTools.toArray(tools); runningTools.toArray(tools);
return tools; return tools;
} }
@Override @Override
public Tool createTool() { public PluginTool createTool() {
// launch the empty tool // launch the empty tool
Tool emptyTool = toolManager.createEmptyTool(); PluginTool emptyTool = toolManager.createEmptyTool();
// add the new tool to our list of running tools // add the new tool to our list of running tools
runningTools.add(emptyTool); runningTools.add(emptyTool);
@ -70,9 +72,9 @@ class WorkspaceImpl implements Workspace {
} }
@Override @Override
public Tool runTool(ToolTemplate template) { public PluginTool runTool(ToolTemplate template) {
Tool tool = toolManager.getTool(this, template); PluginTool tool = toolManager.getTool(this, template);
if (tool != null) { if (tool != null) {
tool.setVisible(true); tool.setVisible(true);
@ -129,7 +131,7 @@ class WorkspaceImpl implements Workspace {
root.setAttribute("NAME", name); root.setAttribute("NAME", name);
root.setAttribute("ACTIVE", "" + isActive); root.setAttribute("ACTIVE", "" + isActive);
for (Tool tool : runningTools) { for (PluginTool tool : runningTools) {
Element elem = new Element("RUNNING_TOOL"); Element elem = new Element("RUNNING_TOOL");
elem.setAttribute("TOOL_NAME", tool.getToolName()); elem.setAttribute("TOOL_NAME", tool.getToolName());
elem.addContent(tool.saveWindowingDataToXml()); elem.addContent(tool.saveWindowingDataToXml());
@ -156,7 +158,7 @@ class WorkspaceImpl implements Workspace {
String defaultTool = System.getProperty("ghidra.defaulttool"); String defaultTool = System.getProperty("ghidra.defaulttool");
if (defaultTool != null && !defaultTool.equals("")) { if (defaultTool != null && !defaultTool.equals("")) {
Tool tool = toolManager.getTool(defaultTool); PluginTool tool = toolManager.getTool(defaultTool);
runningTools.add(tool); runningTools.add(tool);
toolManager.fireToolAddedEvent(this, tool); toolManager.fireToolAddedEvent(this, tool);
return; return;
@ -170,7 +172,7 @@ class WorkspaceImpl implements Workspace {
continue; continue;
} }
Tool tool = toolManager.getTool(toolName); PluginTool tool = toolManager.getTool(toolName);
if (tool != null) { if (tool != null) {
tool.setVisible(isActive); tool.setVisible(isActive);
@ -198,26 +200,19 @@ class WorkspaceImpl implements Workspace {
} }
} }
/********************************************************************* //==================================================================================================
* package level methods // Package Methods
********************************************************************/ //==================================================================================================
/**
* sets the workspace inactive so it can hide its tools
*/
void setVisible(boolean state) { void setVisible(boolean state) {
isActive = state; isActive = state;
Tool[] tools = getTools(); PluginTool[] tools = getTools();
for (int t = 0; t < tools.length; t++) { for (PluginTool tool : tools) {
tools[t].setVisible(state); tool.setVisible(state);
} }
} }
/** void closeRunningTool(PluginTool tool) {
* Called by the ToolManagerImpl when ToolServices calls
* the closeTool() method.
*/
void closeRunningTool(Tool tool) {
// tool is already closed via the call that got us here, so just clean up // tool is already closed via the call that got us here, so just clean up
runningTools.remove(tool); runningTools.remove(tool);
@ -232,7 +227,7 @@ class WorkspaceImpl implements Workspace {
* ToolManagerImpl which is called from the Project's close() * ToolManagerImpl which is called from the Project's close()
*/ */
void close() { void close() {
for (Tool tool : runningTools) { for (PluginTool tool : runningTools) {
try { try {
tool.exit(); tool.exit();
} }

View file

@ -15,7 +15,6 @@
*/ */
package ghidra.framework.plugintool; package ghidra.framework.plugintool;
import ghidra.framework.model.Tool;
import ghidra.framework.plugintool.util.PluginClassManager; import ghidra.framework.plugintool.util.PluginClassManager;
/** /**
@ -37,7 +36,7 @@ public class DummyPluginTool extends PluginTool {
private static class DummyToolServices extends ToolServicesAdapter { private static class DummyToolServices extends ToolServicesAdapter {
@Override @Override
public void closeTool(Tool t) { public void closeTool(PluginTool t) {
// If we call this, then the entire test VM will exit, which is bad // If we call this, then the entire test VM will exit, which is bad
// System.exit(0); // System.exit(0);
} }

View file

@ -17,7 +17,6 @@ package ghidra.test;
import java.awt.Window; import java.awt.Window;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
@ -34,18 +33,20 @@ import docking.util.image.ToolIconURL;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.options.ToolOptions; import ghidra.framework.options.ToolOptions;
import ghidra.framework.plugintool.PluginEvent; import ghidra.framework.plugintool.PluginEvent;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginClassManager;
import ghidra.framework.plugintool.util.ServiceListener; import ghidra.framework.plugintool.util.ServiceListener;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
public class DummyTool implements Tool { public class DummyTool extends PluginTool {
private final static String DEFAULT_NAME = "untitled"; private final static String DEFAULT_NAME = "untitled";
private String name = DEFAULT_NAME; private String name = DEFAULT_NAME;
private String instanceName; private String instanceName;
private String description; private String description;
private ToolIconURL iconURL; private ToolIconURL dummyIconUrl;
private Project project; private Project project;
private DockingToolActions toolActions = new DummyToolActions(); private DockingToolActions dummyToolActions = new DummyToolActions();
public DummyTool() { public DummyTool() {
this(DEFAULT_NAME); this(DEFAULT_NAME);
@ -61,7 +62,7 @@ public class DummyTool implements Tool {
} }
@Override @Override
public void setToolName(String typeName) throws PropertyVetoException { public void setToolName(String typeName) {
name = typeName; name = typeName;
} }
@ -194,10 +195,6 @@ public class DummyTool implements Tool {
return null; return null;
} }
public void restoreFromXml(Element root) {
//do nothing
}
@Override @Override
public void restoreDataStateFromXml(Element root) { public void restoreDataStateFromXml(Element root) {
//do nothing //do nothing
@ -227,18 +224,18 @@ public class DummyTool implements Tool {
} }
@Override @Override
public void setIconURL(ToolIconURL iconURL) { public void setIconURL(ToolIconURL iconUrl) {
this.iconURL = iconURL; this.dummyIconUrl = iconUrl;
} }
@Override @Override
public ToolIconURL getIconURL() { public ToolIconURL getIconURL() {
return iconURL; return dummyIconUrl;
} }
@Override @Override
public ImageIcon getIcon() { public ImageIcon getIcon() {
return iconURL.getIcon(); return dummyIconUrl.getIcon();
} }
@Override @Override
@ -417,7 +414,7 @@ public class DummyTool implements Tool {
@Override @Override
public DockingToolActions getToolActions() { public DockingToolActions getToolActions() {
return toolActions; return dummyToolActions;
} }
@Override @Override
@ -434,4 +431,9 @@ public class DummyTool implements Tool {
public void removeServiceListener(ServiceListener listener) { public void removeServiceListener(ServiceListener listener) {
//do nothing //do nothing
} }
@Override
public PluginClassManager getPluginClassManager() {
return null;
}
} }

View file

@ -20,6 +20,7 @@ import java.util.Set;
import docking.ComponentProvider; import docking.ComponentProvider;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.actions.DockingToolActions; import docking.actions.DockingToolActions;
import docking.actions.SharedDockingActionPlaceholder;
public class DummyToolActions implements DockingToolActions { public class DummyToolActions implements DockingToolActions {
@ -67,4 +68,9 @@ public class DummyToolActions implements DockingToolActions {
public void removeActions(ComponentProvider provider) { public void removeActions(ComponentProvider provider) {
// stub // stub
} }
@Override
public void registerSharedActionPlaceholder(SharedDockingActionPlaceholder placeholder) {
// stub
}
} }

View file

@ -20,13 +20,15 @@ import javax.swing.ImageIcon;
import org.jdom.Element; import org.jdom.Element;
import docking.util.image.ToolIconURL; import docking.util.image.ToolIconURL;
import ghidra.framework.model.*; import ghidra.framework.model.Project;
import ghidra.framework.model.ToolTemplate;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
public class DummyToolTemplate implements ToolTemplate { public class DummyToolTemplate implements ToolTemplate {
@Override @Override
public Tool createTool(Project project) { public PluginTool createTool(Project project) {
return new DummyTool(project); return new DummyTool(project);
} }

View file

@ -30,7 +30,6 @@ import docking.action.DockingActionIf;
import docking.test.AbstractDockingTest; import docking.test.AbstractDockingTest;
import ghidra.app.plugin.core.byteviewer.ByteViewerPlugin; import ghidra.app.plugin.core.byteviewer.ByteViewerPlugin;
import ghidra.app.services.ProgramManager; import ghidra.app.services.ProgramManager;
import ghidra.framework.model.Tool;
import ghidra.framework.plugintool.Plugin; import ghidra.framework.plugintool.Plugin;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginException; import ghidra.framework.plugintool.util.PluginException;
@ -62,7 +61,7 @@ public class ByteViewerToolConnectionTest extends AbstractGhidraHeadedIntegratio
pressButtonByText(dialog, "OK"); pressButtonByText(dialog, "OK");
} }
closeAllWindowsAndFrames(); closeAllWindows();
env.dispose(); env.dispose();
} }
@ -265,8 +264,8 @@ public class ByteViewerToolConnectionTest extends AbstractGhidraHeadedIntegratio
DockingActionIf runAction = getAction(toolName, "Run Tool"); DockingActionIf runAction = getAction(toolName, "Run Tool");
assertNotNull(runAction);// if action is null, the name of the tool changed assertNotNull(runAction);// if action is null, the name of the tool changed
performAction(runAction, toolName, true); performAction(runAction, toolName, true);
Tool[] tools = frontEndTool.getToolServices().getRunningTools(); PluginTool[] tools = frontEndTool.getToolServices().getRunningTools();
return (PluginTool) tools[tools.length - 1]; return tools[tools.length - 1];
} }
private void performAction(final DockingActionIf action, String name, boolean doWait) private void performAction(final DockingActionIf action, String name, boolean doWait)

View file

@ -125,7 +125,7 @@ public class ToolActionManagerTest extends AbstractGhidraHeadedIntegrationTest {
DockingActionIf closeAction = getAction("Close Tool"); DockingActionIf closeAction = getAction("Close Tool");
performToolButtonAction(closeAction, "Untitled", true, true); performToolButtonAction(closeAction, "Untitled", true, true);
Tool[] tools = frontEndTool.getProject().getToolServices().getRunningTools(); PluginTool[] tools = frontEndTool.getProject().getToolServices().getRunningTools();
assertEquals(0, tools.length); assertEquals(0, tools.length);
} }
@ -136,7 +136,7 @@ public class ToolActionManagerTest extends AbstractGhidraHeadedIntegrationTest {
DockingActionIf runAction = getAction("Untitled", "Run Tool"); DockingActionIf runAction = getAction("Untitled", "Run Tool");
performAction(runAction, "Untitled", true); performAction(runAction, "Untitled", true);
Tool[] tools = frontEndTool.getProject().getToolServices().getRunningTools(); PluginTool[] tools = frontEndTool.getProject().getToolServices().getRunningTools();
assertEquals(2, tools.length); assertEquals(2, tools.length);
} }
@ -160,7 +160,7 @@ public class ToolActionManagerTest extends AbstractGhidraHeadedIntegrationTest {
assertNotNull(window); assertNotNull(window);
waitForCondition(() -> { waitForCondition(() -> {
Tool[] tools = frontEndTool.getToolServices().getRunningTools(); PluginTool[] tools = frontEndTool.getToolServices().getRunningTools();
return tools.length == 2; return tools.length == 2;
}); });
@ -238,7 +238,7 @@ public class ToolActionManagerTest extends AbstractGhidraHeadedIntegrationTest {
clickMouse(jTree, MouseEvent.BUTTON1, bounds.x + 5, bounds.y + 5, 2, 0); clickMouse(jTree, MouseEvent.BUTTON1, bounds.x + 5, bounds.y + 5, 2, 0);
waitForSwing(); waitForSwing();
Tool tool = waitForTool("CodeBrowser", project); PluginTool tool = waitForTool("CodeBrowser", project);
// close the CodeBrowser tool // close the CodeBrowser tool
close(tool); close(tool);
@ -609,7 +609,7 @@ public class ToolActionManagerTest extends AbstractGhidraHeadedIntegrationTest {
return builder.getProgram(); return builder.getProgram();
} }
private void close(final Tool tool) { private void close(final PluginTool tool) {
runSwing(() -> tool.close()); runSwing(() -> tool.close());
} }
@ -617,15 +617,15 @@ public class ToolActionManagerTest extends AbstractGhidraHeadedIntegrationTest {
Preferences.clear(); Preferences.clear();
} }
private Tool waitForTool(String toolName, Project project) { private PluginTool waitForTool(String toolName, Project project) {
Tool tool = null; PluginTool tool = null;
int sleepTime = 100; int sleepTime = 100;
int waitCount = 0; int waitCount = 0;
while (tool == null && waitCount < 300) { while (tool == null && waitCount < 300) {
waitForSwing(); waitForSwing();
sleep(sleepTime); sleep(sleepTime);
ToolManager toolManager = project.getToolManager(); ToolManager toolManager = project.getToolManager();
Tool[] runningTools = toolManager.getRunningTools(); PluginTool[] runningTools = toolManager.getRunningTools();
if (runningTools != null && runningTools.length > 0) { if (runningTools != null && runningTools.length > 0) {
tool = runningTools[0]; tool = runningTools[0];
} }
@ -689,7 +689,7 @@ public class ToolActionManagerTest extends AbstractGhidraHeadedIntegrationTest {
private PluginTool createTool() throws Exception { private PluginTool createTool() throws Exception {
DockingActionIf createAction = getAction("Create Tool"); DockingActionIf createAction = getAction("Create Tool");
performAction(createAction, true); performAction(createAction, true);
Tool[] tools = frontEndTool.getProject().getToolManager().getRunningTools(); PluginTool[] tools = frontEndTool.getProject().getToolManager().getRunningTools();
final PluginTool tool = (PluginTool) tools[0]; final PluginTool tool = (PluginTool) tools[0];
runSwing(() -> { runSwing(() -> {
try { try {

View file

@ -29,7 +29,6 @@ import docking.ActionContext;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import ghidra.app.plugin.core.byteviewer.ByteViewerPlugin; import ghidra.app.plugin.core.byteviewer.ByteViewerPlugin;
import ghidra.app.services.ProgramManager; import ghidra.app.services.ProgramManager;
import ghidra.framework.model.Tool;
import ghidra.framework.plugintool.Plugin; import ghidra.framework.plugintool.Plugin;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginException; import ghidra.framework.plugintool.util.PluginException;
@ -232,8 +231,8 @@ public class ToolConnectionTest extends AbstractGhidraHeadedIntegrationTest {
DockingActionIf runAction = getAction(toolName, "Run Tool"); DockingActionIf runAction = getAction(toolName, "Run Tool");
assertNotNull(runAction);// if action is null, the name of the tool changed assertNotNull(runAction);// if action is null, the name of the tool changed
performAction(runAction, toolName, true); performAction(runAction, toolName, true);
Tool[] tools = frontEndTool.getToolServices().getRunningTools(); PluginTool[] tools = frontEndTool.getToolServices().getRunningTools();
return (PluginTool) tools[tools.length - 1]; return tools[tools.length - 1];
} }
private void performAction(final DockingActionIf action, String name, boolean doWait) private void performAction(final DockingActionIf action, String name, boolean doWait)

View file

@ -32,7 +32,9 @@ import docking.DialogComponentProvider;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.widgets.table.*; import docking.widgets.table.*;
import docking.widgets.tree.GTreeNode; import docking.widgets.tree.GTreeNode;
import ghidra.framework.model.*; import ghidra.framework.model.DomainFile;
import ghidra.framework.model.DomainFolder;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.store.ItemCheckoutStatus; import ghidra.framework.store.ItemCheckoutStatus;
import ghidra.framework.store.Version; import ghidra.framework.store.Version;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
@ -213,16 +215,18 @@ public class VersionControlAction1Test extends AbstractVersionControlActionTest
waitForTasks(); waitForTasks();
// make some changes to check in // make some changes to check in
Program program = (Program) ((DomainFileNode) node).getDomainFile().getDomainObject(this, Program program = (Program) ((DomainFileNode) node).getDomainFile()
true, false, TaskMonitor.DUMMY); .getDomainObject(this,
true, false, TaskMonitor.DUMMY);
editProgram(program, (p) -> { editProgram(program, (p) -> {
SymbolTable symTable = p.getSymbolTable(); SymbolTable symTable = p.getSymbolTable();
symTable.createLabel(p.getMinAddress().getNewAddress(0x010001000), "fred", symTable.createLabel(p.getMinAddress().getNewAddress(0x010001000), "fred",
SourceType.USER_DEFINED); SourceType.USER_DEFINED);
}); });
program = (Program) ((DomainFileNode) xnode).getDomainFile().getDomainObject(this, true, program = (Program) ((DomainFileNode) xnode).getDomainFile()
false, TaskMonitor.DUMMY); .getDomainObject(this, true,
false, TaskMonitor.DUMMY);
editProgram(program, (p) -> { editProgram(program, (p) -> {
SymbolTable symTable = p.getSymbolTable(); SymbolTable symTable = p.getSymbolTable();
symTable.createLabel(p.getMinAddress(), "bob", SourceType.USER_DEFINED); symTable.createLabel(p.getMinAddress(), "bob", SourceType.USER_DEFINED);
@ -251,8 +255,9 @@ public class VersionControlAction1Test extends AbstractVersionControlActionTest
checkout(programNode); checkout(programNode);
Program program = Program program =
(Program) ((DomainFileNode) programNode).getDomainFile().getDomainObject(this, true, (Program) ((DomainFileNode) programNode).getDomainFile()
false, TaskMonitor.DUMMY); .getDomainObject(this, true,
false, TaskMonitor.DUMMY);
createHistoryEntry(program, "Symbol1"); createHistoryEntry(program, "Symbol1");
frontEnd.checkIn(programNode, "This is checkin 1"); frontEnd.checkIn(programNode, "This is checkin 1");
@ -334,7 +339,7 @@ public class VersionControlAction1Test extends AbstractVersionControlActionTest
waitForSwing(); waitForSwing();
List<Tool> tools = frontEnd.getTools(); List<PluginTool> tools = frontEnd.getTools();
assertEquals(1, tools.size()); assertEquals(1, tools.size());
DomainFile[] dfs = tools.get(0).getDomainFiles(); DomainFile[] dfs = tools.get(0).getDomainFiles();
@ -405,7 +410,7 @@ public class VersionControlAction1Test extends AbstractVersionControlActionTest
waitForSwing(); waitForSwing();
List<Tool> tools = frontEnd.getTools(); List<PluginTool> tools = frontEnd.getTools();
assertEquals(1, tools.size()); assertEquals(1, tools.size());
DomainFile[] dfs = tools.get(0).getDomainFiles(); DomainFile[] dfs = tools.get(0).getDomainFiles();
@ -482,7 +487,7 @@ public class VersionControlAction1Test extends AbstractVersionControlActionTest
waitForSwing(); waitForSwing();
List<Tool> tools = frontEnd.getTools(); List<PluginTool> tools = frontEnd.getTools();
assertEquals(1, tools.size()); assertEquals(1, tools.size());
DomainFile[] dfs = tools.get(0).getDomainFiles(); DomainFile[] dfs = tools.get(0).getDomainFiles();

View file

@ -335,8 +335,8 @@ public class FrontEndTestEnv {
return env.showTool(); return env.showTool();
} }
public List<Tool> getTools() { public List<PluginTool> getTools() {
Tool[] tools = frontEndTool.getProject().getToolManager().getActiveWorkspace().getTools(); PluginTool[] tools = frontEndTool.getProject().getToolManager().getActiveWorkspace().getTools();
return new ArrayList<>(Arrays.asList(tools)); return new ArrayList<>(Arrays.asList(tools));
} }