2
votes

In the given code, a swingworker thread will capture the packets, encapsulate its fields into a string array and then add this string array as a row in the jtable in the GUI. My JTable follows the AbstractTableModel. I am manually copying the old data in JTable with the new data and then use FireTableDataChanged() methods so that the changes are reflected in the table in GUI. But the GUI table remains blank. I am not able to update my JTable with the new data. I also tried to use DefaultTableModel but had the same result.

/*************CaptureThread class**************/

package TestClasses;
import javax.swing.*;
import javax.swing.table.*;
import jpcap.*;
import jpcap.packet.*;

public class CaptureThread extends SwingWorker<Void,String[]>
{
    JTable capture_tab;
    CaptureTableModel model;
    JpcapCaptor capture;
    CaptureThread(JpcapCaptor capture,CaptureTableModel model,JTable capture_tab)
    {
        this.capture = capture;
        this.model = model;
        this.capture_tab = capture_tab;
    }
    public Void doInBackground()
    {
        int pkt_count = 0,i=0;
        jpcap.packet.Packet p;
        ARPPacket arp_pkt;
        IPPacket ip_pkt;
        TCPPacket tcp_pkt;
        UDPPacket udp_pkt;        
        EthernetPacket eth_pkt;
        String new_pkt[] = new String[10];        
        while(!isCancelled())
        {              
            p = capture.getPacket();                 
            eth_pkt =(EthernetPacket)p.datalink;
            new_pkt[0] = Integer.toString(++pkt_count);
            new_pkt[1] = Long.toString(p.sec);            
            new_pkt[2] = eth_pkt.getSourceAddress();
            new_pkt[5] = eth_pkt.getSourceAddress();             
            if(eth_pkt.frametype==EthernetPacket.ETHERTYPE_ARP)
            {
                System.out.println("ARP packet");
                arp_pkt = (ARPPacket)p;
                new_pkt[3] = "--";
                new_pkt[4] = arp_pkt.sender_protoaddr.toString();
                new_pkt[6] = "--";
                new_pkt[7] = arp_pkt.target_protoaddr.toString();
                new_pkt[8] = "ARP";
                new_pkt[9] = "--";
            }
            else
            {
                System.out.println("IP packet");
                ip_pkt = (IPPacket)p;
                new_pkt[3] = ip_pkt.src_ip.toString();
                new_pkt[6] = ip_pkt.dst_ip.toString();
                switch(ip_pkt.protocol)
                {
                    case IPPacket.IPPROTO_ICMP:
                        new_pkt[4] = "--";
                        new_pkt[7] = "--";
                        new_pkt[8] = "ICMP";
                        System.out.println("ICMP packet");
                        break;
                    case IPPacket.IPPROTO_TCP:
                        tcp_pkt = (TCPPacket)ip_pkt;
                        new_pkt[4] = Integer.toString(tcp_pkt.src_port);
                        new_pkt[7] = Integer.toString(tcp_pkt.dst_port);
                        new_pkt[8] = "TCP";
                        System.out.println("TCP packet");
                        break;
                    case IPPacket.IPPROTO_UDP:
                        udp_pkt = (UDPPacket)ip_pkt;
                        new_pkt[4] = Integer.toString(udp_pkt.src_port);
                        new_pkt[7] = Integer.toString(udp_pkt.dst_port);
                        new_pkt[8] = "UDP";
                        System.out.println("UDP packet");
                        break;
                }
                new_pkt[9] = Integer.toString(ip_pkt.hop_limit);  
                publish(new_pkt);
            }
        }
        return null;
    }
    public void process(String str[])
    {
        model.addPacket(str);
        model.fireTableDataChanged();
    }
}

/*******************MainWin class***********/

package TestClasses;
import javax.swing.table.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import jpcap.*;
import jpcap.packet.*;

public class MainWin extends javax.swing.JFrame implements ActionListener
    {
    /** Creates new form Temp */
    public MainWin() {
        initComponents();
    }

    /** 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() {

        model = new CaptureTableModel(packet,columnNames);
        capture_tab = new JTable(model);          
        dev = new SystemInterfaces();
        str = dev.getInterfaceList();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();        
        ipaddr_field = new javax.swing.JTextField();
        interface_combo = new javax.swing.JComboBox();
        promiscuous = new javax.swing.JCheckBox();
        jLabel3 = new javax.swing.JLabel();
        jComboBox1 = new javax.swing.JComboBox();            
        start_button = new javax.swing.JButton();
        stop_button = new javax.swing.JButton();
        clear_button = new javax.swing.JButton();
        save_button = new javax.swing.JButton();
        jMenuBar1 = new javax.swing.JMenuBar();
        menu1 = new javax.swing.JMenu();
        file_item1 = new javax.swing.JMenuItem();
        file_item2 = new javax.swing.JMenuItem();
        file_item3 = new javax.swing.JMenuItem();
        file_item4 = new javax.swing.JMenuItem();
        menu2 = new javax.swing.JMenu();
        menu3 = new javax.swing.JMenu();
        capture_item1 = new javax.swing.JMenuItem();
        capture_item2 = new javax.swing.JMenuItem();
        capture_item3 = new javax.swing.JMenuItem();
        menu4 = new javax.swing.JMenu();
        help_item1 = new javax.swing.JMenuItem();

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setBackground(java.awt.Color.black);
        setTitle("Packet Tracer Tool");

        jLabel1.setBackground(java.awt.Color.black);
        jLabel1.setFont(new java.awt.Font("Times New Roman", 0, 14));
        jLabel1.setForeground(java.awt.Color.white);
        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel1.setText("Interface:");
        jLabel1.setToolTipText("Select any interface from the list");

        interface_combo.setBackground(java.awt.Color.gray);
        interface_combo.setForeground(java.awt.Color.white);
        interface_combo.setModel(new javax.swing.DefaultComboBoxModel(str));
        interface_combo.addActionListener(this);  
        interface_combo.setActionCommand("select_interface");

        jLabel2.setBackground(java.awt.Color.black);
        jLabel2.setFont(new java.awt.Font("Times New Roman", 0, 14));
        jLabel2.setForeground(java.awt.Color.white);
        jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel2.setText("IP Address:");
        jLabel2.setToolTipText("IP Address of the selected interface");        

        ipaddr_field.setBackground(java.awt.Color.gray);
        ipaddr_field.setEditable(false);
        ipaddr_field.setFont(new java.awt.Font("Times New Roman", 0, 14));
        ipaddr_field.setForeground(java.awt.Color.white);
        ipaddr_field.setHorizontalAlignment(javax.swing.JTextField.CENTER);        
        ipaddr_field.setText(dev.getInterfaceIPAddr(interface_combo.getSelectedIndex()));

        promiscuous.setBackground(java.awt.Color.gray);
        promiscuous.setFont(new java.awt.Font("Times New Roman", 0, 14));
        promiscuous.setForeground(java.awt.Color.white);
        promiscuous.setSelected(true);
        promiscuous.setText("Promiscuous Mode");
        promiscuous.setToolTipText("Check if you want to enable promiscuous mode");

        jLabel3.setBackground(java.awt.Color.black);
        jLabel3.setFont(new java.awt.Font("Times New Roman", 0, 14));
        jLabel3.setForeground(java.awt.Color.white);
        jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel3.setText("Filter: ");
        jLabel3.setToolTipText("Select a filter to apply");

        jComboBox1.setBackground(java.awt.Color.gray);
        jComboBox1.setFont(new java.awt.Font("Times New Roman", 0, 14));
        jComboBox1.setForeground(java.awt.Color.white);
        jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));

        capture_tab.setBackground(java.awt.Color.lightGray);
        capture_tab.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0), 2));
        capture_tab.setFont(new java.awt.Font("Times New Roman", 0, 14)); // NOI18N
        capture_tab.setForeground(java.awt.Color.white);        
        capture_tab.setPreferredScrollableViewportSize(new Dimension(500,70));
        capture_tab.setFillsViewportHeight(true);
        scroll = new javax.swing.JScrollPane(capture_tab);

        start_button.setBackground(java.awt.Color.gray);
        start_button.setFont(new java.awt.Font("Times New Roman", 0, 14)); // NOI18N
        start_button.setForeground(java.awt.Color.white);
        start_button.setText("START");
        start_button.setToolTipText("Start capture on the selected interface");
        start_button.addActionListener(this);
        start_button.setActionCommand("start");

        stop_button.setBackground(java.awt.Color.gray);
        stop_button.setFont(new java.awt.Font("Times New Roman", 0, 14)); // NOI18N
        stop_button.setForeground(java.awt.Color.white);
        stop_button.setText("STOP");
        stop_button.setToolTipText("Stop capture");
        stop_button.setText("STOP");
        stop_button.setActionCommand("stop");

        clear_button.setBackground(java.awt.Color.gray);
        clear_button.setFont(new java.awt.Font("Times New Roman", 0, 14)); // NOI18N
        clear_button.setForeground(java.awt.Color.white);
        clear_button.setText("CLEAR");
        clear_button.setToolTipText("Clear capture table");

        save_button.setBackground(java.awt.Color.gray);
        save_button.setFont(new java.awt.Font("Times New Roman", 0, 14)); // NOI18N
        save_button.setForeground(java.awt.Color.white);
        save_button.setText("SAVE");
        save_button.setToolTipText("Save captured packets to a file");

        menu1.setText("File");

        file_item1.setText("Open");
        menu1.add(file_item1);

        file_item2.setText("Save");
        menu1.add(file_item2);

        file_item3.setText("Save as");
        menu1.add(file_item3);

        file_item4.setText("Exit");
        menu1.add(file_item4);

        jMenuBar1.add(menu1);

        menu2.setText("Edit");
        jMenuBar1.add(menu2);

        menu3.setText("Capture");

        capture_item1.setText("Interface");
        menu3.add(capture_item1);

        capture_item2.setText("Start");
        menu3.add(capture_item2);

        capture_item3.setText("Stop");
        menu3.add(capture_item3);

        jMenuBar1.add(menu3);

        menu4.setText("Help");

        help_item1.setText("About");
        menu4.add(help_item1);

        jMenuBar1.add(menu4);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(scroll, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 740, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel2)
                            .addComponent(jLabel1)
                            .addComponent(jLabel3))
                        .addGap(31, 31, 31)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(ipaddr_field, javax.swing.GroupLayout.PREFERRED_SIZE, 102, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(interface_combo, 0, 643, Short.MAX_VALUE)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                .addComponent(jComboBox1, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(promiscuous, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                        .addComponent(start_button, javax.swing.GroupLayout.PREFERRED_SIZE, 86, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(36, 36, 36)
                        .addComponent(stop_button, javax.swing.GroupLayout.PREFERRED_SIZE, 88, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(35, 35, 35)
                        .addComponent(clear_button, javax.swing.GroupLayout.PREFERRED_SIZE, 87, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(36, 36, 36)
                        .addComponent(save_button, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(interface_combo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(ipaddr_field, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(promiscuous)
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addComponent(scroll, javax.swing.GroupLayout.PREFERRED_SIZE, 300, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(49, 49, 49)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(start_button, javax.swing.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE)
                    .addComponent(stop_button, javax.swing.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE)
                    .addComponent(clear_button, javax.swing.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE)
                    .addComponent(save_button, javax.swing.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE))
                .addGap(111, 111, 111))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    public void actionPerformed(ActionEvent e)
    {
        String action;
        action = e.getActionCommand();        
        if(action.equals("start"))
        {            
            capture = dev.openInterface(dev.getInterfaceByIndex(interface_combo.getSelectedIndex()),promiscuous.isSelected()); 
            capture_thread = new CaptureThread(capture,model,capture_tab);
            capture_thread.execute();
        }
        if(action.equals("stop"))
        {            
            capture_thread.cancel(true);            
        }
    }    

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new MainWin().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private CaptureThread capture_thread;
    private SystemInterfaces dev;    
    private String str[] = null;
    private CaptureTableModel model;
    private JpcapCaptor capture;    
    private javax.swing.JMenuItem capture_item1;
    private javax.swing.JMenuItem capture_item2;
    private javax.swing.JMenuItem capture_item3;
    private javax.swing.JTable capture_tab;
    private javax.swing.JButton clear_button;
    private javax.swing.JMenuItem file_item1;
    private javax.swing.JMenuItem file_item2;
    private javax.swing.JMenuItem file_item3;
    private javax.swing.JMenuItem file_item4;
    private javax.swing.JMenuItem help_item1;
    private javax.swing.JComboBox interface_combo;
    private javax.swing.JTextField ipaddr_field;
    private javax.swing.JComboBox jComboBox1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JScrollPane scroll;
    private javax.swing.JMenu menu1;
    private javax.swing.JMenu menu2;
    private javax.swing.JMenu menu3;
    private javax.swing.JMenu menu4;
    private javax.swing.JCheckBox promiscuous;
    private javax.swing.JButton save_button;
    private javax.swing.JButton start_button;
    private javax.swing.JButton stop_button;
    private String[][] packet = {{"#","#","#","#","#","#","#","#","#","#"}};
    private String[] columnNames = {"Sr. No.", "Time", "src MAC", "src IP", "src Port", "dest MAC", "dest IP", "dest Port", "Protocol", "TTL"};
    // End of variables declaration//GEN-END:variables
}


/************************************CaptureTableModel*********************/
    package TestClasses;
    import javax.swing.table.*;

    public class CaptureTableModel extends AbstractTableModel
    {
    String packet[][],columnNames[];
    CaptureTableModel(String[][] packet,String[] columnNames)
    {
        this.packet = packet;
        this.columnNames = columnNames;
    }    
    public int getColumnCount()
    {
        return columnNames.length;
    }
    public int getRowCount()
    {
        return packet.length;
    }
    public String getColumnName(int index)
    {
        return columnNames[index];
    } 
    public Object getValueAt(int row,int col)
        {
        return packet[row][col];
        }
    public Object[] getRow(int index)
        {
        return packet[index];
        }
    public void addPacket(String p[])
        {        
        String temp[][] = new String[getRowCount()+1][getColumnCount()];
        System.arraycopy(packet,0,temp,0,packet.length);
        temp[getRowCount()] = p;
        packet = temp;
        }
    }
2
Where is the relevant code? Namely model implementation, table instatiation. Are you sure the publish method gets called? - Howard
@Manan Pancholi, and why haven't you updated you other cross postings (coderanch.com/t/544918/GUI/java/JTable) to let people know that a solution has been found so people don't waste time answering questions that have already been answered. - camickr

2 Answers

4
votes

I cannot run your code, but I believe that your process method should accept a List of String array as a parameter and then have a for loop in it where you iterate through the list adding String arrays to the model inside of the loop. If you add the @Override annotation, I wonder if the compiler will complain that process doesn't truly override a super method. Something like this perhaps:

@Override // don't forget this!
public void process(List<String[]> chunks) {
  for(int i = 0; i < chunks.size(); i++) {
    model.addPacket(chunks.get(i));
    model.fireTableDataChanged();
  }
}

Note that code has not been tested.

4
votes

The SwingWorker method you have to override has the following signature:

@Override
protected void process(List<String[]> strs) {
    for(String[] str : strs) {
        model.addPacket(str);
    }
    model.fireTableDataChanged();
}

Therein you have to loop over several arrays (they may be accumulated from several calls to publish).

Instead you are defining a completely new method in your class (which does not override anything and therefore is never called).