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 }