7
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 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 0000000000000000000000000000000000000000..024138eb33b9124af6db8149747adbb41c1b8cfc
GIT binary patch
literal 748
zcmVzR>QH2KN`fNj
zBHaWZEgiB#>49kYe(borqx+hj`JS_1d)R}7LjHa+tu+qg(TC+eO4&q(D;ZL8C8o8;
zLEfZxiIlQ~iE1b1qBZ2=VhsA0V`*@y@M|Sc2@Wtadv3g0hOc*O(ADVFjPTWAYz(JXS
z8MBaa%aCO{h8lvp*ONKIh5Bg|-DNo^;jg=q=uDZ@vodOJXfu;GK`ze`H-VrWK!nUg
zje)ufRUJ&ouB2nYB2_pI=gji&GcuBL=+DM-wBZ)fbc7&a9AP1Ztk5)S4Ah03bqXOt
zxx}VdK|CIVljyc=oqO1G{;Qew7T~%?tSw{^mi$E(2^Td6>M8+m4H!qrBtj~%w(Y~Q
zVrXkVOEN#2&@(U(cX3H&S97B(;-}{)?<>?0)RjVZqrJ&ONChgCgE9%PC}CSBp!+d1
z`bkAqacXYz!94aLsJZ!K=3b*?T#ge1nL>bsZNf4&8mt(EkXYZ?MK0YwH2ZOI9{(VN
z&%WPH*v6AY+yG?)mZ`CxE@5ZK2lW}4Pr-ctMRE2V`yf8$PurT4&^p3q*2kt>M8OM&
zl@MbQ=U&8BS_$dSjo(q&2Pyd!8`}{~Xr#A_DDL|G({Ha$;Xe@?&|@q4QbvV}D#ixB
ey}zEqA^Zgf(1+rQ>#k7%0000h5&w{Y-QlBkdy7eSyz8|k(w=syt3MbOGZFmTy2f|dnI3kj6Sz)H!`
z%1hM3FiovS8#Qs98Rxs5^PSs#9S4da6*};44(Iv3@B5rb3BwQ$Is?0$0ilY#Q^EELL=6SfS*Ly93GR<|lPYvfPXoM^)HN1)!-B@N5Zi(e|Ge`rl{XLurIiz-D}wH 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.*;