GP-4151 fixing wizard pattern to better handle expensive checks between panels.

This commit is contained in:
ghidragon 2025-01-24 17:31:03 -05:00
parent bb4853e414
commit 32bf68b8f3
159 changed files with 5692 additions and 5916 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Before After
Before After

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -20,11 +20,11 @@ import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import docking.tool.ToolConstants;
import docking.wizard.WizardManager;
import docking.wizard.WizardDialog;
import generic.theme.GIcon;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.wizard.VTAddToSessionWizardManager;
import ghidra.feature.vt.gui.wizard.add.VTAddToSessionWizardModel;
import ghidra.util.HelpLocation;
public class AddToVersionTrackingSessionAction extends DockingAction {
@ -46,10 +46,9 @@ public class AddToVersionTrackingSessionAction extends DockingAction {
@Override
public void actionPerformed(ActionContext context) {
VTAddToSessionWizardManager vtWizardManager = new VTAddToSessionWizardManager(controller);
WizardManager wizardManager =
new WizardManager("Version Tracking Wizard", true, vtWizardManager);
wizardManager.showWizard(controller.getParentComponent());
VTAddToSessionWizardModel model = new VTAddToSessionWizardModel(controller);
WizardDialog wizardDialog = new WizardDialog(model);
wizardDialog.show(controller.getParentComponent());
}
@Override

View file

@ -21,11 +21,11 @@ import docking.ActionContext;
import docking.action.*;
import docking.tool.ToolConstants;
import docking.widgets.OptionDialog;
import docking.wizard.WizardManager;
import docking.wizard.WizardDialog;
import generic.theme.GIcon;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.wizard.VTNewSessionWizardManager;
import ghidra.feature.vt.gui.wizard.session.VTNewSessionWizardModel;
import ghidra.util.HelpLocation;
public class CreateVersionTrackingSessionAction extends DockingAction {
@ -58,10 +58,9 @@ public class CreateVersionTrackingSessionAction extends DockingAction {
if (!controller.closeVersionTrackingSession()) {
return; // user cancelled during save dialog
}
VTNewSessionWizardManager vtWizardManager = new VTNewSessionWizardManager(controller);
WizardManager wizardManager =
new WizardManager("Version Tracking Wizard", true, vtWizardManager);
wizardManager.showWizard(controller.getParentComponent());
VTNewSessionWizardModel model = new VTNewSessionWizardModel(controller);
WizardDialog wizardDialog = new WizardDialog(model);
wizardDialog.show(controller.getParentComponent());
}
}

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -24,7 +24,7 @@ import javax.swing.JFrame;
import docking.action.DockingActionIf;
import docking.tool.ToolConstants;
import docking.wizard.WizardManager;
import docking.wizard.WizardDialog;
import generic.theme.GIcon;
import ghidra.GhidraOptions;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
@ -37,7 +37,7 @@ import ghidra.feature.vt.gui.provider.functionassociation.VTFunctionAssociationP
import ghidra.feature.vt.gui.provider.impliedmatches.*;
import ghidra.feature.vt.gui.provider.markuptable.VTMarkupItemsTableProvider;
import ghidra.feature.vt.gui.provider.matchtable.VTMatchTableProvider;
import ghidra.feature.vt.gui.wizard.VTNewSessionWizardManager;
import ghidra.feature.vt.gui.wizard.session.VTNewSessionWizardModel;
import ghidra.framework.model.*;
import ghidra.framework.options.Options;
import ghidra.framework.options.SaveState;
@ -268,11 +268,10 @@ public class VTPlugin extends Plugin {
if (!controller.closeVersionTrackingSession()) {
return false; // user cancelled during save dialog
}
VTNewSessionWizardManager vtWizardManager =
new VTNewSessionWizardManager(controller, programFile1, programFile2);
WizardManager wizardManager =
new WizardManager("Version Tracking Wizard", true, vtWizardManager);
wizardManager.showWizard(tool.getToolFrame());
VTNewSessionWizardModel model =
new VTNewSessionWizardModel(controller, programFile1, programFile2);
WizardDialog wizardDialog = new WizardDialog(model);
wizardDialog.show(tool.getToolFrame());
return true;
}

View file

@ -1,13 +1,12 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -16,7 +15,7 @@
*/
package ghidra.feature.vt.gui.task;
import ghidra.feature.vt.gui.wizard.VTWizardUtils;
import ghidra.feature.vt.gui.wizard.session.VTWizardUtils;
import ghidra.framework.model.DomainFile;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;

View file

@ -1,25 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.feature.vt.gui.wizard;
import ghidra.program.model.address.Address;
public interface AddressRangeListener {
public void processAddressRange(Address minAddress, Address maxAddress);
}

View file

@ -1,152 +0,0 @@
/* ###
* 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.feature.vt.gui.wizard;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import docking.widgets.checkbox.GCheckBox;
import docking.wizard.*;
import ghidra.feature.vt.api.main.VTProgramCorrelatorAddressRestrictionPreference;
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
import ghidra.program.model.address.AddressSetView;
import ghidra.util.HTMLUtilities;
import ghidra.util.HelpLocation;
import ghidra.util.layout.VerticalLayout;
public class AddressSetOptionsPanel extends AbstractMageJPanel<VTWizardStateKey> {
private JCheckBox excludeCheckbox;
private JCheckBox showAddressSetPanelsCheckbox;
public AddressSetOptionsPanel() { //
setBorder(BorderFactory.createEmptyBorder(40, 40, 0, 0));
excludeCheckbox = new GCheckBox("Exclude accepted matches", false);
String excludeAcceptedTooltip = "This option will cause the correlator algorithm " +
"to <b>not</b> consider any functions or data that have already been " +
"accepted. Using this option can greatly speed up the processing time " +
"of the correlator algorithm; however, this options should only be " +
"used when you trust that your accepted matches are correct.";
excludeCheckbox.setToolTipText(HTMLUtilities.toWrappedHTML(excludeAcceptedTooltip));
showAddressSetPanelsCheckbox = new GCheckBox("Limit source and destination address sets");
String manuallyLimitTooltip = "Selecting this checkbox will trigger additional wizard " +
" panels allowing you to customize the address sets used " +
" by the selected algorithm. When not selected, the entire address space is used.";
showAddressSetPanelsCheckbox.setToolTipText(
HTMLUtilities.toWrappedHTML(manuallyLimitTooltip));
add(excludeCheckbox);
add(showAddressSetPanelsCheckbox);
setLayout(new VerticalLayout(20));
}
@Override
public void addDependencies(WizardState<VTWizardStateKey> state) {
// none
}
@Override
public void dispose() {
// nothing to do
}
@Override
public void enterPanel(WizardState<VTWizardStateKey> state) {
@SuppressWarnings("unchecked")
List<VTProgramCorrelatorFactory> list = (List<VTProgramCorrelatorFactory>) state.get(
VTWizardStateKey.PROGRAM_CORRELATOR_FACTORY_LIST);
Boolean value = (Boolean) state.get(VTWizardStateKey.EXCLUDE_ACCEPTED_MATCHES);
if (value != null) {
excludeCheckbox.setSelected(value.booleanValue());
}
value = (Boolean) state.get(VTWizardStateKey.SHOW_ADDRESS_SET_PANELS);
if (value != null) {
showAddressSetPanelsCheckbox.setSelected(value.booleanValue());
}
else {
AddressSetView sourceSelection =
(AddressSetView) state.get(VTWizardStateKey.SOURCE_SELECTION);
AddressSetView destinationSelection =
(AddressSetView) state.get(VTWizardStateKey.DESTINATION_SELECTION);
boolean somethingSelected = (sourceSelection != null && !sourceSelection.isEmpty()) ||
(destinationSelection != null && !destinationSelection.isEmpty());
showAddressSetPanelsCheckbox.setSelected(somethingSelected);
}
if (allowRestrictions(list)) {
excludeCheckbox.setEnabled(true);
}
else {
excludeCheckbox.setSelected(false);
excludeCheckbox.setEnabled(false);
}
}
private boolean allowRestrictions(List<VTProgramCorrelatorFactory> list) {
for (VTProgramCorrelatorFactory factory : list) {
if (factory.getAddressRestrictionPreference() != VTProgramCorrelatorAddressRestrictionPreference.RESTRICTION_NOT_ALLOWED) {
return true;
}
}
return false;
}
@Override
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
WizardState<VTWizardStateKey> state) {
return WizardPanelDisplayability.CAN_BE_DISPLAYED;
}
@Override
public void leavePanel(WizardState<VTWizardStateKey> state) {
updateStateObjectWithPanelInfo(state);
}
@Override
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
state.put(VTWizardStateKey.EXCLUDE_ACCEPTED_MATCHES, excludeCheckbox.isSelected());
state.put(VTWizardStateKey.SHOW_ADDRESS_SET_PANELS,
showAddressSetPanelsCheckbox.isSelected());
}
@Override
public HelpLocation getHelpLocation() {
return new HelpLocation("VersionTrackingPlugin", "Address_Set_Panel");
}
@Override
public String getTitle() {
return "Address Set Options";
}
@Override
public void initialize() {
// nothing to do
}
@Override
public boolean isValidInformation() {
return true;
}
}

View file

@ -1,156 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.feature.vt.gui.wizard;
import ghidra.feature.vt.gui.wizard.ChooseAddressSetEditorPanel.AddressSetChoice;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
import java.awt.BorderLayout;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import docking.wizard.*;
public class AddressSetPanel extends AbstractMageJPanel<VTWizardStateKey> {
private final PluginTool tool;
private final String name;
private final VTWizardStateKey programDependencyKey;
private final VTWizardStateKey addressSetViewKey;
private final VTWizardStateKey selectionKey;
private final VTWizardStateKey addressSetChoiceKey;
private ChooseAddressSetEditorPanel panel;
private Program program;
public AddressSetPanel(PluginTool tool, String name, VTWizardStateKey programFileDependencyKey,
VTWizardStateKey programDependencyKey, VTWizardStateKey addressSetViewKey,
VTWizardStateKey selectionKey, VTWizardStateKey addressSetChoiceKey) {
this.tool = tool;
this.name = name;
this.programDependencyKey = programDependencyKey;
this.addressSetViewKey = addressSetViewKey;
this.selectionKey = selectionKey;
this.addressSetChoiceKey = addressSetChoiceKey;
setLayout(new BorderLayout());
}
@Override
public void addDependencies(WizardState<VTWizardStateKey> state) {
// no dependencies
}
@Override
public void dispose() {
// nothing to do
}
// Keep this method for now in case we want it as the default for the entire program address set
// instead of the program's memory address set.
@SuppressWarnings("unused")
private AddressSet getAddressFactoryAddressSet(WizardState<VTWizardStateKey> state) {
Program programFromState = (Program) state.get(programDependencyKey);
AddressFactory factory = programFromState.getAddressFactory();
AddressSet everything = new AddressSet();
AddressSpace[] addressSpaces = factory.getAddressSpaces();
for (AddressSpace addressSpace : addressSpaces) {
Address minAddress = addressSpace.getMinAddress();
Address maxAddress = addressSpace.getMaxAddress();
AddressRangeImpl range = new AddressRangeImpl(minAddress, maxAddress);
everything.add(range);
}
return everything;
}
@Override
public HelpLocation getHelpLocation() {
return new HelpLocation("VersionTrackingPlugin", "Address_Set_Panel");
}
@Override
public void enterPanel(WizardState<VTWizardStateKey> state) {
if (panel != null) {
remove(panel);
}
program = (Program) state.get(programDependencyKey);
AddressSetView addressSetView = (AddressSetView) state.get(addressSetViewKey);
AddressSetView selection = (AddressSetView) state.get(selectionKey);
AddressSetChoice addressSetChoice = (AddressSetChoice) state.get(addressSetChoiceKey);
if (addressSetChoice == null) {
if (selection != null && !selection.isEmpty()) {
addressSetChoice = AddressSetChoice.SELECTION;
}
else {
addressSetChoice = AddressSetChoice.ENTIRE_PROGRAM;
}
}
panel =
new ChooseAddressSetEditorPanel(tool, name, program, selection, addressSetView,
addressSetChoice);
panel.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
notifyListenersOfValidityChanged();
}
});
add(panel, BorderLayout.CENTER);
}
@Override
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
WizardState<VTWizardStateKey> state) {
Boolean value = (Boolean) state.get(VTWizardStateKey.SHOW_ADDRESS_SET_PANELS);
boolean showPanel = value == null ? false : value.booleanValue();
if (!showPanel) {
return WizardPanelDisplayability.DO_NOT_DISPLAY;
}
return WizardPanelDisplayability.CAN_BE_DISPLAYED;
}
@Override
public void leavePanel(WizardState<VTWizardStateKey> state) {
updateStateObjectWithPanelInfo(state);
}
@Override
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
AddressSetView addressSetView = panel.getAddressSetView();
state.put(addressSetViewKey, addressSetView);
state.put(addressSetChoiceKey, panel.getAddressSetChoice());
}
@Override
public String getTitle() {
return "Select " + name + " Address Range(s)";
}
@Override
public void initialize() {
// not sure if we need this
}
@Override
public boolean isValidInformation() {
boolean empty = panel.getAddressSetView().isEmpty();
String msg = empty ? "At least one address range is required" : "";
notifyListenersOfStatusMessage(msg);
return !empty;
}
}

View file

@ -1,109 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.feature.vt.gui.wizard;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.HelpLocation;
import java.awt.GridLayout;
import docking.wizard.*;
public class LimitAddressSetsPanel extends AbstractMageJPanel<VTWizardStateKey> {
private AddressSetPanel sourcePanel;
private AddressSetPanel destinationPanel;
public LimitAddressSetsPanel(PluginTool tool) {
setLayout(new GridLayout());
sourcePanel =
new AddressSetPanel(tool, "Source", VTWizardStateKey.SOURCE_PROGRAM_FILE,
VTWizardStateKey.SOURCE_PROGRAM, VTWizardStateKey.SOURCE_ADDRESS_SET_VIEW,
VTWizardStateKey.SOURCE_SELECTION, VTWizardStateKey.SOURCE_ADDRESS_SET_CHOICE);
destinationPanel =
new AddressSetPanel(tool, "Destination", VTWizardStateKey.DESTINATION_PROGRAM_FILE,
VTWizardStateKey.DESTINATION_PROGRAM,
VTWizardStateKey.DESTINATION_ADDRESS_SET_VIEW,
VTWizardStateKey.DESTINATION_SELECTION,
VTWizardStateKey.DESTINATION_ADDRESS_SET_CHOICE);
add(sourcePanel);
add(destinationPanel);
}
@Override
public HelpLocation getHelpLocation() {
return new HelpLocation("VersionTrackingPlugin", "Select_Address_Ranges_Panel");
}
@Override
public void addDependencies(WizardState<VTWizardStateKey> state) {
sourcePanel.addDependencies(state);
destinationPanel.addDependencies(state);
}
@Override
public void dispose() {
sourcePanel.dispose();
destinationPanel.dispose();
}
@Override
public void enterPanel(WizardState<VTWizardStateKey> state) {
sourcePanel.enterPanel(state);
destinationPanel.enterPanel(state);
}
@Override
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
WizardState<VTWizardStateKey> state) {
WizardPanelDisplayability sourceDisplayability =
sourcePanel.getPanelDisplayabilityAndUpdateState(state);
destinationPanel.getPanelDisplayabilityAndUpdateState(state);
// Use the displayability of the source panel as that of the source/destination combined.
return sourceDisplayability;
}
@Override
public void leavePanel(WizardState<VTWizardStateKey> state) {
sourcePanel.leavePanel(state);
destinationPanel.leavePanel(state);
}
@Override
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
sourcePanel.updateStateObjectWithPanelInfo(state);
destinationPanel.updateStateObjectWithPanelInfo(state);
}
@Override
public String getTitle() {
return "Select Address Range(s)";
}
@Override
public void initialize() {
sourcePanel.initialize();
destinationPanel.initialize();
}
@Override
public boolean isValidInformation() {
return sourcePanel.isValidInformation() && destinationPanel.isValidInformation();
}
}

View file

@ -1,611 +0,0 @@
/* ###
* 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.feature.vt.gui.wizard;
import static ghidra.framework.main.DataTreeDialogType.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.apache.commons.lang3.StringUtils;
import docking.widgets.button.BrowseButton;
import docking.widgets.label.GDLabel;
import docking.wizard.*;
import generic.theme.GIcon;
import generic.theme.GThemeDefaults.Ids.Fonts;
import generic.theme.Gui;
import ghidra.app.util.task.OpenProgramRequest;
import ghidra.app.util.task.OpenProgramTask;
import ghidra.feature.vt.api.util.VTSessionFileUtil;
import ghidra.framework.main.DataTreeDialog;
import ghidra.framework.model.DomainFile;
import ghidra.framework.model.DomainFolder;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
import ghidra.util.*;
import ghidra.util.task.TaskLauncher;
/**
* Version tracking wizard panel to create a new session.
*/
public class NewSessionPanel extends AbstractMageJPanel<VTWizardStateKey> {
// The maximum length to allow for each program's name portion of the session name.
// In the filesystem API, when saved, the session name is restricted to 60 characters.
// The default VTSession name combines the two program names so split the length between them,
// minus text we add below.
private static final int VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH = 28;
private static final int TEXT_FIELD_LENGTH = 40;
private static final Icon SWAP_ICON = new GIcon("icon.version.tracking.new.session.swap");
private static final Icon INFO_ICON = new GIcon("icon.version.tracking.new.session.info");
private JTextField sourceField;
private JTextField destinationField;
private JButton sourceBrowseButton;
private JButton destinationBrowseButton;
private JButton swapProgramsButton;
private JTextField sessionNameField;
private JTextField folderNameField;
private DomainFolder folder;
private PluginTool tool;
// All program info objects that the user may have opened while using the wizard. We keep
// these around to avoid reopening them and any accompanying upgrading that may be required.
// These will be released when the wizard is finished.
private Map<DomainFile, ProgramInfo> allProgramInfos = new HashMap<>();
private ProgramInfo sourceProgramInfo;
private ProgramInfo destinationProgramInfo;
NewSessionPanel(PluginTool tool) {
this.tool = tool;
setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
JLabel folderLabel = new GDLabel("Project folder ");
folderLabel.setHorizontalAlignment(SwingConstants.RIGHT);
folderLabel.setToolTipText("The folder to store the new Version Tracking Session");
folderNameField = new JTextField();
Gui.registerFont(folderNameField, Fonts.MONOSPACED);
folderNameField.setEditable(false); // force user to browse to choose
JButton browseFolderButton = new BrowseButton();
browseFolderButton.addActionListener(e -> browseDataTreeFolders());
JLabel newSessionLabel = new GDLabel("New Session Name: ");
newSessionLabel.setToolTipText("The name for the new Version Tracking Session");
newSessionLabel.setHorizontalAlignment(SwingConstants.RIGHT);
sessionNameField = new JTextField(TEXT_FIELD_LENGTH);
sessionNameField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
// do nothing
}
@Override
public void insertUpdate(DocumentEvent e) {
notifyListenersOfValidityChanged();
}
@Override
public void removeUpdate(DocumentEvent e) {
notifyListenersOfValidityChanged();
}
});
JLabel sourceLabel = new GDLabel("Source Program: ");
sourceLabel.setIcon(INFO_ICON);
sourceLabel.setToolTipText("Analyzed program with markup to transfer");
sourceLabel.setHorizontalAlignment(SwingConstants.RIGHT);
JLabel destinationLabel = new GDLabel("Destination Program: ");
destinationLabel.setIcon(INFO_ICON);
destinationLabel.setToolTipText("New program that receives the transferred markup");
destinationLabel.setHorizontalAlignment(SwingConstants.RIGHT);
sourceField = new JTextField(TEXT_FIELD_LENGTH);
sourceField.setEditable(false);
destinationField = new JTextField(TEXT_FIELD_LENGTH);
destinationField.setEditable(false);
sourceBrowseButton = createSourceBrowseButton();
destinationBrowseButton = createDestinationBrowseButton();
swapProgramsButton = new JButton(SWAP_ICON);
swapProgramsButton.setText("swap");
swapProgramsButton.setName("SWAP_BUTTON");
swapProgramsButton.addActionListener(arg0 -> swapPrograms());
JPanel mainPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
mainPanel.add(Box.createVerticalStrut(15), gbc);
gbc.gridy++;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainPanel.add(folderLabel, gbc);
gbc.gridx++;
mainPanel.add(folderNameField, gbc);
gbc.gridx++;
mainPanel.add(Box.createHorizontalStrut(5), gbc);
gbc.gridx++;
mainPanel.add(browseFolderButton, gbc);
gbc.gridx = 0;
gbc.gridy++;
mainPanel.add(Box.createVerticalStrut(10), gbc);
gbc.gridy++;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainPanel.add(newSessionLabel, gbc);
gbc.gridx++;
mainPanel.add(sessionNameField, gbc);
gbc.gridx = 0;
gbc.gridy++;
mainPanel.add(Box.createVerticalStrut(15), gbc);
gbc.gridy++;
gbc.gridwidth = 4;
mainPanel.add(new JSeparator(), gbc);
gbc.gridy++;
gbc.gridwidth = 1;
mainPanel.add(Box.createVerticalStrut(25), gbc);
gbc.gridy++;
mainPanel.add(sourceLabel, gbc);
gbc.gridx++;
mainPanel.add(sourceField, gbc);
gbc.gridx += 2;
mainPanel.add(sourceBrowseButton, gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.fill = GridBagConstraints.NONE;
gbc.gridwidth = 4;
mainPanel.add(swapProgramsButton, gbc);
gbc.gridwidth = 1;
gbc.gridy++;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainPanel.add(destinationLabel, gbc);
gbc.gridx++;
mainPanel.add(destinationField, gbc);
gbc.gridx += 2;
mainPanel.add(destinationBrowseButton, gbc);
gbc.gridx = 0;
gbc.gridy++;
mainPanel.add(Box.createVerticalStrut(25), gbc);
gbc.gridy++;
gbc.gridwidth = 4;
mainPanel.add(new JSeparator(), gbc);
gbc.gridy++;
gbc.gridwidth = 1;
mainPanel.add(Box.createVerticalStrut(60), gbc);
setLayout(new BorderLayout());
add(mainPanel, BorderLayout.NORTH);
}
private void initializePrograms(WizardState<VTWizardStateKey> state) {
DomainFile source = (DomainFile) state.get(VTWizardStateKey.SOURCE_PROGRAM_FILE);
DomainFile destintation = (DomainFile) state.get(VTWizardStateKey.DESTINATION_PROGRAM_FILE);
if (source != null) {
setSourceProgram(source);
}
if (destintation != null) {
setDestinationProgram(destintation);
}
}
/**
* Presents the user with a tree of the existing project folders and allows
* them to pick one
*/
private void browseDataTreeFolders() {
final DataTreeDialog dataTreeDialog =
new DataTreeDialog(this, "Choose a project folder", CHOOSE_FOLDER);
dataTreeDialog.addOkActionListener(e -> {
dataTreeDialog.close();
setFolder(dataTreeDialog.getDomainFolder());
});
dataTreeDialog.showComponent();
}
void setFolder(DomainFolder folder) {
this.folder = folder;
if (folder != null) {
folderNameField.setText(folder.toString());
}
else {
folderNameField.setText("< Choose a folder >");
}
notifyListenersOfValidityChanged();
}
private void setSourceProgram(DomainFile programFile) {
notifyListenersOfStatusMessage(" ");
String path;
if (programFile == null) {
sourceProgramInfo = null;
path = "";
}
else {
sourceProgramInfo =
allProgramInfos.computeIfAbsent(programFile, file -> new ProgramInfo(file));
path = programFile.getPathname();
}
sourceField.setText(path);
updateSessionNameIfBlank();
notifyListenersOfValidityChanged();
}
private void updateSessionNameIfBlank() {
if (!StringUtils.isBlank(sessionNameField.getText())) {
return;
}
if (sourceProgramInfo == null || destinationProgramInfo == null) {
return;
}
String defaultSessionName =
createVTSessionName(sourceProgramInfo.getName(), destinationProgramInfo.getName());
sessionNameField.setText(defaultSessionName);
}
private String createVTSessionName(String sourceName, String destinationName) {
// if together they are within the bounds just return session name with both full names
if (sourceName.length() + destinationName.length() <= 2 *
VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH) {
return "VT_" + sourceName + "_" + destinationName;
}
// give destination name all space not used by source name
if (sourceName.length() < VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH) {
int leftover = VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH - sourceName.length();
destinationName = StringUtilities.trimMiddle(destinationName,
VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH + leftover);
return "VT_" + sourceName + "_" + destinationName;
}
// give source name all space not used by destination name
if (destinationName.length() < VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH) {
int leftover = VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH - destinationName.length();
sourceName = StringUtilities.trimMiddle(sourceName,
VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH + leftover);
return "VT_" + sourceName + "_" + destinationName;
}
// if both too long, shorten both of them
sourceName = StringUtilities.trimMiddle(sourceName, VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH);
destinationName =
StringUtilities.trimMiddle(destinationName, VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH);
return "VT_" + sourceName + "_" + destinationName;
}
private void setDestinationProgram(DomainFile programFile) {
notifyListenersOfStatusMessage(" ");
String path;
if (programFile == null) {
destinationProgramInfo = null;
path = "";
}
else {
destinationProgramInfo =
allProgramInfos.computeIfAbsent(programFile, file -> new ProgramInfo(file));
path = programFile.getPathname();
}
destinationField.setText(path);
updateSessionNameIfBlank();
notifyListenersOfValidityChanged();
}
private void swapPrograms() {
notifyListenersOfStatusMessage(" ");
ProgramInfo temp = destinationProgramInfo;
destinationProgramInfo = sourceProgramInfo;
sourceProgramInfo = temp;
if (sourceProgramInfo != null) {
sourceField.setText(sourceProgramInfo.getPathname());
}
else {
sourceField.setText("");
}
if (destinationProgramInfo != null) {
destinationField.setText(destinationProgramInfo.getPathname());
}
else {
destinationField.setText("");
}
notifyListenersOfValidityChanged();
}
@Override
public HelpLocation getHelpLocation() {
return new HelpLocation("VersionTrackingPlugin", "New_Session_Panel");
}
private void releaseConsumers() {
for (ProgramInfo info : allProgramInfos.values()) {
info.release(tool);
}
allProgramInfos.clear();
}
@Override
public void enterPanel(WizardState<VTWizardStateKey> state) {
initializePrograms(state);
}
@Override
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
WizardState<VTWizardStateKey> state) {
return WizardPanelDisplayability.MUST_BE_DISPLAYED;
}
@Override
public void leavePanel(WizardState<VTWizardStateKey> state) {
updateStateObjectWithPanelInfo(state);
}
@Override
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
state.put(VTWizardStateKey.SOURCE_PROGRAM_FILE, sourceProgramInfo.getFile());
state.put(VTWizardStateKey.DESTINATION_PROGRAM_FILE, destinationProgramInfo.getFile());
state.put(VTWizardStateKey.SOURCE_PROGRAM, sourceProgramInfo.getProgram());
state.put(VTWizardStateKey.DESTINATION_PROGRAM, destinationProgramInfo.getProgram());
state.put(VTWizardStateKey.SESSION_NAME, sessionNameField.getText());
state.put(VTWizardStateKey.NEW_SESSION_FOLDER, folder);
}
private boolean openProgram(ProgramInfo programInfo) {
if (programInfo.hasProgram()) {
return true; // already open
}
OpenProgramTask openProgramTask = new OpenProgramTask(programInfo.getFile(), tool);
new TaskLauncher(openProgramTask, tool.getActiveWindow());
OpenProgramRequest openProgram = openProgramTask.getOpenProgram();
programInfo.setProgram(openProgram != null ? openProgram.getProgram() : null);
return programInfo.hasProgram();
}
@Override
public String getTitle() {
return "New Version Tracking Session";
}
@Override
public void initialize() {
sourceProgramInfo = null;
destinationProgramInfo = null;
sessionNameField.setText("");
sourceField.setText("");
destinationField.setText("");
setFolder(tool.getProject().getProjectData().getRootFolder());
}
@Override
public boolean isValidInformation() {
if (folder == null) {
notifyListenersOfStatusMessage("Choose a project folder to continue!");
return false;
}
if (sourceProgramInfo == null || destinationProgramInfo == null) {
return false;
}
if (sourceProgramInfo.hasSameFile(destinationProgramInfo)) {
notifyListenersOfStatusMessage("Source and Destination Programs must be different");
releaseConsumers();
return false;
}
String name = sessionNameField.getText().trim();
if (StringUtils.isBlank(name)) {
notifyListenersOfStatusMessage("Please enter a name for this session");
return false;
}
try {
tool.getProject().getProjectData().testValidName(name, false);
}
catch (InvalidNameException e) {
notifyListenersOfStatusMessage("'" + name + "' contains invalid characters");
return false;
}
DomainFile file = folder.getFile(name);
if (file != null) {
notifyListenersOfStatusMessage(
"'" + file.getPathname() + "' is the name of an existing project file");
return false;
}
// Known Issue: Opening programs before comitted to using them (i.e., Next is clicked) seems
// premature and will subject user to prompts about possible checkout and/or upgrades
// with possible slow re-disassembly (see GP-4151)
if (!isValidDestinationProgramFile() || !isValidSourceProgramFile()) {
return false;
}
if (!openProgram(sourceProgramInfo)) {
notifyListenersOfStatusMessage(
"Can't open source program " + sourceProgramInfo.getName());
return false;
}
if (!openProgram(destinationProgramInfo)) {
notifyListenersOfStatusMessage(
"Can't open destination program " + destinationProgramInfo.getName());
return false;
}
notifyListenersOfStatusMessage(" ");
return true;
}
private boolean isValidSourceProgramFile() {
try {
VTSessionFileUtil.validateSourceProgramFile(sourceProgramInfo.file, false);
}
catch (Exception e) {
notifyListenersOfStatusMessage(e.getMessage());
return false;
}
return true;
}
private boolean isValidDestinationProgramFile() {
try {
VTSessionFileUtil.validateDestinationProgramFile(destinationProgramInfo.file, false,
false);
}
catch (Exception e) {
notifyListenersOfStatusMessage(e.getMessage());
return false;
}
return true;
}
@Override
public void addDependencies(WizardState<VTWizardStateKey> state) {
// none
}
private JButton createSourceBrowseButton() {
JButton button = new BrowseButton();
button.setName("SOURCE_BUTTON");
button.addActionListener(e -> {
DomainFile programFile = VTWizardUtils.chooseDomainFile(NewSessionPanel.this,
"a source program", VTWizardUtils.PROGRAM_FILTER, null);
if (programFile != null) {
setSourceProgram(programFile);
}
});
return button;
}
private JButton createDestinationBrowseButton() {
JButton button = new BrowseButton();
button.setName("DESTINATION_BUTTON");
button.addActionListener(e -> {
DomainFile programFile = VTWizardUtils.chooseDomainFile(NewSessionPanel.this,
"a destination program", VTWizardUtils.PROGRAM_FILTER, null);
if (programFile != null) {
setDestinationProgram(programFile);
}
});
return button;
}
@Override
public void dispose() {
releaseConsumers();
}
// simple object to track a domain file and its program
private class ProgramInfo {
private Program program;
private DomainFile file;
public ProgramInfo(DomainFile file) {
this.file = Objects.requireNonNull(file);
}
void setProgram(Program program) {
this.program = program;
}
Program getProgram() {
return program;
}
DomainFile getFile() {
return file;
}
String getPathname() {
return file.getPathname();
}
String getName() {
return file.getName();
}
void release(Object consumer) {
if (program == null) {
return;
}
if (program.getConsumerList().contains(consumer)) {
program.release(consumer);
}
program = null;
}
boolean hasSameFile(ProgramInfo other) {
return file.getPathname().equals(other.getPathname());
}
boolean hasProgram() {
return program != null;
}
}
}

View file

@ -1,233 +0,0 @@
/* ###
* 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.feature.vt.gui.wizard;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.*;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import docking.options.editor.OptionsEditorPanel;
import docking.wizard.*;
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
import ghidra.feature.vt.api.util.VTOptions;
import ghidra.framework.options.EditorStateFactory;
import ghidra.framework.options.Options;
import ghidra.util.HelpLocation;
import ghidra.util.layout.MiddleLayout;
import ghidra.util.layout.VerticalLayout;
import util.CollectionUtils;
public class OptionsPanel extends AbstractMageJPanel<VTWizardStateKey> {
private static final Dimension DEFAULT_PREFERRED_SIZE = new Dimension(650, 350);
private List<OptionsEditorPanel> optionsEditorPanelList;
private List<VTOptions> optionsList = null;
private PropertyChangeListener propertyChangeListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
notifyListenersOfValidityChanged();
}
};
OptionsPanel() {
super(new BorderLayout());
// restricting use?
}
@Override
public HelpLocation getHelpLocation() {
if (optionsList != null) {
for (VTOptions options : optionsList) {
if (options != null) {
HelpLocation helpLocation = options.getOptionsHelpLocation();
if (helpLocation != null) {
return helpLocation;
}
}
}
}
// default
return new HelpLocation("VersionTrackingPlugin", "Options_Panel");
}
@Override
public Dimension getPreferredSize() {
Dimension preferredSize = super.getPreferredSize();
if (preferredSize.width < DEFAULT_PREFERRED_SIZE.width) {
return DEFAULT_PREFERRED_SIZE;
}
return preferredSize;
}
@Override
public void dispose() {
if (optionsEditorPanelList != null) {
removeAll();
optionsEditorPanelList = null;
optionsList = null;
}
}
@Override
public void enterPanel(WizardState<VTWizardStateKey> state) {
dispose();
List<VTProgramCorrelatorFactory> correlatorFactoryList = getCorrelators(state);
optionsList = getCorrelatorOptions(state);
if (optionsList == null) {
optionsList = generateDefaultOptions(state);
}
JPanel panel = new JPanel(new VerticalLayout(30));
optionsEditorPanelList = new ArrayList<OptionsEditorPanel>();
for (int i = 0; i < correlatorFactoryList.size(); i++) {
String correlatorName = correlatorFactoryList.get(i).getName();
String title = correlatorName + " Options";
if (optionsList.get(i) == null) {
continue;
}
EditorStateFactory editorStateFactory = new EditorStateFactory();
Options options = optionsList.get(i);
List<String> optionNames = options.getLeafOptionNames();
if (optionNames.isEmpty()) {
continue;
}
Collections.sort(optionNames);
OptionsEditorPanel optionsPanel =
new OptionsEditorPanel(title, options, optionNames, editorStateFactory);
optionsPanel.setOptionsPropertyChangeListener(propertyChangeListener);
optionsEditorPanelList.add(optionsPanel);
panel.add(optionsPanel);
}
JPanel outerPanel = new JPanel(new MiddleLayout());
outerPanel.add(panel);
JScrollPane scrollPane = new JScrollPane(outerPanel);
scrollPane.getVerticalScrollBar().setUnitIncrement(5);
add(scrollPane);
}
private List<VTOptions> generateDefaultOptions(WizardState<VTWizardStateKey> state) {
List<VTOptions> list = new ArrayList<VTOptions>();
List<VTProgramCorrelatorFactory> correlatorFactoryList = getCorrelators(state);
for (VTProgramCorrelatorFactory vtProgramCorrelatorFactory : correlatorFactoryList) {
list.add(vtProgramCorrelatorFactory.createDefaultOptions());
}
return list;
}
private List<VTOptions> getCorrelatorOptions(WizardState<VTWizardStateKey> state) {
List<?> list = (List<?>) state.get(VTWizardStateKey.PROGRAM_CORRELATOR_OPTIONS_LIST);
if (list == null) {
return null;
}
return CollectionUtils.asList(list, VTOptions.class);
}
private List<VTProgramCorrelatorFactory> getCorrelators(WizardState<VTWizardStateKey> state) {
List<?> list = (List<?>) state.get(VTWizardStateKey.PROGRAM_CORRELATOR_FACTORY_LIST);
if (list == null) {
return null;
}
return CollectionUtils.asList(list, VTProgramCorrelatorFactory.class);
}
@Override
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
WizardState<VTWizardStateKey> state) {
List<VTOptions> tmpOptions = getCorrelatorOptions(state);
if (tmpOptions == null) {
tmpOptions = generateDefaultOptions(state);
}
for (VTOptions vtOptions : tmpOptions) {
if (vtOptions == null) {
continue;
}
List<String> names = vtOptions.getOptionNames();
if (names.isEmpty()) {
continue;
}
return WizardPanelDisplayability.MUST_BE_DISPLAYED;
}
return WizardPanelDisplayability.DO_NOT_DISPLAY;
}
@Override
public void leavePanel(WizardState<VTWizardStateKey> state) {
updateStateObjectWithPanelInfo(state);
}
@Override
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
if (optionsList != null) {
applyOptions();
}
List<VTOptions> newOptions =
optionsList != null ? optionsList : generateDefaultOptions(state);
state.put(VTWizardStateKey.PROGRAM_CORRELATOR_OPTIONS_LIST, newOptions);
}
@Override
public String getTitle() {
return "Correlator Options";
}
@Override
public void initialize() {
// nothing to do
}
@Override
public boolean isValidInformation() {
applyOptions();
for (VTOptions options : optionsList) {
if (options != null) {
if (!options.validate()) {
return false;
}
}
}
return true;
}
private void applyOptions() {
for (OptionsEditorPanel panel : optionsEditorPanelList) {
panel.apply();
}
}
@Override
public void addDependencies(WizardState<VTWizardStateKey> state) {
state.addDependency(VTWizardStateKey.PROGRAM_CORRELATOR_OPTIONS_LIST,
VTWizardStateKey.PROGRAM_CORRELATOR_FACTORY_LIST);
}
}

View file

@ -1,252 +0,0 @@
/* ###
* 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.feature.vt.gui.wizard;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Constructor;
import java.util.*;
import java.util.List;
import javax.swing.*;
import docking.widgets.conditiontestpanel.*;
import docking.wizard.*;
import ghidra.feature.vt.api.main.VTSession;
import ghidra.feature.vt.gui.validator.VTPreconditionValidator;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import ghidra.util.classfinder.ClassSearcher;
public class PreconditionsPanel extends AbstractMageJPanel<VTWizardStateKey> implements Scrollable {
private static final Dimension DEFAULT_SIZE = new Dimension(650, 480);
private ConditionTestPanel conditionsTestPanel;
private boolean testsDone = false;
private VTNewSessionWizardManager wizardManager;
public PreconditionsPanel(VTNewSessionWizardManager panelManager) {
this.wizardManager = panelManager;
setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
setLayout(new BorderLayout());
JPanel runButtonPanel = new JPanel();
runButtonPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0));
runButtonPanel.setLayout(new FlowLayout());
JButton runTestsButton = new JButton("Run Precondition Checks");
runTestsButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
conditionsTestPanel.runTests();
}
});
runButtonPanel.add(runTestsButton);
JButton skipTestsButton = new JButton("Skip");
skipTestsButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
conditionsTestPanel.skipTests();
wizardManager.getWizardManager().next();
}
});
runButtonPanel.add(skipTestsButton);
add(runButtonPanel, BorderLayout.SOUTH);
}
@Override
public HelpLocation getHelpLocation() {
return new HelpLocation("VersionTrackingPlugin", "Preconditions_Panel");
}
@Override
public void addDependencies(WizardState<VTWizardStateKey> state) {
state.addDependency(VTWizardStateKey.PRECONDITION_CHECKS_RUN,
VTWizardStateKey.SOURCE_PROGRAM_FILE);
state.addDependency(VTWizardStateKey.PRECONDITION_CHECKS_RUN,
VTWizardStateKey.DESTINATION_PROGRAM_FILE);
state.addDependency(VTWizardStateKey.HIGHEST_PRECONDITION_STATUS,
VTWizardStateKey.PRECONDITION_CHECKS_RUN);
}
@Override
public void dispose() {
if (conditionsTestPanel != null) {
conditionsTestPanel.cancel();
}
}
@Override
public void enterPanel(WizardState<VTWizardStateKey> state) {
initializeRunState(state);
if (!testsDone) {
if (conditionsTestPanel != null) {
remove(conditionsTestPanel);
}
conditionsTestPanel = buildConditionPanel(state);
add(conditionsTestPanel, BorderLayout.CENTER);
}
}
private void initializeRunState(WizardState<VTWizardStateKey> state) {
Boolean b = (Boolean) state.get(VTWizardStateKey.PRECONDITION_CHECKS_RUN);
testsDone = b == null ? false : b.booleanValue();
}
private ConditionTestPanel buildConditionPanel(final WizardState<VTWizardStateKey> state) {
Program sourceProgram = (Program) state.get(VTWizardStateKey.SOURCE_PROGRAM);
Program destinationProgram = (Program) state.get(VTWizardStateKey.DESTINATION_PROGRAM);
VTSession existingResults = (VTSession) state.get(VTWizardStateKey.EXISTING_SESSION);
List<ConditionTester> list =
getConditionTests(sourceProgram, destinationProgram, existingResults);
Collections.sort(list, new ConditionsComparator());
ConditionTestPanel panel = new ConditionTestPanel(list);
panel.addListener(new ConditionTestListener() {
@Override
public void testsCompleted() {
state.put(VTWizardStateKey.PRECONDITION_CHECKS_RUN, Boolean.valueOf(testsDone));
testsDone();
}
});
return panel;
}
private void testsDone() {
testsDone = true;
notifyListenersOfValidityChanged();
if (hasAnyErrorStatus()) {
Msg.showError(getClass(), this, "Warning - Serious Precondition failures",
"The precondition checks discovered one or more serious problems. \n\n"
+ "If you continue, your version tracking results may be invalid.\n"
+ "You should review the errors, cancel this wizard, and correct the problems.");
}
}
private List<ConditionTester> getConditionTests(Program sourceProgram,
Program destinationProgram, VTSession existingResults) throws SecurityException {
List<ConditionTester> list = new ArrayList<ConditionTester>();
List<Class<? extends VTPreconditionValidator>> vtValidatorClasses =
ClassSearcher.getClasses(VTPreconditionValidator.class);
for (Class<? extends VTPreconditionValidator> validatorClass : vtValidatorClasses) {
try {
Constructor<? extends VTPreconditionValidator> ctor =
validatorClass.getConstructor(Program.class, Program.class, VTSession.class);
VTPreconditionValidator validator =
ctor.newInstance(sourceProgram, destinationProgram, existingResults);
list.add(validator);
}
catch (Exception e) {
Msg.error(this, "error including VTPreconditionValidator " + validatorClass, e);
}
}
return list;
}
@Override
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
WizardState<VTWizardStateKey> state) {
initializeRunState(state);
return testsDone ? WizardPanelDisplayability.CAN_BE_DISPLAYED
: WizardPanelDisplayability.MUST_BE_DISPLAYED;
}
@Override
public void leavePanel(WizardState<VTWizardStateKey> state) {
updateStateObjectWithPanelInfo(state);
}
@Override
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
state.put(VTWizardStateKey.PRECONDITION_CHECKS_RUN, Boolean.valueOf(testsDone));
state.put(VTWizardStateKey.HIGHEST_PRECONDITION_STATUS, hasAnyErrorStatus());
}
private Boolean hasAnyErrorStatus() {
return conditionsTestPanel.getErrorCount() > 0;
}
@Override
public String getTitle() {
return "Precondition Checklist";
}
@Override
public void initialize() {
// do nothing
}
@Override
public boolean isValidInformation() {
return testsDone;
}
@Override
// Overridden to account for the fact that we don't know our preferred size until later in
// the wizard flow. At that point, the initial size of the wizard is already too small.
public Dimension getPreferredSize() {
Dimension superSize = super.getPreferredSize();
if (superSize.width > DEFAULT_SIZE.width && superSize.height > DEFAULT_SIZE.height) {
return superSize;
}
return DEFAULT_SIZE;
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 25;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return true;
}
@Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 10;
}
//==================================================================================================
// Inner Classes
//==================================================================================================
private class ConditionsComparator implements Comparator<ConditionTester> {
@Override
public int compare(ConditionTester o1, ConditionTester o2) {
return o1.getName().compareTo(o2.getName());
}
}
}

View file

@ -1,221 +0,0 @@
/* ###
* 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.feature.vt.gui.wizard;
import java.awt.BorderLayout;
import java.util.List;
import javax.swing.*;
import docking.widgets.label.GDHtmlLabel;
import docking.wizard.*;
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
import ghidra.feature.vt.gui.wizard.ChooseAddressSetEditorPanel.AddressSetChoice;
import ghidra.framework.model.DomainFile;
import ghidra.util.HTMLUtilities;
import ghidra.util.HelpLocation;
import ghidra.util.layout.PairLayout;
import util.CollectionUtils;
public class SummaryPanel extends AbstractMageJPanel<VTWizardStateKey> {
private JLabel labelLabel;
private JLabel summaryLabel;
private static String NEW_SUMMARY_PANEL = "New_Session_Summary_Panel";
private static String ADD_SUMMARY_PANEL = "Add_To_Session_Summary_Panel";
private String helpName = ADD_SUMMARY_PANEL;
SummaryPanel() {
labelLabel = new GDHtmlLabel();
summaryLabel = new GDHtmlLabel();
JPanel mainPanel = new JPanel(new PairLayout(5, 10));
mainPanel.add(labelLabel);
mainPanel.add(summaryLabel);
setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
setLayout(new BorderLayout());
add(mainPanel, BorderLayout.CENTER);
}
@Override
public void dispose() {
// nothing to do
}
@Override
public HelpLocation getHelpLocation() {
return new HelpLocation("VersionTrackingPlugin", helpName);
}
@Override
public void enterPanel(WizardState<VTWizardStateKey> state) {
StringBuilder label = new StringBuilder();
StringBuilder summary = new StringBuilder();
label.append("<html>");
summary.append("<html>");
// session mode
label.append("Operation:");
String opDescription = (String) state.get(VTWizardStateKey.WIZARD_OP_DESCRIPTION);
helpName = ((opDescription != null) && opDescription.startsWith("New")) ? NEW_SUMMARY_PANEL
: ADD_SUMMARY_PANEL;
summary.append(opDescription);
label.append("<br>");
summary.append("<br>");
String sessionName = (String) state.get(VTWizardStateKey.SESSION_NAME);
label.append("Session Name:");
summary.append(sessionName);
label.append("<br>");
summary.append("<br>");
String sourceProgramName = null;
String destinationProgramName = null;
DomainFile sourceProgram = (DomainFile) state.get(VTWizardStateKey.SOURCE_PROGRAM_FILE);
sourceProgramName = sourceProgram.getName();
DomainFile destinationProgram =
(DomainFile) state.get(VTWizardStateKey.DESTINATION_PROGRAM_FILE);
destinationProgramName = destinationProgram.getName();
// source program
label.append("Source Program:");
summary.append(
sourceProgramName == null ? "(null)" : HTMLUtilities.escapeHTML(sourceProgramName));
label.append("<br>");
summary.append("<br>");
// destination program
label.append("Destination Program:");
summary.append(destinationProgramName == null ? "(null)"
: HTMLUtilities.escapeHTML(destinationProgramName));
label.append("<br>");
summary.append("<br>");
String correlatorLabel = "";
String correlatorName = null;
List<VTProgramCorrelatorFactory> correlators = getCorrelators(state);
if (correlators != null) {
for (VTProgramCorrelatorFactory correlatorFactory : correlators) {
correlatorName = correlatorFactory.getName();
label.append(correlatorLabel + "Program Correlator:");
summary.append(correlatorName == null ? "(null)" : correlatorName);
label.append("<br>");
summary.append("<br>");
}
}
Boolean excludeAcceptedMatches =
(Boolean) state.get(VTWizardStateKey.EXCLUDE_ACCEPTED_MATCHES);
if (excludeAcceptedMatches != null) {
label.append("Exclude Accepted Matches:");
summary.append(excludeAcceptedMatches.booleanValue() ? "Yes" : "No");
label.append("<br>");
summary.append("<br>");
}
Boolean showAddressSetPanels =
(Boolean) state.get(VTWizardStateKey.SHOW_ADDRESS_SET_PANELS);
if (showAddressSetPanels != null) {
boolean manuallySpecifiedAddresses = showAddressSetPanels.booleanValue();
AddressSetChoice sourceAddressSetChoice =
(AddressSetChoice) state.get(VTWizardStateKey.SOURCE_ADDRESS_SET_CHOICE);
AddressSetChoice destinationAddressSetChoice =
(AddressSetChoice) state.get(VTWizardStateKey.DESTINATION_ADDRESS_SET_CHOICE);
String sourceAddressesInfo =
(sourceAddressSetChoice == AddressSetChoice.MANUALLY_DEFINED) ? "Manually Defined"
: ((sourceAddressSetChoice == AddressSetChoice.SELECTION))
? "Source Tool Selection"
: "Entire Source Program";
String destinationAddressesInfo =
(destinationAddressSetChoice == AddressSetChoice.MANUALLY_DEFINED)
? "Manually Defined"
: ((destinationAddressSetChoice == AddressSetChoice.SELECTION))
? "Destination Tool Selection"
: "Entire Destination Program";
label.append("Source Address Set:");
summary.append(sourceAddressesInfo);
label.append("<br>");
summary.append("<br>");
label.append("Destination Address Set:");
summary.append(destinationAddressesInfo);
label.append("<br>");
summary.append("<br>");
}
label.append("</html>");
summary.append("</html>");
labelLabel.setText(label.toString());
summaryLabel.setText(summary.toString());
}
private List<VTProgramCorrelatorFactory> getCorrelators(WizardState<VTWizardStateKey> state) {
List<?> list = (List<?>) state.get(VTWizardStateKey.PROGRAM_CORRELATOR_FACTORY_LIST);
if (list == null) {
return null;
}
return CollectionUtils.asList(list, VTProgramCorrelatorFactory.class);
}
@Override
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
WizardState<VTWizardStateKey> state) {
return WizardPanelDisplayability.CAN_BE_DISPLAYED;
}
@Override
public void leavePanel(WizardState<VTWizardStateKey> state) {
updateStateObjectWithPanelInfo(state);
}
@Override
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
// Do nothing. The summary panel only displays information.
}
@Override
public String getTitle() {
return "Summary";
}
@Override
public void initialize() {
// nothing to do
}
@Override
public boolean isValidInformation() {
return true;
}
@Override
public void addDependencies(WizardState<VTWizardStateKey> state) {
// no dependencies; we just confirm what's going to happen
}
}

View file

@ -1,76 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.feature.vt.gui.wizard;
import ghidra.feature.vt.api.main.VTSession;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.program.model.listing.Program;
import ghidra.util.task.Task;
import ghidra.util.task.TaskLauncher;
import java.util.ArrayList;
import docking.wizard.*;
public class VTAddToSessionWizardManager extends AbstractMagePanelManager<VTWizardStateKey> {
private final VTController controller;
public VTAddToSessionWizardManager(VTController controller) {
super(new WizardState<VTWizardStateKey>());
this.controller = controller;
Program sourceProgram = controller.getSourceProgram();
Program destinationProgram = controller.getDestinationProgram();
VTSession session = controller.getSession();
WizardState<VTWizardStateKey> state = getState();
state.put(VTWizardStateKey.SOURCE_PROGRAM, sourceProgram);
state.put(VTWizardStateKey.DESTINATION_PROGRAM, destinationProgram);
state.put(VTWizardStateKey.SOURCE_PROGRAM_FILE, sourceProgram.getDomainFile());
state.put(VTWizardStateKey.DESTINATION_PROGRAM_FILE, destinationProgram.getDomainFile());
state.put(VTWizardStateKey.EXISTING_SESSION, session);
state.put(VTWizardStateKey.SESSION_NAME, session.getName());
state.put(VTWizardStateKey.WIZARD_OP_DESCRIPTION, "Add to Version Tracking Session");
state.put(VTWizardStateKey.SOURCE_SELECTION, controller.getSelectionInSourceTool());
state.put(VTWizardStateKey.DESTINATION_SELECTION,
controller.getSelectionInDestinationTool());
}
protected ArrayList<MagePanel<VTWizardStateKey>> createPanels() {
ArrayList<MagePanel<VTWizardStateKey>> panels =
new ArrayList<MagePanel<VTWizardStateKey>>();
panels.add(new CorrelatorPanel(controller.getSession()));
panels.add(new OptionsPanel());
panels.add(new AddressSetOptionsPanel());
panels.add(new LimitAddressSetsPanel(controller.getTool()));
panels.add(new SummaryPanel());
return panels;
}
@Override
protected void doFinish() {
try {
Task task = new AddToSessionTask(controller, getState());
new TaskLauncher(task, getWizardManager().getComponent());
}
finally {
getWizardManager().completed(true);
}
}
}

View file

@ -1,82 +0,0 @@
/* ###
* 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.feature.vt.gui.wizard;
import java.util.ArrayList;
import java.util.List;
import docking.wizard.*;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.framework.model.DomainFile;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.task.Task;
import ghidra.util.task.TaskLauncher;
public class VTNewSessionWizardManager extends AbstractMagePanelManager<VTWizardStateKey> {
private final VTController controller;
public VTNewSessionWizardManager(VTController controller) {
super(new WizardState<VTWizardStateKey>());
this.controller = controller;
getState().put(VTWizardStateKey.WIZARD_OP_DESCRIPTION, "New Version Tracking Session");
}
public VTNewSessionWizardManager(VTController controller, DomainFile sourceFile,
DomainFile destinationFile) {
this(controller);
getState().put(VTWizardStateKey.SOURCE_PROGRAM_FILE, sourceFile);
getState().put(VTWizardStateKey.DESTINATION_PROGRAM_FILE, destinationFile);
}
@Override
protected List<MagePanel<VTWizardStateKey>> createPanels() {
List<MagePanel<VTWizardStateKey>> panels = new ArrayList<>();
panels.add(new NewSessionPanel(controller.getTool()));
panels.add(new PreconditionsPanel(this));
panels.add(new SummaryPanel());
return panels;
}
@Override
protected void doFinish() {
try {
Task task = new CreateNewSessionTask(controller, getState());
new TaskLauncher(task, getWizardManager().getComponent());
}
finally {
getWizardManager().completed(true);
cleanup();
}
}
@Override
public void cancel() {
cleanup();
}
private void cleanup() {
List<MagePanel<VTWizardStateKey>> panels = getPanels();
for (MagePanel<VTWizardStateKey> magePanel : panels) {
magePanel.dispose();
}
}
public PluginTool getTool() {
return controller.getTool();
}
}

View file

@ -1,45 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.feature.vt.gui.wizard;
enum VTWizardStateKey {
WIZARD_OP_DESCRIPTION, EXISTING_SESSION, SESSION_NAME,
SOURCE_PROGRAM_FILE, DESTINATION_PROGRAM_FILE,
SOURCE_PROGRAM, DESTINATION_PROGRAM,
SOURCE_ADDRESS_SET_VIEW, DESTINATION_ADDRESS_SET_VIEW,
PRECONDITION_CHECKS_RUN,
NEW_SESSION_FOLDER,
ADDRESS_RANGES_MODE,
PROGRAM_CORRELATOR_FACTORY_LIST,
PROGRAM_CORRELATOR_OPTIONS_LIST, HIGHEST_PRECONDITION_STATUS,
SHOW_ADDRESS_SET_PANELS,
EXCLUDE_ACCEPTED_MATCHES,
SOURCE_SELECTION, DESTINATION_SELECTION,
SOURCE_ADDRESS_SET_CHOICE, DESTINATION_ADDRESS_SET_CHOICE;
}

View file

@ -13,9 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.feature.vt.gui.wizard;
package ghidra.feature.vt.gui.wizard.add;
import java.awt.Dimension;
import java.util.Objects;
import java.util.function.Consumer;
import javax.swing.*;
@ -23,7 +25,7 @@ import docking.DialogComponentProvider;
import docking.widgets.label.GDLabel;
import ghidra.app.util.AddressInput;
import ghidra.app.util.HelpTopics;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
import ghidra.util.layout.PairLayout;
@ -31,7 +33,7 @@ import ghidra.util.layout.PairLayout;
public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
private Program program;
private AddressRangeListener listener;
private Consumer<AddressRange> addressRangeConsumer;
private JPanel addressRangePanel;
private JLabel minLabel;
@ -40,10 +42,10 @@ public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
private AddressInput maxAddressField;
protected AddRemoveAddressRangeDialog(String type, String programIndicator, Program program,
AddressRangeListener listener) {
Consumer<AddressRange> addressRangeConsumer) {
super(programIndicator + " Address Range", true, true, true, false);
this.program = program;
this.listener = listener;
this.addressRangeConsumer = Objects.requireNonNull(addressRangeConsumer);
setHelpLocation(new HelpLocation(HelpTopics.LABEL, "AddEditDialog"));
addWorkPanel(createAddressRangePanel());
@ -99,9 +101,7 @@ public class AddRemoveAddressRangeDialog extends DialogComponentProvider {
@Override
protected void okCallback() {
if (isValidRange()) {
if (listener != null) {
listener.processAddressRange(getMinAddress(), getMaxAddress());
}
addressRangeConsumer.accept(new AddressRangeImpl(getMinAddress(), getMaxAddress()));
close();
}
}

View file

@ -0,0 +1,177 @@
/* ###
* 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.feature.vt.gui.wizard.add;
import java.util.*;
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
import ghidra.feature.vt.api.main.VTSession;
import ghidra.feature.vt.api.util.VTOptions;
import ghidra.framework.model.DomainFile;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.Program;
/**
* Wizard data used by the {@link VTAddToSessionWizardModel} and its steps for the "add to version
* tracking session" wizard.
*/
public class AddToSessionData {
public static enum AddressSetChoice {
ENTIRE_PROGRAM, SELECTION, MANUALLY_DEFINED
}
private Program sourceProgram;
private Program destinationProgram;
private VTSession session;
private AddressSetView customSourceAddressSet;
private AddressSetView customDestinationAddressSet;
private AddressSetView sourceSelection;
private AddressSetView destinationSelection;
private List<VTProgramCorrelatorFactory> correlators;
private Map<VTProgramCorrelatorFactory, VTOptions> optionsMap = new HashMap<>();
private boolean shouldExcludeAcceptedMatches;
private boolean shouldLimitAddressSets;
private AddressSetChoice sourceAddressSetChoice = AddressSetChoice.ENTIRE_PROGRAM;
private AddressSetChoice destinationAddressSetChoice = AddressSetChoice.ENTIRE_PROGRAM;
public void setSourceProgram(Program sourceProgram) {
this.sourceProgram = sourceProgram;
}
public Program getSourceProgram() {
return sourceProgram;
}
public void setDestinationProgram(Program destinationProgram) {
this.destinationProgram = destinationProgram;
}
public Program getDestinationProgram() {
return destinationProgram;
}
public void setSession(VTSession session) {
this.session = session;
}
public VTSession getSession() {
return session;
}
public DomainFile getSourceFile() {
return sourceProgram.getDomainFile();
}
public DomainFile getDestinationFile() {
return destinationProgram.getDomainFile();
}
public AddressSetChoice getSourceAddressSetChoice() {
return sourceAddressSetChoice;
}
public AddressSetChoice getDestinationAddressSetChoice() {
return destinationAddressSetChoice;
}
public void setSourceAddressSetChoice(AddressSetChoice choice) {
this.sourceAddressSetChoice = choice;
}
public void setDestinationAddressSetChoice(AddressSetChoice choice) {
this.destinationAddressSetChoice = choice;
}
public void setSourceSelection(AddressSetView addressSet) {
this.sourceSelection = addressSet;
// if a source selection is set, the limit option defaults to true;
if (addressSet != null && !addressSet.isEmpty()) {
shouldLimitAddressSets = true;
sourceAddressSetChoice = AddressSetChoice.SELECTION;
}
}
public void setDestinationSelection(AddressSetView addresseSet) {
this.destinationSelection = addresseSet;
// if a destination selection is set, the limit option defaults to true;
if (addresseSet != null && !addresseSet.isEmpty()) {
shouldLimitAddressSets = true;
destinationAddressSetChoice = AddressSetChoice.SELECTION;
}
}
public AddressSetView getCustomSourceAddressSet() {
return customSourceAddressSet;
}
public void setCustomSourceAddressSet(AddressSetView addressSet) {
customSourceAddressSet = addressSet;
}
public void setCustomDestinationAddressSet(AddressSetView addressSet) {
customDestinationAddressSet = addressSet;
}
public AddressSetView getCustomDestinationAddressSet() {
return customDestinationAddressSet;
}
public AddressSetView getSourceSelection() {
return sourceSelection;
}
public AddressSetView getDestinationSelection() {
return destinationSelection;
}
public List<VTProgramCorrelatorFactory> getCorrelators() {
return correlators;
}
public void setCorrelators(List<VTProgramCorrelatorFactory> correlators) {
if (!correlators.equals(this.correlators)) {
this.correlators = correlators;
// whenever the set of correlators changes, reset the options to force options panel
// to show
optionsMap = null;
}
}
public void setOptions(Map<VTProgramCorrelatorFactory, VTOptions> optionsMap) {
this.optionsMap = optionsMap;
}
public Map<VTProgramCorrelatorFactory, VTOptions> getOptions() {
return optionsMap;
}
public boolean shouldExcludeAcceptedMatches() {
return shouldExcludeAcceptedMatches;
}
public void setShouldExcludeAcceptedMatches(boolean b) {
shouldExcludeAcceptedMatches = b;
}
public boolean shouldLimitAddressSets() {
return shouldLimitAddressSets;
}
public void setShouldLimitAddressSets(boolean b) {
shouldLimitAddressSets = b;
}
}

View file

@ -4,25 +4,23 @@
* 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.feature.vt.gui.wizard;
package ghidra.feature.vt.gui.wizard.add;
import java.util.*;
import docking.wizard.WizardState;
import ghidra.feature.vt.api.main.*;
import ghidra.feature.vt.api.util.VTMatchUtil;
import ghidra.feature.vt.api.util.VTOptions;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.wizard.ChooseAddressSetEditorPanel.AddressSetChoice;
import ghidra.framework.data.DomainObjectAdapterDB;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.address.AddressSetView;
@ -31,16 +29,15 @@ import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.Task;
import ghidra.util.task.TaskMonitor;
import util.CollectionUtils;
public class AddToSessionTask extends Task {
private final WizardState<VTWizardStateKey> state;
private final AddToSessionData data;
private final VTController controller;
public AddToSessionTask(VTController controller, WizardState<VTWizardStateKey> state) {
public AddToSessionTask(VTController controller, AddToSessionData data) {
super("Merge Version Tracking Session", true, true, true);
this.controller = controller;
this.state = state;
this.data = data;
}
@Override
@ -51,49 +48,10 @@ public class AddToSessionTask extends Task {
Program sourceProgram = session.getSourceProgram();
Program destinationProgram = session.getDestinationProgram();
Boolean value = (Boolean) state.get(VTWizardStateKey.EXCLUDE_ACCEPTED_MATCHES);
boolean excludeAcceptedMatches = (value == null) ? false : value.booleanValue();
boolean excludeAcceptedMatches = data.shouldExcludeAcceptedMatches();
AddressSetChoice sourceAddressSetChoice =
(AddressSetChoice) state.get(VTWizardStateKey.SOURCE_ADDRESS_SET_CHOICE);
AddressSetChoice destinationAddressSetChoice =
(AddressSetChoice) state.get(VTWizardStateKey.DESTINATION_ADDRESS_SET_CHOICE);
if (sourceAddressSetChoice == null) {
sourceAddressSetChoice = AddressSetChoice.ENTIRE_PROGRAM;
}
if (destinationAddressSetChoice == null) {
destinationAddressSetChoice = AddressSetChoice.ENTIRE_PROGRAM;
}
AddressSetView sourceAddressSet;
switch (sourceAddressSetChoice) {
case SELECTION:
sourceAddressSet = (AddressSetView) state.get(VTWizardStateKey.SOURCE_SELECTION);
break;
case MANUALLY_DEFINED:
sourceAddressSet =
(AddressSetView) state.get(VTWizardStateKey.SOURCE_ADDRESS_SET_VIEW);
break;
case ENTIRE_PROGRAM:
default:
sourceAddressSet = sourceProgram.getMemory();
break;
}
AddressSetView destinationAddressSet;
switch (destinationAddressSetChoice) {
case SELECTION:
destinationAddressSet =
(AddressSetView) state.get(VTWizardStateKey.DESTINATION_SELECTION);
break;
case MANUALLY_DEFINED:
destinationAddressSet =
(AddressSetView) state.get(VTWizardStateKey.DESTINATION_ADDRESS_SET_VIEW);
break;
case ENTIRE_PROGRAM:
default:
destinationAddressSet = destinationProgram.getMemory();
break;
}
AddressSetView sourceAddressSet = getSourceAddressSet();
AddressSetView destinationAddressSet = getDestinationAddressSet();
if (excludeAcceptedMatches) {
sourceAddressSet = excludeAcceptedMatches(sourceAddressSet, true);
@ -104,14 +62,14 @@ public class AddToSessionTask extends Task {
boolean completedSucessfully = false;
try {
session.setEventsEnabled(false); // prevent table updates while busy
List<VTProgramCorrelatorFactory> correlatorFactories = getCorrelators(state);
List<VTOptions> correlatorOptions = getCorrelatorOptions(state);
List<VTProgramCorrelatorFactory> correlatorFactories = data.getCorrelators();
Map<VTProgramCorrelatorFactory, VTOptions> optionsMap = data.getOptions();
List<VTProgramCorrelator> noMatchList = new ArrayList<>();
for (int i = 0; i < correlatorFactories.size(); i++) {
VTProgramCorrelatorFactory factory = correlatorFactories.get(i);
for (VTProgramCorrelatorFactory factory : correlatorFactories) {
VTOptions options = optionsMap.get(factory);
VTProgramCorrelator correlator =
factory.createCorrelator(sourceProgram, sourceAddressSet, destinationProgram,
destinationAddressSet, correlatorOptions.get(i));
destinationAddressSet, options);
VTMatchSet resultSet = correlator.correlate(session, monitor);
if (resultSet.getMatchCount() == 0) {
@ -150,6 +108,36 @@ public class AddToSessionTask extends Task {
}
}
private AddressSetView getSourceAddressSet() {
if (!data.shouldLimitAddressSets()) {
return data.getSourceProgram().getMemory();
}
switch (data.getSourceAddressSetChoice()) {
case MANUALLY_DEFINED:
return data.getCustomSourceAddressSet();
case SELECTION:
return data.getSourceSelection();
case ENTIRE_PROGRAM:
default:
return data.getSourceProgram().getMemory();
}
}
private AddressSetView getDestinationAddressSet() {
if (!data.shouldLimitAddressSets()) {
return data.getDestinationProgram().getMemory();
}
switch (data.getDestinationAddressSetChoice()) {
case MANUALLY_DEFINED:
return data.getCustomDestinationAddressSet();
case SELECTION:
return data.getDestinationSelection();
case ENTIRE_PROGRAM:
default:
return data.getDestinationProgram().getMemory();
}
}
private void endTransaction(VTSession session, int transactionID,
boolean completedSucessfully) {
if (transactionID == -1) {
@ -165,21 +153,8 @@ public class AddToSessionTask extends Task {
return -1;
}
private List<VTOptions> getCorrelatorOptions(WizardState<VTWizardStateKey> stateKey) {
return CollectionUtils.asList(
(List<?>) stateKey.get(VTWizardStateKey.PROGRAM_CORRELATOR_OPTIONS_LIST),
VTOptions.class);
}
private List<VTProgramCorrelatorFactory> getCorrelators(
WizardState<VTWizardStateKey> stateKey) {
return CollectionUtils.asList(
(List<?>) stateKey.get(VTWizardStateKey.PROGRAM_CORRELATOR_FACTORY_LIST),
VTProgramCorrelatorFactory.class);
}
private AddressSet excludeAcceptedMatches(AddressSetView addrSetView, boolean source) {
VTSession session = (VTSession) state.get(VTWizardStateKey.EXISTING_SESSION);
VTSession session = data.getSession();
AddressSet addrSet = new AddressSet(addrSetView);
if (session != null) {
List<VTMatchSet> matchSets = session.getMatchSets();

View file

@ -0,0 +1,90 @@
/* ###
* 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.feature.vt.gui.wizard.add;
import static ghidra.feature.vt.api.main.VTProgramCorrelatorAddressRestrictionPreference.*;
import java.util.List;
import javax.swing.*;
import docking.widgets.checkbox.GCheckBox;
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
import ghidra.util.HTMLUtilities;
import ghidra.util.layout.VerticalLayout;
/**
* Panel for choosing the address set to used for performing new correlations when adding to
* a version tracking session. Used by the {@link AddressSetOptionsStep}.
*/
public class AddressSetOptionsPanel extends JPanel {
private JCheckBox excludeCheckbox;
private JCheckBox limitAddressSetsCheckbox;
public AddressSetOptionsPanel() { //
setBorder(BorderFactory.createEmptyBorder(40, 40, 0, 0));
excludeCheckbox = new GCheckBox("Exclude accepted matches", false);
String excludeAcceptedTooltip = "This option will cause the correlator algorithm " +
"to <b>not</b> consider any functions or data that have already been " +
"accepted. Using this option can greatly speed up the processing time " +
"of the correlator algorithm; however, this options should only be " +
"used when you trust that your accepted matches are correct.";
excludeCheckbox.setToolTipText(HTMLUtilities.toWrappedHTML(excludeAcceptedTooltip));
limitAddressSetsCheckbox = new GCheckBox("Limit source and destination address sets");
String manuallyLimitTooltip = "Selecting this checkbox will trigger additional wizard " +
" panels allowing you to customize the address sets used " +
" by the selected algorithm. When not selected, the entire address space is used.";
limitAddressSetsCheckbox.setToolTipText(
HTMLUtilities.toWrappedHTML(manuallyLimitTooltip));
add(excludeCheckbox);
add(limitAddressSetsCheckbox);
setLayout(new VerticalLayout(20));
}
public void initialize(AddToSessionData data) {
excludeCheckbox.setSelected(data.shouldExcludeAcceptedMatches());
limitAddressSetsCheckbox.setSelected(data.shouldLimitAddressSets());
if (allowRestrictions(data.getCorrelators())) {
excludeCheckbox.setEnabled(true);
}
else {
excludeCheckbox.setSelected(false);
excludeCheckbox.setEnabled(false);
}
}
private boolean allowRestrictions(List<VTProgramCorrelatorFactory> list) {
for (VTProgramCorrelatorFactory factory : list) {
if (factory.getAddressRestrictionPreference() != RESTRICTION_NOT_ALLOWED) {
return true;
}
}
return false;
}
void updateChoices(AddToSessionData data) {
data.setShouldExcludeAcceptedMatches(excludeCheckbox.isSelected());
data.setShouldLimitAddressSets(limitAddressSetsCheckbox.isSelected());
}
}

View file

@ -0,0 +1,67 @@
/* ###
* 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.feature.vt.gui.wizard.add;
import javax.swing.JComponent;
import docking.wizard.WizardModel;
import docking.wizard.WizardStep;
import ghidra.util.HelpLocation;
/**
* Wizard step for configuring address sets when adding correlations to an existing version
* tracking session.
*/
public class AddressSetOptionsStep extends WizardStep<AddToSessionData> {
private AddressSetOptionsPanel panel;
protected AddressSetOptionsStep(WizardModel<AddToSessionData> model) {
super(model, "Address Set Options",
new HelpLocation("VersionTrackingPlugin", "Address_Set_Panel"));
panel = new AddressSetOptionsPanel();
}
@Override
public void initialize(AddToSessionData data) {
panel.initialize(data);
}
@Override
public boolean isValid() {
return true;
}
@Override
public void populateData(AddToSessionData data) {
panel.updateChoices(data);
}
@Override
public boolean canFinish(AddToSessionData data) {
return true;
}
@Override
public boolean apply(AddToSessionData data) {
return true;
}
@Override
public JComponent getComponent() {
return panel;
}
}

View file

@ -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.feature.vt.gui.wizard;
package ghidra.feature.vt.gui.wizard.add;
import java.awt.BorderLayout;
import java.awt.Component;
@ -28,18 +28,18 @@ import docking.widgets.button.GRadioButton;
import docking.widgets.label.GLabel;
import docking.widgets.list.GList;
import generic.theme.GIcon;
import ghidra.feature.vt.gui.wizard.add.AddToSessionData.AddressSetChoice;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
import ghidra.util.layout.MiddleLayout;
import ghidra.util.layout.VerticalLayout;
/**
* Panel for manually adjusting address sets.
*/
public class ChooseAddressSetEditorPanel extends JPanel {
public static enum AddressSetChoice {
ENTIRE_PROGRAM, SELECTION, MANUALLY_DEFINED
}
private static Icon ADD_ICON = new GIcon("icon.version.tracking.add");
private static Icon SUBTRACT_ICON = new GIcon("icon.version.tracking.subtract");
@ -210,18 +210,14 @@ public class ChooseAddressSetEditorPanel extends JPanel {
}
protected void showAddRangeDialog() {
AddressRangeListener addListener =
(minAddress, maxAddress) -> addRange(minAddress, maxAddress);
AddRemoveAddressRangeDialog addRangeDialog =
new AddRemoveAddressRangeDialog("Add", name, program, addListener);
new AddRemoveAddressRangeDialog("Add", name, program, r -> addRange(r));
tool.showDialog(addRangeDialog, this.getRootPane());
}
protected void showSubtractRangeDialog() {
AddressRangeListener subtractListener =
(minAddress, maxAddress) -> subtractRange(minAddress, maxAddress);
AddRemoveAddressRangeDialog removeRangeDialog =
new AddRemoveAddressRangeDialog("Remove", name, program, subtractListener);
new AddRemoveAddressRangeDialog("Remove", name, program, r -> subtractRange(r));
tool.showDialog(removeRangeDialog, this.getRootPane());
}
@ -246,14 +242,14 @@ public class ChooseAddressSetEditorPanel extends JPanel {
notifyListeners();
}
private synchronized void addRange(Address minAddress, Address maxAddress) {
myCurrentAddressSet.addRange(minAddress, maxAddress);
private synchronized void addRange(AddressRange range) {
myCurrentAddressSet.add(range);
listModel.setData(myCurrentAddressSet.toList());
notifyListeners();
}
private synchronized void subtractRange(Address minAddress, Address maxAddress) {
myCurrentAddressSet.deleteRange(minAddress, maxAddress);
private synchronized void subtractRange(AddressRange range) {
myCurrentAddressSet.delete(range);
listModel.setData(myCurrentAddressSet.toList());
notifyListeners();
}

View file

@ -4,19 +4,20 @@
* 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.feature.vt.gui.wizard;
package ghidra.feature.vt.gui.wizard.add;
import java.awt.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.*;
@ -25,21 +26,26 @@ import javax.swing.table.TableColumnModel;
import docking.widgets.table.GTableCellRenderer;
import docking.widgets.table.GTableCellRenderingData;
import docking.wizard.*;
import ghidra.feature.vt.api.impl.VTProgramCorrelatorInfo;
import ghidra.feature.vt.api.main.*;
import ghidra.util.HelpLocation;
import ghidra.util.table.GhidraTable;
import utility.function.Callback;
public class CorrelatorPanel extends AbstractMageJPanel<VTWizardStateKey> implements Scrollable {
/**
* Panel for displaying and choosing from a list of version tracking correlators. Used by the
* {@link CorrelatorChooserStep} of the "add to version tracking session" wizard.
*/
public class CorrelatorChooserPanel extends JPanel {
private VTProgramTableCorrelatorModel model;
private GhidraTable table;
private Callback statusChangedCallback;
CorrelatorPanel(VTSession session) {
CorrelatorChooserPanel(VTSession session, Callback statusChangedCallback) {
setLayout(new BorderLayout());
table = createBasicTable(getPreviouslyRunAlgorithms(session));
add(new JScrollPane(table), BorderLayout.CENTER);
this.statusChangedCallback = statusChangedCallback;
}
private GhidraTable createBasicTable(Set<String> previouslyRunCorrelators) {
@ -56,16 +62,16 @@ public class CorrelatorPanel extends AbstractMageJPanel<VTWizardStateKey> implem
return table;
}
@Override
protected void notifyListenersOfValidityChanged() {
super.notifyListenersOfValidityChanged();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(1000, 400);
}
void notifyStatusChanged() {
statusChangedCallback.call();
}
private void setColumnSizes() {
TableColumnModel columnModel = table.getColumnModel();
int width = 0;
@ -102,87 +108,8 @@ public class CorrelatorPanel extends AbstractMageJPanel<VTWizardStateKey> implem
return set;
}
@Override
public void dispose() {
// nothing to do
}
@Override
public HelpLocation getHelpLocation() {
return new HelpLocation("VersionTrackingPlugin", "Correlator_Panel");
}
@Override
public void enterPanel(WizardState<VTWizardStateKey> state) {
// nothing to do
}
static WizardPanelDisplayability correlatorDisplayability(WizardState<VTWizardStateKey> state) {
return WizardPanelDisplayability.MUST_BE_DISPLAYED;
}
@Override
public WizardPanelDisplayability getPanelDisplayabilityAndUpdateState(
WizardState<VTWizardStateKey> state) {
return correlatorDisplayability(state);
}
@Override
public void leavePanel(WizardState<VTWizardStateKey> state) {
updateStateObjectWithPanelInfo(state);
}
@Override
public void updateStateObjectWithPanelInfo(WizardState<VTWizardStateKey> state) {
java.util.List<VTProgramCorrelatorFactory> selectedFactories = model.getSelectedFactories();
if (!selectedFactories.isEmpty()) {
state.put(VTWizardStateKey.PROGRAM_CORRELATOR_FACTORY_LIST, selectedFactories);
}
}
@Override
public String getTitle() {
return "Select Correlation Algorithm(s)";
}
@Override
public void initialize() {
// nothing to do
}
@Override
public boolean isValidInformation() {
return !model.getSelectedFactories().isEmpty();
}
@Override
public void addDependencies(WizardState<VTWizardStateKey> state) {
// no dependencies
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return null;
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 25;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return true;
}
@Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 10;
public List<VTProgramCorrelatorFactory> getSelectedCorrelators() {
return model.getSelectedFactories();
}
//==================================================================================================
@ -209,4 +136,5 @@ public class CorrelatorPanel extends AbstractMageJPanel<VTWizardStateKey> implem
return renderer;
}
}
}

View file

@ -0,0 +1,75 @@
/* ###
* 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.feature.vt.gui.wizard.add;
import java.util.List;
import javax.swing.JComponent;
import docking.wizard.WizardStep;
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
import ghidra.feature.vt.api.main.VTSession;
import ghidra.util.HelpLocation;
/**
* Wizard step for choosing which correlators to run when adding to an existing version
* tracking session.
*/
public class CorrelatorChooserStep extends WizardStep<AddToSessionData> {
private CorrelatorChooserPanel panel;
public CorrelatorChooserStep(VTAddToSessionWizardModel model, VTSession session) {
super(model, "Select Correlation Algorithm(s)",
new HelpLocation("VersionTrackingPlugin", "Correlator_Panel"));
panel = new CorrelatorChooserPanel(session, this::notifyStatusChanged);
}
@Override
public void initialize(AddToSessionData data) {
// nothing to do
}
@Override
public boolean isValid() {
List<VTProgramCorrelatorFactory> correlators = panel.getSelectedCorrelators();
if (!correlators.isEmpty()) {
return true;
}
return false;
}
@Override
public void populateData(AddToSessionData data) {
data.setCorrelators(panel.getSelectedCorrelators());
}
@Override
public boolean apply(AddToSessionData data) {
return true;
}
@Override
public JComponent getComponent() {
return panel;
}
@Override
public boolean canFinish(AddToSessionData data) {
return data.getCorrelators() != null;
}
}

View file

@ -0,0 +1,85 @@
/* ###
* 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.feature.vt.gui.wizard.add;
import java.awt.GridLayout;
import javax.swing.JPanel;
import ghidra.feature.vt.gui.wizard.add.AddToSessionData.AddressSetChoice;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.Program;
/**
* Panel for adjusting address sets for both the source and destination programs at the same time.
* Used by the {@link LimitAddressSetsStep} of the "add to version tracking session wizard.
*/
public class LimitAddressSetsPanel extends JPanel {
private ChooseAddressSetEditorPanel sourcePanel;
private ChooseAddressSetEditorPanel destinationPanel;
private PluginTool tool;
public LimitAddressSetsPanel(PluginTool tool) {
this.tool = tool;
setLayout(new GridLayout());
}
public void initialize(AddToSessionData data) {
removeAll();
sourcePanel = buildSourcePanel(data);
destinationPanel = buildDestinationPanel(data);
add(sourcePanel);
add(destinationPanel);
}
private ChooseAddressSetEditorPanel buildSourcePanel(AddToSessionData data) {
Program program = data.getSourceProgram();
AddressSetView selection = data.getSourceSelection();
AddressSetView set = data.getCustomSourceAddressSet();
AddressSetChoice choice = data.getSourceAddressSetChoice();
return new ChooseAddressSetEditorPanel(tool, "Source", program, selection, set, choice);
}
private ChooseAddressSetEditorPanel buildDestinationPanel(AddToSessionData data) {
Program program = data.getDestinationProgram();
AddressSetView selection = data.getDestinationSelection();
AddressSetView set = data.getCustomDestinationAddressSet();
AddressSetChoice choice = data.getDestinationAddressSetChoice();
return new ChooseAddressSetEditorPanel(tool, "Destination", program, selection, set,
choice);
}
public void apply(AddToSessionData data) {
AddressSetChoice sourceChoice = sourcePanel.getAddressSetChoice();
AddressSetChoice destinationChoice = destinationPanel.getAddressSetChoice();
data.setSourceAddressSetChoice(sourceChoice);
data.setDestinationAddressSetChoice(destinationChoice);
data.setCustomSourceAddressSet(null);
data.setCustomDestinationAddressSet(null);
if (sourceChoice == AddressSetChoice.MANUALLY_DEFINED) {
data.setCustomSourceAddressSet(sourcePanel.getAddressSetView());
}
if (destinationChoice == AddressSetChoice.MANUALLY_DEFINED) {
data.setCustomDestinationAddressSet(destinationPanel.getAddressSetView());
}
}
}

View file

@ -0,0 +1,73 @@
/* ###
* 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.feature.vt.gui.wizard.add;
import javax.swing.JComponent;
import docking.wizard.WizardStep;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.HelpLocation;
/**
* Wizard step for choosing the addresses to apply for adding correlation runs to an existing
* version tracking session.
*/
public class LimitAddressSetsStep extends WizardStep<AddToSessionData> {
private LimitAddressSetsPanel panel;
public LimitAddressSetsStep(VTAddToSessionWizardModel model, PluginTool tool) {
super(model, "Select Address Range(s)",
new HelpLocation("VersionTrackingPlugin", "Select_Address_Ranges_Panel"));
panel = new LimitAddressSetsPanel(tool);
}
@Override
public void initialize(AddToSessionData data) {
panel.initialize(data);
}
@Override
public boolean isValid() {
return true;
}
@Override
public boolean apply(AddToSessionData data) {
return true;
}
@Override
public void populateData(AddToSessionData data) {
panel.apply(data);
}
@Override
public boolean isApplicable(AddToSessionData data) {
return data.shouldLimitAddressSets();
}
@Override
public boolean canFinish(AddToSessionData data) {
return true;
}
@Override
public JComponent getComponent() {
return panel;
}
}

View file

@ -0,0 +1,141 @@
/* ###
* 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.feature.vt.gui.wizard.add;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.*;
import javax.swing.*;
import docking.options.editor.OptionsEditorPanel;
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
import ghidra.feature.vt.api.util.VTOptions;
import ghidra.framework.options.EditorStateFactory;
import ghidra.util.layout.VerticalLayout;
import utility.function.Callback;
/**
* Panel for displaying version tracking correlator options for selected correlators. Used by
* the {@link OptionsStep} of the "add to version tracking session" wizard to configure the
* selected correlators from a previous step.
*/
public class OptionsPanel extends JPanel {
private static final Dimension DEFAULT_PREFERRED_SIZE = new Dimension(650, 350);
private List<OptionsEditorPanel> optionsEditorPanelList = new ArrayList<>();
private Callback statusChangedCallback;
private Map<VTProgramCorrelatorFactory, VTOptions> optionsMap = new HashMap<>();
private JPanel stagingPanel;
OptionsPanel(Callback statusChangedCallback) {
super(new BorderLayout());
this.statusChangedCallback = statusChangedCallback;
stagingPanel = new JPanel(new BorderLayout());
stagingPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
JScrollPane scrollPane = new JScrollPane(stagingPanel);
scrollPane.getVerticalScrollBar().setUnitIncrement(5);
add(scrollPane);
}
@Override
public Dimension getPreferredSize() {
Dimension preferredSize = super.getPreferredSize();
if (preferredSize.width < DEFAULT_PREFERRED_SIZE.width) {
return DEFAULT_PREFERRED_SIZE;
}
return preferredSize;
}
public boolean isApplicable(List<VTProgramCorrelatorFactory> correlators) {
updateOptionsMap(correlators);
return !optionsMap.isEmpty();
}
private void updateOptionsMap(List<VTProgramCorrelatorFactory> correlators) {
optionsMap.keySet().retainAll(correlators);
for (VTProgramCorrelatorFactory correlator : correlators) {
if (!optionsMap.containsKey(correlator)) {
VTOptions defaultOptions = correlator.createDefaultOptions();
if (defaultOptions != null) {
optionsMap.put(correlator, defaultOptions);
}
}
}
}
void initialize(List<VTProgramCorrelatorFactory> correlators) {
updateOptionsMap(correlators);
JPanel panel = new JPanel(new VerticalLayout(30));
optionsEditorPanelList.clear();
for (VTProgramCorrelatorFactory correlator : correlators) {
OptionsEditorPanel optionsPanel = buildOptionsPanel(correlator);
if (optionsPanel != null) {
optionsEditorPanelList.add(optionsPanel);
optionsPanel.setOptionsPropertyChangeListener(e -> statusChangedCallback.call());
panel.add(optionsPanel);
}
}
stagingPanel.removeAll();
stagingPanel.add(panel, BorderLayout.CENTER);
stagingPanel.revalidate();
}
private OptionsEditorPanel buildOptionsPanel(VTProgramCorrelatorFactory factory) {
VTOptions options = optionsMap.get(factory);
if (options == null) {
return null;
}
String title = factory.getName() + " Options";
EditorStateFactory editorStateFactory = new EditorStateFactory();
List<String> optionNames = options.getLeafOptionNames();
if (optionNames.isEmpty()) {
return null;
}
Collections.sort(optionNames);
return new OptionsEditorPanel(title, options, optionNames, editorStateFactory);
}
public boolean hasValidOptions() {
applyOptions();
for (VTOptions options : optionsMap.values()) {
if (options != null) {
if (!options.validate()) {
return false;
}
}
}
return true;
}
private void applyOptions() {
for (OptionsEditorPanel panel : optionsEditorPanelList) {
panel.apply();
}
}
Map<VTProgramCorrelatorFactory, VTOptions> getOptionsMap() {
return optionsMap;
}
}

View file

@ -0,0 +1,75 @@
/* ###
* 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.feature.vt.gui.wizard.add;
import javax.swing.JComponent;
import docking.wizard.WizardModel;
import docking.wizard.WizardStep;
import ghidra.util.HelpLocation;
/**
* Wizard step for configuring options for the selected correlators when adding to an existing
* version tracking session.
*/
public class OptionsStep extends WizardStep<AddToSessionData> {
private OptionsPanel panel;
protected OptionsStep(WizardModel<AddToSessionData> model) {
super(model, "Correlator Options",
new HelpLocation("VersionTrackingPlugin", "Options_Panel"));
panel = new OptionsPanel(this::notifyStatusChanged);
}
@Override
public void initialize(AddToSessionData data) {
panel.initialize(data.getCorrelators());
// set the options here so that we know this step was visited
data.setOptions(panel.getOptionsMap());
}
@Override
public boolean isApplicable(AddToSessionData data) {
return panel.isApplicable(data.getCorrelators());
}
@Override
public boolean isValid() {
return panel.hasValidOptions();
}
@Override
public boolean canFinish(AddToSessionData data) {
return true;
}
@Override
public void populateData(AddToSessionData data) {
data.setOptions(panel.getOptionsMap());
}
@Override
public boolean apply(AddToSessionData data) {
return true;
}
@Override
public JComponent getComponent() {
return panel;
}
}

View file

@ -0,0 +1,163 @@
/* ###
* 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.feature.vt.gui.wizard.add;
import java.util.List;
import javax.swing.JComponent;
import docking.wizard.WizardModel;
import docking.wizard.WizardStep;
import ghidra.feature.vt.api.main.VTProgramCorrelatorFactory;
import ghidra.feature.vt.gui.wizard.add.AddToSessionData.AddressSetChoice;
import ghidra.feature.vt.gui.wizard.session.SummaryPanel;
import ghidra.framework.model.DomainFile;
import ghidra.util.HTMLUtilities;
import ghidra.util.HelpLocation;
/**
* Wizard step in the "add to tracking session" wizard for summarizing the information that
* will be used to add correlations to a version tracking session.
*/
public class SummaryStep extends WizardStep<AddToSessionData> {
private SummaryPanel summaryPanel;
protected SummaryStep(WizardModel<AddToSessionData> model) {
super(model, "Summary",
new HelpLocation("VersionTrackingPlugin", "New_Session_Summary_Panel"));
summaryPanel = new SummaryPanel();
}
@Override
public void initialize(AddToSessionData data) {
StringBuilder label = new StringBuilder();
StringBuilder summary = new StringBuilder();
label.append("<html>");
summary.append("<html>");
// session mode
label.append("Operation:");
summary.append("Add to Version Tracking Session");
label.append("<br>");
summary.append("<br>");
String sessionName = data.getSession().getName();
label.append("Session Name:");
summary.append(sessionName);
label.append("<br>");
summary.append("<br>");
String sourceProgramName = null;
String destinationProgramName = null;
DomainFile sourceProgram = data.getSourceFile();
sourceProgramName = sourceProgram.getName();
DomainFile destinationProgram = data.getDestinationFile();
destinationProgramName = destinationProgram.getName();
// source program
label.append("Source Program:");
summary.append(HTMLUtilities.escapeHTML(sourceProgramName));
label.append("<br>");
summary.append("<br>");
// destination program
label.append("Destination Program:");
summary.append(HTMLUtilities.escapeHTML(destinationProgramName));
label.append("<br>");
summary.append("<br>");
String correlatorLabel = "";
String correlatorName = null;
List<VTProgramCorrelatorFactory> correlators = data.getCorrelators();
for (VTProgramCorrelatorFactory correlatorFactory : correlators) {
correlatorName = correlatorFactory.getName();
label.append(correlatorLabel + "Program Correlator:");
summary.append(correlatorName == null ? "(null)" : correlatorName);
label.append("<br>");
summary.append("<br>");
}
boolean excludeAcceptedMatches = data.shouldExcludeAcceptedMatches();
label.append("Exclude Accepted Matches:");
summary.append(excludeAcceptedMatches ? "Yes" : "No");
label.append("<br>");
summary.append("<br>");
AddressSetChoice sourceAddressSetChoice = data.getSourceAddressSetChoice();
AddressSetChoice destinationAddressSetChoice = data.getDestinationAddressSetChoice();
String sourceAddressesInfo =
(sourceAddressSetChoice == AddressSetChoice.MANUALLY_DEFINED) ? "Manually Defined"
: ((sourceAddressSetChoice == AddressSetChoice.SELECTION))
? "Source Tool Selection"
: "Entire Source Program";
String destinationAddressesInfo =
(destinationAddressSetChoice == AddressSetChoice.MANUALLY_DEFINED)
? "Manually Defined"
: ((destinationAddressSetChoice == AddressSetChoice.SELECTION))
? "Destination Tool Selection"
: "Entire Destination Program";
label.append("Source Address Set:");
summary.append(sourceAddressesInfo);
label.append("<br>");
summary.append("<br>");
label.append("Destination Address Set:");
summary.append(destinationAddressesInfo);
label.append("<br>");
summary.append("<br>");
label.append("</html>");
summary.append("</html>");
summaryPanel.initialize(label.toString(), summary.toString());
}
@Override
public boolean isValid() {
return true;
}
@Override
public boolean canFinish(AddToSessionData data) {
return true;
}
@Override
public boolean apply(AddToSessionData data) {
return true;
}
@Override
public void populateData(AddToSessionData data) {
// nothing to do
}
@Override
public JComponent getComponent() {
return summaryPanel;
}
}

View file

@ -0,0 +1,66 @@
/* ###
* 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.feature.vt.gui.wizard.add;
import java.util.List;
import docking.wizard.WizardModel;
import docking.wizard.WizardStep;
import ghidra.feature.vt.api.main.VTSession;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.program.model.listing.Program;
import ghidra.util.task.Task;
import ghidra.util.task.TaskLauncher;
/**
* Wizard model for adding correlation runs to an existing version tracking session.
*/
public class VTAddToSessionWizardModel extends WizardModel<AddToSessionData> {
private final VTController controller;
public VTAddToSessionWizardModel(VTController controller) {
super("Add to Version Tracking Session", new AddToSessionData());
this.controller = controller;
Program sourceProgram = controller.getSourceProgram();
Program destinationProgram = controller.getDestinationProgram();
VTSession session = controller.getSession();
data.setSourceProgram(sourceProgram);
data.setDestinationProgram(destinationProgram);
data.setSession(session);
data.setSourceSelection(controller.getSelectionInSourceTool());
data.setDestinationSelection(controller.getSelectionInDestinationTool());
}
@Override
protected void addWizardSteps(List<WizardStep<AddToSessionData>> list) {
list.add(new CorrelatorChooserStep(this, controller.getSession()));
list.add(new OptionsStep(this));
list.add(new AddressSetOptionsStep(this));
list.add(new LimitAddressSetsStep(this, controller.getTool()));
list.add(new SummaryStep(this));
}
@Override
protected boolean doFinish() {
Task task = new AddToSessionTask(controller, data);
new TaskLauncher(task, wizardDialog.getComponent());
return true;
}
}

View file

@ -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.feature.vt.gui.wizard;
package ghidra.feature.vt.gui.wizard.add;
import java.util.*;
@ -26,6 +26,9 @@ import ghidra.feature.vt.api.util.VTAbstractProgramCorrelatorFactory;
import ghidra.util.classfinder.ClassSearcher;
import ghidra.util.exception.AssertException;
/**
* Table model for showing version tracking correlators.
*/
public class VTProgramTableCorrelatorModel extends AbstractGTableModel<VTProgramCorrelatorFactory> {
static final String NAME_COLUMN_NAME = "Name";
@ -47,9 +50,9 @@ public class VTProgramTableCorrelatorModel extends AbstractGTableModel<VTProgram
private Set<String> previouslyRunCorrelators;
private Set<VTProgramCorrelatorFactory> selectedFactories =
new HashSet<>();
private CorrelatorPanel panel;
private CorrelatorChooserPanel panel;
public VTProgramTableCorrelatorModel(CorrelatorPanel panel,
public VTProgramTableCorrelatorModel(CorrelatorChooserPanel panel,
Set<String> previouslyRunCorrelators) {
this.panel = panel;
this.previouslyRunCorrelators = previouslyRunCorrelators;
@ -57,7 +60,9 @@ public class VTProgramTableCorrelatorModel extends AbstractGTableModel<VTProgram
}
public List<VTProgramCorrelatorFactory> getSelectedFactories() {
return new ArrayList<>(selectedFactories);
List<VTProgramCorrelatorFactory> factories = new ArrayList<>(selectedFactories);
factories.sort(comparator);
return factories;
}
private static List<VTProgramCorrelatorFactory> generateList() {
@ -136,7 +141,7 @@ public class VTProgramTableCorrelatorModel extends AbstractGTableModel<VTProgram
else {
selectedFactories.remove(factory);
}
panel.notifyListenersOfValidityChanged();
panel.notifyStatusChanged();
}
@Override

View file

@ -4,20 +4,19 @@
* 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.feature.vt.gui.wizard;
package ghidra.feature.vt.gui.wizard.session;
import java.io.IOException;
import docking.wizard.WizardState;
import ghidra.feature.vt.api.db.VTSessionDB;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.framework.model.DomainFolder;
@ -29,13 +28,13 @@ import ghidra.util.task.Task;
import ghidra.util.task.TaskMonitor;
public class CreateNewSessionTask extends Task {
private final WizardState<VTWizardStateKey> state;
private final NewSessionData data;
private final VTController controller;
public CreateNewSessionTask(VTController controller, WizardState<VTWizardStateKey> state) {
public CreateNewSessionTask(VTController controller, NewSessionData data) {
super("Create New Version Tracking Session", true, true, true);
this.controller = controller;
this.state = state;
this.data = data;
}
@Override
@ -43,16 +42,16 @@ public class CreateNewSessionTask extends Task {
VTSessionDB session = null;
String name = null;
try {
Program sourceProgram = (Program) state.get(VTWizardStateKey.SOURCE_PROGRAM);
Program destinationProgram = (Program) state.get(VTWizardStateKey.DESTINATION_PROGRAM);
Program sourceProgram = data.getSourceProgram();
Program destinationProgram = data.getDestinationProgram();
session = new VTSessionDB("New Session", sourceProgram, destinationProgram, this);
sourceProgram.release(controller.getTool());
destinationProgram.release(controller.getTool());
name = (String) state.get(VTWizardStateKey.SESSION_NAME);
DomainFolder folder = (DomainFolder) state.get(VTWizardStateKey.NEW_SESSION_FOLDER);
name = data.getSessionName();
DomainFolder folder = data.getSessionFolder();
try {
folder.createFile(name, session, monitor);
}

View file

@ -0,0 +1,112 @@
/* ###
* 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.feature.vt.gui.wizard.session;
import ghidra.framework.model.DomainFile;
import ghidra.framework.model.DomainFolder;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
/**
* Wizard data used by the {@link VTNewSessionWizardModel} and its steps for the "create new version
* tracking session" wizard.
*/
public class NewSessionData {
private Program sourceProgram;
private Program destinationProgram;
private DomainFile sourceFile;
private DomainFile destinationFile;
private DomainFolder sessionFolder;
private String sessionName;
private boolean preconditionChecksCompleted;
public DomainFile getSourceFile() {
return sourceFile;
}
public DomainFile getDestinationFile() {
return destinationFile;
}
public Program getSourceProgram() {
return sourceProgram;
}
public Program getDestinationProgram() {
return destinationProgram;
}
public String getSessionName() {
return sessionName;
}
public DomainFolder getSessionFolder() {
return sessionFolder;
}
public void setSourceFile(DomainFile file, PluginTool tool) {
this.sourceFile = file;
if (isProgramInvalidForFile(file, sourceProgram)) {
sourceProgram.release(tool);
sourceProgram = null;
}
}
private boolean isProgramInvalidForFile(DomainFile file, Program program) {
if (program == null) {
return false;
}
if (program.getDomainFile().equals(file)) {
return false;
}
return true;
}
public void setDestinationFile(DomainFile file, PluginTool tool) {
this.destinationFile = file;
if (isProgramInvalidForFile(file, destinationProgram)) {
sourceProgram.release(tool);
sourceProgram = null;
}
}
public void setSourceProgram(Program program) {
this.sourceProgram = program;
preconditionChecksCompleted = false;
}
public void setDestinationProgram(Program program) {
this.destinationProgram = program;
preconditionChecksCompleted = false;
}
public void setSessionName(String name) {
this.sessionName = name;
}
public void setSessionFolder(DomainFolder folder) {
this.sessionFolder = folder;
}
public boolean hasPerformedPreconditionChecks() {
return preconditionChecksCompleted;
}
public void setPerformedPreconditionChecks(boolean b) {
preconditionChecksCompleted = b;
}
}

View file

@ -0,0 +1,152 @@
/* ###
* 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.feature.vt.gui.wizard.session;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.*;
import docking.widgets.conditiontestpanel.*;
import docking.wizard.WizardModel;
import ghidra.feature.vt.api.main.VTSession;
import ghidra.feature.vt.gui.validator.VTPreconditionValidator;
import ghidra.program.model.listing.Program;
import ghidra.util.Msg;
import ghidra.util.classfinder.ClassSearcher;
import utility.function.Callback;
public class PreconditionsPanel extends JPanel {
private static final Dimension DEFAULT_SIZE = new Dimension(650, 480);
private ConditionTestPanel conditionsTestPanel;
private boolean testsDone = false;
private Callback statusChangedCallback;
public PreconditionsPanel(WizardModel<NewSessionData> model,
Callback statusChangedCallback) {
this.statusChangedCallback = statusChangedCallback;
setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
setLayout(new BorderLayout());
JPanel runButtonPanel = new JPanel();
runButtonPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0));
runButtonPanel.setLayout(new FlowLayout());
JButton runTestsButton = new JButton("Run Precondition Checks");
runTestsButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
conditionsTestPanel.runTests();
}
});
runButtonPanel.add(runTestsButton);
JButton skipTestsButton = new JButton("Skip");
skipTestsButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
conditionsTestPanel.skipTests();
model.goNext();
}
});
runButtonPanel.add(skipTestsButton);
add(runButtonPanel, BorderLayout.SOUTH);
}
void dispose() {
if (conditionsTestPanel != null) {
conditionsTestPanel.cancel();
}
}
private ConditionTestPanel buildConditionPanel(Program source, Program destination) {
List<ConditionTester> list = getConditionTests(source, destination);
Collections.sort(list, (t1, t2) -> t1.getName().compareTo(t2.getName()));
ConditionTestPanel panel = new ConditionTestPanel(list);
panel.addListener(new ConditionTestListener() {
@Override
public void testsCompleted() {
testsDone();
}
});
return panel;
}
private void testsDone() {
testsDone = true;
statusChangedCallback.call();
if (hasAnyErrorStatus()) {
Msg.showError(getClass(), this, "Warning - Serious Precondition failures",
"The precondition checks discovered one or more serious problems. \n\n" +
"If you continue, your version tracking results may be invalid.\n" +
"You should review the errors, cancel this wizard, and correct the problems.");
}
}
private List<ConditionTester> getConditionTests(Program sourceProgram,
Program destinationProgram) throws SecurityException {
List<ConditionTester> list = new ArrayList<ConditionTester>();
List<Class<? extends VTPreconditionValidator>> vtValidatorClasses =
ClassSearcher.getClasses(VTPreconditionValidator.class);
for (Class<? extends VTPreconditionValidator> validatorClass : vtValidatorClasses) {
try {
Constructor<? extends VTPreconditionValidator> ctor =
validatorClass.getConstructor(Program.class, Program.class, VTSession.class);
VTPreconditionValidator validator =
ctor.newInstance(sourceProgram, destinationProgram, null);
list.add(validator);
}
catch (Exception e) {
Msg.error(this, "error including VTPreconditionValidator " + validatorClass, e);
}
}
return list;
}
private Boolean hasAnyErrorStatus() {
return conditionsTestPanel.getErrorCount() > 0;
}
@Override
// Overridden to account for the fact that we don't know our preferred size until later in
// the wizard flow. At that point, the initial size of the wizard is already too small.
public Dimension getPreferredSize() {
Dimension superSize = super.getPreferredSize();
if (superSize.width > DEFAULT_SIZE.width && superSize.height > DEFAULT_SIZE.height) {
return superSize;
}
return DEFAULT_SIZE;
}
public void initializeTests(Program sourceProgram, Program destinationProgram) {
testsDone = false;
if (conditionsTestPanel != null) {
remove(conditionsTestPanel);
}
conditionsTestPanel = buildConditionPanel(sourceProgram, destinationProgram);
add(conditionsTestPanel, BorderLayout.CENTER);
}
public boolean hasRunTests() {
return testsDone;
}
}

View file

@ -0,0 +1,82 @@
/* ###
* 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.feature.vt.gui.wizard.session;
import javax.swing.JComponent;
import docking.wizard.WizardModel;
import docking.wizard.WizardStep;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
/**
* Wizard step for running version tracking precondition tests when creating a new version tracking
* session.
*/
public class PreconditionsStep extends WizardStep<NewSessionData> {
private PreconditionsPanel preconditionsPanel;
protected PreconditionsStep(WizardModel<NewSessionData> model) {
super(model, "Precondition Checklist",
new HelpLocation("VersionTrackingPlugin", "Preconditions_Panel"));
preconditionsPanel = new PreconditionsPanel(model, this::notifyStatusChanged);
}
@Override
public void initialize(NewSessionData data) {
if (!data.hasPerformedPreconditionChecks()) {
Program sourceProgram = data.getSourceProgram();
Program destinationProgram = data.getDestinationProgram();
preconditionsPanel.initializeTests(sourceProgram, destinationProgram);
}
}
@Override
public boolean isValid() {
boolean hasRunTests = preconditionsPanel.hasRunTests();
if (hasRunTests) {
return true;
}
return false;
}
@Override
public void populateData(NewSessionData data) {
data.setPerformedPreconditionChecks(true);
}
@Override
public boolean apply(NewSessionData data) {
return true;
}
@Override
public boolean canFinish(NewSessionData data) {
return data.hasPerformedPreconditionChecks();
}
@Override
public JComponent getComponent() {
return preconditionsPanel;
}
@Override
protected void dispose(NewSessionData data) {
preconditionsPanel.dispose();
}
}

View file

@ -0,0 +1,348 @@
/* ###
* 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.feature.vt.gui.wizard.session;
import static ghidra.framework.main.DataTreeDialogType.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.apache.commons.lang3.StringUtils;
import docking.widgets.button.BrowseButton;
import docking.widgets.label.GDLabel;
import generic.theme.GIcon;
import generic.theme.GThemeDefaults.Ids.Fonts;
import generic.theme.Gui;
import ghidra.framework.main.DataTreeDialog;
import ghidra.framework.model.DomainFile;
import ghidra.framework.model.DomainFolder;
import ghidra.util.StringUtilities;
import utility.function.Callback;
public class SessionConfigurationPanel extends JPanel {
// The maximum length to allow for each program's name portion of the session name.
// In the filesystem API, when saved, the session name is restricted to 60 characters.
// The default VTSession name combines the two program names so split the length between them,
// minus text we add below.
private static final int VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH = 28;
private static final int TEXT_FIELD_LENGTH = 40;
private static final Icon SWAP_ICON = new GIcon("icon.version.tracking.new.session.swap");
private static final Icon INFO_ICON = new GIcon("icon.version.tracking.new.session.info");
private JTextField sourceField;
private JTextField destinationField;
private JButton sourceBrowseButton;
private JButton destinationBrowseButton;
private JButton swapProgramsButton;
private JTextField sessionNameField;
private JTextField folderNameField;
private DomainFile sourceFile;
private DomainFile destinationFile;
private DomainFolder sessionFolder;
private Callback statusChangedCallback;
SessionConfigurationPanel(Callback statusChangedCallback) {
this.statusChangedCallback = statusChangedCallback;
setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
JLabel folderLabel = new GDLabel("Project folder ");
folderLabel.setHorizontalAlignment(SwingConstants.RIGHT);
folderLabel.setToolTipText("The folder to store the new Version Tracking Session");
folderNameField = new JTextField();
Gui.registerFont(folderNameField, Fonts.MONOSPACED);
folderNameField.setEditable(false); // force user to browse to choose
JButton browseFolderButton = new BrowseButton();
browseFolderButton.addActionListener(e -> browseDataTreeFolders());
JLabel newSessionLabel = new GDLabel("New Session Name: ");
newSessionLabel.setToolTipText("The name for the new Version Tracking Session");
newSessionLabel.setHorizontalAlignment(SwingConstants.RIGHT);
sessionNameField = new JTextField(TEXT_FIELD_LENGTH);
sessionNameField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
statusChangedCallback.call();
}
@Override
public void insertUpdate(DocumentEvent e) {
statusChangedCallback.call();
}
@Override
public void removeUpdate(DocumentEvent e) {
statusChangedCallback.call();
}
});
JLabel sourceLabel = new GDLabel("Source Program: ");
sourceLabel.setIcon(INFO_ICON);
sourceLabel.setToolTipText("Analyzed program with markup to transfer");
sourceLabel.setHorizontalAlignment(SwingConstants.RIGHT);
JLabel destinationLabel = new GDLabel("Destination Program: ");
destinationLabel.setIcon(INFO_ICON);
destinationLabel.setToolTipText("New program that receives the transferred markup");
destinationLabel.setHorizontalAlignment(SwingConstants.RIGHT);
sourceField = new JTextField(TEXT_FIELD_LENGTH);
sourceField.setEditable(false);
destinationField = new JTextField(TEXT_FIELD_LENGTH);
destinationField.setEditable(false);
sourceBrowseButton = createSourceBrowseButton();
destinationBrowseButton = createDestinationBrowseButton();
swapProgramsButton = new JButton(SWAP_ICON);
swapProgramsButton.setText("swap");
swapProgramsButton.setName("SWAP_BUTTON");
swapProgramsButton.addActionListener(arg0 -> swapPrograms());
JPanel mainPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
mainPanel.add(Box.createVerticalStrut(15), gbc);
gbc.gridy++;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainPanel.add(folderLabel, gbc);
gbc.gridx++;
mainPanel.add(folderNameField, gbc);
gbc.gridx++;
mainPanel.add(Box.createHorizontalStrut(5), gbc);
gbc.gridx++;
mainPanel.add(browseFolderButton, gbc);
gbc.gridx = 0;
gbc.gridy++;
mainPanel.add(Box.createVerticalStrut(10), gbc);
gbc.gridy++;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainPanel.add(newSessionLabel, gbc);
gbc.gridx++;
mainPanel.add(sessionNameField, gbc);
gbc.gridx = 0;
gbc.gridy++;
mainPanel.add(Box.createVerticalStrut(15), gbc);
gbc.gridy++;
gbc.gridwidth = 4;
mainPanel.add(new JSeparator(), gbc);
gbc.gridy++;
gbc.gridwidth = 1;
mainPanel.add(Box.createVerticalStrut(25), gbc);
gbc.gridy++;
mainPanel.add(sourceLabel, gbc);
gbc.gridx++;
mainPanel.add(sourceField, gbc);
gbc.gridx += 2;
mainPanel.add(sourceBrowseButton, gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.fill = GridBagConstraints.NONE;
gbc.gridwidth = 4;
mainPanel.add(swapProgramsButton, gbc);
gbc.gridwidth = 1;
gbc.gridy++;
gbc.fill = GridBagConstraints.HORIZONTAL;
mainPanel.add(destinationLabel, gbc);
gbc.gridx++;
mainPanel.add(destinationField, gbc);
gbc.gridx += 2;
mainPanel.add(destinationBrowseButton, gbc);
gbc.gridx = 0;
gbc.gridy++;
mainPanel.add(Box.createVerticalStrut(25), gbc);
gbc.gridy++;
gbc.gridwidth = 4;
mainPanel.add(new JSeparator(), gbc);
gbc.gridy++;
gbc.gridwidth = 1;
mainPanel.add(Box.createVerticalStrut(60), gbc);
setLayout(new BorderLayout());
add(mainPanel, BorderLayout.NORTH);
}
public void setDestinationFile(DomainFile file) {
destinationFile = file;
if (destinationFile != null) {
destinationField.setText(destinationFile.getPathname());
}
else {
destinationField.setText("");
}
updateSessionNameIfBlank();
}
public void setSourceFile(DomainFile file) {
sourceFile = file;
if (sourceFile != null) {
sourceField.setText(sourceFile.getPathname());
}
else {
sourceField.setText("");
}
updateSessionNameIfBlank();
}
private JButton createSourceBrowseButton() {
JButton button = new BrowseButton();
button.setName("SOURCE_BUTTON");
button.addActionListener(e -> {
DomainFile programFile = VTWizardUtils.chooseDomainFile(SessionConfigurationPanel.this,
"a source program", VTWizardUtils.PROGRAM_FILTER, null);
if (programFile != null) {
setSourceFile(programFile);
statusChangedCallback.call();
}
});
return button;
}
private JButton createDestinationBrowseButton() {
JButton button = new BrowseButton();
button.setName("DESTINATION_BUTTON");
button.addActionListener(e -> {
DomainFile programFile = VTWizardUtils.chooseDomainFile(SessionConfigurationPanel.this,
"a destination program", VTWizardUtils.PROGRAM_FILTER, null);
if (programFile != null) {
setDestinationFile(programFile);
statusChangedCallback.call();
}
});
return button;
}
/**
* Presents the user with a tree of the existing project folders and allows
* them to pick one
*/
private void browseDataTreeFolders() {
final DataTreeDialog dataTreeDialog =
new DataTreeDialog(this, "Choose a project folder", CHOOSE_FOLDER);
dataTreeDialog.addOkActionListener(e -> {
dataTreeDialog.close();
sessionFolder = dataTreeDialog.getDomainFolder();
folderNameField.setText(sessionFolder.toString());
statusChangedCallback.call();
});
dataTreeDialog.showComponent();
}
private void swapPrograms() {
DomainFile newSourceFile = destinationFile;
DomainFile newDestionationFile = sourceFile;
setSourceFile(newSourceFile);
setDestinationFile(newDestionationFile);
statusChangedCallback.call();
}
public DomainFolder getSessionFolder() {
return sessionFolder;
}
public String getSessionName() {
return sessionNameField.getText().trim();
}
public DomainFile getSourceFile() {
return sourceFile;
}
public DomainFile getDestinationFile() {
return destinationFile;
}
private void updateSessionNameIfBlank() {
if (!StringUtils.isBlank(sessionNameField.getText())) {
return;
}
if (sourceFile == null || destinationFile == null || sourceFile == destinationFile) {
return;
}
String defaultSessionName =
createVTSessionName(sourceFile.getName(), destinationFile.getName());
sessionNameField.setText(defaultSessionName);
}
private String createVTSessionName(String sourceName, String destinationName) {
// if together they are within the bounds just return session name with both full names
if (sourceName.length() + destinationName.length() <= 2 *
VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH) {
return "VT_" + sourceName + "_" + destinationName;
}
// give destination name all space not used by source name
if (sourceName.length() < VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH) {
int leftover = VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH - sourceName.length();
destinationName = StringUtilities.trimMiddle(destinationName,
VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH + leftover);
return "VT_" + sourceName + "_" + destinationName;
}
// give source name all space not used by destination name
if (destinationName.length() < VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH) {
int leftover = VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH - destinationName.length();
sourceName = StringUtilities.trimMiddle(sourceName,
VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH + leftover);
return "VT_" + sourceName + "_" + destinationName;
}
// if both too long, shorten both of them
sourceName = StringUtilities.trimMiddle(sourceName, VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH);
destinationName =
StringUtilities.trimMiddle(destinationName, VTSESSION_NAME_PROGRAM_NAME_MAX_LENGTH);
return "VT_" + sourceName + "_" + destinationName;
}
public void setSessionFolder(DomainFolder folder) {
sessionFolder = folder;
folderNameField.setText(sessionFolder.toString());
}
}

View file

@ -0,0 +1,205 @@
/* ###
* 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.feature.vt.gui.wizard.session;
import javax.swing.JComponent;
import org.apache.commons.lang3.StringUtils;
import docking.wizard.WizardModel;
import docking.wizard.WizardStep;
import ghidra.app.util.task.OpenProgramRequest;
import ghidra.app.util.task.OpenProgramTask;
import ghidra.feature.vt.api.util.VTSessionFileUtil;
import ghidra.framework.model.DomainFile;
import ghidra.framework.model.DomainFolder;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
import ghidra.util.InvalidNameException;
import ghidra.util.task.TaskLauncher;
/**
* Wizard step in the new version tracking session wizard for choosing which programs to
* track and naming the session.
*/
public class SessionConfigurationStep extends WizardStep<NewSessionData> {
private PluginTool tool;
private SessionConfigurationPanel sessionPanel;
protected SessionConfigurationStep(WizardModel<NewSessionData> model, PluginTool tool) {
super(model, "New Version Tracking Session",
new HelpLocation("VersionTrackingPlugin", "New_Session_Panel"));
this.tool = tool;
sessionPanel = new SessionConfigurationPanel(this::notifyStatusChanged);
}
@Override
public void initialize(NewSessionData data) {
sessionPanel.setSessionFolder(data.getSessionFolder());
sessionPanel.setSourceFile(data.getSourceFile());
sessionPanel.setDestinationFile(data.getDestinationFile());
}
@Override
public boolean isValid() {
setStatusMessage("");
DomainFolder sessionFolder = sessionPanel.getSessionFolder();
String sessionName = sessionPanel.getSessionName();
DomainFile sourceFile = sessionPanel.getSourceFile();
DomainFile destinationFile = sessionPanel.getDestinationFile();
if (!isValid(sessionFolder, sessionName, sourceFile, destinationFile)) {
return false;
}
return true;
}
@Override
public void populateData(NewSessionData data) {
data.setSessionName(sessionPanel.getSessionName());
data.setSessionFolder(sessionPanel.getSessionFolder());
data.setSourceFile(sessionPanel.getSourceFile(), tool);
data.setDestinationFile(sessionPanel.getDestinationFile(), tool);
}
@Override
public boolean canFinish(NewSessionData data) {
return true;
}
@Override
protected void dispose(NewSessionData data) {
releaseProgram(data.getSourceProgram());
releaseProgram(data.getDestinationProgram());
}
private void releaseProgram(Program program) {
if (program != null) {
if (program.getConsumerList().contains(tool)) {
program.release(tool);
}
}
}
private boolean isValid(DomainFolder sessionFolder, String sessionName, DomainFile sourceFile,
DomainFile destinationFile) {
if (sessionFolder == null) {
setStatusMessage("Choose a project folder to continue!");
return false;
}
if (sourceFile == null) {
setStatusMessage("Please choose a source program.");
return false;
}
if (destinationFile == null) {
setStatusMessage("Please choose a destination program.");
return false;
}
if (sourceFile.equals(destinationFile)) {
setStatusMessage("Source and destination files must be different.");
return false;
}
if (StringUtils.isBlank(sessionName)) {
setStatusMessage("Please enter a name for this session");
return false;
}
try {
tool.getProject().getProjectData().testValidName(sessionName, false);
}
catch (InvalidNameException e) {
setStatusMessage("'" + sessionName + "' contains invalid characters");
return false;
}
DomainFile file = sessionFolder.getFile(sessionName);
if (file != null) {
setStatusMessage(
"'" + file.getPathname() + "' is the name of an existing project file");
return false;
}
return true;
}
@Override
public boolean apply(NewSessionData data) {
if (data.getSourceProgram() == null) {
Program program = openSourceProgram(data.getSourceFile());
if (program == null) {
return false;
}
data.setSourceProgram(program);
}
if (data.getDestinationProgram() == null) {
Program program = openDestinationProgram(data.getDestinationFile());
if (program == null) {
return false;
}
data.setDestinationProgram(program);
}
return true;
}
private Program openSourceProgram(DomainFile file) {
try {
VTSessionFileUtil.validateSourceProgramFile(file, false);
}
catch (Exception e) {
setStatusMessage(e.getMessage());
return null;
}
Program program = openProgram(file);
if (program == null) {
setStatusMessage("Open source program failed for " + file.getPathname());
}
return program;
}
private Program openDestinationProgram(DomainFile file) {
try {
VTSessionFileUtil.validateDestinationProgramFile(file, false, false);
}
catch (Exception e) {
setStatusMessage(e.getMessage());
return null;
}
Program program = openProgram(file);
if (program == null) {
setStatusMessage("Open destination program failed for " + file.getPathname());
}
return program;
}
private Program openProgram(DomainFile domainFile) {
OpenProgramTask openProgramTask = new OpenProgramTask(domainFile, tool);
new TaskLauncher(openProgramTask, tool.getActiveWindow());
OpenProgramRequest openProgramRequest = openProgramTask.getOpenProgram();
return openProgramRequest != null ? openProgramRequest.getProgram() : null;
}
@Override
public JComponent getComponent() {
return sessionPanel;
}
}

View file

@ -0,0 +1,48 @@
/* ###
* 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.feature.vt.gui.wizard.session;
import java.awt.BorderLayout;
import javax.swing.*;
import docking.widgets.label.GDHtmlLabel;
import ghidra.util.layout.PairLayout;
public class SummaryPanel extends JPanel {
private JLabel labelLabel;
private JLabel summaryLabel;
public SummaryPanel() {
labelLabel = new GDHtmlLabel();
summaryLabel = new GDHtmlLabel();
JPanel mainPanel = new JPanel(new PairLayout(5, 10));
mainPanel.add(labelLabel);
mainPanel.add(summaryLabel);
setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
setLayout(new BorderLayout());
add(mainPanel, BorderLayout.CENTER);
}
public void initialize(String labelText, String summaryText) {
labelLabel.setText(labelText);
summaryLabel.setText(summaryText);
}
}

View file

@ -0,0 +1,117 @@
/* ###
* 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.feature.vt.gui.wizard.session;
import javax.swing.JComponent;
import docking.wizard.WizardModel;
import docking.wizard.WizardStep;
import ghidra.framework.model.DomainFile;
import ghidra.util.HTMLUtilities;
import ghidra.util.HelpLocation;
/**
* Wizard step in the new version tracking session wizard for summarizing the information that
* will be used to create a new session.
*/
public class SummaryStep extends WizardStep<NewSessionData> {
private SummaryPanel summaryPanel;
protected SummaryStep(WizardModel<NewSessionData> model) {
super(model, "Summary",
new HelpLocation("VersionTrackingPlugin", "New_Session_Summary_Panel"));
summaryPanel = new SummaryPanel();
}
@Override
public void initialize(NewSessionData data) {
StringBuilder label = new StringBuilder();
StringBuilder summary = new StringBuilder();
label.append("<html>");
summary.append("<html>");
// session mode
label.append("Operation:");
String opDescription = "New Version Tracking Session";
summary.append(opDescription);
label.append("<br>");
summary.append("<br>");
String sessionName = data.getSessionName();
label.append("Session Name:");
summary.append(sessionName);
label.append("<br>");
summary.append("<br>");
String sourceProgramName = null;
String destinationProgramName = null;
DomainFile sourceProgram = data.getSourceFile();
sourceProgramName = sourceProgram.getName();
DomainFile destinationProgram = data.getDestinationFile();
destinationProgramName = destinationProgram.getName();
// source program
label.append("Source Program:");
summary.append(HTMLUtilities.escapeHTML(sourceProgramName));
label.append("<br>");
summary.append("<br>");
// destination program
label.append("Destination Program:");
summary.append(HTMLUtilities.escapeHTML(destinationProgramName));
label.append("<br>");
summary.append("<br>");
label.append("</html>");
summary.append("</html>");
summaryPanel.initialize(label.toString(), summary.toString());
}
@Override
public boolean isValid() {
return true;
}
@Override
public boolean apply(NewSessionData data) {
return true;
}
@Override
public JComponent getComponent() {
return summaryPanel;
}
@Override
public boolean canFinish(NewSessionData data) {
return true;
}
@Override
public void populateData(NewSessionData data) {
// this step is display only
}
}

View file

@ -0,0 +1,66 @@
/* ###
* 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.feature.vt.gui.wizard.session;
import java.util.List;
import docking.wizard.WizardModel;
import docking.wizard.WizardStep;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.framework.model.DomainFile;
import ghidra.framework.model.DomainFolder;
import ghidra.framework.plugintool.PluginTool;
import ghidra.util.task.Task;
import ghidra.util.task.TaskLauncher;
/**
* Wizard model for creating a new version tracking session.
*/
public class VTNewSessionWizardModel extends WizardModel<NewSessionData> {
private final VTController controller;
public VTNewSessionWizardModel(VTController controller) {
this(controller, null, null);
}
public VTNewSessionWizardModel(VTController controller, DomainFile sourceFile,
DomainFile destinationFile) {
super("New Version Tracking Session", new NewSessionData());
this.controller = controller;
PluginTool tool = controller.getTool();
data.setSourceFile(sourceFile, tool);
data.setDestinationFile(destinationFile, tool);
DomainFolder folder = tool.getProject().getProjectData().getRootFolder();
data.setSessionFolder(folder);
}
@Override
protected void addWizardSteps(List<WizardStep<NewSessionData>> list) {
list.add(new SessionConfigurationStep(this, controller.getTool()));
list.add(new PreconditionsStep(this));
list.add(new SummaryStep(this));
}
@Override
protected boolean doFinish() {
Task task = new CreateNewSessionTask(controller, data);
new TaskLauncher(task, wizardDialog.getComponent());
return true;
}
}

View file

@ -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.feature.vt.gui.wizard;
package ghidra.feature.vt.gui.wizard.session;
import static ghidra.framework.main.DataTreeDialogType.*;
@ -54,7 +54,7 @@ public class VTWizardUtils {
return Program.class.isAssignableFrom(f.getDomainObjectClass());
};
static DomainFile chooseDomainFile(Component parent, String domainIdentifier,
public static DomainFile chooseDomainFile(Component parent, String domainIdentifier,
DomainFileFilter filter, DomainFile fileToSelect) {
final DataTreeDialog dataTreeDialog = filter == null
? new DataTreeDialog(parent, "Choose " + domainIdentifier, OPEN)

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -51,7 +51,7 @@ import ghidra.feature.vt.gui.provider.onetomany.VTMatchDestinationTableProvider;
import ghidra.feature.vt.gui.provider.onetomany.VTMatchSourceTableProvider;
import ghidra.feature.vt.gui.task.*;
import ghidra.feature.vt.gui.util.MatchInfo;
import ghidra.feature.vt.gui.wizard.*;
import ghidra.feature.vt.gui.wizard.add.*;
import ghidra.features.base.codecompare.listing.ListingCodeComparisonPanel;
import ghidra.framework.main.DataTreeDialog;
import ghidra.framework.main.datatree.DataTree;
@ -228,11 +228,13 @@ public class VersionTrackingPluginScreenShots extends GhidraScreenShotGenerator
selectMatch("Call_strncpy_s");
dualListingIsVisible(getProvider(VTMarkupItemsTableProvider.class));
VTMarkupItemsTableProvider provider = getProvider(VTMarkupItemsTableProvider.class);
tool.showComponentProvider(provider, true);
assertTrue(dualListingIsVisible(provider));
hideDualListing(VTMarkupItemsTableProvider.class);
dualListingIsVisible(getProvider(VTMarkupItemsTableProvider.class));
assertFalse(dualListingIsVisible(provider));
setToolSize(1300, 750);
@ -441,6 +443,8 @@ public class VersionTrackingPluginScreenShots extends GhidraScreenShotGenerator
assertNotNull(destinationTool);
tool = sourceTool;
ComponentProvider provider = tool.getComponentProvider("Decompiler");
tool.showComponentProvider(provider, BATCH_MODE);
setToolSize(1200, 550);
sourceTool.toFront();
captureToolWindow(1200, 550);
@ -785,7 +789,7 @@ public class VersionTrackingPluginScreenShots extends GhidraScreenShotGenerator
assertNotNull(provider);
ToggleDockingAction action =
(ToggleDockingAction) getLocalAction(provider, "Dual Listing Toggle Orientation");
(ToggleDockingAction) getLocalAction(provider, "Listing View Toggle Orientation");
assertNotNull(action);
setToggleActionSelected(action, new DefaultActionContext(), vertical);
waitForSwing();
@ -817,12 +821,10 @@ public class VersionTrackingPluginScreenShots extends GhidraScreenShotGenerator
DialogComponentProvider dialog = getDialog();
LimitAddressSetsPanel panel = findComponent(dialog, LimitAddressSetsPanel.class);
AddressSetPanel destinationPanel =
(AddressSetPanel) getInstanceField("destinationPanel", panel);
ChooseAddressSetEditorPanel choosePanel =
findComponent(destinationPanel, ChooseAddressSetEditorPanel.class);
ChooseAddressSetEditorPanel destinationPanel =
(ChooseAddressSetEditorPanel) getInstanceField("destinationPanel", panel);
JRadioButton myRangesButton =
(JRadioButton) getInstanceField("myRangesButton", choosePanel);
(JRadioButton) getInstanceField("myRangesButton", destinationPanel);
pressButton(myRangesButton);
}
@ -833,17 +835,18 @@ public class VersionTrackingPluginScreenShots extends GhidraScreenShotGenerator
DialogComponentProvider dialog = getDialog();
AddressSetOptionsPanel panel = findComponent(dialog, AddressSetOptionsPanel.class);
JCheckBox showAddressSetPanelsCheckbox =
(JCheckBox) getInstanceField("showAddressSetPanelsCheckbox", panel);
(JCheckBox) getInstanceField("limitAddressSetsCheckbox", panel);
showAddressSetPanelsCheckbox.setSelected(true);
}
private void setupVTWizardOptionsPanel() throws Exception {
setupVTWizardCorrelatorPanel();
DialogComponentProvider dialog = getDialog();
CorrelatorPanel correlatorPanel = findComponent(dialog, CorrelatorPanel.class);
CorrelatorChooserPanel correlatorPanel =
findComponent(dialog, CorrelatorChooserPanel.class);
VTProgramTableCorrelatorModel model =
(VTProgramTableCorrelatorModel) getInstanceField("model", correlatorPanel);
model.setValueAt(true, 1, 0);// Set "Exact Function Bytes Match" to selected.
runSwing(() -> model.setValueAt(true, 6, 0));// Set "Exact Function Bytes Match" to selected
model.fireTableDataChanged();
waitForSwing();
pressNextButtonWhenEnabled();

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -24,16 +24,17 @@ import javax.swing.table.TableModel;
import org.junit.*;
import docking.wizard.WizardManager;
import docking.wizard.WizardPanel;
import docking.wizard.WizardDialog;
import docking.wizard.WizardStep;
import generic.test.TestUtils;
import ghidra.app.services.CodeViewerService;
import ghidra.app.util.AddressInput;
import ghidra.feature.vt.api.db.VTSessionDB;
import ghidra.feature.vt.api.main.VTMatchSet;
import ghidra.feature.vt.gui.plugin.*;
import ghidra.feature.vt.gui.wizard.*;
import ghidra.feature.vt.gui.wizard.ChooseAddressSetEditorPanel.AddressSetChoice;
import ghidra.feature.vt.gui.wizard.add.*;
import ghidra.feature.vt.gui.wizard.add.AddToSessionData.AddressSetChoice;
import ghidra.feature.vt.gui.wizard.session.SummaryPanel;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.database.ProgramDB;
import ghidra.program.model.address.*;
@ -59,8 +60,8 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
private ProgramDB sourceProgram;
private ProgramDB destinationProgram;
private VTSessionDB session;
private VTAddToSessionWizardManager vtWizardManager;
private WizardManager wizardManager;
private VTAddToSessionWizardModel wizardModel;
private WizardDialog wizardDialog;
private AddressSet sourceSelection;
private AddressSet destinationSelection;
@ -125,11 +126,11 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
assertNotNull(controller.getSourceProgram());
assertNotNull(controller.getDestinationProgram());
createWizardManager();
createWizardDialog();
runSwingLater(() -> wizardManager.showWizard(controller.getParentComponent()));
runSwingLater(() -> wizardDialog.show(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
waitForDialogComponent(WizardDialog.class);
checkWizardButtonEnablement(false, false, false, true);
chooseFromCorrelationPanel("Exact Function Instructions Match", VTWizardPanelAction.NEXT);
@ -179,11 +180,11 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
assertNotNull(controller.getSourceProgram());
assertNotNull(controller.getDestinationProgram());
createWizardManager();
createWizardDialog();
runSwingLater(() -> wizardManager.showWizard(controller.getParentComponent()));
runSwingLater(() -> wizardDialog.show(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
waitForDialogComponent(WizardDialog.class);
checkWizardButtonEnablement(false, false, false, true);
chooseFromCorrelationPanel("Exact Function Instructions Match", VTWizardPanelAction.NEXT);
@ -239,11 +240,11 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
assertNotNull(controller.getSourceProgram());
assertNotNull(controller.getDestinationProgram());
createWizardManager();
createWizardDialog();
runSwingLater(() -> wizardManager.showWizard(controller.getParentComponent()));
runSwingLater(() -> wizardDialog.show(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
waitForDialogComponent(WizardDialog.class);
checkWizardButtonEnablement(false, false, false, true);
chooseFromCorrelationPanel("Exact Function Instructions Match", VTWizardPanelAction.NEXT);
@ -299,11 +300,11 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
assertNotNull(controller.getSourceProgram());
assertNotNull(controller.getDestinationProgram());
createWizardManager();
createWizardDialog();
runSwingLater(() -> wizardManager.showWizard(controller.getParentComponent()));
runSwingLater(() -> wizardDialog.show(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
waitForDialogComponent(WizardDialog.class);
checkWizardButtonEnablement(false, false, false, true);
chooseFromCorrelationPanel("Exact Function Instructions Match", VTWizardPanelAction.NEXT);
@ -374,11 +375,11 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
createSelectionInSourceAndDestinationTools();
createWizardManager();
createWizardDialog();
runSwingLater(() -> wizardManager.showWizard(controller.getParentComponent()));
runSwingLater(() -> wizardDialog.show(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
waitForDialogComponent(WizardDialog.class);
checkWizardButtonEnablement(false, false, false, true);
chooseFromCorrelationPanel("Exact Function Instructions Match", VTWizardPanelAction.NEXT);
@ -436,11 +437,11 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
createSelectionInSourceAndDestinationTools();
createWizardManager();
createWizardDialog();
runSwingLater(() -> wizardManager.showWizard(controller.getParentComponent()));
runSwingLater(() -> wizardDialog.show(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
waitForDialogComponent(WizardDialog.class);
checkWizardButtonEnablement(false, false, false, true);
chooseFromCorrelationPanel("Exact Function Instructions Match", VTWizardPanelAction.NEXT);
@ -498,11 +499,11 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
createSelectionInSourceAndDestinationTools();
createWizardManager();
createWizardDialog();
runSwingLater(() -> wizardManager.showWizard(controller.getParentComponent()));
runSwingLater(() -> wizardDialog.show(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
waitForDialogComponent(WizardDialog.class);
checkWizardButtonEnablement(false, false, false, true);
chooseFromCorrelationPanel("Exact Function Instructions Match", VTWizardPanelAction.NEXT);
@ -573,11 +574,11 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
createSelectionInSourceAndDestinationTools();
createWizardManager();
createWizardDialog();
runSwingLater(() -> wizardManager.showWizard(controller.getParentComponent()));
runSwingLater(() -> wizardDialog.show(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
waitForDialogComponent(WizardDialog.class);
checkWizardButtonEnablement(false, false, false, true);
chooseFromCorrelationPanel("Exact Function Instructions Match", VTWizardPanelAction.NEXT);
@ -673,11 +674,11 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
assertNotNull(controller.getSourceProgram());
assertNotNull(controller.getDestinationProgram());
createWizardManager();
createWizardDialog();
runSwingLater(() -> wizardManager.showWizard(controller.getParentComponent()));
runSwingLater(() -> wizardDialog.show(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
waitForDialogComponent(WizardDialog.class);
checkWizardButtonEnablement(false, false, false, true);
chooseFromCorrelationPanel("Data Reference Match", VTWizardPanelAction.NEXT);
@ -730,10 +731,10 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
private void chooseFromCorrelationPanel(String correlatorName,
VTWizardPanelAction wizardAction) {
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof CorrelatorPanel);
CorrelatorPanel correlatorPanel = (CorrelatorPanel) currentWizardPanel;
WizardStep<?> currentStep = wizardDialog.getCurrentStep();
assertNotNull(currentStep);
CorrelatorChooserPanel correlatorPanel =
(CorrelatorChooserPanel) currentStep.getComponent();
SystemUtilities.runSwingNow(() -> {
GhidraTable table = (GhidraTable) TestUtils.getInstanceField("table", correlatorPanel);
TableModel model = table.getModel();
@ -750,59 +751,28 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
VTWizardPanelAction wizardAction) {
// Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof OptionsPanel);
// Nothing else to check in this panel for now.
// TODO Use an OptionsObject or something to pass in correlator options and set them in the panel.
// // get out the correlator options
// AddressCorrelatorManager correlator = controller.getCorrelator();
// assertNotNull("The controller did not find any correlators", correlator);
//
// // set some options settings
// Options options = correlator.getOptions(LCSAddressCorrelator.class);
// String testDefaultValue = "Test Default Value";
// String testOptionKey = "Test Option Name";
// String value = options.getString(testOptionKey, testDefaultValue);
// assertEquals(value, testDefaultValue);
//
// String firstNewOptionValue = "New Option Value";
// options.putString(testOptionKey, firstNewOptionValue);
// assertEquals(firstNewOptionValue, options.getString(testOptionKey, null));
// correlator.setOptions(LCSAddressCorrelator.class, options);
// // save the options
// SaveState saveState = new SaveState();
// controller.writeConfigState(saveState);
//
// // change the options
// String secondNewValue = "Second New Value";
// options.putString(testOptionKey, secondNewValue);
// correlator.setOptions(LCSAddressCorrelator.class, options);
//
// // pull the values again and make sure they are still correct (that writing the config
// // state did not change the cached controller and options)
// correlator = controller.getCorrelator();
// options = correlator.getOptions(LCSAddressCorrelator.class);
// assertEquals(secondNewValue, options.getString(testOptionKey, null));
WizardStep<?> currentStep = wizardDialog.getCurrentStep();
JComponent component = currentStep.getComponent();
assertTrue(component instanceof OptionsPanel);
OptionsPanel optionsPanel = (OptionsPanel) component;
assertNotNull(optionsPanel);
SystemUtilities.runSwingNow(() -> invoke(wizardAction));
}
private void checkAddressSetOptionsPanel(boolean excludeAccepted, boolean limitAddressSets) {
// Address Set Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof AddressSetOptionsPanel);
AddressSetOptionsPanel addressSetOptionsPanel = (AddressSetOptionsPanel) currentWizardPanel;
WizardStep<?> currentStep = wizardDialog.getCurrentStep();
JComponent component = currentStep.getComponent();
assertTrue(component instanceof AddressSetOptionsPanel);
AddressSetOptionsPanel addressSetOptionsPanel = (AddressSetOptionsPanel) component;
JCheckBox excludeCheckbox =
(JCheckBox) TestUtils.getInstanceField("excludeCheckbox", addressSetOptionsPanel);
assertNotNull(excludeCheckbox);
JCheckBox showAddressSetPanelsCheckbox = (JCheckBox) TestUtils
.getInstanceField("showAddressSetPanelsCheckbox", addressSetOptionsPanel);
.getInstanceField("limitAddressSetsCheckbox", addressSetOptionsPanel);
assertNotNull(showAddressSetPanelsCheckbox);
assertEquals("Exclude Accepted Matches checkbox", excludeAccepted,
@ -815,17 +785,17 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
VTWizardPanelAction wizardAction) {
// Address Set Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof AddressSetOptionsPanel);
AddressSetOptionsPanel addressSetOptionsPanel = (AddressSetOptionsPanel) currentWizardPanel;
WizardStep<?> currentStep = wizardDialog.getCurrentStep();
JComponent component = currentStep.getComponent();
assertTrue(component instanceof AddressSetOptionsPanel);
AddressSetOptionsPanel addressSetOptionsPanel = (AddressSetOptionsPanel) component;
JCheckBox excludeCheckbox =
(JCheckBox) TestUtils.getInstanceField("excludeCheckbox", addressSetOptionsPanel);
assertNotNull(excludeCheckbox);
JCheckBox showAddressSetPanelsCheckbox = (JCheckBox) TestUtils
.getInstanceField("showAddressSetPanelsCheckbox", addressSetOptionsPanel);
.getInstanceField("limitAddressSetsCheckbox", addressSetOptionsPanel);
assertNotNull(showAddressSetPanelsCheckbox);
if (excludeCheckbox.isSelected() != excludeAccepted) {
@ -843,17 +813,18 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
AddressSetChoice destinationChoice) {
// Address Set Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof LimitAddressSetsPanel);
LimitAddressSetsPanel limitAddressSetsPanel = (LimitAddressSetsPanel) currentWizardPanel;
WizardStep<?> currentStep = wizardDialog.getCurrentStep();
JComponent component = currentStep.getComponent();
assertTrue(component instanceof LimitAddressSetsPanel);
LimitAddressSetsPanel limitAddressSetsPanel = (LimitAddressSetsPanel) component;
ChooseAddressSetEditorPanel sourcePanel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("sourcePanel",
limitAddressSetsPanel);
ChooseAddressSetEditorPanel destinationPanel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("destinationPanel",
limitAddressSetsPanel);
AddressSetPanel sourcePanel =
(AddressSetPanel) TestUtils.getInstanceField("sourcePanel", limitAddressSetsPanel);
assertNotNull(sourcePanel);
AddressSetPanel destinationPanel =
(AddressSetPanel) TestUtils.getInstanceField("destinationPanel", limitAddressSetsPanel);
assertNotNull(destinationPanel);
changeAddressChoice(sourcePanel, sourceChoice);
@ -864,31 +835,25 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
AddressSetView desiredDestinationSet) {
// Address Set Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof LimitAddressSetsPanel);
LimitAddressSetsPanel limitAddressSetsPanel = (LimitAddressSetsPanel) currentWizardPanel;
WizardStep<?> currentStep = wizardDialog.getCurrentStep();
JComponent component = currentStep.getComponent();
assertTrue(component instanceof LimitAddressSetsPanel);
LimitAddressSetsPanel limitAddressSetsPanel = (LimitAddressSetsPanel) component;
ChooseAddressSetEditorPanel sourcePanel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("sourcePanel",
limitAddressSetsPanel);
ChooseAddressSetEditorPanel destinationPanel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("destinationPanel",
limitAddressSetsPanel);
AddressSetPanel sourcePanel =
(AddressSetPanel) TestUtils.getInstanceField("sourcePanel", limitAddressSetsPanel);
assertNotNull(sourcePanel);
AddressSetPanel destinationPanel =
(AddressSetPanel) TestUtils.getInstanceField("destinationPanel", limitAddressSetsPanel);
assertNotNull(destinationPanel);
ChooseAddressSetEditorPanel sourceSetPanel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("panel", sourcePanel);
assertNotNull(sourceSetPanel);
ChooseAddressSetEditorPanel destinationSetPanel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("panel", destinationPanel);
assertNotNull(destinationSetPanel);
AddressSetView panelSourceSet =
(AddressSetView) TestUtils.invokeInstanceMethod("getAddressSetView", sourceSetPanel);
(AddressSetView) TestUtils.invokeInstanceMethod("getAddressSetView", sourcePanel);
AddressSetView panelDestinationSet = (AddressSetView) TestUtils
.invokeInstanceMethod("getAddressSetView", destinationSetPanel);
.invokeInstanceMethod("getAddressSetView", destinationPanel);
assertEquals("Source Address Set", desiredSourceSet, panelSourceSet);
assertEquals("Destination Address Set", desiredDestinationSet, panelDestinationSet);
}
@ -897,17 +862,19 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
AddressSetView desiredDestinationSet) {
// Address Set Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof LimitAddressSetsPanel);
LimitAddressSetsPanel limitAddressSetsPanel = (LimitAddressSetsPanel) currentWizardPanel;
WizardStep<?> currentStep = wizardDialog.getCurrentStep();
JComponent component = currentStep.getComponent();
assertTrue(component instanceof LimitAddressSetsPanel);
LimitAddressSetsPanel limitAddressSetsPanel = (LimitAddressSetsPanel) component;
ChooseAddressSetEditorPanel sourcePanel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("sourcePanel",
limitAddressSetsPanel);
ChooseAddressSetEditorPanel destinationPanel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("destinationPanel",
limitAddressSetsPanel);
AddressSetPanel sourcePanel =
(AddressSetPanel) TestUtils.getInstanceField("sourcePanel", limitAddressSetsPanel);
assertNotNull(sourcePanel);
AddressSetPanel destinationPanel =
(AddressSetPanel) TestUtils.getInstanceField("destinationPanel", limitAddressSetsPanel);
assertNotNull(destinationPanel);
changeAddressSetViaListRemoveRange(true, sourcePanel, desiredSourceSet);
@ -918,37 +885,35 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
AddressSetChoice destinationChoice) {
// Address Set Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof LimitAddressSetsPanel);
LimitAddressSetsPanel limitAddressSetsPanel = (LimitAddressSetsPanel) currentWizardPanel;
WizardStep<?> currentStep = wizardDialog.getCurrentStep();
JComponent component = currentStep.getComponent();
assertTrue(component instanceof LimitAddressSetsPanel);
LimitAddressSetsPanel limitAddressSetsPanel = (LimitAddressSetsPanel) component;
AddressSetPanel sourcePanel =
(AddressSetPanel) TestUtils.getInstanceField("sourcePanel", limitAddressSetsPanel);
ChooseAddressSetEditorPanel sourcePanel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("sourcePanel",
limitAddressSetsPanel);
assertNotNull(sourcePanel);
AddressSetPanel destinationPanel =
(AddressSetPanel) TestUtils.getInstanceField("destinationPanel", limitAddressSetsPanel);
ChooseAddressSetEditorPanel destinationPanel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("destinationPanel",
limitAddressSetsPanel);
assertNotNull(destinationPanel);
checkAddressChoice(sourcePanel, sourceChoice);
checkAddressChoice(destinationPanel, destinationChoice);
}
private void checkAddressChoice(AddressSetPanel addressSetPanel,
private void checkAddressChoice(ChooseAddressSetEditorPanel panel,
AddressSetChoice expectedChoice) {
ChooseAddressSetEditorPanel panel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("panel", addressSetPanel);
assertNotNull(panel);
AddressSetChoice addressSetChoice = panel.getAddressSetChoice();
assertEquals(addressSetPanel.getName() + " Panel address set choice", expectedChoice,
assertEquals(panel.getName() + " Panel address set choice", expectedChoice,
addressSetChoice);
}
private void changeAddressChoice(AddressSetPanel addressSetPanel,
private void changeAddressChoice(ChooseAddressSetEditorPanel panel,
AddressSetChoice expectedChoice) {
ChooseAddressSetEditorPanel panel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("panel", addressSetPanel);
assertNotNull(panel);
AddressSetChoice addressSetChoice = panel.getAddressSetChoice();
if (expectedChoice != addressSetChoice) {
@ -976,9 +941,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
}
private void changeAddressSetViaListRemoveRange(boolean isSource,
AddressSetPanel addressSetPanel, AddressSetView desiredAddressSet) {
ChooseAddressSetEditorPanel panel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("panel", addressSetPanel);
ChooseAddressSetEditorPanel panel, AddressSetView desiredAddressSet) {
assertNotNull(panel);
JButton addRangeButton = (JButton) TestUtils.getInstanceField("addRangeButton", panel);
@ -1006,9 +969,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
}
private void changeAddressSetViaSubtractDialog(boolean isSource,
AddressSetPanel addressSetPanel, AddressSetView desiredAddressSet) {
ChooseAddressSetEditorPanel panel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("panel", addressSetPanel);
ChooseAddressSetEditorPanel panel, AddressSetView desiredAddressSet) {
assertNotNull(panel);
JButton addRangeButton = (JButton) TestUtils.getInstanceField("addRangeButton", panel);
@ -1128,11 +1089,11 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
VTWizardPanelAction wizardAction) {
// Address Set Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof SummaryPanel);
SummaryPanel summaryPanel = (SummaryPanel) currentWizardPanel;
WizardStep<?> currentStep = wizardDialog.getCurrentStep();
assertNotNull(currentStep);
JComponent component = currentStep.getComponent();
assertTrue(component instanceof SummaryPanel);
SummaryPanel summaryPanel = (SummaryPanel) component;
JLabel labelLabel = (JLabel) TestUtils.getInstanceField("labelLabel", summaryPanel);
assertNotNull(labelLabel);
@ -1180,7 +1141,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
private void checkWizardButtonEnablement(boolean backEnabled, boolean nextEnabled,
boolean finishEnabled, boolean cancelEnabled) {
JComponent component = wizardManager.getComponent();
JComponent component = wizardDialog.getComponent();
JButton backButton = findButtonByText(component, "<< Back");
JButton nextButton = findButtonByText(component, "Next >>");
JButton finishButton = findButtonByText(component, "Finish");
@ -1198,16 +1159,16 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
public void invoke(VTWizardPanelAction wizardAction) {
switch (wizardAction) {
case BACK:
wizardManager.back();
wizardModel.goBack();
break;
case NEXT:
wizardManager.next();
wizardModel.goNext();
break;
case FINISH:
wizardManager.finish();
wizardModel.finish();
break;
case CANCEL:
wizardManager.close();
wizardDialog.close();
break;
}
}
@ -1228,10 +1189,10 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
return destinationProgram.getAddressFactory().getAddress(addressString);
}
private void createWizardManager() {
private void createWizardDialog() {
runSwing(() -> {
vtWizardManager = new VTAddToSessionWizardManager(controller);
wizardManager = new WizardManager("Version Tracking Wizard", true, vtWizardManager);
wizardModel = new VTAddToSessionWizardModel(controller);
wizardDialog = new WizardDialog(wizardModel);
});
}
}

View file

@ -5,9 +5,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,8 +30,8 @@ import org.junit.After;
import org.junit.Before;
import docking.options.editor.OptionsEditorPanel;
import docking.wizard.WizardManager;
import docking.wizard.WizardPanel;
import docking.wizard.WizardDialog;
import docking.wizard.WizardStep;
import generic.lsh.LSHMemoryModel;
import generic.test.TestUtils;
import ghidra.feature.vt.api.correlator.program.VTAbstractReferenceProgramCorrelatorFactory;
@ -42,7 +42,8 @@ import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.feature.vt.gui.plugin.VTPlugin;
import ghidra.feature.vt.gui.task.AcceptMatchTask;
import ghidra.feature.vt.gui.task.ApplyMatchTask;
import ghidra.feature.vt.gui.wizard.*;
import ghidra.feature.vt.gui.wizard.add.*;
import ghidra.feature.vt.gui.wizard.session.SummaryPanel;
import ghidra.framework.options.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
@ -70,8 +71,8 @@ public abstract class AbstractVTCorrelatorTest extends AbstractGhidraHeadedInteg
protected Program destProg;
protected VTController controller;
protected VTPlugin plugin;
protected VTAddToSessionWizardManager vtWizardManager;
protected WizardManager wizardManager;
protected VTAddToSessionWizardModel wizardModel;
protected WizardDialog wizardDialog;
public AbstractVTCorrelatorTest(String sourceProgLoc, String destProgLoc) {
this.sourceProgLoc = sourceProgLoc;
@ -105,17 +106,17 @@ public abstract class AbstractVTCorrelatorTest extends AbstractGhidraHeadedInteg
private void setupWizardBeforeCorrelatorOptions(String correlatorName) {
runSwing(() -> {
vtWizardManager = new VTAddToSessionWizardManager(controller);
wizardManager = new WizardManager("Version Tracking Wizard", true, vtWizardManager);
wizardManager.showWizard(controller.getParentComponent());
wizardModel = new VTAddToSessionWizardModel(controller);
wizardDialog = new WizardDialog(wizardModel);
wizardDialog.show(controller.getParentComponent());
}, false);
waitForSwing();
waitForDialogComponent(WizardManager.class);
assertNotNull(wizardManager);
waitForDialogComponent(WizardDialog.class);
assertNotNull(wizardDialog);
checkWizardButtonEnablement(false, false, false, true);
chooseFromCorrelationPanel(correlatorName, wizardManager::next);
chooseFromCorrelationPanel(correlatorName, wizardModel::goNext);
checkWizardButtonEnablement(true, true, true, true);
}
@ -123,7 +124,7 @@ public abstract class AbstractVTCorrelatorTest extends AbstractGhidraHeadedInteg
private void finishWizardAfterCorrelatorOptions(String correlatorName) {
checkAddressSetOptionsPanel(false, false);
checkWizardButtonEnablement(true, true, true, true);
changeAddressSetOptionsPanel(false, false, wizardManager::next);
changeAddressSetOptionsPanel(false, false, wizardModel::goNext);
// Check the summary panel.
checkWizardButtonEnablement(true, false, true, true);
@ -137,7 +138,7 @@ public abstract class AbstractVTCorrelatorTest extends AbstractGhidraHeadedInteg
String summaryString = "Add to Version Tracking Session<br>" + session.getName() + "<br>" +
srcProg.getName() + "<br>" + destProg.getName() + "<br>" + correlatorName + "<br>" +
"No<br>" + "Entire Source Program<br>" + "Entire Destination Program<br>" + "</html>";
checkSummaryPanel(labelString, summaryString, wizardManager::finish);
checkSummaryPanel(labelString, summaryString, wizardModel::finish);
}
public void runTestCorrelator(String correlatorName) {
@ -154,7 +155,7 @@ public abstract class AbstractVTCorrelatorTest extends AbstractGhidraHeadedInteg
long start = System.nanoTime();
setupWizardBeforeCorrelatorOptions(correlatorName);
useDefaultCorrelatorOptions(correlatorName, wizardManager::next);
useDefaultCorrelatorOptions(correlatorName, wizardModel::goNext);
finishWizardAfterCorrelatorOptions(correlatorName);
@ -179,7 +180,7 @@ public abstract class AbstractVTCorrelatorTest extends AbstractGhidraHeadedInteg
setupWizardBeforeCorrelatorOptions(correlatorName);
changeReferenceCorrelatorOptions(correlatorName, confidence, memoryModel, score,
refineResults, wizardManager::next);
refineResults, wizardModel::goNext);
finishWizardAfterCorrelatorOptions(correlatorName);
}
@ -385,7 +386,7 @@ public abstract class AbstractVTCorrelatorTest extends AbstractGhidraHeadedInteg
protected void checkWizardButtonEnablement(boolean backEnabled, boolean nextEnabled,
boolean finishEnabled, boolean cancelEnabled) {
JComponent component = wizardManager.getComponent();
JComponent component = wizardDialog.getComponent();
JButton backButton = findButtonByText(component, "<< Back");
JButton nextButton = findButtonByText(component, "Next >>");
JButton finishButton = findButtonByText(component, "Finish");
@ -402,10 +403,10 @@ public abstract class AbstractVTCorrelatorTest extends AbstractGhidraHeadedInteg
protected void chooseFromCorrelationPanel(final String correlatorName, Runnable wizardAction) {
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof CorrelatorPanel);
CorrelatorPanel correlatorPanel = (CorrelatorPanel) currentWizardPanel;
WizardStep<?> currentWizardStep = wizardModel.getCurrentStep();
JComponent component = currentWizardStep.getComponent();
assertTrue(component instanceof CorrelatorChooserPanel);
CorrelatorChooserPanel correlatorPanel = (CorrelatorChooserPanel) component;
runSwing(() -> {
GhidraTable table = (GhidraTable) TestUtils.getInstanceField("table", correlatorPanel);
TableModel model = table.getModel();
@ -422,9 +423,9 @@ public abstract class AbstractVTCorrelatorTest extends AbstractGhidraHeadedInteg
Runnable wizardAction) {
// Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof OptionsPanel);
WizardStep<?> currentWizardStep = wizardModel.getCurrentStep();
JComponent component = currentWizardStep.getComponent();
assertTrue(component instanceof ghidra.feature.vt.gui.wizard.add.OptionsPanel);
runSwing(wizardAction);
}
@ -496,10 +497,10 @@ public abstract class AbstractVTCorrelatorTest extends AbstractGhidraHeadedInteg
private OptionsEditorPanel getCorrelatorOptionsPanel(String correlatorName) {
String desiredTitle = correlatorName + " Options";
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof OptionsPanel);
OptionsPanel optionsPanel = (OptionsPanel) currentWizardPanel;
WizardStep<?> currentStep = wizardModel.getCurrentStep();
JComponent component = currentStep.getComponent();
assertTrue(component instanceof OptionsPanel);
OptionsPanel optionsPanel = (OptionsPanel) component;
Object instanceField = TestUtils.getInstanceField("optionsEditorPanelList", optionsPanel);
@SuppressWarnings("unchecked")
List<OptionsEditorPanel> optionsEditorPanelList = (List<OptionsEditorPanel>) instanceField;
@ -523,17 +524,17 @@ public abstract class AbstractVTCorrelatorTest extends AbstractGhidraHeadedInteg
protected void checkAddressSetOptionsPanel(boolean excludeAccepted, boolean limitAddressSets) {
// Address Set Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof AddressSetOptionsPanel);
AddressSetOptionsPanel addressSetOptionsPanel = (AddressSetOptionsPanel) currentWizardPanel;
WizardStep<?> currentStep = wizardModel.getCurrentStep();
JComponent component = currentStep.getComponent();
assertTrue(component instanceof AddressSetOptionsPanel);
AddressSetOptionsPanel addressSetOptionsPanel = (AddressSetOptionsPanel) component;
JCheckBox excludeCheckbox =
(JCheckBox) TestUtils.getInstanceField("excludeCheckbox", addressSetOptionsPanel);
assertNotNull(excludeCheckbox);
JCheckBox showAddressSetPanelsCheckbox = (JCheckBox) TestUtils
.getInstanceField("showAddressSetPanelsCheckbox", addressSetOptionsPanel);
.getInstanceField("limitAddressSetsCheckbox", addressSetOptionsPanel);
assertNotNull(showAddressSetPanelsCheckbox);
assertEquals("Exclude Accepted Matches checkbox", excludeAccepted,
@ -546,17 +547,17 @@ public abstract class AbstractVTCorrelatorTest extends AbstractGhidraHeadedInteg
Runnable wizardAction) {
// Address Set Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof AddressSetOptionsPanel);
AddressSetOptionsPanel addressSetOptionsPanel = (AddressSetOptionsPanel) currentWizardPanel;
WizardStep<?> currentStep = wizardModel.getCurrentStep();
JComponent component = currentStep.getComponent();
assertTrue(component instanceof AddressSetOptionsPanel);
AddressSetOptionsPanel addressSetOptionsPanel = (AddressSetOptionsPanel) component;
JCheckBox excludeCheckbox =
(JCheckBox) TestUtils.getInstanceField("excludeCheckbox", addressSetOptionsPanel);
assertNotNull(excludeCheckbox);
JCheckBox showAddressSetPanelsCheckbox = (JCheckBox) TestUtils
.getInstanceField("showAddressSetPanelsCheckbox", addressSetOptionsPanel);
.getInstanceField("limitAddressSetsCheckbox", addressSetOptionsPanel);
assertNotNull(showAddressSetPanelsCheckbox);
if (excludeCheckbox.isSelected() != excludeAccepted) {
@ -594,10 +595,10 @@ public abstract class AbstractVTCorrelatorTest extends AbstractGhidraHeadedInteg
Runnable wizardAction) {
// Address Set Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof SummaryPanel);
SummaryPanel summaryPanel = (SummaryPanel) currentWizardPanel;
WizardStep<?> currentStep = wizardModel.getCurrentStep();
JComponent component = currentStep.getComponent();
assertTrue(component instanceof SummaryPanel);
SummaryPanel summaryPanel = (SummaryPanel) component;
JLabel labelLabel = (JLabel) TestUtils.getInstanceField("labelLabel", summaryPanel);
assertNotNull(labelLabel);