Merge remote-tracking branch 'origin/GP-5458_ryanmkurtz_project-lock--SQUASHED'

This commit is contained in:
Ryan Kurtz 2025-03-24 14:06:03 -04:00
commit bd60eda15e
6 changed files with 33 additions and 61 deletions

View file

@ -189,9 +189,6 @@ public class GhidraRun implements GhidraLaunchable {
try { try {
ProjectManager pm = tool.getProjectManager(); ProjectManager pm = tool.getProjectManager();
Project activeProject = pm.openProject(projectLocator, true, false); Project activeProject = pm.openProject(projectLocator, true, false);
if (activeProject == null) {
return;
}
tool.setActiveProject(activeProject); tool.setActiveProject(activeProject);
@ -210,10 +207,7 @@ public class GhidraRun implements GhidraLaunchable {
catch (Throwable t) { catch (Throwable t) {
if (t instanceof UsrException) { if (t instanceof UsrException) {
if (t instanceof LockException) { if (t instanceof LockException) {
Msg.showInfo(GhidraRun.class, null, "Project is Locked", Msg.showInfo(GhidraRun.class, null, "Project is Locked", t.getMessage());
"Can't open project: " + projectLocator.toString() +
"\nProject is already locked");
} }
else { else {
Msg.showInfo(GhidraRun.class, null, "Project Open Failed", Msg.showInfo(GhidraRun.class, null, "Project Open Failed",

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.
@ -23,13 +22,6 @@ import ghidra.util.exception.UsrException;
*/ */
public class LockException extends UsrException { public class LockException extends UsrException {
/**
* Construct a new LockException
*/
public LockException() {
super("Operation requires exclusive access to object.");
}
/** /**
* Construct a new LockException with the given message * Construct a new LockException with the given message
* @param msg the exception message * @param msg the exception message

View file

@ -321,9 +321,6 @@ public class DefaultProjectData implements ProjectData {
private void initLock(boolean creatingProject) throws LockException, IOException { private void initLock(boolean creatingProject) throws LockException, IOException {
this.projectLock = getProjectLock(localStorageLocator, !creatingProject); this.projectLock = getProjectLock(localStorageLocator, !creatingProject);
if (projectLock == null) {
throw new LockException("Unable to lock project! " + localStorageLocator);
}
if (!properties.exists()) { if (!properties.exists()) {
owner = getUserName(); owner = getUserName();
@ -339,28 +336,31 @@ public class DefaultProjectData implements ProjectData {
* @param locator the project locator * @param locator the project locator
* @param allowInteractiveForce if true, when a lock cannot be obtained, the * @param allowInteractiveForce if true, when a lock cannot be obtained, the
* user will be prompted * user will be prompted
* @return A locked ProjectLock or null if lock fails * @return A locked ProjectLock
* @throws LockException if the lock fails
*/ */
private ProjectLock getProjectLock(ProjectLocator locator, boolean allowInteractiveForce) { private ProjectLock getProjectLock(ProjectLocator locator, boolean allowInteractiveForce)
throws LockException {
ProjectLock lock = new ProjectLock(locator); ProjectLock lock = new ProjectLock(locator);
if (lock.lock()) { if (lock.lock()) {
return lock; return lock;
} }
String defaultMsg = "Unable to lock project! " + locator;
// in headless mode, just spit out an error // in headless mode, just spit out an error
if (!allowInteractiveForce || SystemUtilities.isInHeadlessMode()) { if (!allowInteractiveForce || SystemUtilities.isInHeadlessMode()) {
return null; throw new LockException(defaultMsg);
} }
String projectStr = "Project: " + HTMLUtilities.escapeHTML(locator.getLocation()) + String projectStr = "Project: " + HTMLUtilities.escapeHTML(locator.getLocation()) +
System.getProperty("file.separator") + HTMLUtilities.escapeHTML(locator.getName()); System.getProperty("file.separator") + HTMLUtilities.escapeHTML(locator.getName());
String lockInformation = lock.getExistingLockFileInformation(); String lockInformation = lock.getExistingLockFileInformation();
if (!lock.canForceLock()) { if (!lock.canForceLock()) {
Msg.showInfo(getClass(), null, "Project Locked", String msg = "<html>Project is locked. You have another instance of Ghidra<br>" +
"<html>Project is locked. You have another instance of Ghidra<br>" +
"already running with this project open (locally or remotely).<br><br>" + "already running with this project open (locally or remotely).<br><br>" +
projectStr + "<br><br>" + "Lock information: " + lockInformation); projectStr + "<br><br>" + "Lock information: " + lockInformation;
return null; throw new LockException(msg);
} }
int userChoice = OptionDialog.showOptionDialog(null, "Project Locked - Delete Lock?", int userChoice = OptionDialog.showOptionDialog(null, "Project Locked - Delete Lock?",
@ -377,7 +377,8 @@ public class DefaultProjectData implements ProjectData {
Msg.showError(this, null, "Error", "Attempt to force lock failed! " + locator); Msg.showError(this, null, "Error", "Attempt to force lock failed! " + locator);
} }
return null;
throw new LockException(defaultMsg);
} }
/** /**

View file

@ -347,7 +347,7 @@ public abstract class DomainObjectAdapter implements DomainObject {
public void checkExclusiveAccess() throws LockException { public void checkExclusiveAccess() throws LockException {
if (!hasExclusiveAccess()) { if (!hasExclusiveAccess()) {
throw new LockException(); throw new LockException("Operation requires exclusive access to object.");
} }
} }

View file

@ -247,9 +247,7 @@ class FileActionManager {
* @return true if the project was opened * @return true if the project was opened
*/ */
final boolean doOpenProject(ProjectLocator projectLocator) { final boolean doOpenProject(ProjectLocator projectLocator) {
String status = "Opened project: " + projectLocator.getName();
Project project = null; Project project = null;
boolean openStatus = false;
try { try {
// first close the active project (if there is one) // first close the active project (if there is one)
// but if user cancels operation, don't continue // but if user cancels operation, don't continue
@ -258,49 +256,38 @@ class FileActionManager {
} }
ProjectManager pm = plugin.getProjectManager(); ProjectManager pm = plugin.getProjectManager();
project = pm.openProject(projectLocator, true, false); project = pm.openProject(projectLocator, true, false);
if (project == null) {
status = "Error opening project: " + projectLocator.toString();
}
else {
firingProjectOpened = true; firingProjectOpened = true;
tool.setActiveProject(project); tool.setActiveProject(project);
openProjectAndNotify(project); openProjectAndNotify(project);
openStatus = true;
firingProjectOpened = false; firingProjectOpened = false;
} Msg.info(this, "Opened project: " + projectLocator.getName());
} }
catch (NotFoundException nfe) { catch (NotFoundException nfe) {
status = "Project not found for " + projectLocator.toString(); String msg = "Project not found for " + projectLocator;
Msg.showInfo(getClass(), tool.getToolFrame(), "Error Opening Project", status); Msg.showInfo(getClass(), tool.getToolFrame(), "Error Opening Project", msg);
Msg.error(this, msg);
} }
catch (NotOwnerException e) { catch (NotOwnerException e) {
status = "Cannot open project: " + e.getMessage();
Msg.showError(this, null, "Not Project Owner", "Cannot open project " + projectLocator + Msg.showError(this, null, "Not Project Owner", "Cannot open project " + projectLocator +
"\n" + e.getMessage() + "\n" + e.getMessage() +
"\n \nEach user must create their own project. If needed, another user's project may be viewed\n" + "\n \nEach user must create their own project. If needed, another user's project may be viewed\n" +
"and files copied, using the View Other action from your own open project. Alternatively, \n" + "and files copied, using the View Other action from your own open project. Alternatively, \n" +
"creating a \"Shared Project\" will allow a group of users to use a shared server-based repository."); "creating a \"Shared Project\" will allow a group of users to use a shared server-based repository.");
Msg.error(this, "Cannot open project: " + e.getMessage());
} }
catch (LockException e) { catch (LockException e) {
status = "Project is already open for update: " + projectLocator.toString(); Msg.showInfo(this, null, "Open Project Failed", e.getMessage());
Msg.showError(this, null, "Open Project Failed", status);
} }
catch (Exception e) { catch (Exception e) {
status = "Error opening project: " + projectLocator.toString(); Msg.showError(this, null, "Open Project Failed",
Msg.showError(this, null, "Open Project Failed", status, e); "Error opening project: " + projectLocator, e);
} }
finally { finally {
// update our list of recent projects // update our list of recent projects
plugin.rebuildRecentMenus(); plugin.rebuildRecentMenus();
} }
if (!openStatus) { return project != null;
Msg.error(this, status);
}
else {
Msg.info(this, status);
}
return openStatus;
} }
/** /**

View file

@ -151,8 +151,6 @@ public class DefaultProjectManager implements ProjectManager {
return currentProject; return currentProject;
} }
catch (LockException e) { catch (LockException e) {
Msg.showError(LOG, null, "Locked Project!",
"Cannot open locked project: " + projectLocator, e);
throw e; throw e;
} }
catch (ReadOnlyException e) { catch (ReadOnlyException e) {