mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
Task Launcher - refactored odd use-case
This commit is contained in:
parent
2cf9f7dded
commit
454ce9c817
7 changed files with 80 additions and 95 deletions
|
@ -32,8 +32,9 @@ public class MoveBlockTask extends ProgramTask {
|
|||
private Address currentStart;
|
||||
private Address newStart;
|
||||
private MoveBlockListener listener;
|
||||
private boolean wasCancelled;
|
||||
private boolean status;
|
||||
private boolean cancelled;
|
||||
private String statusMessage;
|
||||
private boolean success;
|
||||
|
||||
/**
|
||||
* Creates a background command for moving memory blocks. The memory block
|
||||
|
@ -62,58 +63,53 @@ public class MoveBlockTask extends ProgramTask {
|
|||
Memory mem = program.getMemory();
|
||||
MemoryBlock block = mem.getBlock(currentStart);
|
||||
monitor.setMessage("Moving Memory Block ...");
|
||||
String msg = "";
|
||||
statusMessage = "";
|
||||
Throwable cause = null;
|
||||
try {
|
||||
mem.moveBlock(block, newStart, monitor);
|
||||
if (monitor.isCancelled()) {
|
||||
wasCancelled = true;
|
||||
cancelled = true;
|
||||
}
|
||||
else {
|
||||
status = true;
|
||||
success = true;
|
||||
listener.moveBlockCompleted(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (OutOfMemoryError e) {
|
||||
msg = "Insufficient memory to complete operation";
|
||||
statusMessage = "Insufficient memory to complete operation";
|
||||
cause = e;
|
||||
}
|
||||
catch (NotFoundException exc) {
|
||||
msg = "Memory block not found";
|
||||
cause = exc;
|
||||
catch (NotFoundException e) {
|
||||
statusMessage = "Memory block not found";
|
||||
cause = e;
|
||||
}
|
||||
catch (MemoryConflictException exc) {
|
||||
msg = exc.getMessage();
|
||||
cause = exc;
|
||||
}
|
||||
catch (MemoryBlockException exc) {
|
||||
msg = exc.getMessage();
|
||||
cause = exc;
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
msg = e.getMessage();
|
||||
catch (MemoryConflictException | MemoryBlockException | IllegalArgumentException e) {
|
||||
statusMessage = e.getMessage();
|
||||
cause = e;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
Msg.error(this, "Unexpected Exception: " + t.getMessage(), t);
|
||||
msg = t.getMessage();
|
||||
if (msg == null) {
|
||||
msg = t.toString();
|
||||
statusMessage = t.getMessage();
|
||||
if (statusMessage == null) {
|
||||
statusMessage = t.toString();
|
||||
}
|
||||
cause = t;
|
||||
}
|
||||
|
||||
monitor.setMessage(msg);
|
||||
listener.moveBlockCompleted(this);
|
||||
throw new RollbackException(msg, cause);
|
||||
throw new RollbackException(statusMessage, cause);
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
return wasCancelled;
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
public boolean getStatus() {
|
||||
return status;
|
||||
public boolean wasSuccessful() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public String getStatusMessage() {
|
||||
return statusMessage;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,9 @@ import ghidra.framework.plugintool.PluginTool;
|
|||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.layout.PairLayout;
|
||||
import ghidra.util.task.BackgroundThreadTaskLauncher;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
import ghidra.util.task.TaskBuilder;
|
||||
|
||||
/**
|
||||
* Dialog that uses a model to validate the fields for moving a block of memory.
|
||||
|
@ -49,15 +49,6 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
|
|||
private MoveBlockModel model;
|
||||
private PluginTool tool;
|
||||
|
||||
/**
|
||||
* Constructor for MoveBlockDialog.
|
||||
*
|
||||
* @param dialog
|
||||
* @param title
|
||||
* @param modal
|
||||
* @param includeStatus
|
||||
* @param includeButtons
|
||||
*/
|
||||
MoveBlockDialog(MoveBlockModel model, PluginTool tool) {
|
||||
super("Move Memory Block");
|
||||
this.model = model;
|
||||
|
@ -69,33 +60,22 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
|
|||
addCancelButton();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.app.plugin.contrib.memory.MoveBlockListener#moveBlockCompleted(boolean,
|
||||
* java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void moveBlockCompleted(final MoveBlockTask cmd) {
|
||||
Runnable r = () -> {
|
||||
if (cmd.getStatus()) {
|
||||
close();
|
||||
model.dispose();
|
||||
}
|
||||
else {
|
||||
public void moveBlockCompleted(MoveBlockTask task) {
|
||||
|
||||
setCursor(Cursor.getDefaultCursor());
|
||||
setOkEnabled(false);
|
||||
if (cmd.isCancelled()) {
|
||||
tool.setStatusInfo(getStatusText());
|
||||
boolean success = task.wasSuccessful();
|
||||
setOkEnabled(success);
|
||||
setStatusText(task.getStatusMessage());
|
||||
|
||||
Swing.runLater(() -> {
|
||||
if (success) {
|
||||
close();
|
||||
model.dispose();
|
||||
}
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(r);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.app.plugin.contrib.memory.MoveBlockListener#stateChanged()
|
||||
*/
|
||||
@Override
|
||||
public void stateChanged() {
|
||||
setOkEnabled(false);
|
||||
|
@ -138,18 +118,20 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
|
|||
setOkEnabled(false);
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
|
||||
BackgroundThreadTaskLauncher launcher = new BackgroundThreadTaskLauncher(model.makeTask());
|
||||
launcher.run(new TaskMonitorAdapter() {
|
||||
@Override
|
||||
public void setMessage(String message) {
|
||||
setStatusText(message);
|
||||
}
|
||||
});
|
||||
MoveBlockTask task = model.makeTask();
|
||||
|
||||
//@formatter:off
|
||||
TaskBuilder.withTask(task)
|
||||
.setParent(this.getComponent())
|
||||
.launchModal()
|
||||
;
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cancelCallback() {
|
||||
close();
|
||||
model.dispose();
|
||||
}
|
||||
|
||||
private JPanel buildMainPanel() {
|
||||
|
|
|
@ -17,15 +17,10 @@ package ghidra.app.plugin.core.memory;
|
|||
|
||||
import ghidra.app.cmd.memory.MoveBlockListener;
|
||||
import ghidra.app.cmd.memory.MoveBlockTask;
|
||||
import ghidra.framework.model.DomainObject;
|
||||
import ghidra.framework.model.DomainObjectChangedEvent;
|
||||
import ghidra.framework.model.DomainObjectListener;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.program.model.address.AddressOverflowException;
|
||||
import ghidra.framework.model.*;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.util.task.Task;
|
||||
|
||||
/**
|
||||
* Model for moving a memory block; this class does validation of the new start
|
||||
|
@ -172,11 +167,11 @@ class MoveBlockModel implements DomainObjectListener {
|
|||
}
|
||||
|
||||
/**
|
||||
* Start the task that will move the block.
|
||||
* Create the task that will move the block
|
||||
*
|
||||
* @param delay number of ms to delay until the progress dialog is displayed
|
||||
* @return the new task
|
||||
*/
|
||||
Task makeTask() {
|
||||
MoveBlockTask makeTask() {
|
||||
return new MoveBlockTask(program, block.getStart(), newStartAddr, listener);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ import ghidra.program.model.listing.Program;
|
|||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
import ghidra.test.TestEnv;
|
||||
import ghidra.util.task.*;
|
||||
import ghidra.util.task.TaskBuilder;
|
||||
|
||||
public class MoveBlockModelTest extends AbstractGhidraHeadedIntegrationTest
|
||||
implements MoveBlockListener {
|
||||
|
@ -42,7 +42,7 @@ public class MoveBlockModelTest extends AbstractGhidraHeadedIntegrationTest
|
|||
private MemoryBlock block;
|
||||
|
||||
private volatile boolean moveCompleted;
|
||||
private volatile boolean status;
|
||||
private volatile boolean success;
|
||||
private volatile String errMsg;
|
||||
|
||||
private Program buildProgram1(String programName) throws Exception {
|
||||
|
@ -134,7 +134,7 @@ public class MoveBlockModelTest extends AbstractGhidraHeadedIntegrationTest
|
|||
|
||||
// wait until the we get the move complete notification
|
||||
waitForCondition(() -> moveCompleted && notepad.canLock());
|
||||
assertTrue("Error message= [" + errMsg + "], ", status);
|
||||
assertTrue("Error message= [" + errMsg + "], ", success);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -145,7 +145,7 @@ public class MoveBlockModelTest extends AbstractGhidraHeadedIntegrationTest
|
|||
|
||||
// wait until the we get the move complete notification
|
||||
waitForCondition(() -> moveCompleted && notepad.canLock());
|
||||
assertTrue("Error message= [" + errMsg + "], ", status);
|
||||
assertTrue("Error message= [" + errMsg + "], ", success);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -177,7 +177,7 @@ public class MoveBlockModelTest extends AbstractGhidraHeadedIntegrationTest
|
|||
waitForCondition(() -> moveCompleted && x8051.canLock());
|
||||
setErrorsExpected(false);
|
||||
|
||||
assertFalse("Error message= [" + errMsg + "], ", status);
|
||||
assertFalse("Error message= [" + errMsg + "], ", success);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -242,15 +242,10 @@ public class MoveBlockModelTest extends AbstractGhidraHeadedIntegrationTest
|
|||
assertNotNull(errMsg);
|
||||
}
|
||||
|
||||
private void launch(Task task) {
|
||||
private void launch(MoveBlockTask task) {
|
||||
|
||||
BackgroundThreadTaskLauncher launcher = new BackgroundThreadTaskLauncher(task);
|
||||
launcher.run(new TaskMonitorAdapter() {
|
||||
@Override
|
||||
public void setMessage(String message) {
|
||||
errMsg = message;
|
||||
}
|
||||
});
|
||||
TaskBuilder.withTask(task).launchModal();
|
||||
errMsg = task.getStatusMessage();
|
||||
}
|
||||
|
||||
private Address getNotepadAddr(int offset) {
|
||||
|
@ -265,7 +260,7 @@ public class MoveBlockModelTest extends AbstractGhidraHeadedIntegrationTest
|
|||
@Override
|
||||
public void moveBlockCompleted(MoveBlockTask cmd) {
|
||||
moveCompleted = true;
|
||||
this.status = cmd.getStatus();
|
||||
this.success = cmd.wasSuccessful();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -221,8 +221,8 @@ public abstract class DataLoadingConstraintEditor<T> extends AbstractColumnConst
|
|||
reloadDataButton.setVisible(false);
|
||||
Task task = new LoadDataTask();
|
||||
task.addTaskListener(this);
|
||||
BackgroundThreadTaskLauncher launcher = new BackgroundThreadTaskLauncher(task);
|
||||
launcher.run(taskMonitorComponent);
|
||||
|
||||
TaskBuilder.withTask(task).launchInBackground(taskMonitorComponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,15 +30,15 @@ import ghidra.util.TaskUtilities;
|
|||
*
|
||||
* <p>See {@link TaskLauncher}.
|
||||
*/
|
||||
public class BackgroundThreadTaskLauncher {
|
||||
class BackgroundThreadTaskLauncher {
|
||||
|
||||
private Task task;
|
||||
|
||||
public BackgroundThreadTaskLauncher(Task task) {
|
||||
BackgroundThreadTaskLauncher(Task task) {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
public void run(TaskMonitor monitor) {
|
||||
void run(TaskMonitor monitor) {
|
||||
// add the task here, so we can track it before it is actually started by the thread
|
||||
TaskUtilities.addTrackedTask(task, monitor);
|
||||
|
||||
|
@ -49,5 +49,6 @@ public class BackgroundThreadTaskLauncher {
|
|||
Thread.currentThread().setName(name);
|
||||
task.monitoredRun(monitor);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -255,6 +255,22 @@ public class TaskBuilder {
|
|||
new TaskLauncher(t, parent, delay, dialogWidth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the task in a background thread with the given monitor that cannot be null. This
|
||||
* is a special case for clients that already have a task monitor widget in their UI and
|
||||
* they wish to let it show the progress of the given task while not blocking the Swing
|
||||
* thread.
|
||||
*
|
||||
* @param monitor the task monitor; may not be null
|
||||
*/
|
||||
public void launchInBackground(TaskMonitor monitor) {
|
||||
// validate(); // not needed since we are in the background
|
||||
Objects.requireNonNull(monitor);
|
||||
BackgroundThreadTaskLauncher launcher =
|
||||
new BackgroundThreadTaskLauncher(new TaskBuilderTask(false));
|
||||
launcher.run(monitor);
|
||||
}
|
||||
|
||||
private void validate() {
|
||||
if (title == null) {
|
||||
throw new NullPointerException("Task title cannot be null");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue