/*
*
* Paros and its related class files.
*
* Paros is an HTTP/HTTPS proxy for assessing web application security.
* Copyright (C) 2003-2004 Chinotec Technologies Company
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the Clarified Artistic License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Clarified Artistic License for more details.
*
* You should have received a copy of the Clarified Artistic License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// ZAP: 2013/03/03 Issue 546: Remove all template Javadoc comments
// ZAP: 2013/11/28 Issue 923: Allow individual rule thresholds and strengths to be set via GUI
// ZAP: 2016/01/19 Allow to obtain the ScanPolicy
// ZAP: 2016/04/04 Use StatusUI in scanners' dialogues
// ZAP: 2016/07/25 Use new AllCategoryTableModel's constructor
package org.zaproxy.zap.extension.ascan;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.List;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.table.TableColumn;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.core.scanner.Plugin;
import org.parosproxy.paros.core.scanner.Plugin.AlertThreshold;
import org.parosproxy.paros.core.scanner.Plugin.AttackStrength;
import org.parosproxy.paros.view.AbstractParamPanel;
import org.parosproxy.paros.view.View;
import org.zaproxy.zap.control.AddOn;
import org.zaproxy.zap.utils.DisplayUtils;
import org.zaproxy.zap.utils.ZapTextField;
import org.zaproxy.zap.view.LayoutHelper;
public class PolicyAllCategoryPanel extends AbstractParamPanel {
//private static final String ILLEGAL_CHRS = "/`?*\\<>|\":\t\n\r";
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(PolicyAllCategoryPanel.class);
private ZapTextField policyName = null;
private JTable tableTest = null;
private JScrollPane jScrollPane = null;
private AllCategoryTableModel allCategoryTableModel = null;
private JComboBox<String> policySelector = null;
private JComboBox<String> comboThreshold = null;
private JLabel labelThresholdNotes = null;
private JComboBox<String> comboStrength = null;
private JLabel labelStrengthNotes = null;
private JComboBox<String> applyToThreshold = null;
private JComboBox<String> applyToStrength = null;
private JComboBox<String> applyToThresholdTarget = null;
private JComboBox<String> applyToStrengthTarget = null;
private ExtensionActiveScan extension;
private ScanPolicy policy;
private String currentName;
private boolean switchable = false;
private static final int[] width = {300, 100, 100};
public PolicyAllCategoryPanel(Window parent, ExtensionActiveScan extension, ScanPolicy policy) {
this(parent, extension, policy, false);
}
public PolicyAllCategoryPanel(Window parent, ExtensionActiveScan extension, ScanPolicy policy, boolean switchable) {
super();
this.extension = extension;
this.policy = policy;
this.currentName = policy.getName();
this.switchable = switchable;
initialize();
}
/**
* This method initializes this
*/
private void initialize() {
this.setLayout(new GridBagLayout());
this.setSize(375, 205);
this.setName("categoryPanel");
// Add Attack settings section - a copy of the options dialog
// ---------------------------------------------
int row = 0;
this.add(new JLabel(Constant.messages.getString("ascan.policy.name.label")),
LayoutHelper.getGBC(0, row, 1, 0.0D, 0, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2)));
if (this.switchable) {
this.add(getPolicySelector(),
LayoutHelper.getGBC(1, row, 2, 1.0D, 0, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2)));
} else {
this.add(getPolicyName(),
LayoutHelper.getGBC(1, row, 2, 1.0D, 0, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2)));
}
row++;
this.add(new JLabel(Constant.messages.getString("ascan.options.level.label")),
LayoutHelper.getGBC(0, row, 1, 0.0D, 0, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2)));
this.add(getComboThreshold(),
LayoutHelper.getGBC(1, row, 1, 0.0D, 0, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2)));
this.add(getThresholdNotes(),
LayoutHelper.getGBC(2, row, 1, 1.0D, 0, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2)));
row++;
this.add(new JLabel(Constant.messages.getString("ascan.options.strength.label")),
LayoutHelper.getGBC(0, row, 1, 0.0D, 0, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2)));
this.add(getComboStrength(),
LayoutHelper.getGBC(1, row, 1, 0.0D, 0, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2)));
this.add(getStrengthNotes(),
LayoutHelper.getGBC(2, row, 1, 1.0D, 0, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2)));
// 'Apply to' controls
JPanel applyToPanel = new JPanel();
applyToPanel.setLayout(new GridBagLayout());
applyToPanel.add(new JLabel(Constant.messages.getString("ascan.options.apply.label")),
LayoutHelper.getGBC(0, 0, 1, 0.0, new Insets(2, 2, 2, 2)));
applyToPanel.add(getApplyToThreshold(), LayoutHelper.getGBC(1, 0, 1, 0.0));
applyToPanel.add(new JLabel(Constant.messages.getString("ascan.options.thresholdTo.label")),
LayoutHelper.getGBC(2, 0, 1, 0.0, new Insets(2, 2, 2, 2)));
applyToPanel.add(getApplyToThresholdTarget(), LayoutHelper.getGBC(3, 0, 1, 0.0));
applyToPanel.add(new JLabel(Constant.messages.getString("ascan.options.rules.label")), LayoutHelper.getGBC(4, 0, 1, 0.0, new Insets(2, 2, 2, 2)));
JButton applyThresholdButton = new JButton(Constant.messages.getString("ascan.options.go.button"));
applyThresholdButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
applyThreshold (strToThreshold((String)getApplyToThreshold().getSelectedItem()),
(String)getApplyToThresholdTarget().getSelectedItem());
getAllCategoryTableModel().fireTableDataChanged();
}});
applyToPanel.add(applyThresholdButton, LayoutHelper.getGBC(5, 0, 1, 0.0));
applyToPanel.add(new JLabel(""), LayoutHelper.getGBC(6, 0, 1, 1.0)); // Spacer
applyToPanel.add(new JLabel(Constant.messages.getString("ascan.options.apply.label")),
LayoutHelper.getGBC(0, 1, 1, 0.0, new Insets(2, 2, 2, 2)));
applyToPanel.add(getApplyToStrength(), LayoutHelper.getGBC(1, 1, 1, 0.0));
applyToPanel.add(new JLabel(Constant.messages.getString("ascan.options.strengthTo.label")), LayoutHelper.getGBC(2, 1, 1, 0.0, new Insets(2, 2, 2, 2)));
applyToPanel.add(getApplyToStrengthTarget(), LayoutHelper.getGBC(3, 1, 1, 0.0));
applyToPanel.add(new JLabel(Constant.messages.getString("ascan.options.rules.label")), LayoutHelper.getGBC(4, 1, 1, 0.0, new Insets(2, 2, 2, 2)));
JButton applyStrengthButton = new JButton(Constant.messages.getString("ascan.options.go.button"));
applyStrengthButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
applyStrength (strToStrength((String)getApplyToStrength().getSelectedItem()),
(String)getApplyToStrengthTarget().getSelectedItem());
getAllCategoryTableModel().fireTableDataChanged();
}});
applyToPanel.add(applyStrengthButton, LayoutHelper.getGBC(5, 1, 1, 0.0));
applyToPanel.add(new JLabel(""), LayoutHelper.getGBC(6, 1, 1, 1.0)); // Spacer
row++;
this.add(applyToPanel,
LayoutHelper.getGBC(0, row, 3, 0.0D, 0.0D, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0)));
// Add the scrolling list of active plugin categories
row++;
this.add(getJScrollPane(),
LayoutHelper.getGBC(0, row, 3, 1.0D, 1.0D, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0)));
this.setThreshold(policy.getDefaultThreshold());
this.setStrength(policy.getDefaultStrength());
}
public void initialise(ScanPolicy policy) {
this.getPolicyName().setText(policy.getName());
}
private ZapTextField getPolicyName() {
if (policyName == null) {
policyName = new ZapTextField();
policyName.setText(policy.getName());
}
return policyName;
}
private JComboBox<String> getPolicySelector() {
if (policySelector == null) {
policySelector = new JComboBox<>();
for (String policy : extension.getPolicyManager().getAllPolicyNames()) {
policySelector.addItem(policy);
}
policySelector.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
String policyName = (String) policySelector.getSelectedItem();
if (policyName == null) {
return;
}
ScanPolicy policy;
try {
policy = extension.getPolicyManager().getPolicy(policyName);
if (policy != null) {
setScanPolicy(policy);
fireScanPolicyChanged(policy);
}
} catch (ConfigurationException e1) {
logger.error(e1.getMessage(), e1);
}
}});
}
return policySelector;
}
/**
* Reloads the scan policies, which will pick any new ones that have been defined and selects the policy with the given
* name.
*
* @param scanPolicyName the name of the policy that should be selected
* @since 2.5.0
*/
public void reloadPolicies(String scanPolicyName) {
DefaultComboBoxModel<String> policies = new DefaultComboBoxModel<>();
for (String policy : extension.getPolicyManager().getAllPolicyNames()) {
policies.addElement(policy);
}
getPolicySelector().setModel(policies);
getPolicySelector().setSelectedItem(scanPolicyName);
}
/**
* Reloads the scan policies, which will pick any new ones that have been defined
*/
public void reloadPolicies() {
// Ensure policySelector is initialized
Object selected = getPolicySelector().getSelectedItem();
reloadPolicies((String) selected);
}
private AlertThreshold strToThreshold(String str) {
if (str.equals(Constant.messages.getString("ascan.options.level.off"))) {
return AlertThreshold.OFF;
}
if (str.equals(Constant.messages.getString("ascan.options.level.low"))) {
return AlertThreshold.LOW;
}
if (str.equals(Constant.messages.getString("ascan.options.level.medium"))) {
return AlertThreshold.MEDIUM;
}
if (str.equals(Constant.messages.getString("ascan.options.level.high"))) {
return AlertThreshold.HIGH;
}
return AlertThreshold.DEFAULT;
}
private JComboBox<String> getApplyToThreshold() {
if (applyToThreshold == null) {
applyToThreshold = new JComboBox<>();
applyToThreshold.addItem(Constant.messages.getString("ascan.options.level.default"));
applyToThreshold.addItem(Constant.messages.getString("ascan.options.level.off"));
applyToThreshold.addItem(Constant.messages.getString("ascan.options.level.low"));
applyToThreshold.addItem(Constant.messages.getString("ascan.options.level.medium"));
applyToThreshold.addItem(Constant.messages.getString("ascan.options.level.high"));
}
return applyToThreshold;
}
private JComboBox<String> getApplyToThresholdTarget() {
if (applyToThresholdTarget == null) {
applyToThresholdTarget = createStatusComboBox();
}
return applyToThresholdTarget;
}
/**
* Creates a {@code JComboBox} with scanners' statuses, "all", release, beta and alpha.
*
* @return a {@code JComboBox} with scanners' statuses
*/
private JComboBox<String> createStatusComboBox() {
JComboBox<String> comboBox = new JComboBox<>();
comboBox.addItem(Constant.messages.getString("ascan.policy.table.quality.all"));
View view = View.getSingleton();
comboBox.addItem(view.getStatusUI(AddOn.Status.release).toString());
comboBox.addItem(view.getStatusUI(AddOn.Status.beta).toString());
comboBox.addItem(view.getStatusUI(AddOn.Status.alpha).toString());
return comboBox;
}
private void applyThreshold(AlertThreshold threshold, String target) {
for (Plugin plugin : policy.getPluginFactory().getAllPlugin()) {
if (hasSameStatus(plugin, target)) {
plugin.setAlertThreshold(threshold);
}
}
}
/**
* Tells whether or not the given {@code scanner} has the given {@code status}.
* <p>
* If the given {@code status} represents all statuses it returns always {@code true}.
*
* @param scanner the scanner that will be checked
* @param status the status to check
* @return {@code true} if it has the same status, {@code false} otherwise.
* @see Plugin#getStatus()
*/
private boolean hasSameStatus(Plugin scanner, String status) {
if (status.equals(Constant.messages.getString("ascan.policy.table.quality.all"))) {
return true;
}
return status.equals(View.getSingleton().getStatusUI(scanner.getStatus()).toString());
}
private AttackStrength strToStrength(String str) {
if (str.equals(Constant.messages.getString("ascan.options.strength.low"))) {
return AttackStrength.LOW;
}
if (str.equals(Constant.messages.getString("ascan.options.strength.medium"))) {
return AttackStrength.MEDIUM;
}
if (str.equals(Constant.messages.getString("ascan.options.strength.high"))) {
return AttackStrength.HIGH;
}
if (str.equals(Constant.messages.getString("ascan.options.strength.insane"))) {
return AttackStrength.INSANE;
}
return AttackStrength.DEFAULT;
}
private JComboBox<String> getApplyToStrength() {
if (applyToStrength == null) {
applyToStrength = new JComboBox<>();
applyToStrength.addItem(Constant.messages.getString("ascan.options.strength.default"));
applyToStrength.addItem(Constant.messages.getString("ascan.options.strength.low"));
applyToStrength.addItem(Constant.messages.getString("ascan.options.strength.medium"));
applyToStrength.addItem(Constant.messages.getString("ascan.options.strength.high"));
applyToStrength.addItem(Constant.messages.getString("ascan.options.strength.insane"));
}
return applyToStrength;
}
private JComboBox<String> getApplyToStrengthTarget() {
if (applyToStrengthTarget == null) {
applyToStrengthTarget = createStatusComboBox();
}
return applyToStrengthTarget;
}
private void applyStrength(AttackStrength strength, String target) {
for (Plugin plugin : policy.getPluginFactory().getAllPlugin()) {
if (hasSameStatus(plugin, target)) {
plugin.setAttackStrength(strength);
}
}
}
private void setThreshold(AlertThreshold threshold) {
getComboThreshold().setSelectedItem(
Constant.messages.getString("ascan.options.level." + threshold.name().toLowerCase()));
getThresholdNotes().setText(
Constant.messages.getString("ascan.options.level." + threshold.name().toLowerCase() + ".label"));
}
private void setStrength(AttackStrength strength) {
getComboStrength().setSelectedItem(
Constant.messages.getString("ascan.options.strength." + strength.name().toLowerCase()));
getStrengthNotes().setText(
Constant.messages.getString("ascan.options.strength." + strength.name().toLowerCase() + ".label"));
}
/**
* This method initializes tableTest
*
* @return javax.swing.JTable
*/
private JTable getTableTest() {
if (tableTest == null) {
tableTest = new JTable();
tableTest.setModel(getAllCategoryTableModel());
tableTest.setRowHeight(DisplayUtils.getScaledSize(18));
tableTest.setIntercellSpacing(new java.awt.Dimension(1, 1));
tableTest.setAutoCreateRowSorter(true);
//Default sort by name (column 0)
List<RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>(1);
sortKeys.add(new RowSorter.SortKey(0, SortOrder.ASCENDING));
tableTest.getRowSorter().setSortKeys(sortKeys);
for (int i = 0; i < tableTest.getColumnCount()-1; i++) {
TableColumn column = tableTest.getColumnModel().getColumn(i);
column.setPreferredWidth(width[i]);
}
JComboBox<String> jcb1 = new JComboBox<>();
jcb1.addItem(""); // Always show a blank one for where they are not all the same
for (AlertThreshold level : AlertThreshold.values()) {
jcb1.addItem(Constant.messages.getString("ascan.policy.level." + level.name().toLowerCase()));
}
tableTest.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(jcb1));
JComboBox<String> jcb2 = new JComboBox<>();
jcb2.addItem(""); // Always show a blank one for where they are not all the same
for (AttackStrength level : AttackStrength.values()) {
jcb2.addItem(Constant.messages.getString("ascan.policy.level." + level.name().toLowerCase()));
}
tableTest.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(jcb2));
}
return tableTest;
}
public void setScanPolicy(ScanPolicy scanPolicy) {
if (! switchable) {
throw new InvalidParameterException("Cannot change policy if the panel has not been defined as switchable");
}
this.policy = scanPolicy;
this.getPolicySelector().setSelectedItem(scanPolicy.getName());
this.setThreshold(scanPolicy.getDefaultThreshold());
this.setStrength(scanPolicy.getDefaultStrength());
this.getAllCategoryTableModel().setPluginFactory(scanPolicy.getPluginFactory());
}
@Override
public void initParam(Object obj) {
}
@Override
public void validateParam(Object obj) throws Exception {
String newName = getPolicyName().getText();
if (newName.length() == 0) {
throw new Exception(Constant.messages.getString("ascan.policy.warn.noname"));
} else if (! extension.getPolicyManager().isLegalPolicyName(newName)) {
throw new Exception(Constant.messages.getString("ascan.policy.warn.badname", PolicyManager.ILLEGAL_POLICY_NAME_CHRS));
} else if (! newName.equals(currentName)) {
// Name changed
if (extension.getPolicyManager().getAllPolicyNames().contains(newName)) {
throw new Exception(Constant.messages.getString("ascan.policy.warn.exists"));
}
}
}
@Override
public void saveParam(Object obj) throws Exception {
this.policy.setName(getPolicyName().getText());
}
/**
* This method initializes jScrollPane
*
* @return javax.swing.JScrollPane
*/
private JScrollPane getJScrollPane() {
if (jScrollPane == null) {
jScrollPane = new JScrollPane();
jScrollPane.setViewportView(getTableTest());
jScrollPane.setBorder(javax.swing.BorderFactory.createEtchedBorder(javax.swing.border.EtchedBorder.RAISED));
}
return jScrollPane;
}
/**
* This method initializes categoryTableModel
*
* @return TableModel
*/
private AllCategoryTableModel getAllCategoryTableModel() {
if (allCategoryTableModel == null) {
allCategoryTableModel = new AllCategoryTableModel(policy.getPluginFactory());
}
return allCategoryTableModel;
}
private JLabel getThresholdNotes() {
if (labelThresholdNotes == null) {
labelThresholdNotes = new JLabel();
}
return labelThresholdNotes;
}
private JComboBox<String> getComboThreshold() {
if (comboThreshold == null) {
comboThreshold = new JComboBox<>();
comboThreshold.addItem(Constant.messages.getString("ascan.options.level.low"));
comboThreshold.addItem(Constant.messages.getString("ascan.options.level.medium"));
comboThreshold.addItem(Constant.messages.getString("ascan.options.level.high"));
comboThreshold.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Set the explanation and save
if (comboThreshold.getSelectedItem().equals(Constant.messages.getString("ascan.options.level.low"))) {
getThresholdNotes().setText(Constant.messages.getString("ascan.options.level.low.label"));
policy.setDefaultThreshold(AlertThreshold.LOW);
} else if (comboThreshold.getSelectedItem().equals(Constant.messages.getString("ascan.options.level.medium"))) {
getThresholdNotes().setText(Constant.messages.getString("ascan.options.level.medium.label"));
policy.setDefaultThreshold(AlertThreshold.MEDIUM);
} else {
getThresholdNotes().setText(Constant.messages.getString("ascan.options.level.high.label"));
policy.setDefaultThreshold(AlertThreshold.HIGH);
}
}
});
}
return comboThreshold;
}
private JLabel getStrengthNotes() {
if (labelStrengthNotes == null) {
labelStrengthNotes = new JLabel();
}
return labelStrengthNotes;
}
private JComboBox<String> getComboStrength() {
if (comboStrength == null) {
comboStrength = new JComboBox<>();
comboStrength.addItem(Constant.messages.getString("ascan.options.strength.low"));
comboStrength.addItem(Constant.messages.getString("ascan.options.strength.medium"));
comboStrength.addItem(Constant.messages.getString("ascan.options.strength.high"));
comboStrength.addItem(Constant.messages.getString("ascan.options.strength.insane"));
comboStrength.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Set the explanation and save
if (comboStrength.getSelectedItem().equals(Constant.messages.getString("ascan.options.strength.low"))) {
getStrengthNotes().setText(Constant.messages.getString("ascan.options.strength.low.label"));
policy.setDefaultStrength(AttackStrength.LOW);
} else if (comboStrength.getSelectedItem().equals(Constant.messages.getString("ascan.options.strength.medium"))) {
getStrengthNotes().setText(Constant.messages.getString("ascan.options.strength.medium.label"));
policy.setDefaultStrength(AttackStrength.MEDIUM);
} else if (comboStrength.getSelectedItem().equals(Constant.messages.getString("ascan.options.strength.high"))) {
getStrengthNotes().setText(Constant.messages.getString("ascan.options.strength.high.label"));
policy.setDefaultStrength(AttackStrength.HIGH);
} else {
getStrengthNotes().setText(Constant.messages.getString("ascan.options.strength.insane.label"));
policy.setDefaultStrength(AttackStrength.INSANE);
}
}
});
}
return comboStrength;
}
@Override
public String getHelpIndex() {
return "ui.dialogs.scanpolicy";
}
/**
* Adds the given {@code listener} to the list that's notified of each change in the selected scan policy.
*
* @param listener the listener that will be added
* @since 2.5.0
*/
public void addScanPolicyChangedEventListener(ScanPolicyChangedEventListener listener) {
listenerList.add(ScanPolicyChangedEventListener.class, listener);
}
/**
* Removes the given {@code listener} from the list that's notified of each change in the selected scan policy.
*
* @param listener the listener that will be removed
* @since 2.5.0
*/
public void removeScanPolicyChangedEventListener(ScanPolicyChangedEventListener listener) {
listenerList.remove(ScanPolicyChangedEventListener.class, listener);
}
private void fireScanPolicyChanged(ScanPolicy scanPolicy) {
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == ScanPolicyChangedEventListener.class) {
((ScanPolicyChangedEventListener) listeners[i + 1]).scanPolicyChanged(scanPolicy);
}
}
}
/**
* The listener interface for receiving notifications of changes in the selected scan policy.
*
* @since 2.5.0
* @see PolicyAllCategoryPanel#addScanPolicyChangedEventListener(ScanPolicyChangedEventListener)
* @see PolicyAllCategoryPanel#removeScanPolicyChangedEventListener(ScanPolicyChangedEventListener)
*/
public interface ScanPolicyChangedEventListener extends EventListener {
/**
* Notifies that the selected scan policy was changed.
*
* @param scanPolicy the new selected scan policy
*/
public void scanPolicyChanged(ScanPolicy scanPolicy);
}
}