package ciscoroutertool.gui;
import ciscoroutertool.output.OutputManager;
import ciscoroutertool.rules.Rule;
import ciscoroutertool.scanner.FullReport;
import ciscoroutertool.scanner.HostReport;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
/**
* This window displays the output in a tree format and lets the user remove
* nodes from the report, and then output it to a file.
* @version 0.01ALPHA
* @author Andrew H. Johnston
*/
public class OutputReview extends javax.swing.JFrame {
/**
* The object holding all individual host reports as well as some global data
*/
private FullReport report;
/**
* The selected tree node (used to find nodes to delete)
*/
private DefaultMutableTreeNode selected = null;
/**
* The model that the tree is based on.
*/
private DefaultTreeModel model;
/**
* The modal that handles saving files
*/
private JFileChooser fileChooser = new JFileChooser();
/**
* Creates new form OutputReview
*/
public OutputReview(FullReport r) {
report = r;
DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
ArrayList<HostReport> reports = report.getReports();
for (HostReport h : reports) {
DefaultMutableTreeNode host = new DefaultMutableTreeNode(h.getHost().toString());
ArrayList<Rule> matchedRules = h.getMatchedRules();
for (Rule rule : matchedRules) {
DefaultMutableTreeNode ruleName = new DefaultMutableTreeNode(rule.getName());
DefaultMutableTreeNode ruleDesc = new DefaultMutableTreeNode(rule.getDescription());
ruleName.add(ruleDesc);
host.add(ruleName);
}
root.add(host);
}
initComponents();
model = new DefaultTreeModel(root);
reportTree.setModel(model);
//The following allows for us to select one node at a time (for deletion)
reportTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
//Hide the root node so it looks like the hosts are the root node
reportTree.setRootVisible(false);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
lblPrompt = new javax.swing.JLabel();
btnDelete = new javax.swing.JButton();
btnXML = new javax.swing.JButton();
btnTXT = new javax.swing.JButton();
btnCSV = new javax.swing.JButton();
treeScrollPane = new javax.swing.JScrollPane();
reportTree = new javax.swing.JTree();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Review Output");
lblPrompt.setText("Please review the following finds. Press delete to remove an item from the list.");
btnDelete.setText("Delete");
btnDelete.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnDeleteActionPerformed(evt);
}
});
btnXML.setText("Output to XML");
btnXML.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnXMLActionPerformed(evt);
}
});
btnTXT.setText("Output to TXT");
btnTXT.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnTXTActionPerformed(evt);
}
});
btnCSV.setText("Output to CSV");
btnCSV.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCSVActionPerformed(evt);
}
});
treeScrollPane.setViewportView(reportTree);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblPrompt, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addComponent(btnXML)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCSV)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnTXT))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(treeScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 649, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createSequentialGroup()
.addGap(589, 589, 589)
.addComponent(btnDelete))))
.addGap(0, 14, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(lblPrompt, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnDelete)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(treeScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 232, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnTXT)
.addComponent(btnCSV)
.addComponent(btnXML))
.addContainerGap(23, Short.MAX_VALUE))
);
pack();
}// </editor-fold>//GEN-END:initComponents
/**
* Deletes the selected node from the tree and removes the corresponding entry from the report.
* @param evt
*/
private void btnDeleteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeleteActionPerformed
selected = (DefaultMutableTreeNode) reportTree.getLastSelectedPathComponent();
if (selected == null) {
//Nothing is selected
return;
}
//If it's a host
if (selected.getPath().length == 2) {
String hostname = selected.toString();
int toDelete = this.getIndexOfHost(hostname);
if (toDelete == -1) {
return;
}
report.getReports().remove(toDelete);
} else if (selected.getPath().length == 3) { //If it's a rule
String host = selected.getParent().toString();
String rule = selected.toString();
int hostNum = this.getIndexOfHost(host);
int ruleNum = this.getIndexOfRule(hostNum, rule);
if (hostNum == -1 || ruleNum == -1) {
return;
}
report.getReports().get(hostNum).getMatchedRules().remove(ruleNum);
}
MutableTreeNode parent = (MutableTreeNode) selected.getParent();
int index = parent.getIndex(selected);
parent.remove(selected);
model.nodesWereRemoved(parent, new int[]{index}, new Object[]{selected});
reportTree.setModel(model);
}//GEN-LAST:event_btnDeleteActionPerformed
private void btnXMLActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnXMLActionPerformed
this.genericSaveToFile("xml", OutputManager.XML_OUTPUT);
}//GEN-LAST:event_btnXMLActionPerformed
private void btnCSVActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCSVActionPerformed
this.genericSaveToFile("csv", OutputManager.CSV_OUTPUT);
}//GEN-LAST:event_btnCSVActionPerformed
private void btnTXTActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTXTActionPerformed
this.genericSaveToFile("txt", OutputManager.TXT_OUTPUT);
}//GEN-LAST:event_btnTXTActionPerformed
private void genericSaveToFile(String extension, int saveType) {
int returnCode = fileChooser.showSaveDialog(this);
try {
if (returnCode == JFileChooser.APPROVE_OPTION) {
File saveFile = fileChooser.getSelectedFile();
saveFile = this.ensureFileExtensionPresent(saveFile, extension);
OutputManager manager = new OutputManager(report, saveFile, saveType);
manager.saveFile();
}
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "Error",
"Tried to save file and got exception: " + e.getMessage(),
JOptionPane.ERROR_MESSAGE);
}
}
/**
* Uses the name of the host to find it's position in the ArrayList of hosts in the FullReport
* @param hostname the name of the host to find
* @return the index of the host in the array
*/
private int getIndexOfHost(String hostname) {
int toDelete = -1;
for (int i = 0; i < report.getReports().size(); i++) {
String host = report.getReports().get(i).toString(); //Get this HostReport's host
if (hostname.compareTo(host) == 0) {
toDelete = i;
break;
}
}
//While this should *never* happen, it's safer to do it this way
if (toDelete == -1) {
} else { //We have an error, let's provide debugging information
System.err.println("ERROR: Tried to delete host " + hostname + " but couldn't find it.");
}
return toDelete;
}
/**
* Uses the position of the host in the array and the name of the rule to find the rule's position in the host's report
* @param host the index of the host in the FullReport's HostReport ArrayList.
* @param ruleName the name of the rule to find the index of
* @return the index of the rule.
*/
private int getIndexOfRule(int host, String ruleName) {
int toDelete = -1;
for (int i = 0; i < report.getReports().size(); i++) {
String rule = report.getReports().get(host).getMatchedRules().get(i).toString(); //Get this Host's rules
if (rule.compareTo(ruleName) == 0) {
toDelete = i;
break;
}
}
//While this should *never* happen, it's safer to do it this way
if (toDelete == -1) {
System.err.println("ERROR: Tried to delete rule " + ruleName + "on host " +
report.getReports().get(host).toString() + " but couldn't find it.");
}
return toDelete;
}
private File ensureFileExtensionPresent(File file, String extension) {
if (file.getName().toLowerCase().matches("(.*)\\." + extension)) { //If file is already correct
return file;
}
File retFile = new File(file.getPath() + "." + extension);
return retFile;
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCSV;
private javax.swing.JButton btnDelete;
private javax.swing.JButton btnTXT;
private javax.swing.JButton btnXML;
private javax.swing.JLabel lblPrompt;
private javax.swing.JTree reportTree;
private javax.swing.JScrollPane treeScrollPane;
// End of variables declaration//GEN-END:variables
}