mcghidra/src/main/java/eu/starsong/ghidra/util/TransactionHelper.java
Teal Bauer bc1e137878 chore: prepare v2.0.0 release
- Update version to v2.0.0 in ApiConstants.java and bridge_mcp_hydra.py
- Create CHANGELOG v2.0.0 section with release date
- Fix Ghidra 11.3.2+ compatibility in TransactionHelper (endTransaction signature)
- Clarify instances_list vs instances_discover usage in documentation
- Remove commented-out code in pom.xml

Fixes #7
Closes #5
2025-11-11 12:54:03 +01:00

60 lines
2.1 KiB
Java

package eu.starsong.ghidra.util;
import ghidra.program.model.listing.Program;
import ghidra.util.Msg;
import javax.swing.SwingUtilities;
import java.util.concurrent.atomic.AtomicReference;
public class TransactionHelper {
@FunctionalInterface
public interface GhidraSupplier<T> {
T get() throws Exception;
}
public static <T> T executeInTransaction(Program program, String transactionName, GhidraSupplier<T> operation)
throws TransactionException {
if (program == null) {
throw new IllegalArgumentException("Program cannot be null for transaction");
}
AtomicReference<T> result = new AtomicReference<>();
AtomicReference<Exception> exception = new AtomicReference<>();
try {
SwingUtilities.invokeAndWait(() -> {
int txId = -1;
boolean success = false;
try {
txId = program.startTransaction(transactionName);
if (txId < 0) {
throw new TransactionException("Failed to start transaction: " + transactionName);
}
result.set(operation.get());
success = true;
} catch (Exception e) {
exception.set(e);
Msg.error(TransactionHelper.class, "Transaction failed: " + transactionName, e);
} finally {
if (txId >= 0) {
success = program.endTransaction(txId, success);
}
}
});
} catch (Exception e) {
throw new TransactionException("Swing thread execution failed", e);
}
if (exception.get() != null) {
throw new TransactionException("Operation failed", exception.get());
}
return result.get();
}
public static class TransactionException extends Exception {
public TransactionException(String message) { super(message); }
public TransactionException(String message, Throwable cause) { super(message, cause); }
}
}