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

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

View file

@ -1,13 +1,12 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* 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.
@ -22,13 +21,6 @@ import ghidra.util.exception.UsrException;
* Indicates a failure to obtain a required lock.
*/
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

View file

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

View file

@ -347,7 +347,7 @@ public abstract class DomainObjectAdapter implements DomainObject {
public void checkExclusiveAccess() throws LockException {
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
*/
final boolean doOpenProject(ProjectLocator projectLocator) {
String status = "Opened project: " + projectLocator.getName();
Project project = null;
boolean openStatus = false;
try {
// first close the active project (if there is one)
// but if user cancels operation, don't continue
@ -258,49 +256,38 @@ class FileActionManager {
}
ProjectManager pm = plugin.getProjectManager();
project = pm.openProject(projectLocator, true, false);
if (project == null) {
status = "Error opening project: " + projectLocator.toString();
}
else {
firingProjectOpened = true;
tool.setActiveProject(project);
openProjectAndNotify(project);
openStatus = true;
firingProjectOpened = false;
}
firingProjectOpened = true;
tool.setActiveProject(project);
openProjectAndNotify(project);
firingProjectOpened = false;
Msg.info(this, "Opened project: " + projectLocator.getName());
}
catch (NotFoundException nfe) {
status = "Project not found for " + projectLocator.toString();
Msg.showInfo(getClass(), tool.getToolFrame(), "Error Opening Project", status);
String msg = "Project not found for " + projectLocator;
Msg.showInfo(getClass(), tool.getToolFrame(), "Error Opening Project", msg);
Msg.error(this, msg);
}
catch (NotOwnerException e) {
status = "Cannot open project: " + e.getMessage();
Msg.showError(this, null, "Not Project Owner", "Cannot open project " + projectLocator +
"\n" + e.getMessage() +
"\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" +
"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) {
status = "Project is already open for update: " + projectLocator.toString();
Msg.showError(this, null, "Open Project Failed", status);
Msg.showInfo(this, null, "Open Project Failed", e.getMessage());
}
catch (Exception e) {
status = "Error opening project: " + projectLocator.toString();
Msg.showError(this, null, "Open Project Failed", status, e);
Msg.showError(this, null, "Open Project Failed",
"Error opening project: " + projectLocator, e);
}
finally {
// update our list of recent projects
plugin.rebuildRecentMenus();
}
if (!openStatus) {
Msg.error(this, status);
}
else {
Msg.info(this, status);
}
return openStatus;
return project != null;
}
/**

View file

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