PeerPanel.java Source code

Java tutorial

Introduction

Here is the source code for PeerPanel.java

Source

import java.awt.Font;
import java.awt.FontMetrics;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.WritableByteChannel;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.SwingWorker;
import org.apache.commons.io.IOUtils;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Alex
 */
public class PeerPanel extends javax.swing.JPanel {
    private File saveDirectory;
    private final MainFrame mainFrame;
    private ReceiveTransferableFiles transfer;

    /**
     * Creates new form PeerPanel
     */
    public PeerPanel(MainFrame main) {
        mainFrame = main;
        saveDirectory = new File(".").getAbsoluteFile().getParentFile();
        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() {

        saveLocationTitle = new javax.swing.JLabel();
        saveLocationDisplay = new javax.swing.JTextField();
        saveLocationButton = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JSeparator();
        transferTitle = new javax.swing.JLabel();
        transferValue = new javax.swing.JLabel();
        currentTitle = new javax.swing.JLabel();
        currentValue = new javax.swing.JLabel();
        filenameTitle = new javax.swing.JLabel();
        filenameValue = new javax.swing.JLabel();
        lengthTitle = new javax.swing.JLabel();
        lengthValue = new javax.swing.JLabel();
        jSeparator2 = new javax.swing.JSeparator();
        serverTitle = new javax.swing.JLabel();
        serverValue = new javax.swing.JTextField();
        portTitle = new javax.swing.JLabel();
        portValue = new javax.swing.JTextField();
        globalProgress = new javax.swing.JProgressBar();
        currentProgress = new javax.swing.JProgressBar();
        transferButton = new javax.swing.JButton();

        saveLocationTitle.setText("Save Location");
        saveLocationTitle.setFocusable(false);

        saveLocationDisplay.setEditable(false);
        saveLocationDisplay.setText(saveDirectory.getAbsolutePath());
        saveLocationDisplay.setFocusable(false);

        saveLocationButton.setText("Browse");
        saveLocationButton.setFocusable(false);
        saveLocationButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveLocationButtonActionPerformed(evt);
            }
        });

        transferTitle.setText("Total Files to Transfer:");
        transferTitle.setFocusable(false);

        transferValue.setText("");
        transferValue.setFocusable(false);

        currentTitle.setText("Current File:");
        currentTitle.setFocusable(false);

        currentValue.setText("");
        currentValue.setFocusable(false);

        filenameTitle.setText("Filename:");
        filenameTitle.setFocusable(false);

        filenameValue.setText("");
        filenameValue.setFocusable(false);

        lengthTitle.setText("File Size:");
        lengthTitle.setFocusable(false);

        lengthValue.setText("");
        lengthValue.setFocusable(false);

        serverTitle.setText("Server:");
        serverTitle.setFocusable(false);

        serverValue.setBackground(javax.swing.UIManager.getDefaults().getColor("Panel.background"));
        serverValue.setHorizontalAlignment(javax.swing.JTextField.CENTER);

        portTitle.setText("Port:");
        portTitle.setFocusable(false);

        portValue.setBackground(javax.swing.UIManager.getDefaults().getColor("Panel.background"));
        portValue.setHorizontalAlignment(javax.swing.JTextField.CENTER);

        globalProgress.setFocusable(false);
        globalProgress.setStringPainted(true);

        currentProgress.setFocusable(false);
        currentProgress.setStringPainted(true);

        transferButton.setText("Receive");
        transferButton.setActionCommand("receive");
        transferButton.setPreferredSize(new java.awt.Dimension(57, 23));
        transferButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                transferButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup().addContainerGap().addGroup(layout
                        .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(jSeparator2, javax.swing.GroupLayout.Alignment.TRAILING)
                        .addGroup(layout.createSequentialGroup().addComponent(saveLocationTitle).addGap(18, 18, 18)
                                .addComponent(saveLocationDisplay).addGap(18, 18, 18)
                                .addComponent(saveLocationButton, javax.swing.GroupLayout.PREFERRED_SIZE, 75,
                                        javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.TRAILING)
                        .addGroup(layout.createSequentialGroup().addGroup(layout
                                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addGroup(layout.createSequentialGroup().addGroup(
                                        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                                .addComponent(portTitle).addComponent(serverTitle))
                                        .addGap(18, 18, 18)
                                        .addGroup(layout
                                                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                                .addComponent(serverValue, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                        127, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                .addComponent(portValue, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                        127, javax.swing.GroupLayout.PREFERRED_SIZE)))
                                .addComponent(globalProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 165,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(currentProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 165,
                                        javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 379,
                                        Short.MAX_VALUE)
                                .addComponent(transferButton, javax.swing.GroupLayout.PREFERRED_SIZE, 120,
                                        javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                        .addComponent(currentTitle).addComponent(transferTitle)
                                        .addComponent(filenameTitle).addComponent(lengthTitle))
                                .addGap(18, 18, 18)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(transferValue, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addComponent(currentValue, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addComponent(filenameValue, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addComponent(lengthValue, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                        .addContainerGap()));
        layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup().addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(saveLocationTitle).addComponent(saveLocationButton)
                                .addComponent(saveLocationDisplay, javax.swing.GroupLayout.PREFERRED_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10,
                                javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(transferTitle).addComponent(transferValue))
                        .addGap(18, 18, 18)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(currentTitle).addComponent(currentValue))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(filenameTitle).addComponent(filenameValue))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(lengthTitle).addComponent(lengthValue))
                        .addGap(18, 18, 18)
                        .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10,
                                javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(serverTitle).addComponent(serverValue,
                                        javax.swing.GroupLayout.PREFERRED_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(portTitle).addComponent(portValue,
                                        javax.swing.GroupLayout.PREFERRED_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 72, Short.MAX_VALUE)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                .addGroup(layout.createSequentialGroup()
                                        .addComponent(currentProgress, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(globalProgress, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addComponent(transferButton, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addContainerGap()));
    }// </editor-fold>//GEN-END:initComponents

    private void saveLocationButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveLocationButtonActionPerformed
        JFileChooser jfc = new JFileChooser();
        jfc.setCurrentDirectory(saveDirectory);
        jfc.setMultiSelectionEnabled(false);
        jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        if (jfc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            saveDirectory = jfc.getSelectedFile();
            saveLocationDisplay.setText(saveDirectory.getAbsolutePath());
        }
    }//GEN-LAST:event_saveLocationButtonActionPerformed

    private void transferButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_transferButtonActionPerformed
        switch (evt.getActionCommand()) {
        case "receive":
            transfer = new ReceiveTransferableFiles("localhost", //serverValue.getText(),
                    12345//Integer.parseInt(portValue.getText())
            );
            transfer.execute();

            mainFrame.jTabbedPane1.setEnabledAt(0, false);
            saveLocationButton.setEnabled(false);
            mainFrame.setTitle(
                    "JavaP2P - Listening on: " + serverValue.getText() + ":" + portValue.getText() + "...");
            transferButton.setText("Cancel");
            transferButton.setActionCommand("cancel");
            break;

        case "cancel":
            if (transfer != null)
                transfer.cancel(true);
            break;
        }
    }//GEN-LAST:event_transferButtonActionPerformed

    private class ReceiveTransferableFiles extends SwingWorker<Boolean, String> {
        private final String ip;
        private final int port;

        public ReceiveTransferableFiles(String ip, int port) {
            this.ip = ip;
            this.port = port;
            this.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if ("progress".equals(evt.getPropertyName()))
                        currentProgress.setValue((Integer) evt.getNewValue());
                }
            });
        }

        @Override
        protected Boolean doInBackground() throws Exception {
            try (Socket socket = new Socket(ip, port);
                    BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
                    DataInputStream dis = new DataInputStream(bis)) {
                int transfers = dis.readInt();
                transferValue.setText(Integer.toString(transfers));

                mainFrame.setTitle("JavaP2P - Receiving data...");
                for (int i = 0; i < transfers; i++) {
                    File relativeFile = new File(saveDirectory, dis.readUTF());
                    long fileLength = dis.readLong();

                    globalProgress.setValue(calcPercent(i + 1, transfers));
                    currentValue.setText((i + 1) + " of " + transfers);

                    int truncatePoint = truncatePoint(
                            filenameValue.getFontMetrics(new Font("Segoe UI", Font.PLAIN, 11)),
                            relativeFile.getName(), filenameValue.getBounds().width);
                    filenameValue.setText(relativeFile.getName().substring(0, truncatePoint));
                    lengthValue.setText(humanReadableByteCount(fileLength, false));

                    try (FileOutputStream fos = new FileOutputStream(relativeFile);
                            BufferedOutputStream bos = new BufferedOutputStream(fos)) {
                        long bl = fileLength, bp = 0;
                        byte[] bb = new byte[socket.getReceiveBufferSize()];
                        int br = 0;

                        while (!this.isCancelled() && bl > 0
                                && (br = dis.read(bb, 0, (int) Math.min(bb.length, bl -= br))) != -1) {
                            bos.write(bb, 0, br);
                            this.setProgress(calcPercent(bp += br, fileLength));
                        }
                    }
                    if (this.isCancelled())
                        return false;
                }
            }

            return true;
        }

        @Override
        protected void done() {
            try {
                this.get();
            } catch (InterruptedException | ExecutionException | CancellationException ex) {
                Logger.getLogger(HostPanel.class.getName()).log(Level.SEVERE, null, ex);
            }

            mainFrame.jTabbedPane1.setEnabledAt(0, true);
            saveLocationButton.setEnabled(true);
            transferButton.setText("Receive");
            transferButton.setActionCommand("receive");
            mainFrame.setTitle("JavaP2P");
        }
    }

    private int truncatePoint(FontMetrics fontMetrics, String string, int boundsWidth) {
        int stringWidth = fontMetrics.stringWidth(string);
        if (stringWidth > boundsWidth)
            return truncatePoint(fontMetrics, string.substring(0, string.length() - 1), boundsWidth);
        return string.length();
    }

    private String humanReadableByteCount(long bytes, boolean si) {
        int unit = si ? 1000 : 1024;
        if (bytes < unit)
            return bytes + " B";
        int exp = (int) (Math.log(bytes) / Math.log(unit));
        String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "i" : "");
        return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
    }

    private int calcPercent(long numerator, long denominator) {
        return (int) (numerator * 100.0 / denominator + 0.5);
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JProgressBar currentProgress;
    private javax.swing.JLabel currentTitle;
    private javax.swing.JLabel currentValue;
    private javax.swing.JLabel filenameTitle;
    private javax.swing.JLabel filenameValue;
    private javax.swing.JProgressBar globalProgress;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JLabel lengthTitle;
    private javax.swing.JLabel lengthValue;
    private javax.swing.JLabel portTitle;
    private javax.swing.JTextField portValue;
    private javax.swing.JButton saveLocationButton;
    private javax.swing.JTextField saveLocationDisplay;
    private javax.swing.JLabel saveLocationTitle;
    private javax.swing.JLabel serverTitle;
    private javax.swing.JTextField serverValue;
    private javax.swing.JButton transferButton;
    private javax.swing.JLabel transferTitle;
    private javax.swing.JLabel transferValue;
    // End of variables declaration//GEN-END:variables
}