org.zaproxy.zap.utils.TableExportAction Maven / Gradle / Ivy
Show all versions of zap Show documentation
/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2017 The ZAP Development Team
*
* 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 org.zaproxy.zap.utils;
import java.awt.event.ActionEvent;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.log4j.Logger;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.model.Model;
import org.parosproxy.paros.view.View;
import org.zaproxy.zap.view.widgets.WritableFileChooser;
/**
* An {@code AbstractAction} to facilitate exporting tables (as shown) to a file (such as CSV).
*
* Filters, sorting, column order, and column visibility may all impact the data exported.
*
* @param the type of the table.
* @since 2.7.0
* @see TableExportButton
*/
public class TableExportAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(TableExportAction.class);
private static final String CSV_EXTENSION = ".csv";
/**
* The default text for the action.
*
* Lazily initialised.
*
* @see #getDefaultText()
*/
private static String defaultText;
/**
* The default icon for the action.
*
*
Lazily initialised.
*
* @see #getDefaultIcon()
*/
private static Icon defaultIcon;
private T exportTable;
/**
* Constructs a {@code TableExportAction} with the given table and default text/icon.
*
* @param table the Table for which the data should be exported.
* @see #getDefaultText()
* @see #getDefaultIcon()
*/
public TableExportAction(T table) {
this(table, getDefaultText(), getDefaultIcon());
}
/**
* Constructs a {@code TableExportAction} with the given table and name and with default icon.
*
* @param table the Table for which the data should be exported.
* @param name the name of the action.
* @see #getDefaultIcon()
*/
public TableExportAction(T table, String name) {
this(table, name, getDefaultIcon());
}
/**
* Constructs a {@code TableExportAction} with the given table, name, and icon.
*
* @param table the Table for which the data should be exported
* @param name the name of the action.
* @param icon the icon of the action.
*/
public TableExportAction(T table, String name, Icon icon) {
super(name, icon);
exportTable = table;
}
/**
* Gets the default text used for the action.
*
* @return the default text.
*/
public static String getDefaultText() {
if (defaultText == null) {
defaultText = Constant.messages.getString("export.button.name");
}
return defaultText;
}
/**
* Gets the default icon used for the action.
*
* @return the default icon.
*/
public static Icon getDefaultIcon() {
if (defaultIcon == null) {
defaultIcon =
new ImageIcon(TableExportAction.class.getResource("/resource/icon/16/115.png"));
}
return defaultIcon;
}
@Override
public void actionPerformed(ActionEvent e) {
WritableFileChooser chooser =
new WritableFileChooser(Model.getSingleton().getOptionsParam().getUserDirectory()) {
private static final long serialVersionUID = 1L;
@Override
public void approveSelection() {
File file = getSelectedFile();
if (file != null) {
String filePath = file.getAbsolutePath();
if (!filePath.toLowerCase(Locale.ROOT).endsWith(CSV_EXTENSION)) {
setSelectedFile(new File(filePath + CSV_EXTENSION));
}
}
super.approveSelection();
}
};
chooser.setSelectedFile(
new File(Constant.messages.getString("export.button.default.filename")));
if (chooser.showSaveDialog(View.getSingleton().getMainFrame())
== WritableFileChooser.APPROVE_OPTION) {
boolean success = true;
try (CSVPrinter pw =
new CSVPrinter(
Files.newBufferedWriter(
chooser.getSelectedFile().toPath(), StandardCharsets.UTF_8),
CSVFormat.DEFAULT)) {
pw.printRecord(getColumnNames());
int rowCount = getTable().getRowCount();
for (int row = 0; row < rowCount; row++) {
pw.printRecord(getRowCells(row));
}
} catch (Exception ex) {
success = false;
JOptionPane.showMessageDialog(
View.getSingleton().getMainFrame(),
Constant.messages.getString("export.button.error")
+ "\n"
+ ex.getMessage());
LOGGER.error("Export Failed: " + ex.getMessage(), ex);
}
// Delay the presentation of success message, to ensure all the data was already
// flushed.
if (success) {
JOptionPane.showMessageDialog(
View.getSingleton().getMainFrame(),
Constant.messages.getString("export.button.success"));
}
}
}
/**
* Gets a {@code List} of (visible) column names for the given table.
*
*
Called when exporting the column names.
*
* @return the {@code List} of column names, never {@code null}.
*/
protected List getColumnNames() {
List columnNamesList = new ArrayList<>();
for (int col = 0; col < getTable().getColumnCount(); col++) {
columnNamesList.add(
getTable().getColumnModel().getColumn(col).getHeaderValue().toString());
}
return columnNamesList;
}
/**
* Gets the cell values (in view order) for the given row.
*
* Called for each (visible) row that's being exported.
*
* @param row the row, in view coordinates.
* @return a {@code List} containing the values of the cells for the given row, never {@code
* null}.
*/
protected List