/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with this * work for additional information regarding copyright ownership. The ASF * licenses this file to You 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 org.apache.jmeter.protocol.http.gui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import org.apache.jmeter.config.gui.AbstractConfigGui; import org.apache.jmeter.gui.util.PowerTableModel; import org.apache.jmeter.protocol.http.control.DNSCacheManager; import org.apache.jmeter.protocol.http.control.StaticHost; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.property.JMeterProperty; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.gui.GuiUtils; import org.apache.jorphan.gui.layout.VerticalLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This gui part of @see * {@link org.apache.jmeter.protocol.http.control.DNSCacheManager}. Using * radiobuttons, user can switch between using system DNS resolver and custom * resolver. Custom resolver functionality is provided by dnsjava library. * "DNS servers" may contain one or more IP/Name of dns server for resolving * name DNS servers are chosen via round-robin. If table is empty - system * resolver is used. * * @since 2.12 */ public class DNSCachePanel extends AbstractConfigGui implements ActionListener { private static final Logger LOGGER = LoggerFactory.getLogger(DNSCacheManager.class); private static final long serialVersionUID = 2120L; public static final String OPTIONS = JMeterUtils.getResString("option"); private static final String ADD_COMMAND = JMeterUtils.getResString("add"); // $NON-NLS-1$ private static final String ADD_HOST_COMMAND = JMeterUtils.getResString("add_host"); // $NON-NLS-1$ private static final String DELETE_COMMAND = JMeterUtils.getResString("delete"); // $NON-NLS-1$ private static final String DELETE_HOST_COMMAND = JMeterUtils.getResString("delete_host"); // $NON-NLS-1$ private static final String SYS_RES_COMMAND = JMeterUtils.getResString("use_system_dns_resolver"); // $NON-NLS-1$ private static final String CUST_RES_COMMAND = JMeterUtils.getResString("use_custom_dns_resolver"); // $NON-NLS-1$ private JTable dnsHostsTable; private JPanel dnsHostsPanel; private JPanel dnsHostsButPanel; private JTable dnsServersTable; private JPanel dnsServersPanel; private JPanel dnsServButPanel; private PowerTableModel dnsServersTableModel; private PowerTableModel dnsHostsTableModel; private JRadioButton sysResButton; private JRadioButton custResButton; private JButton deleteButton; private JButton addButton; private JButton addHostButton; private JButton deleteHostButton; private ButtonGroup providerDNSradioGroup = new ButtonGroup(); private static final String[] COLUMN_RESOURCE_NAMES = { JMeterUtils.getResString("dns_hostname_or_ip"), //$NON-NLS-1$ }; private static final Class<?>[] columnClasses = { String.class }; private static final String[] HOSTS_COLUMN_RESOURCE_NAMES = { JMeterUtils.getResString("dns_host"), JMeterUtils.getResString("dns_hostname_or_ip") }; private static final Class<?>[] HOSTS_COLUMN_CLASSES = { String.class, String.class }; private JCheckBox clearEachIteration; /** * Default constructor. */ public DNSCachePanel() { init(); } @Override public String getLabelResource() { return "dns_cache_manager_title"; } /** * Modifies a given TestElement to mirror the data in the gui components. * * @see org.apache.jmeter.gui.JMeterGUIComponent#modifyTestElement(org.apache.jmeter.testelement.TestElement) */ @Override public void modifyTestElement(TestElement dnsRes) { GuiUtils.stopTableEditing(dnsServersTable); dnsRes.clear(); configureTestElement(dnsRes); if (dnsRes instanceof DNSCacheManager) { DNSCacheManager dnsCacheManager = (DNSCacheManager) dnsRes; for (int i = 0; i < dnsServersTableModel.getRowCount(); i++) { String server = (String) dnsServersTableModel.getRowData(i)[0]; dnsCacheManager.addServer(server); } for (int i = 0; i < dnsHostsTableModel.getRowCount(); i++) { String host = (String) dnsHostsTableModel.getRowData(i)[0]; String addresses = (String) dnsHostsTableModel.getRowData(i)[1]; dnsCacheManager.addHost(host, addresses); } dnsCacheManager.setClearEachIteration(clearEachIteration.isSelected()); if (providerDNSradioGroup.isSelected(custResButton.getModel())) { dnsCacheManager.setCustomResolver(true); } else { dnsCacheManager.setCustomResolver(false); } } } /** * Implements JMeterGUIComponent.clearGui */ @Override public void clearGui() { super.clearGui(); clearEachIteration.setSelected(DNSCacheManager.DEFAULT_CLEAR_CACHE_EACH_ITER); providerDNSradioGroup.setSelected(sysResButton.getModel(), true); dnsServersTableModel.clearData(); deleteButton.setEnabled(false); dnsHostsTableModel.clearData(); deleteHostButton.setEnabled(false); } private void populateTable(DNSCacheManager resolver) { dnsServersTableModel.clearData(); for (JMeterProperty jMeterProperty : resolver.getServers()) { addServerToTable((String) jMeterProperty.getObjectValue()); } } private void populateHostsTable(DNSCacheManager resolver) { dnsHostsTableModel.clearData(); for (JMeterProperty hostEntry : resolver.getHosts()) { addHostToTable((StaticHost) hostEntry.getObjectValue()); } } @Override public TestElement createTestElement() { DNSCacheManager dnsCacheManager = new DNSCacheManager(); modifyTestElement(dnsCacheManager); return dnsCacheManager; } @Override public void configure(TestElement el) { super.configure(el); DNSCacheManager dnsCacheManager = (DNSCacheManager) el; populateTable(dnsCacheManager); populateHostsTable(dnsCacheManager); clearEachIteration.setSelected(dnsCacheManager.isClearEachIteration()); if (dnsCacheManager.isCustomResolver()) { providerDNSradioGroup.setSelected(custResButton.getModel(), true); deleteButton.setEnabled(dnsServersTable.getColumnCount() > 0); deleteHostButton.setEnabled(dnsHostsTable.getColumnCount() > 0); addButton.setEnabled(true); addHostButton.setEnabled(true); } else { providerDNSradioGroup.setSelected(sysResButton.getModel(), true); } } private void init() { // WARNING: called from ctor so must not be overridden (i.e. must be private or final) dnsServersTableModel = new PowerTableModel(COLUMN_RESOURCE_NAMES, columnClasses); dnsHostsTableModel = new PowerTableModel(HOSTS_COLUMN_RESOURCE_NAMES, HOSTS_COLUMN_CLASSES); clearEachIteration = new JCheckBox(JMeterUtils.getResString("clear_cache_each_iteration"), true); //$NON-NLS-1$ setLayout(new BorderLayout()); setBorder(makeBorder()); JPanel northPanel = new JPanel(); northPanel.setLayout(new VerticalLayout(5, VerticalLayout.BOTH)); northPanel.add(makeTitlePanel()); JPanel optionsPane = new JPanel(); optionsPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), OPTIONS)); // $NON-NLS-1$ optionsPane.setLayout(new VerticalLayout(5, VerticalLayout.BOTH)); optionsPane.add(clearEachIteration, BorderLayout.WEST); optionsPane.add(createChooseResPanel(), BorderLayout.SOUTH); northPanel.add(optionsPane); add(northPanel, BorderLayout.NORTH); JPanel tables = new JPanel(); tables.setLayout(new VerticalLayout(2, VerticalLayout.BOTH)); dnsServersPanel = createDnsServersTablePanel(); dnsHostsPanel = createDnsHostsTablePanel(); tables.add(dnsServersPanel); tables.add(dnsHostsPanel); add(tables, BorderLayout.CENTER); } public JPanel createDnsServersTablePanel() { // create the JTable that holds header per row dnsServersTable = new JTable(dnsServersTableModel); JMeterUtils.applyHiDPI(dnsServersTable); dnsServersTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); dnsServersTable.setPreferredScrollableViewportSize(new Dimension(400, 100)); JPanel panel = new JPanel(new BorderLayout(0, 5)); panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), JMeterUtils.getResString("dns_servers"))); // $NON-NLS-1$ JScrollPane dnsServScrollPane = new JScrollPane(dnsServersTable); panel.add(dnsServScrollPane, BorderLayout.CENTER); dnsServButPanel = createButtonPanel(); panel.add(dnsServButPanel, BorderLayout.SOUTH); return panel; } public JPanel createDnsHostsTablePanel() { // create the JTable that holds header per row dnsHostsTable = new JTable(dnsHostsTableModel); JMeterUtils.applyHiDPI(dnsHostsTable); dnsHostsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); dnsHostsTable.setPreferredScrollableViewportSize(new Dimension(400, 100)); JPanel panel = new JPanel(new BorderLayout(0, 5)); panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), JMeterUtils.getResString("dns_hosts"))); // $NON-NLS-1$ JScrollPane dnsHostsScrollPane = new JScrollPane(dnsHostsTable); panel.add(dnsHostsScrollPane, BorderLayout.CENTER); dnsHostsButPanel = createHostsButtonPanel(); panel.add(dnsHostsButPanel, BorderLayout.SOUTH); return panel; } private JPanel createChooseResPanel() { JPanel chooseResPanel = new JPanel(new BorderLayout(0, 5)); sysResButton = new JRadioButton(); sysResButton.setSelected(true); sysResButton.setText(SYS_RES_COMMAND); sysResButton.setToolTipText(SYS_RES_COMMAND); sysResButton.setEnabled(true); sysResButton.addActionListener(this); custResButton = new JRadioButton(); custResButton.setSelected(false); custResButton.setText(CUST_RES_COMMAND); custResButton.setToolTipText(CUST_RES_COMMAND); custResButton.setEnabled(true); custResButton.addActionListener(this); providerDNSradioGroup.add(sysResButton); providerDNSradioGroup.add(custResButton); chooseResPanel.add(sysResButton, BorderLayout.WEST); chooseResPanel.add(custResButton, BorderLayout.CENTER); return chooseResPanel; } private JPanel createButtonPanel() { boolean tableEmpty = dnsServersTableModel.getRowCount() == 0; addButton = createButton("add", 'A', ADD_COMMAND, custResButton.isSelected()); // $NON-NLS-1$ deleteButton = createButton("delete", 'D', DELETE_COMMAND, !tableEmpty); // $NON-NLS-1$ JPanel buttonPanel = new JPanel(); buttonPanel.add(addButton, BorderLayout.WEST); buttonPanel.add(deleteButton, BorderLayout.LINE_END); return buttonPanel; } private JPanel createHostsButtonPanel() { boolean tableEmpty = dnsHostsTableModel.getRowCount() == 0; addHostButton = createButton("add_host", 'H', ADD_HOST_COMMAND, custResButton.isSelected()); // $NON-NLS-1$ deleteHostButton = createButton("delete_host", 'X', DELETE_HOST_COMMAND, !tableEmpty); // $NON-NLS-1$ JPanel buttonPanel = new JPanel(); buttonPanel.add(addHostButton, BorderLayout.WEST); buttonPanel.add(deleteHostButton, BorderLayout.LINE_END); return buttonPanel; } private JButton createButton(String resName, char mnemonic, String command, boolean enabled) { JButton button = new JButton(JMeterUtils.getResString(resName)); button.setMnemonic(mnemonic); button.setActionCommand(command); button.setEnabled(enabled); button.addActionListener(this); return button; } private void addServerToTable(String dnsServer) { dnsServersTableModel.addRow(new Object[] { dnsServer }); } private void addHostToTable(StaticHost hostEntry) { LOGGER.debug("Adding entry {}", hostEntry); dnsHostsTableModel.addRow(new Object[] { hostEntry.getName(), hostEntry.getAddress() }); } @Override public void actionPerformed(ActionEvent e) { String action = e.getActionCommand(); enableTable(custResButton.isSelected(), sysResButton.isSelected(), dnsServersTable, dnsServersTableModel, addButton, deleteButton); enableTable(custResButton.isSelected(), sysResButton.isSelected(), dnsHostsTable, dnsHostsTableModel, addHostButton, deleteHostButton); if (action.equals(DELETE_COMMAND)) { deleteTableRow(dnsServersTable, dnsServersTableModel, deleteButton); } else if (action.equals(ADD_COMMAND)) { addTableRow(dnsServersTable, dnsServersTableModel, deleteButton); } else if (DELETE_HOST_COMMAND.equals(action)) { deleteTableRow(dnsHostsTable, dnsHostsTableModel, deleteHostButton); } else if (ADD_HOST_COMMAND.equals(action)) { addTableRow(dnsHostsTable, dnsHostsTableModel, deleteHostButton); } } private void enableTable(boolean custEnabled, boolean sysEnabled, JTable table, PowerTableModel model, JButton addButton, JButton deleteButton) { table.setEnabled(custEnabled); Color greyColor = new Color(240, 240, 240); Color blueColor = new Color(184, 207, 229); table.setBackground(sysEnabled ? greyColor : Color.WHITE); table.setSelectionBackground(sysEnabled ? greyColor : blueColor); addButton.setEnabled(custEnabled); deleteButton.setEnabled(custEnabled); if (custEnabled && (model.getRowCount() > 0)) { deleteButton.setEnabled(true); addButton.setEnabled(true); } } private void addTableRow(JTable table, PowerTableModel model, JButton button) { // If a table cell is being edited, we should accept the current // value and stop the editing before adding a new row. GuiUtils.stopTableEditing(table); model.addNewRow(); model.fireTableDataChanged(); if (!button.isEnabled()) { button.setEnabled(true); } // Highlight (select) the appropriate row. int rowToSelect = model.getRowCount() - 1; table.setRowSelectionInterval(rowToSelect, rowToSelect); } private void deleteTableRow(JTable table, PowerTableModel model, JButton button) { if (model.getRowCount() > 0) { // If a table cell is being edited, we must cancel the editing // before deleting the row. GuiUtils.cancelEditing(table); int rowSelected = table.getSelectedRow(); if (rowSelected != -1) { model.removeRow(rowSelected); model.fireTableDataChanged(); if (model.getRowCount() == 0) { button.setEnabled(false); } else { int rowToSelect = Math.min(rowSelected, model.getRowCount() - 1); table.setRowSelectionInterval(rowToSelect, rowToSelect); } } } } }