GP-4151 fixing wizard pattern to better handle expensive checks between panels.
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 59 KiB |
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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)
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|