diff --git a/Ghidra/Features/BSim/certification.manifest b/Ghidra/Features/BSim/certification.manifest
index 12c5480cf9..137ac8dcbf 100755
--- a/Ghidra/Features/BSim/certification.manifest
+++ b/Ghidra/Features/BSim/certification.manifest
@@ -42,6 +42,8 @@ src/main/help/help/topics/BSimSearchPlugin/images/BSimSearchDialog.png||GHIDRA||
src/main/help/help/topics/BSimSearchPlugin/images/ManageServersDialog.png||GHIDRA||||END|
src/main/resources/bsim.log4j.xml||GHIDRA||||END|
src/main/resources/images/checkmark_yellow.gif||GHIDRA||||END|
+src/main/resources/images/connect.png||FAMFAMFAM Icons - CC 2.5||||END|
+src/main/resources/images/disconnect.png||FAMFAMFAM Icons - CC 2.5||||END|
src/main/resources/images/flag_green.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|
src/main/resources/images/preferences-desktop-user-password.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
src/main/resources/images/preferences-web-browser-shortcuts-32.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
diff --git a/Ghidra/Features/BSim/data/bsim.theme.properties b/Ghidra/Features/BSim/data/bsim.theme.properties
index c0efedbea0..497af941d8 100644
--- a/Ghidra/Features/BSim/data/bsim.theme.properties
+++ b/Ghidra/Features/BSim/data/bsim.theme.properties
@@ -14,4 +14,7 @@ icon.bsim.results.status.ignored = checkmark_yellow.gif
icon.bsim.functions.table = FunctionScope.gif
+icon.bsim.connected = connect.png
+icon.bsim.disconnected = disconnect.png
+
[Dark Defaults]
diff --git a/Ghidra/Features/BSim/ghidra_scripts/AddProgramToH2BSimDatabaseScript.java b/Ghidra/Features/BSim/ghidra_scripts/AddProgramToH2BSimDatabaseScript.java
index 648768ce7c..adbe50e621 100644
--- a/Ghidra/Features/BSim/ghidra_scripts/AddProgramToH2BSimDatabaseScript.java
+++ b/Ghidra/Features/BSim/ghidra_scripts/AddProgramToH2BSimDatabaseScript.java
@@ -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.
@@ -71,22 +71,17 @@ public class AddProgramToH2BSimDatabaseScript extends GhidraScript {
askValues("Select Database File", null, values);
File h2DbFile = values.getFile(DATABASE);
+ BSimServerInfo serverInfo =
+ new BSimServerInfo(DBType.file, null, 0, h2DbFile.getAbsolutePath());
- FunctionDatabase h2Database = null;
- try {
- BSimServerInfo serverInfo =
- new BSimServerInfo(DBType.file, null, 0, h2DbFile.getAbsolutePath());
- h2Database = BSimClientFactory.buildClient(serverInfo, false);
- BSimH2FileDataSource bds =
- BSimH2FileDBConnectionManager.getDataSourceIfExists(h2Database.getServerInfo());
- if (bds == null) {
- popup(h2DbFile.getAbsolutePath() + " is not an H2 database file");
- return;
- }
- if (bds.getActiveConnections() > 0) {
- popup("There is an existing connection to the database.");
- return;
- }
+ BSimH2FileDataSource existingBDS =
+ BSimH2FileDBConnectionManager.getDataSourceIfExists(serverInfo);
+ if (existingBDS != null && existingBDS.getActiveConnections() > 0) {
+ popup("There is an existing connection to the database.");
+ return;
+ }
+
+ try (FunctionDatabase h2Database = BSimClientFactory.buildClient(serverInfo, false)) {
h2Database.initialize();
DatabaseInformation dbInfo = h2Database.getInfo();
@@ -169,11 +164,13 @@ public class AddProgramToH2BSimDatabaseScript extends GhidraScript {
}
finally {
- if (h2Database != null) {
- h2Database.close();
+ if (existingBDS == null) {
+ // Dispose database source if it did not previously exist
BSimH2FileDataSource bds =
- BSimH2FileDBConnectionManager.getDataSourceIfExists(h2Database.getServerInfo());
- bds.dispose();
+ BSimH2FileDBConnectionManager.getDataSourceIfExists(serverInfo);
+ if (bds != null) {
+ bds.dispose();
+ }
}
}
}
diff --git a/Ghidra/Features/BSim/ghidra_scripts/CreateH2BSimDatabaseScript.java b/Ghidra/Features/BSim/ghidra_scripts/CreateH2BSimDatabaseScript.java
index ef332f6d64..f30b1c65d5 100644
--- a/Ghidra/Features/BSim/ghidra_scripts/CreateH2BSimDatabaseScript.java
+++ b/Ghidra/Features/BSim/ghidra_scripts/CreateH2BSimDatabaseScript.java
@@ -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.
@@ -31,7 +31,6 @@ import ghidra.features.bsim.query.file.BSimH2FileDBConnectionManager;
import ghidra.features.bsim.query.file.BSimH2FileDBConnectionManager.BSimH2FileDataSource;
import ghidra.features.bsim.query.protocol.*;
import ghidra.util.MessageType;
-import ghidra.util.Msg;
public class CreateH2BSimDatabaseScript extends GhidraScript {
private static final String NAME = "Database Name";
@@ -80,31 +79,27 @@ public class CreateH2BSimDatabaseScript extends GhidraScript {
askValues("Enter Database Parameters",
"Enter values required to create a new BSim H2 database.", values);
- FunctionDatabase h2Database = null;
- try {
- String databaseName = values.getString(NAME);
- File dbDir = values.getFile(DIRECTORY);
- String template = values.getChoice(DATABASE_TEMPLATE);
- String functionTagsCSV = values.getString(FUNCTION_TAGS);
- List tags = parseCSV(functionTagsCSV);
+ String databaseName = values.getString(NAME);
+ File dbDir = values.getFile(DIRECTORY);
+ String template = values.getChoice(DATABASE_TEMPLATE);
+ String functionTagsCSV = values.getString(FUNCTION_TAGS);
+ List tags = parseCSV(functionTagsCSV);
- String exeCatCSV = values.getString(EXECUTABLE_CATEGORIES);
- List cats = parseCSV(exeCatCSV);
+ String exeCatCSV = values.getString(EXECUTABLE_CATEGORIES);
+ List cats = parseCSV(exeCatCSV);
- File dbFile = new File(dbDir, databaseName);
+ File dbFile = new File(dbDir, databaseName);
+ BSimServerInfo serverInfo =
+ new BSimServerInfo(DBType.file, null, 0, dbFile.getAbsolutePath());
- BSimServerInfo serverInfo =
- new BSimServerInfo(DBType.file, null, 0, dbFile.getAbsolutePath());
- h2Database = BSimClientFactory.buildClient(serverInfo, false);
- BSimH2FileDataSource bds =
- BSimH2FileDBConnectionManager.getDataSourceIfExists(h2Database.getServerInfo());
- if (bds.getActiveConnections() > 0) {
- //if this happens, there is a connection to the database but the
- //database file was deleted
- Msg.showError(this, null, "Connection Error",
- "There is an existing connection to the database!");
- return;
- }
+ BSimH2FileDataSource existingBDS =
+ BSimH2FileDBConnectionManager.getDataSourceIfExists(serverInfo);
+ if (existingBDS != null && existingBDS.getActiveConnections() > 0) {
+ popup("There is an existing connection to the database.");
+ return;
+ }
+
+ try (FunctionDatabase h2Database = BSimClientFactory.buildClient(serverInfo, false)) {
CreateDatabase command = new CreateDatabase();
command.info = new DatabaseInformation();
@@ -140,11 +135,13 @@ public class CreateH2BSimDatabaseScript extends GhidraScript {
popup("Database " + values.getString(NAME) + " created successfully!");
}
finally {
- if (h2Database != null) {
- h2Database.close();
+ if (existingBDS == null) {
+ // Dispose database source if it did not previously exist
BSimH2FileDataSource bds =
- BSimH2FileDBConnectionManager.getDataSourceIfExists(h2Database.getServerInfo());
- bds.dispose();
+ BSimH2FileDBConnectionManager.getDataSourceIfExists(serverInfo);
+ if (bds != null) {
+ bds.dispose();
+ }
}
}
diff --git a/Ghidra/Features/BSim/src/main/help/help/topics/BSimSearchPlugin/BSimSearch.html b/Ghidra/Features/BSim/src/main/help/help/topics/BSimSearchPlugin/BSimSearch.html
index bdbfd102af..ffecfeb75d 100644
--- a/Ghidra/Features/BSim/src/main/help/help/topics/BSimSearchPlugin/BSimSearch.html
+++ b/Ghidra/Features/BSim/src/main/help/help/topics/BSimSearchPlugin/BSimSearch.html
@@ -57,18 +57,24 @@
entry shows a name for the BSim database, its type (postgres, elastic, or file), a host ip
and port (if applicable), and finally the number of active connections.
- There are three primary actions for this dialog:
+ There are four primary actions for this dialog:
-
Add a new database/server definition - a
- Define Server Dialog will be shown.
+
Add a new BSim database/server definition - an
+ Add BSim Server Dialog will be shown.
Delete a database/server definition - The
- selected entry will be deleted.
+ selected entry will be deleted. This action will force an immediate disconnect for an
+ active/idle connection and should be used with care.
+
+ 
+ Connect or disconnect an inactive database/server connection. This action is not supported
+ by Elastic database servers.
Change password - A change password
- dialog will appear for the selected entry
+ dialog will appear for the selected database server. Action is disabled for databases
+ which do not use a password (e.g., Local H2 File database).
diff --git a/Ghidra/Features/BSim/src/main/help/help/topics/BSimSearchPlugin/images/ManageServersDialog.png b/Ghidra/Features/BSim/src/main/help/help/topics/BSimSearchPlugin/images/ManageServersDialog.png
index abe6af8494..59f713dc8c 100644
Binary files a/Ghidra/Features/BSim/src/main/help/help/topics/BSimSearchPlugin/images/ManageServersDialog.png and b/Ghidra/Features/BSim/src/main/help/help/topics/BSimSearchPlugin/images/ManageServersDialog.png differ
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/BSimSearchPlugin.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/BSimSearchPlugin.java
index 1b47e7aa23..0abaed6e10 100644
--- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/BSimSearchPlugin.java
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/BSimSearchPlugin.java
@@ -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.
@@ -72,7 +72,7 @@ public class BSimSearchPlugin extends ProgramPlugin {
private Set searchResultsProviders = new HashSet<>();
private Set overviewProviders = new HashSet<>();
- private BSimServerManager serverManager = new BSimServerManager();
+ private BSimServerManager serverManager = BSimServerManager.getBSimServerManager();
private BSimSearchService searchService;
private BSimServerCache lastUsedServerCache = null;
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimServerManager.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/BSimServerManager.java
similarity index 65%
rename from Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimServerManager.java
rename to Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/BSimServerManager.java
index 9e1559af07..df21cbbbfb 100644
--- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimServerManager.java
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/BSimServerManager.java
@@ -4,25 +4,25 @@
* 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.features.bsim.gui.search.dialog;
+package ghidra.features.bsim.gui;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
-import ghidra.features.bsim.query.BSimPostgresDBConnectionManager;
+import ghidra.features.bsim.gui.search.dialog.BSimServerManagerListener;
+import ghidra.features.bsim.query.*;
import ghidra.features.bsim.query.BSimPostgresDBConnectionManager.BSimPostgresDataSource;
-import ghidra.features.bsim.query.BSimServerInfo;
import ghidra.features.bsim.query.BSimServerInfo.DBType;
import ghidra.features.bsim.query.file.BSimH2FileDBConnectionManager;
import ghidra.features.bsim.query.file.BSimH2FileDBConnectionManager.BSimH2FileDataSource;
@@ -36,12 +36,24 @@ import ghidra.util.Swing;
* Managers BSim database server definitions and connections
*/
public class BSimServerManager {
- // TODO: Do not allow removal of active server. Dispose data source when removed.
+
+ private static BSimServerManager instance;
+
+ /**
+ * Get static singleton instance for BSimServerManager
+ * @return BSimServerManager instance
+ */
+ static synchronized BSimServerManager getBSimServerManager() {
+ if (instance == null) {
+ instance = new BSimServerManager();
+ }
+ return instance;
+ }
private Set serverInfos = new HashSet<>();
private List listeners = new CopyOnWriteArrayList<>();
- public BSimServerManager() {
+ private BSimServerManager() {
List files = Application.getUserSettingsFiles("bsim", ".server.properties");
for (File file : files) {
BSimServerInfo info = readBsimServerInfoFile(file);
@@ -51,6 +63,10 @@ public class BSimServerManager {
}
}
+ /**
+ * Get list of defined servers. Method must be invoked from swing thread only.
+ * @return list of defined servers
+ */
public Set getServerInfos() {
return new HashSet<>(serverInfos);
}
@@ -108,6 +124,10 @@ public class BSimServerManager {
return serverFile.delete();
}
+ /**
+ * Add server to list. Method must be invoked from swing thread only.
+ * @param newServerInfo new BSim DB server
+ */
public void addServer(BSimServerInfo newServerInfo) {
if (saveBSimServerInfo(newServerInfo)) {
serverInfos.add(newServerInfo);
@@ -115,28 +135,42 @@ public class BSimServerManager {
}
}
- public boolean removeServer(BSimServerInfo info, boolean force) {
+ private static boolean disposeServer(BSimServerInfo info, boolean force) {
DBType dbType = info.getDBType();
if (dbType == DBType.file) {
- BSimH2FileDataSource ds = BSimH2FileDBConnectionManager.getDataSource(info);
- int active = ds.getActiveConnections();
- if (active != 0) {
- if (!force) {
+ BSimH2FileDataSource ds = BSimH2FileDBConnectionManager.getDataSourceIfExists(info);
+ if (ds != null) {
+ int active = ds.getActiveConnections();
+ if (active != 0 && !force) {
return false;
}
ds.dispose();
}
}
else if (dbType == DBType.postgres) {
- BSimPostgresDataSource ds = BSimPostgresDBConnectionManager.getDataSource(info);
- int active = ds.getActiveConnections();
- if (active != 0) {
- if (!force) {
+ BSimPostgresDataSource ds = BSimPostgresDBConnectionManager.getDataSourceIfExists(info);
+ if (ds != null) {
+ int active = ds.getActiveConnections();
+ if (active != 0 && !force) {
return false;
}
ds.dispose();
}
}
+ return true;
+ }
+
+ /**
+ * Remove BSim DB server from list. Method must be invoked from swing thread only.
+ * Specified server datasource will be dispose unless it is active or force is true.
+ * @param info BSim DB server to be removed
+ * @param force true if server datasource should be disposed even when active.
+ * @return true if server disposed and removed from list
+ */
+ public boolean removeServer(BSimServerInfo info, boolean force) {
+ if (!disposeServer(info, force)) {
+ return false;
+ }
if (serverInfos.remove(info)) {
removeServerFileFromSettings(info);
notifyServerListChanged();
@@ -160,26 +194,38 @@ public class BSimServerManager {
});
}
- public static int getActiveConnections(BSimServerInfo serverInfo) {
+ /**
+ * Convenience method to get existing BSim JDBC datasource
+ * @param serverInfo BSim DB server info
+ * @return BSim DB datasource or null if not instantiated or server does not support a
+ * {@link BSimJDBCDataSource}.
+ */
+ public static BSimJDBCDataSource getDataSourceIfExists(BSimServerInfo serverInfo) {
switch (serverInfo.getDBType()) {
case postgres:
- BSimPostgresDataSource postgresDs =
- BSimPostgresDBConnectionManager.getDataSourceIfExists(serverInfo);
- if (postgresDs != null) {
- return postgresDs.getActiveConnections();
- }
- break;
+ return BSimPostgresDBConnectionManager.getDataSourceIfExists(serverInfo);
case file:
- BSimH2FileDataSource h2FileDs =
- BSimH2FileDBConnectionManager.getDataSourceIfExists(serverInfo);
- if (h2FileDs != null) {
- return h2FileDs.getActiveConnections();
- }
- break;
+ return BSimH2FileDBConnectionManager.getDataSourceIfExists(serverInfo);
default:
- break;
+ return null;
+ }
+ }
+
+ /**
+ * Convenience method to get a new or existing BSim JDBC datasource
+ * @param serverInfo BSim DB server info
+ * @return BSim DB datasource or null if server does not support a
+ * {@link BSimJDBCDataSource}.
+ */
+ public static BSimJDBCDataSource getDataSource(BSimServerInfo serverInfo) {
+ switch (serverInfo.getDBType()) {
+ case postgres:
+ return BSimPostgresDBConnectionManager.getDataSource(serverInfo);
+ case file:
+ return BSimH2FileDBConnectionManager.getDataSource(serverInfo);
+ default:
+ return null;
}
- return -1;
}
}
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/AbstractBSimSearchDialog.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/AbstractBSimSearchDialog.java
index ff999ee822..9ed6829018 100644
--- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/AbstractBSimSearchDialog.java
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/AbstractBSimSearchDialog.java
@@ -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.
@@ -30,6 +30,7 @@ import docking.widgets.EmptyBorderButton;
import docking.widgets.combobox.GComboBox;
import docking.widgets.textfield.FloatingPointTextField;
import generic.theme.Gui;
+import ghidra.features.bsim.gui.BSimServerManager;
import ghidra.features.bsim.query.BSimServerInfo;
import ghidra.features.bsim.query.description.DatabaseInformation;
import ghidra.features.bsim.query.facade.QueryDatabaseException;
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimOverviewDialog.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimOverviewDialog.java
index 2b44b19bbb..a4afa85649 100644
--- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimOverviewDialog.java
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimOverviewDialog.java
@@ -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.
@@ -16,6 +16,7 @@
package ghidra.features.bsim.gui.search.dialog;
import ghidra.features.bsim.gui.BSimSearchPlugin;
+import ghidra.features.bsim.gui.BSimServerManager;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimSearchDialog.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimSearchDialog.java
index d0df4f8bba..9b9318638e 100644
--- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimSearchDialog.java
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimSearchDialog.java
@@ -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.
@@ -30,6 +30,7 @@ import docking.widgets.textfield.IntegerTextField;
import generic.theme.GIcon;
import ghidra.app.services.GoToService;
import ghidra.features.bsim.gui.BSimSearchPlugin;
+import ghidra.features.bsim.gui.BSimServerManager;
import ghidra.features.bsim.gui.filters.BSimFilterType;
import ghidra.features.bsim.query.description.DatabaseInformation;
import ghidra.framework.plugintool.PluginTool;
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimServerDialog.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimServerDialog.java
index a2c90f1c67..bec9aeee2e 100644
--- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimServerDialog.java
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimServerDialog.java
@@ -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.
@@ -16,21 +16,25 @@
package ghidra.features.bsim.gui.search.dialog;
import java.awt.BorderLayout;
+import java.sql.Connection;
+import java.sql.SQLException;
import javax.swing.*;
import org.bouncycastle.util.Arrays;
-import docking.DialogComponentProvider;
-import docking.DockingWindowManager;
-import docking.action.DockingAction;
+import docking.*;
+import docking.action.*;
import docking.action.builder.ActionBuilder;
+import docking.action.builder.ToggleActionBuilder;
import docking.widgets.OptionDialog;
import docking.widgets.PasswordChangeDialog;
import docking.widgets.table.GFilterTable;
import docking.widgets.table.GTable;
import generic.theme.GIcon;
+import ghidra.features.bsim.gui.BSimServerManager;
import ghidra.features.bsim.query.*;
+import ghidra.features.bsim.query.BSimServerInfo.DBType;
import ghidra.features.bsim.query.FunctionDatabase.Error;
import ghidra.features.bsim.query.FunctionDatabase.ErrorCategory;
import ghidra.framework.plugintool.PluginTool;
@@ -42,15 +46,14 @@ import resources.Icons;
*/
public class BSimServerDialog extends DialogComponentProvider {
- // TODO: Add connected status indicator (not sure how this relates to elastic case which will likely have a Session concept)
- // TODO: Add "Disconnect" action (only works when active connections is 0; does not apply to elastic)
-
private PluginTool tool;
private BSimServerManager serverManager;
private BSimServerTableModel serverTableModel;
- private GFilterTable filterTable;
+ private GFilterTable serverTable;
private BSimServerInfo lastAdded = null;
+ private ToggleDockingAction dbConnectionAction;
+
public BSimServerDialog(PluginTool tool, BSimServerManager serverManager) {
super("BSim Server Manager");
this.tool = tool;
@@ -60,7 +63,7 @@ public class BSimServerDialog extends DialogComponentProvider {
addDismissButton();
setPreferredSize(600, 400);
notifyContextChanged(); // kick actions to initialized enabled state
- setHelpLocation(new HelpLocation("BSimSearchPlugin","BSim_Servers_Dialog" ));
+ setHelpLocation(new HelpLocation("BSimSearchPlugin", "BSim_Servers_Dialog"));
}
@Override
@@ -70,34 +73,101 @@ public class BSimServerDialog extends DialogComponentProvider {
}
private void createToolbarActions() {
- HelpLocation help = new HelpLocation("BSimSearchPlugin","Manage_Servers_Actions" );
-
+ HelpLocation help = new HelpLocation("BSimSearchPlugin", "Manage_Servers_Actions");
+
DockingAction addServerAction =
- new ActionBuilder("Add Server", "Dialog").toolBarIcon(Icons.ADD_ICON)
- .helpLocation(help)
- .onAction(e -> defineBsimServer())
- .build();
+ new ActionBuilder("Add BSim Database", "Dialog").toolBarIcon(Icons.ADD_ICON)
+ .helpLocation(help)
+ .onAction(e -> defineBsimServer())
+ .build();
addAction(addServerAction);
DockingAction removeServerAction =
- new ActionBuilder("Delete Server", "Dialog").toolBarIcon(Icons.DELETE_ICON)
- .helpLocation(help)
- .onAction(e -> deleteBsimServer())
- .enabledWhen(c -> hasSelection())
- .build();
+ new ActionBuilder("Delete BSim Database", "Dialog").toolBarIcon(Icons.DELETE_ICON)
+ .helpLocation(help)
+ .onAction(e -> deleteBsimServer())
+ .enabledWhen(c -> hasSelection())
+ .build();
addAction(removeServerAction);
- DockingAction changePasswordAction = new ActionBuilder("Change User Password", "Dialog")
- .helpLocation(help)
- .toolBarIcon(new GIcon("icon.bsim.change.password"))
- .onAction(e -> changePassword())
- .enabledWhen(c -> hasSelection())
- .build();
+ dbConnectionAction =
+ new ToggleActionBuilder("Toggle Database Connection", "Dialog").helpLocation(help)
+ .toolBarIcon(new GIcon("icon.bsim.disconnected"))
+ .onAction(e -> toggleSelectedJDBCDataSourceConnection())
+ .enabledWhen(c -> isNonActiveJDBCDataSourceSelected(c))
+ .build();
+ addAction(dbConnectionAction);
+
+ DockingAction changePasswordAction =
+ new ActionBuilder("Change User Password", "Dialog").helpLocation(help)
+ .toolBarIcon(new GIcon("icon.bsim.change.password"))
+ .onAction(e -> changePassword())
+ .enabledWhen(c -> canChangePassword())
+ .build();
addAction(changePasswordAction);
}
+ private void toggleSelectedJDBCDataSourceConnection() {
+
+ BSimServerInfo serverInfo = serverTable.getSelectedRowObject();
+ if (serverInfo == null || serverInfo.getDBType() == DBType.elastic) {
+ return;
+ }
+
+ BSimJDBCDataSource dataSource = BSimServerManager.getDataSourceIfExists(serverInfo);
+ if (dataSource == null) {
+ // connect
+ dataSource = BSimServerManager.getDataSource(serverInfo);
+ try (Connection connection = dataSource.getConnection()) {
+ // do nothing
+ }
+ catch (SQLException e) {
+ Msg.showError(this, rootPanel, "BSim Connection Failure", e.getMessage());
+ }
+ }
+ else {
+ dataSource.dispose();
+ }
+ serverTableModel.fireTableDataChanged();
+ notifyContextChanged();
+ }
+
+ private boolean isNonActiveJDBCDataSourceSelected(ActionContext c) {
+ BSimServerInfo serverInfo = serverTable.getSelectedRowObject();
+ if (serverInfo == null) {
+ return false;
+ }
+
+ // TODO: May need connection listener on dataSource to facilitate GUI update,
+ // although modal dialog avoids the issue somewhat
+
+ dbConnectionAction.setDescription(dbConnectionAction.getName());
+
+ ConnectionPoolStatus status = serverTableModel.getConnectionPoolStatus(serverInfo);
+ if (status.isActive) {
+
+ // Show connected icon
+ dbConnectionAction
+ .setToolBarData(new ToolBarData(new GIcon("icon.bsim.connected"), null));
+ dbConnectionAction.setSelected(true);
+ dbConnectionAction.setDescription("Disconnect idle BSim Database connection");
+
+ // disconnect permitted when no active connections
+ return status.activeCount == 0;
+ }
+
+ // Show disconnected icon (elastic always shown as disconnected)
+ dbConnectionAction
+ .setToolBarData(new ToolBarData(new GIcon("icon.bsim.disconnected"), null));
+ dbConnectionAction.setSelected(false);
+ dbConnectionAction.setDescription("Connect BSim Database");
+
+ // Action never enabled for elastic DB (i.e., does not use pooled JDBC data source)
+ return serverInfo.getDBType() != DBType.elastic;
+ }
+
private void changePassword() {
- BSimServerInfo serverInfo = filterTable.getSelectedRowObject();
+ BSimServerInfo serverInfo = serverTable.getSelectedRowObject();
if (serverInfo == null) {
return;
}
@@ -141,8 +211,13 @@ public class BSimServerDialog extends DialogComponentProvider {
}
}
+ private boolean canChangePassword() {
+ BSimServerInfo serverInfo = serverTable.getSelectedRowObject();
+ return serverInfo != null && serverInfo.getDBType() != DBType.file;
+ }
+
private void deleteBsimServer() {
- BSimServerInfo selected = filterTable.getSelectedRowObject();
+ BSimServerInfo selected = serverTable.getSelectedRowObject();
if (selected != null) {
int answer =
OptionDialog.showYesNoDialog(getComponent(), "Delete Server Configuration?",
@@ -152,7 +227,7 @@ public class BSimServerDialog extends DialogComponentProvider {
answer = OptionDialog.showOptionDialogWithCancelAsDefaultButton(getComponent(),
"Active Server Configuration!",
"Database connections are still active!\n" +
- "Are you sure you want to delete server?",
+ "Are you sure you want to terminate connections and delete server?",
"Yes", OptionDialog.WARNING_MESSAGE);
if (answer == OptionDialog.YES_OPTION) {
serverManager.removeServer(selected, true);
@@ -169,7 +244,7 @@ public class BSimServerDialog extends DialogComponentProvider {
if (newServerInfo != null) {
serverManager.addServer(newServerInfo);
lastAdded = newServerInfo;
- Swing.runLater(() -> filterTable.setSelectedRowObject(newServerInfo));
+ Swing.runLater(() -> serverTable.setSelectedRowObject(newServerInfo));
}
}
@@ -178,11 +253,11 @@ public class BSimServerDialog extends DialogComponentProvider {
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
serverTableModel = new BSimServerTableModel(serverManager);
- filterTable = new GFilterTable<>(serverTableModel);
- GTable table = filterTable.getTable();
+ serverTable = new GFilterTable<>(serverTableModel);
+ GTable table = serverTable.getTable();
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(e -> notifyContextChanged());
- panel.add(filterTable, BorderLayout.CENTER);
+ panel.add(serverTable, BorderLayout.CENTER);
if (serverTableModel.getRowCount() > 0) {
table.setRowSelectionInterval(0, 0);
@@ -192,7 +267,7 @@ public class BSimServerDialog extends DialogComponentProvider {
}
private boolean hasSelection() {
- return filterTable.getSelectedRowObject() != null;
+ return serverTable.getSelectedRowObject() != null;
}
public BSimServerInfo getLastAdded() {
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimServerTableModel.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimServerTableModel.java
index b26aeea431..8bed9cc704 100644
--- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimServerTableModel.java
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/BSimServerTableModel.java
@@ -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.
@@ -16,27 +16,33 @@
package ghidra.features.bsim.gui.search.dialog;
import java.awt.Component;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
+import javax.swing.Icon;
import javax.swing.JLabel;
import docking.widgets.table.*;
import ghidra.docking.settings.Settings;
+import ghidra.features.bsim.gui.BSimServerManager;
import ghidra.features.bsim.query.BSimServerInfo;
import ghidra.features.bsim.query.BSimServerInfo.DBType;
import ghidra.framework.plugintool.ServiceProvider;
import ghidra.framework.plugintool.ServiceProviderStub;
-import ghidra.program.model.listing.Program;
import ghidra.util.table.column.AbstractGColumnRenderer;
import ghidra.util.table.column.GColumnRenderer;
-import ghidra.util.table.field.AbstractProgramBasedDynamicTableColumn;
/**
- * Table model for BSim database server definitions
+ * Table model for BSim database server definitions.
+ *
+ * NOTE: This implementation assumes modal dialog use and non-changing connection state
+ * while instance is in-use. This was done to avoid adding a conection listener which could
+ * introduce excessive overhead into the connection pool use.
*/
public class BSimServerTableModel extends GDynamicColumnTableModel {
+
private List servers;
+ private Map statusCache = new HashMap<>();
+
private BSimServerManager serverManager;
private BSimServerManagerListener listener = new BSimServerManagerListener() {
@Override
@@ -63,8 +69,18 @@ public class BSimServerTableModel extends GDynamicColumnTableModel new ConnectionPoolStatus(s));
}
@Override
@@ -74,7 +90,7 @@ public class BSimServerTableModel extends GDynamicColumnTableModel {
+ extends AbstractDynamicTableColumn {
private GColumnRenderer renderer = new AbstractGColumnRenderer<>() {
@Override
public Component getTableCellRendererComponent(GTableCellRenderingData data) {
@@ -112,11 +128,8 @@ public class BSimServerTableModel extends GDynamicColumnTableModel {
+ private static class TypeColumn
+ extends AbstractDynamicTableColumn {
+
+ @Override
+ public String getColumnName() {
+ return "Type";
+ }
+
+ @Override
+ public String getValue(BSimServerInfo serverInfo, Settings settings, Object data,
+ ServiceProvider provider) throws IllegalArgumentException {
+
+ return serverInfo.getDBType().toString();
+ }
+
+ @Override
+ public int getColumnPreferredWidth() {
+ return 80;
+ }
+ }
+
+ private static class HostColumn
+ extends AbstractDynamicTableColumn {
@Override
public String getColumnName() {
@@ -140,8 +174,8 @@ public class BSimServerTableModel extends GDynamicColumnTableModel {
+ private static class PortColumn
+ extends AbstractDynamicTableColumn {
@Override
public String getColumnName() {
@@ -161,64 +195,78 @@ public class BSimServerTableModel extends GDynamicColumnTableModel {
+ private static class ConnectionStatusColumnRenderer
+ extends AbstractGColumnRenderer {
+
+ private static final ConnectionStatusColumnRenderer INSTANCE =
+ new ConnectionStatusColumnRenderer();
@Override
- public String getColumnName() {
- return "Active Connections";
- }
+ public Component getTableCellRendererComponent(GTableCellRenderingData data) {
- @Override
- public Integer getValue(BSimServerInfo serverInfo, Settings settings, Program data,
- ServiceProvider provider) throws IllegalArgumentException {
- int activeConnections = BSimServerManager.getActiveConnections(serverInfo);
- if (activeConnections < 0) {
- return null;
+ JLabel c = (JLabel) super.getTableCellRendererComponent(data);
+
+ ConnectionPoolStatus status = (ConnectionPoolStatus) data.getValue();
+
+ // NOTE: Custom column renderer has neem established with future use of
+ // status icon in mind (e.g., H2 mixed-mode server enabled)
+
+ Icon icon = null; // NOTE: may need default filler icon
+ String text = null;
+ if (status.isActive) {
+ text = Integer.toString(status.activeCount) + " / " +
+ Integer.toString(status.idleCount);
}
- return activeConnections;
+ c.setText(text);
+ c.setIcon(icon);
+ return c;
}
@Override
- public int getColumnPreferredWidth() {
- return 80;
+ public String getFilterString(ConnectionPoolStatus t, Settings settings) {
+ return null; // Filtering not supported
}
+
}
- private class TypeColumn
- extends AbstractProgramBasedDynamicTableColumn {
+ private class ConnectionStatusColumn
+ extends AbstractDynamicTableColumn {
@Override
public String getColumnName() {
- return "Type";
+ return "Active/Idle Connections";
}
@Override
- public String getValue(BSimServerInfo serverInfo, Settings settings, Program data,
- ServiceProvider provider) throws IllegalArgumentException {
-
- return serverInfo.getDBType().toString();
+ public ConnectionPoolStatus getValue(BSimServerInfo serverInfo, Settings settings,
+ Object data, ServiceProvider provider) throws IllegalArgumentException {
+ return getConnectionPoolStatus(serverInfo);
}
@Override
public int getColumnPreferredWidth() {
- return 80;
+ return 150;
+ }
+
+ @Override
+ public GColumnRenderer getColumnRenderer() {
+ return ConnectionStatusColumnRenderer.INSTANCE;
}
}
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/ConnectionPoolStatus.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/ConnectionPoolStatus.java
new file mode 100644
index 0000000000..dc9d7b2dfe
--- /dev/null
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/ConnectionPoolStatus.java
@@ -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.features.bsim.gui.search.dialog;
+
+import ghidra.features.bsim.gui.BSimServerManager;
+import ghidra.features.bsim.query.BSimJDBCDataSource;
+import ghidra.features.bsim.query.BSimServerInfo;
+
+class ConnectionPoolStatus {
+ BSimServerInfo serverInfo;
+
+ final boolean isActive;
+ final int activeCount;
+ final int idleCount;
+
+ ConnectionPoolStatus(BSimServerInfo serverInfo) {
+ this.serverInfo = serverInfo;
+
+ BSimJDBCDataSource dataSource = BSimServerManager.getDataSourceIfExists(serverInfo);
+ if (dataSource == null) {
+ isActive = false;
+ activeCount = 0;
+ idleCount = 0;
+ }
+ else {
+ isActive = true;
+ activeCount = dataSource.getActiveConnections();
+ idleCount = dataSource.getIdleConnections();
+ }
+ }
+}
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/CreateBsimServerInfoDialog.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/CreateBsimServerInfoDialog.java
index badb9638b2..f31c59cd4d 100644
--- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/CreateBsimServerInfoDialog.java
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/gui/search/dialog/CreateBsimServerInfoDialog.java
@@ -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.
@@ -91,8 +91,7 @@ public class CreateBsimServerInfoDialog extends DialogComponentProvider {
public boolean acceptServer(BSimServerInfo serverInfo) {
// FIXME: Use task to correct dialog parenting issue caused by password prompt
String errorMessage = null;
- try {
- FunctionDatabase database = BSimClientFactory.buildClient(serverInfo, true);
+ try (FunctionDatabase database = BSimClientFactory.buildClient(serverInfo, true)) {
if (database.initialize()) {
return true;
}
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimClientFactory.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimClientFactory.java
index 7b207d34ee..291e47316c 100755
--- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimClientFactory.java
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimClientFactory.java
@@ -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.
@@ -118,7 +118,10 @@ public class BSimClientFactory {
}
/**
- * Given the URL for a BSim server construct the appropriate BSim client object (implementing FunctionDatabase)
+ * Given the URL for a BSim server construct the appropriate BSim client object
+ * (implementing FunctionDatabase). Returned instance must be
+ * {@link FunctionDatabase#close() closed} when done using it to prevent depletion
+ * of database connections.
* @param bsimServerInfo BSim server details
* @param async true if database commits should be asynchronous
* @return the database client
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimJDBCDataSource.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimJDBCDataSource.java
index c0ca147904..5e82082b90 100644
--- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimJDBCDataSource.java
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimJDBCDataSource.java
@@ -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.
@@ -48,4 +48,15 @@ public interface BSimJDBCDataSource {
*/
int getActiveConnections();
+ /**
+ * Get the number of idle connections in the associated connection pool
+ * @return number of idle connections
+ */
+ int getIdleConnections();
+
+ /**
+ * Dispose pooled datasource.
+ */
+ void dispose();
+
}
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimPostgresDBConnectionManager.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimPostgresDBConnectionManager.java
index c0dafe4370..70aea9aa2b 100644
--- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimPostgresDBConnectionManager.java
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimPostgresDBConnectionManager.java
@@ -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.
@@ -41,7 +41,8 @@ public class BSimPostgresDBConnectionManager {
private static HashMap dataSourceMap = new HashMap<>();
- public static BSimPostgresDataSource getDataSource(BSimServerInfo postgresServerInfo) {
+ public static synchronized BSimPostgresDataSource getDataSource(
+ BSimServerInfo postgresServerInfo) {
if (postgresServerInfo.getDBType() != DBType.postgres) {
throw new IllegalArgumentException("expected postgres server info");
}
@@ -54,19 +55,20 @@ public class BSimPostgresDBConnectionManager {
return getDataSource(new BSimServerInfo(postgresUrl));
}
- public static BSimPostgresDataSource getDataSourceIfExists(BSimServerInfo serverInfo) {
+ public static synchronized BSimPostgresDataSource getDataSourceIfExists(
+ BSimServerInfo serverInfo) {
return dataSourceMap.get(serverInfo);
}
- private static synchronized void remove(BSimServerInfo serverInfo) {
+ private static synchronized void remove(BSimServerInfo serverInfo, boolean force) {
BSimPostgresDataSource ds = dataSourceMap.get(serverInfo);
if (ds == null) {
return;
}
int n = ds.bds.getNumActive();
- if (n != 0) {
- System.out
- .println("Unable to remove data source which has " + n + " active connections");
+ if (n != 0 && !force) {
+ Msg.error(BSimPostgresDBConnectionManager.class,
+ "Unable to remove data source which has " + n + " active connections");
return;
}
ds.close();
@@ -113,8 +115,9 @@ public class BSimPostgresDBConnectionManager {
bds.setUsername(userName);
}
+ @Override
public void dispose() {
- remove(serverInfo);
+ remove(serverInfo, true);
}
private void close() {
@@ -143,6 +146,11 @@ public class BSimPostgresDBConnectionManager {
return bds.getNumActive();
}
+ @Override
+ public int getIdleConnections() {
+ return bds.getNumIdle();
+ }
+
/**
* Update password on {@link BasicDataSource} for use with future connect attempts.
* Has no affect if username does not match username on data source.
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/FunctionDatabase.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/FunctionDatabase.java
index 4a85e5e54d..6998da5447 100755
--- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/FunctionDatabase.java
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/FunctionDatabase.java
@@ -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.
@@ -33,7 +33,9 @@ import ghidra.features.bsim.query.facade.SFOverviewInfo;
import ghidra.features.bsim.query.facade.SFQueryInfo;
import ghidra.features.bsim.query.protocol.*;
import ghidra.framework.Application;
+import ghidra.program.model.data.DataUtilities;
import ghidra.util.Msg;
+import ghidra.util.StringUtilities;
public interface FunctionDatabase extends AutoCloseable {
@@ -239,7 +241,15 @@ public interface FunctionDatabase extends AutoCloseable {
if (res == 3) {
throw new LSHException("Query signature data has no setting information");
}
- throw new LSHException("Query signature data does not match database");
+ throw new LSHException("Query signature data " +
+ getFormattedVersion(manage.getMajorVersion(), manage.getMinorVersion(),
+ manage.getSettings()) +
+ " does not match database " +
+ getFormattedVersion(info.major, info.minor, info.settings));
+ }
+
+ private static String getFormattedVersion(int maj, int min, int settings) {
+ return String.format("%d.%d:0x%02x", maj, min, settings);
}
public static boolean checkSettingsForInsert(DescriptionManager manage,
@@ -262,8 +272,11 @@ public interface FunctionDatabase extends AutoCloseable {
if (res == 3) {
throw new LSHException("Trying to insert signature data with no setting information");
}
- throw new LSHException(
- "Trying to insert signature data with settings that don't match database");
+ throw new LSHException("Trying to insert signature data " +
+ getFormattedVersion(manage.getMajorVersion(), manage.getMinorVersion(),
+ manage.getSettings()) +
+ " with settings that don't match database " +
+ getFormattedVersion(info.major, info.minor, info.settings));
}
public static String constructFatalError(int flags, ExecutableRecord newrec,
diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/file/BSimH2FileDBConnectionManager.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/file/BSimH2FileDBConnectionManager.java
index a5d13af20f..b7ad1d0629 100644
--- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/file/BSimH2FileDBConnectionManager.java
+++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/file/BSimH2FileDBConnectionManager.java
@@ -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.
@@ -28,6 +28,7 @@ import ghidra.features.bsim.query.*;
import ghidra.features.bsim.query.BSimServerInfo.DBType;
import ghidra.features.bsim.query.FunctionDatabase.ConnectionType;
import ghidra.features.bsim.query.FunctionDatabase.Status;
+import ghidra.util.Msg;
public class BSimH2FileDBConnectionManager {
@@ -44,7 +45,7 @@ public class BSimH2FileDBConnectionManager {
* Get all H2 File DB data sorces which exist in the JVM.
* @return all H2 File DB data sorces
*/
- public static Collection getAllDataSources() {
+ public static synchronized Collection getAllDataSources() {
// Create copy to avoid potential concurrent modification
return Collections.unmodifiableCollection(new ArrayList<>(dataSourceMap.values()));
}
@@ -57,7 +58,7 @@ public class BSimH2FileDBConnectionManager {
* @throws IllegalArgumentException if {@code fileServerInfo} does not specify an
* H2 File DB type.
*/
- public static BSimH2FileDataSource getDataSource(BSimServerInfo fileServerInfo) {
+ public static synchronized BSimH2FileDataSource getDataSource(BSimServerInfo fileServerInfo) {
if (fileServerInfo.getDBType() != DBType.file) {
throw new IllegalArgumentException("expected file info");
}
@@ -79,26 +80,26 @@ public class BSimH2FileDBConnectionManager {
* @return existing H2 File data source or null if server info does not correspond to an
* H2 File or has not be established as an H2 File data source.
*/
- public static BSimH2FileDataSource getDataSourceIfExists(BSimServerInfo serverInfo) {
+ public static synchronized BSimH2FileDataSource getDataSourceIfExists(
+ BSimServerInfo serverInfo) {
return dataSourceMap.get(serverInfo);
}
- private static synchronized void remove(BSimServerInfo serverInfo, boolean force) {
+ private static synchronized boolean remove(BSimServerInfo serverInfo, boolean force) {
BSimH2FileDataSource ds = dataSourceMap.get(serverInfo);
if (ds == null) {
- return;
+ return true;
}
int n = ds.bds.getNumActive();
- if (n != 0) {
- System.out
- .println("Unable to remove data source which has " + n + " active connections");
- if (!force) {
- return;
- }
+ if (n != 0 && !force) {
+ Msg.error(BSimH2FileDBConnectionManager.class,
+ "Unable to remove data source which has " + n + " active connections");
+ return false;
}
ds.close();
dataSourceMap.remove(serverInfo);
BSimVectorStoreManager.remove(serverInfo);
+ return true;
}
/**
@@ -123,20 +124,31 @@ public class BSimH2FileDBConnectionManager {
return serverInfo;
}
+ @Override
public void dispose() {
BSimH2FileDBConnectionManager.remove(serverInfo, true);
}
/**
- * Delete the database files associated with this H2 File DB. When complete
- * this data source will no longer be valid and should no tbe used.
+ * Delete the database files associated with this H2 File DB. This will fail immediately
+ * if active connections exist. Otherwise removal will be attempted and this data source
+ * will no longer be valid.
+ * @return true if DB sucessfully removed
*/
- public void delete() {
- dispose();
+ public synchronized boolean delete() {
File dbf = new File(serverInfo.getDBName());
- // TODO: Should we check for lock on database - could be another process
+ if (getActiveConnections() != 0) {
+ Msg.error(this, "Failed to delete active database: " + dbf);
+ return false;
+ }
+
+ dispose();
+
+ if (dbf.isFile()) {
+ return true;
+ }
String name = dbf.getName();
int ix = name.lastIndexOf(BSimServerInfo.H2_FILE_EXTENSION);
@@ -145,6 +157,13 @@ public class BSimH2FileDBConnectionManager {
}
DeleteDbFiles.execute(dbf.getParent(), name, true);
+
+ if (!dbf.isFile()) {
+ return true;
+ }
+
+ Msg.error(this, "Failed to delete database: " + dbf);
+ return false;
}
/**
@@ -181,6 +200,11 @@ public class BSimH2FileDBConnectionManager {
return bds.getNumActive();
}
+ @Override
+ public int getIdleConnections() {
+ return bds.getNumIdle();
+ }
+
private String getH2FileUrl() {
// Remove H2 db file extension if present
diff --git a/Ghidra/Features/BSim/src/main/resources/images/connect.png b/Ghidra/Features/BSim/src/main/resources/images/connect.png
new file mode 100644
index 0000000000..024138eb33
Binary files /dev/null and b/Ghidra/Features/BSim/src/main/resources/images/connect.png differ
diff --git a/Ghidra/Features/BSim/src/main/resources/images/disconnect.png b/Ghidra/Features/BSim/src/main/resources/images/disconnect.png
new file mode 100644
index 0000000000..b335cb11c4
Binary files /dev/null and b/Ghidra/Features/BSim/src/main/resources/images/disconnect.png differ
diff --git a/Ghidra/Features/BSim/src/screen/java/help/screenshot/BSimSearchPluginScreenShots.java b/Ghidra/Features/BSim/src/screen/java/help/screenshot/BSimSearchPluginScreenShots.java
index 98244f090c..c18470ef4a 100755
--- a/Ghidra/Features/BSim/src/screen/java/help/screenshot/BSimSearchPluginScreenShots.java
+++ b/Ghidra/Features/BSim/src/screen/java/help/screenshot/BSimSearchPluginScreenShots.java
@@ -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.
@@ -23,8 +23,7 @@ import org.junit.Test;
import docking.DockingWindowManager;
import docking.action.DockingActionIf;
import ghidra.app.services.ProgramManager;
-import ghidra.features.bsim.gui.BSimSearchPlugin;
-import ghidra.features.bsim.gui.BSimSearchPluginTestHelper;
+import ghidra.features.bsim.gui.*;
import ghidra.features.bsim.gui.overview.BSimOverviewProvider;
import ghidra.features.bsim.gui.overview.BSimOverviewTestHelper;
import ghidra.features.bsim.gui.search.dialog.*;
diff --git a/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/BSimSearchPluginTestHelper.java b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/BSimSearchPluginTestHelper.java
index c80999009e..9982e019ce 100644
--- a/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/BSimSearchPluginTestHelper.java
+++ b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/BSimSearchPluginTestHelper.java
@@ -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.
@@ -15,7 +15,6 @@
*/
package ghidra.features.bsim.gui;
-import ghidra.features.bsim.gui.search.dialog.BSimServerManager;
import ghidra.features.bsim.query.facade.SFQueryServiceFactory;
public class BSimSearchPluginTestHelper {
diff --git a/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/QueryFilterTest.java b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/QueryFilterTest.java
index 72ffd6a255..57a5a17fdd 100755
--- a/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/QueryFilterTest.java
+++ b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/QueryFilterTest.java
@@ -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.
@@ -65,6 +65,7 @@ public class QueryFilterTest extends AbstractBSimPluginTest {
assertEquals(SQL_TRUTH, sql);
}
+ @Override
protected void initializeTool() throws Exception {
super.initializeTool();
goTo(FUN1_ADDR);
@@ -80,7 +81,6 @@ public class QueryFilterTest extends AbstractBSimPluginTest {
*
* @param ids resolution IDs
* @return the query string
- * @throws SQLException if there is a problem creating the filter
*/
private String generateSQL(IDSQLResolution[] ids) {
try {
@@ -88,7 +88,8 @@ public class QueryFilterTest extends AbstractBSimPluginTest {
BSimFilter filter = filterSet.getBSimFilter();
BSimSqlClause sql = SQLEffects.createFilter(filter, ids, null);
return sql.whereClause().trim();
- } catch (SQLException e) {
+ }
+ catch (SQLException e) {
throw new AssertException(e);
}
}
diff --git a/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/overview/BSimOverviewTestHelper.java b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/overview/BSimOverviewTestHelper.java
index 7be8bb04ff..36c18c254d 100644
--- a/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/overview/BSimOverviewTestHelper.java
+++ b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/overview/BSimOverviewTestHelper.java
@@ -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.
@@ -15,8 +15,7 @@
*/
package ghidra.features.bsim.gui.overview;
-import ghidra.features.bsim.gui.BSimSearchPlugin;
-import ghidra.features.bsim.gui.BSimSearchPluginTestHelper;
+import ghidra.features.bsim.gui.*;
import ghidra.features.bsim.gui.search.dialog.*;
import ghidra.features.bsim.query.BSimServerInfo;
import ghidra.features.bsim.query.FunctionDatabase;
diff --git a/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/search/dialog/BSimFilterPanelTest.java b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/search/dialog/BSimFilterPanelTest.java
index 98cf419d50..db9127b523 100755
--- a/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/search/dialog/BSimFilterPanelTest.java
+++ b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/search/dialog/BSimFilterPanelTest.java
@@ -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.
@@ -18,7 +18,7 @@ package ghidra.features.bsim.gui.search.dialog;
import static org.junit.Assert.*;
import java.sql.SQLException;
-import java.util.*;
+import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -30,7 +30,6 @@ import ghidra.features.bsim.query.SQLFunctionDatabase;
import ghidra.features.bsim.query.client.*;
import ghidra.features.bsim.query.facade.FunctionDatabaseTestDouble;
import ghidra.features.bsim.query.protocol.BSimFilter;
-import ghidra.program.database.symbol.FunctionSymbol;
/**
* Tests the filtering components of BSim accessible from the UI. This will cover the
@@ -44,9 +43,9 @@ import ghidra.program.database.symbol.FunctionSymbol;
*/
public class BSimFilterPanelTest extends AbstractBSimPluginTest {
- private Set selectedFunctions = new HashSet<>();
private BSimFilterPanel filterPanel;
+ @Override
@Before
public void setUp() throws Exception {
super.setUp();
@@ -57,6 +56,7 @@ public class BSimFilterPanelTest extends AbstractBSimPluginTest {
filterPanel = BSimSearchDialogTestHelper.getFilterPanel(searchDialog);
}
+ @Override
@After
public void tearDown() throws Exception {
close(searchDialog);
diff --git a/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/search/dialog/BSimSearchDialogTestHelper.java b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/search/dialog/BSimSearchDialogTestHelper.java
index 4792197296..ac1cb0ef01 100644
--- a/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/search/dialog/BSimSearchDialogTestHelper.java
+++ b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/gui/search/dialog/BSimSearchDialogTestHelper.java
@@ -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.
@@ -17,8 +17,7 @@ package ghidra.features.bsim.gui.search.dialog;
import java.util.Set;
-import ghidra.features.bsim.gui.BSimSearchPlugin;
-import ghidra.features.bsim.gui.BSimSearchPluginTestHelper;
+import ghidra.features.bsim.gui.*;
import ghidra.features.bsim.query.BSimServerInfo;
import ghidra.features.bsim.query.FunctionDatabase;
import ghidra.features.bsim.query.facade.TestBSimServerInfo;
diff --git a/Ghidra/Features/BSim/src/test.slow/java/ghidra/query/inmemory/BSimH2DatabaseManagerTest.java b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/query/file/BSimH2DatabaseManagerTest.java
similarity index 98%
rename from Ghidra/Features/BSim/src/test.slow/java/ghidra/query/inmemory/BSimH2DatabaseManagerTest.java
rename to Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/query/file/BSimH2DatabaseManagerTest.java
index 3878d4caa6..f3dd96c173 100644
--- a/Ghidra/Features/BSim/src/test.slow/java/ghidra/query/inmemory/BSimH2DatabaseManagerTest.java
+++ b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/query/file/BSimH2DatabaseManagerTest.java
@@ -4,16 +4,16 @@
* 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.query.inmemory;
+package ghidra.features.bsim.query.file;
import static org.junit.Assert.*;
@@ -26,7 +26,6 @@ import ghidra.features.bsim.query.*;
import ghidra.features.bsim.query.BSimServerInfo.DBType;
import ghidra.features.bsim.query.FunctionDatabase.Error;
import ghidra.features.bsim.query.description.DatabaseInformation;
-import ghidra.features.bsim.query.file.BSimH2FileDBConnectionManager;
import ghidra.features.bsim.query.file.BSimH2FileDBConnectionManager.BSimH2FileDataSource;
import ghidra.features.bsim.query.protocol.CreateDatabase;
import ghidra.features.bsim.query.protocol.ResponseInfo;
@@ -50,7 +49,7 @@ public class BSimH2DatabaseManagerTest extends AbstractGhidraHeadedIntegrationTe
@After
public void tearDown() {
- //cleanup();
+ cleanup();
}
private File getTempDbDir() {
@@ -77,7 +76,7 @@ public class BSimH2DatabaseManagerTest extends AbstractGhidraHeadedIntegrationTe
}
private BSimServerInfo createDatabase(String databaseName, List tags,
- List execats, String expectedError) {
+ List execats, String expectedError) {
BSimServerInfo h2DbInfo = getBsimServerInfo(databaseName);
Msg.debug(this, "Creating H2 File DB: " + h2DbInfo);
diff --git a/Ghidra/Features/BSim/src/test.slow/java/ghidra/query/test/BSimServerTest.java b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/query/test/BSimServerTest.java
similarity index 99%
rename from Ghidra/Features/BSim/src/test.slow/java/ghidra/query/test/BSimServerTest.java
rename to Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/query/test/BSimServerTest.java
index b1073152bf..07154c507b 100755
--- a/Ghidra/Features/BSim/src/test.slow/java/ghidra/query/test/BSimServerTest.java
+++ b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/query/test/BSimServerTest.java
@@ -4,16 +4,16 @@
* 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.query.test;
+package ghidra.features.bsim.query.test;
import static org.junit.Assert.*;
diff --git a/Ghidra/Features/BSim/src/test.slow/java/ghidra/query/test/BSimServerTestUtil.java b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/query/test/BSimServerTestUtil.java
similarity index 99%
rename from Ghidra/Features/BSim/src/test.slow/java/ghidra/query/test/BSimServerTestUtil.java
rename to Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/query/test/BSimServerTestUtil.java
index 7a1e2f1728..d1ffa67c49 100755
--- a/Ghidra/Features/BSim/src/test.slow/java/ghidra/query/test/BSimServerTestUtil.java
+++ b/Ghidra/Features/BSim/src/test.slow/java/ghidra/features/bsim/query/test/BSimServerTestUtil.java
@@ -4,16 +4,16 @@
* 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.query.test;
+package ghidra.features.bsim.query.test;
import java.io.*;