Java tutorial
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 }