mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Merge remote-tracking branch 'origin/GT-3599-dragonmacher-analysis-rollback-on-exception'
This commit is contained in:
commit
e828628bd9
6 changed files with 291 additions and 76 deletions
|
@ -22,7 +22,6 @@ import java.util.*;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import db.DBHandle;
|
|
||||||
import generic.test.AbstractGenericTest;
|
import generic.test.AbstractGenericTest;
|
||||||
import ghidra.framework.model.*;
|
import ghidra.framework.model.*;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
|
@ -82,23 +81,6 @@ public class PairedTransactionTest extends AbstractGenericTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DummyDomainObject extends DomainObjectAdapterDB {
|
|
||||||
|
|
||||||
protected DummyDomainObject(String name, Object consumer) throws IOException {
|
|
||||||
super(new DBHandle(), name, 10, 1, consumer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return "Test object: " + testName.getMethodName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChangeable() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String START = "Start";
|
private static String START = "Start";
|
||||||
private static String END = "End";
|
private static String END = "End";
|
||||||
private static String UNDO_STATE_CHANGE1 = "UndoRedo1";
|
private static String UNDO_STATE_CHANGE1 = "UndoRedo1";
|
||||||
|
@ -106,7 +88,7 @@ public class PairedTransactionTest extends AbstractGenericTest {
|
||||||
|
|
||||||
class MyListener implements TransactionListener {
|
class MyListener implements TransactionListener {
|
||||||
|
|
||||||
private List<String> events = new ArrayList<String>();
|
private List<String> events = new ArrayList<>();
|
||||||
private Transaction lastTransaction;
|
private Transaction lastTransaction;
|
||||||
private DomainObjectAdapterDB obj;
|
private DomainObjectAdapterDB obj;
|
||||||
|
|
||||||
|
@ -122,7 +104,8 @@ public class PairedTransactionTest extends AbstractGenericTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void transactionStarted(DomainObjectAdapterDB domainObj, Transaction tx) {
|
public synchronized void transactionStarted(DomainObjectAdapterDB domainObj,
|
||||||
|
Transaction tx) {
|
||||||
assertEquals(obj, domainObj);
|
assertEquals(obj, domainObj);
|
||||||
events.add(START);
|
events.add(START);
|
||||||
lastTransaction = tx;
|
lastTransaction = tx;
|
||||||
|
@ -176,8 +159,8 @@ public class PairedTransactionTest extends AbstractGenericTest {
|
||||||
|
|
||||||
assertTrue(obj1.canUndo());
|
assertTrue(obj1.canUndo());
|
||||||
assertTrue(obj2.canUndo());
|
assertTrue(obj2.canUndo());
|
||||||
assertTrue(!obj1.canRedo());
|
assertFalse(obj1.canRedo());
|
||||||
assertTrue(!obj2.canRedo());
|
assertFalse(obj2.canRedo());
|
||||||
|
|
||||||
Transaction tx = obj1Listener.getLastTransaction();
|
Transaction tx = obj1Listener.getLastTransaction();
|
||||||
obj1Listener.getEvents();
|
obj1Listener.getEvents();
|
||||||
|
@ -204,15 +187,15 @@ public class PairedTransactionTest extends AbstractGenericTest {
|
||||||
assertEquals(obj1, synchronizedDomainObjects[0]);
|
assertEquals(obj1, synchronizedDomainObjects[0]);
|
||||||
assertEquals(obj2, synchronizedDomainObjects[1]);
|
assertEquals(obj2, synchronizedDomainObjects[1]);
|
||||||
|
|
||||||
assertEquals(synchronizedDomainObjects, obj2.getSynchronizedDomainObjects());
|
assertArrayEquals(synchronizedDomainObjects, obj2.getSynchronizedDomainObjects());
|
||||||
|
|
||||||
assertEquals(0, obj1.getUndoStackDepth());
|
assertEquals(0, obj1.getUndoStackDepth());
|
||||||
assertEquals(0, obj2.getUndoStackDepth());
|
assertEquals(0, obj2.getUndoStackDepth());
|
||||||
|
|
||||||
assertTrue(!obj1.canUndo());
|
assertFalse(obj1.canUndo());
|
||||||
assertTrue(!obj2.canUndo());
|
assertFalse(obj2.canUndo());
|
||||||
assertTrue(!obj1.canRedo());
|
assertFalse(obj1.canRedo());
|
||||||
assertTrue(!obj2.canRedo());
|
assertFalse(obj2.canRedo());
|
||||||
|
|
||||||
String[] events1 = obj1Listener.getEvents();
|
String[] events1 = obj1Listener.getEvents();
|
||||||
assertEquals(UNDO_STATE_CHANGE1, events1[events1.length - 1]);
|
assertEquals(UNDO_STATE_CHANGE1, events1[events1.length - 1]);
|
||||||
|
@ -269,10 +252,10 @@ public class PairedTransactionTest extends AbstractGenericTest {
|
||||||
assertEquals(0, obj1.getUndoStackDepth());
|
assertEquals(0, obj1.getUndoStackDepth());
|
||||||
assertEquals(0, obj2.getUndoStackDepth());
|
assertEquals(0, obj2.getUndoStackDepth());
|
||||||
|
|
||||||
assertTrue(!obj1.canUndo());
|
assertFalse(obj1.canUndo());
|
||||||
assertTrue(!obj2.canUndo());
|
assertFalse(obj2.canUndo());
|
||||||
assertTrue(!obj1.canRedo());
|
assertFalse(obj1.canRedo());
|
||||||
assertTrue(!obj2.canRedo());
|
assertFalse(obj2.canRedo());
|
||||||
|
|
||||||
events1 = obj1Listener.getEvents();
|
events1 = obj1Listener.getEvents();
|
||||||
events2 = obj2Listener.getEvents();
|
events2 = obj2Listener.getEvents();
|
||||||
|
@ -329,8 +312,8 @@ public class PairedTransactionTest extends AbstractGenericTest {
|
||||||
|
|
||||||
assertTrue(obj1.canUndo());
|
assertTrue(obj1.canUndo());
|
||||||
assertTrue(obj2.canUndo());
|
assertTrue(obj2.canUndo());
|
||||||
assertTrue(!obj1.canRedo());
|
assertFalse(obj1.canRedo());
|
||||||
assertTrue(!obj2.canRedo());
|
assertFalse(obj2.canRedo());
|
||||||
|
|
||||||
events1 = obj1Listener.getEvents();
|
events1 = obj1Listener.getEvents();
|
||||||
events2 = obj2Listener.getEvents();
|
events2 = obj2Listener.getEvents();
|
||||||
|
@ -344,8 +327,8 @@ public class PairedTransactionTest extends AbstractGenericTest {
|
||||||
|
|
||||||
obj1.undo();
|
obj1.undo();
|
||||||
|
|
||||||
assertTrue(!obj1.canUndo());
|
assertFalse(obj1.canUndo());
|
||||||
assertTrue(!obj2.canUndo());
|
assertFalse(obj2.canUndo());
|
||||||
assertTrue(obj1.canRedo());
|
assertTrue(obj1.canRedo());
|
||||||
assertTrue(obj2.canRedo());
|
assertTrue(obj2.canRedo());
|
||||||
|
|
||||||
|
@ -366,8 +349,8 @@ public class PairedTransactionTest extends AbstractGenericTest {
|
||||||
|
|
||||||
assertTrue(obj1.canUndo());
|
assertTrue(obj1.canUndo());
|
||||||
assertTrue(obj2.canUndo());
|
assertTrue(obj2.canUndo());
|
||||||
assertTrue(!obj1.canRedo());
|
assertFalse(obj1.canRedo());
|
||||||
assertTrue(!obj2.canRedo());
|
assertFalse(obj2.canRedo());
|
||||||
|
|
||||||
events1 = obj1Listener.getEvents();
|
events1 = obj1Listener.getEvents();
|
||||||
events2 = obj2Listener.getEvents();
|
events2 = obj2Listener.getEvents();
|
||||||
|
@ -388,10 +371,10 @@ public class PairedTransactionTest extends AbstractGenericTest {
|
||||||
assertEquals(0, obj1.getUndoStackDepth());
|
assertEquals(0, obj1.getUndoStackDepth());
|
||||||
assertEquals(0, obj2.getUndoStackDepth());
|
assertEquals(0, obj2.getUndoStackDepth());
|
||||||
|
|
||||||
assertTrue(!obj1.canUndo());
|
assertFalse(obj1.canUndo());
|
||||||
assertTrue(!obj2.canUndo());
|
assertFalse(obj2.canUndo());
|
||||||
assertTrue(!obj1.canRedo());
|
assertFalse(obj1.canRedo());
|
||||||
assertTrue(!obj2.canRedo());
|
assertFalse(obj2.canRedo());
|
||||||
|
|
||||||
events1 = obj1Listener.getEvents();
|
events1 = obj1Listener.getEvents();
|
||||||
events2 = obj2Listener.getEvents();
|
events2 = obj2Listener.getEvents();
|
||||||
|
@ -449,10 +432,10 @@ public class PairedTransactionTest extends AbstractGenericTest {
|
||||||
assertEquals(0, obj1.getUndoStackDepth());
|
assertEquals(0, obj1.getUndoStackDepth());
|
||||||
assertEquals(1, obj2.getUndoStackDepth());
|
assertEquals(1, obj2.getUndoStackDepth());
|
||||||
|
|
||||||
assertTrue(!obj1.canUndo());
|
assertFalse(obj1.canUndo());
|
||||||
assertTrue(obj2.canUndo());
|
assertTrue(obj2.canUndo());
|
||||||
assertTrue(!obj1.canRedo());
|
assertFalse(obj1.canRedo());
|
||||||
assertTrue(!obj2.canRedo());
|
assertFalse(obj2.canRedo());
|
||||||
|
|
||||||
events1 = obj1Listener.getEvents();
|
events1 = obj1Listener.getEvents();
|
||||||
events2 = obj2Listener.getEvents();
|
events2 = obj2Listener.getEvents();
|
||||||
|
|
|
@ -0,0 +1,184 @@
|
||||||
|
/* ###
|
||||||
|
* 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.plugintool.mgr;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import generic.test.AbstractGenericTest;
|
||||||
|
import ghidra.framework.cmd.BackgroundCommand;
|
||||||
|
import ghidra.framework.data.DummyDomainObject;
|
||||||
|
import ghidra.framework.model.*;
|
||||||
|
import ghidra.test.DummyTool;
|
||||||
|
import ghidra.util.UniversalIdGenerator;
|
||||||
|
import ghidra.util.exception.RollbackException;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
|
public class BackgroundCommandTaskTest extends AbstractGenericTest {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
UniversalIdGenerator.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccessfulCommand() throws Exception {
|
||||||
|
|
||||||
|
DummyTool tool = new DummyTool();
|
||||||
|
ToolTaskManager taskManager = new ToolTaskManager(tool);
|
||||||
|
SpyDomainObject domainObject = new SpyDomainObject(this);
|
||||||
|
SuccessfulDummyCommand cmd = new SuccessfulDummyCommand();
|
||||||
|
taskManager.executeCommand(cmd, domainObject);
|
||||||
|
|
||||||
|
waitFor(taskManager);
|
||||||
|
assertTrue(domainObject.wasCommitted());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExceptionalCommand_NonRollbackException() throws Exception {
|
||||||
|
|
||||||
|
DummyTool tool = new DummyTool();
|
||||||
|
ToolTaskManager taskManager = new ToolTaskManager(tool);
|
||||||
|
SpyDomainObject domainObject = new SpyDomainObject(this);
|
||||||
|
NullPointerExceptionCommand cmd = new NullPointerExceptionCommand();
|
||||||
|
|
||||||
|
setErrorsExpected(true);
|
||||||
|
taskManager.executeCommand(cmd, domainObject);
|
||||||
|
waitFor(taskManager);
|
||||||
|
setErrorsExpected(false);
|
||||||
|
|
||||||
|
assertTrue(domainObject.wasCommitted());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExceptionalCommand_RollbackException() throws Exception {
|
||||||
|
|
||||||
|
DummyTool tool = new DummyTool();
|
||||||
|
ToolTaskManager taskManager = new ToolTaskManager(tool);
|
||||||
|
SpyDomainObject domainObject = new SpyDomainObject(this);
|
||||||
|
RollbackExceptionCommand cmd = new RollbackExceptionCommand();
|
||||||
|
|
||||||
|
setErrorsExpected(true);
|
||||||
|
taskManager.executeCommand(cmd, domainObject);
|
||||||
|
waitFor(taskManager);
|
||||||
|
setErrorsExpected(false);
|
||||||
|
|
||||||
|
assertFalse(domainObject.wasCommitted());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExceptionalCommand_DomainObjectLockedException() throws Exception {
|
||||||
|
|
||||||
|
DummyTool tool = new DummyTool();
|
||||||
|
ToolTaskManager taskManager = new ToolTaskManager(tool);
|
||||||
|
SpyDomainObject domainObject = new SpyDomainObject(this);
|
||||||
|
DomainObjectLockedExceptionCommand cmd = new DomainObjectLockedExceptionCommand();
|
||||||
|
|
||||||
|
setErrorsExpected(true);
|
||||||
|
taskManager.executeCommand(cmd, domainObject);
|
||||||
|
waitFor(taskManager);
|
||||||
|
setErrorsExpected(false);
|
||||||
|
|
||||||
|
assertFalse(domainObject.wasCommitted());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void waitFor(ToolTaskManager taskManager) {
|
||||||
|
waitFor(() -> !taskManager.isBusy());
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SpyDomainObject extends DummyDomainObject {
|
||||||
|
|
||||||
|
private static final int ID = 1;
|
||||||
|
private boolean transactionCommited;
|
||||||
|
|
||||||
|
protected SpyDomainObject(Object consumer) throws IOException {
|
||||||
|
super(consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int startTransaction(String description) {
|
||||||
|
return startTransaction(description, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int startTransaction(String description, AbortedTransactionListener listener) {
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endTransaction(int transactionID, boolean commit) {
|
||||||
|
|
||||||
|
assertEquals(ID, transactionID);
|
||||||
|
transactionCommited = commit;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean wasCommitted() {
|
||||||
|
return transactionCommited;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SuccessfulDummyCommand extends BackgroundCommand {
|
||||||
|
|
||||||
|
SuccessfulDummyCommand() {
|
||||||
|
super("Dummy", true, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NullPointerExceptionCommand extends BackgroundCommand {
|
||||||
|
|
||||||
|
NullPointerExceptionCommand() {
|
||||||
|
super("Dummy", true, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RollbackExceptionCommand extends BackgroundCommand {
|
||||||
|
RollbackExceptionCommand() {
|
||||||
|
super("Dummy", true, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
||||||
|
throw new RollbackException("This is a rollback exception");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DomainObjectLockedExceptionCommand extends BackgroundCommand {
|
||||||
|
DomainObjectLockedExceptionCommand() {
|
||||||
|
super("Dummy", true, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
||||||
|
throw new DomainObjectLockedException("Unable to connect");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,15 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.feature.vt.gui.filters;
|
package ghidra.feature.vt.gui.filters;
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import db.DBHandle;
|
|
||||||
import ghidra.feature.vt.api.db.VTSessionDB;
|
import ghidra.feature.vt.api.db.VTSessionDB;
|
||||||
import ghidra.feature.vt.api.impl.VTChangeManager;
|
import ghidra.feature.vt.api.impl.VTChangeManager;
|
||||||
import ghidra.feature.vt.api.impl.VersionTrackingChangeRecord;
|
import ghidra.feature.vt.api.impl.VersionTrackingChangeRecord;
|
||||||
|
@ -32,7 +30,7 @@ import ghidra.feature.vt.db.DummyTestProgramCorrelator;
|
||||||
import ghidra.feature.vt.db.VTBaseTestCase;
|
import ghidra.feature.vt.db.VTBaseTestCase;
|
||||||
import ghidra.feature.vt.gui.plugin.VTController;
|
import ghidra.feature.vt.gui.plugin.VTController;
|
||||||
import ghidra.feature.vt.gui.plugin.VTControllerListener;
|
import ghidra.feature.vt.gui.plugin.VTControllerListener;
|
||||||
import ghidra.framework.data.DomainObjectAdapterDB;
|
import ghidra.framework.data.DummyDomainObject;
|
||||||
import ghidra.framework.model.*;
|
import ghidra.framework.model.*;
|
||||||
import ghidra.framework.plugintool.ServiceProvider;
|
import ghidra.framework.plugintool.ServiceProvider;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
@ -433,23 +431,6 @@ public class TagFilterTest extends VTBaseTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DummyDomainObject extends DomainObjectAdapterDB {
|
|
||||||
|
|
||||||
protected DummyDomainObject(Object consumer) throws IOException {
|
|
||||||
super(new DBHandle(), "Dummy", 10, 1, consumer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription() {
|
|
||||||
return "Test object: " + getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChangeable() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static VTProgramCorrelator createProgramCorrelator(ServiceProvider serviceProvider,
|
public static VTProgramCorrelator createProgramCorrelator(ServiceProvider serviceProvider,
|
||||||
Program sourceProgram, Program destinationProgram) {
|
Program sourceProgram, Program destinationProgram) {
|
||||||
return new DummyTestProgramCorrelator(serviceProvider, sourceProgram, destinationProgram);
|
return new DummyTestProgramCorrelator(serviceProvider, sourceProgram, destinationProgram);
|
||||||
|
|
|
@ -56,6 +56,7 @@ class BackgroundCommandTask extends Task implements AbortedTransactionListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Domain Object associated with this Task
|
* Returns the Domain Object associated with this Task
|
||||||
|
* @return the object
|
||||||
*/
|
*/
|
||||||
public UndoableDomainObject getDomainObject() {
|
public UndoableDomainObject getDomainObject() {
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -96,13 +97,12 @@ class BackgroundCommandTask extends Task implements AbortedTransactionListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
boolean error = true;
|
boolean commit = true;
|
||||||
try {
|
try {
|
||||||
success = cmd.applyTo(obj, monitor);
|
success = cmd.applyTo(obj, monitor);
|
||||||
if (success) {
|
if (success) {
|
||||||
taskMgr.taskCompleted(obj, this, monitor);
|
taskMgr.taskCompleted(obj, this, monitor);
|
||||||
}
|
}
|
||||||
error = false;
|
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
synchronized (taskMgr) {
|
synchronized (taskMgr) {
|
||||||
|
@ -114,26 +114,28 @@ class BackgroundCommandTask extends Task implements AbortedTransactionListener {
|
||||||
t = t.getCause();
|
t = t.getCause();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ignoreException(t)) {
|
commit = shouldKeepData(t);
|
||||||
|
|
||||||
|
if (isUnrecoverableException(t)) {
|
||||||
monitor.cancel();
|
monitor.cancel();
|
||||||
taskMgr.clearTasks(obj);
|
taskMgr.clearTasks(obj);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!(t instanceof RollbackException)) {
|
else if (!(t instanceof RollbackException)) {
|
||||||
Msg.showError(this, null, "Command Failure",
|
String message =
|
||||||
"An unexpected error occurred while processing the command: " + cmd.getName(),
|
"An unexpected error occurred while processing the command: " + cmd.getName();
|
||||||
t);
|
Msg.showError(this, null, "Command Failure", message, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
TaskUtilities.removeTrackedTask(this);
|
TaskUtilities.removeTrackedTask(this);
|
||||||
try {
|
try {
|
||||||
obj.endTransaction(id, !error);
|
obj.endTransaction(id, commit);
|
||||||
}
|
}
|
||||||
catch (DomainObjectException e) {
|
catch (DomainObjectException e) {
|
||||||
Throwable cause = e.getCause();
|
Throwable cause = e.getCause();
|
||||||
if (!error && !(cause instanceof ClosedException)) {
|
if (commit && !(cause instanceof ClosedException)) {
|
||||||
Msg.showError(this, null, null, null, cause);
|
Msg.error(this, "Transaction error", cause);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +146,13 @@ class BackgroundCommandTask extends Task implements AbortedTransactionListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean ignoreException(Throwable t) {
|
private boolean shouldKeepData(Throwable t) {
|
||||||
|
// unrecoverable exceptions are really bad; rollback exceptions signal to abort
|
||||||
|
boolean reallyBad = isUnrecoverableException(t) || t instanceof RollbackException;
|
||||||
|
return !reallyBad;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isUnrecoverableException(Throwable t) {
|
||||||
|
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
return t instanceof ConnectException ||
|
return t instanceof ConnectException ||
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/* ###
|
||||||
|
* 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.data;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import db.DBHandle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple dummy version of DomainObjectAdapterDB
|
||||||
|
*/
|
||||||
|
public class DummyDomainObject extends DomainObjectAdapterDB {
|
||||||
|
|
||||||
|
public DummyDomainObject(Object consumer) throws IOException {
|
||||||
|
this("Dummy", consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DummyDomainObject(String name, Object consumer) throws IOException {
|
||||||
|
super(new DBHandle(), name, 10, 1, consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "Test object: " + getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChangeable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ import java.beans.PropertyChangeListener;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.*;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
@ -436,4 +436,19 @@ public class DummyTool extends PluginTool {
|
||||||
public PluginClassManager getPluginClassManager() {
|
public PluginClassManager getPluginClassManager() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addStatusComponent(JComponent c, boolean addBorder, boolean rightSide) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeStatusComponent(JComponent c) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JFrame getToolFrame() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue