src/main/java/io/codepace/cozy/p2p/OutputThread.java

Summary

Maintainability
A
3 hrs
Test Coverage
package io.codepace.cozy.p2p;

import java.io.File;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;

/**
 * OutputThread writes data to a peer, and never reads in any data in order to prevent blocking and waiting, or some terrible constant back-and-forth keepalive.
 * Data written isn't saved anywhere. This behavior doesn't need to be run in a thread, but would block activity on the main thread if write calls were direct.
 * Instead, any calls to OutputThread's external methods are extremely lightweight (putting a String in a buffer) rather than waiting on network IO to execute.
 */
public class OutputThread extends Thread {
    private Socket socket;

    //Private to mirror InputThread's structure. For OOP model, it makes more sense for a method to simulate 'writing' data (even though it is delayed until the thread writes the data).

    private ArrayList<String> outputBuffer;
    private boolean shouldContinue = true;

    /**
     * Constructor to set class socket variable
     * @param socket The socket to use with the thread
     */
    public OutputThread(Socket socket) {
        this.socket = socket;
    }

    /**
     * Constantly checks outputBuffer for contents, and writes any contents in outputBuffer.
     */
    public void run() {
        try {
            outputBuffer = new ArrayList<>();
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            while (shouldContinue) {
                if (outputBuffer.size() > 0) {
                    if (outputBuffer.get(0) != null) {
                        for (int i = 0; i < outputBuffer.size(); i++) {
                            if (outputBuffer.get(i).length() > 20) {
                                System.out.println("Sending " + outputBuffer.get(i).substring(0, 20) + " to " + socket.getInetAddress());
                            } else {
                                System.out.println("Sending " + outputBuffer.get(i) + " to " + socket.getInetAddress());
                            }
                            out.println(outputBuffer.get(i));
                        }
                        outputBuffer = new ArrayList<>();
                        outputBuffer.add(null);
                    }
                }
                Thread.sleep(100);
            }
            System.out.println("WHY AM I HERE");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Technically not writing to the network socket, but instead putting the passed-in data in a buffer to be written to the socket as soon as possible.
     *
     * @param data Data to write
     */
    public void write(String data) {
        if (data.length() > 20) {
            System.out.println("PUTTING INTO WRITE BUFFER: " + data.substring(0, 20) + "...");
        } else {
            System.out.println("PUTTING INTO WRITE BUFFER: " + data);
        }
        File f = new File("writebuffer");
        try {
            PrintWriter out = new PrintWriter(f);
            out.println("SENDING: " + data);
            out.close();
        } catch (Exception e) {
        }
        if (outputBuffer.size() > 0) {
            if (outputBuffer.get(0) == null) {
                outputBuffer.remove(0);
            }
        }
        outputBuffer.add(data);
    }

    /**
     * Stops thread during the next write cycle. I couldn't call it stop() like I wanted to, cause you can't overwrite that method of Thread. :'(
     */
    public void shutdown() {
        shouldContinue = false;
    }
}