diff --git a/addonInter/src/main/java/edu/regis/universeplayer/addon/BrowserLink.java b/addonInter/src/main/java/edu/regis/universeplayer/addon/BrowserLink.java index d8a959e..0ad8d60 100644 --- a/addonInter/src/main/java/edu/regis/universeplayer/addon/BrowserLink.java +++ b/addonInter/src/main/java/edu/regis/universeplayer/addon/BrowserLink.java @@ -6,13 +6,21 @@ package edu.regis.universeplayer.addon; import com.google.gson.*; +import com.google.gson.typeadapters.RuntimeTypeAdapterFactory; +import edu.regis.universeplayer.PlaybackInfo; +import edu.regis.universeplayer.PlaybackStatus; import edu.regis.universeplayer.browserCommands.*; +import edu.regis.universeplayer.data.Album; +import edu.regis.universeplayer.data.InternetSong; +import edu.regis.universeplayer.data.Song; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.Serializable; +import java.net.URL; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; @@ -21,7 +29,10 @@ import java.util.HashMap; /** * The browser link serves as a communication between this process and the * browser. It automatically converts information as needed as it passes it to - * and from the browser process. + * and from the browser process. It receives browser JSON data from the + * system input and converts it to Java objects that the interface can read. + * Likewise, it will convert Java objects into JSON objects that will be sent + * to the browser through the system output. * * @author William Hubbard * @version 0.1 @@ -49,6 +60,13 @@ public class BrowserLink extends MessageRunner super(name, System.in, System.out); } + /** + * Converts a Java object into a data stream for sending to the browser. + * + * @param message - The Java object to send. + * @return The byte stream representation of the JSON object that will be + * sent via {@link #writeMessage(OutputStream, int, byte[])} + */ @Override public byte[] serializeObject(Object message) { @@ -60,6 +78,14 @@ public class BrowserLink extends MessageRunner return val.toString().getBytes(StandardCharsets.UTF_8); } + /** + * Converts data string received from the browser into a Java object. + * + * @param message - The message data stream received, as received by + * {@link #readMessage(InputStream)}. + * @return The Java that maps to the JSON data the browser sent. + * @throws IOException + */ @Override public Object deserializeObject(byte[] message) throws IOException { @@ -67,6 +93,21 @@ public class BrowserLink extends MessageRunner return getMessage(val); } + /** + * Writes a message to the output stream. It takes a byte array of JSON + * data and then wraps it in another object containing the "messageNum" + * and "message" properties before writing that stream (preceded by the + * message length) to the browser. + *
+ * This implementation + * + * @param out - The output stream to write to. + * @param messageNum - The ID of the message being sent. This will help keep + * track of responses. + * @param message - The actual message contents to write. This will be + * a byte stream of encoded JSON data. + * @throws IOException + */ @Override public void writeMessage(OutputStream out, int messageNum, byte[] message) throws IOException { @@ -93,6 +134,18 @@ public class BrowserLink extends MessageRunner out.flush(); } + /** + * Reads a message from the input stream. It expects a message length + * followed by an encoded JSON message. This JSON message takes the form + * of two objects containing a "messageNum" property and "message" + * (containing the actual message). + * + * @param in - The input stream to read from. + * @return Two byte arrays, the first one containing the identifier of the + * message, and the second containing the byte stream of the actual JSON + * message sent. + * @throws IOException + */ @Override public byte[][] readMessage(InputStream in) throws IOException { @@ -131,7 +184,7 @@ public class BrowserLink extends MessageRunner lengthBuffer.clear(); lengthBuffer.putInt(messageNum); getLogger().debug("Reading message {}", messageNum); - return new byte[][] {lengthBuffer.array(), message}; + return new byte[][]{lengthBuffer.array(), message}; } /** @@ -270,7 +323,7 @@ public class BrowserLink extends MessageRunner } return returnValue; } - + @Override public Object getErrorObject(Throwable e) { diff --git a/addonInter/src/main/java/edu/regis/universeplayer/addon/Main.java b/addonInter/src/main/java/edu/regis/universeplayer/addon/Main.java index 19980d5..f146a76 100644 --- a/addonInter/src/main/java/edu/regis/universeplayer/addon/Main.java +++ b/addonInter/src/main/java/edu/regis/universeplayer/addon/Main.java @@ -17,6 +17,16 @@ import java.util.LinkedList; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +/** + * This class is responsible for setting up the intermediary program. The + * program is launched by the browser addon when the browser (not a tab, the + * browser) has launched and the addon has loaded. It launches two forwarding + * streams: one between this application and the browser that translates + * between the JSON format the browser uses and the serialized Java objects + * that this program uses (working over console I/O), and a second link to + * communicate between the interface and the browser link over the localhost + * (as defined by the socket server the interface sets up). + */ public class Main { private static final Logger logger = LoggerFactory.getLogger(Main.class); @@ -29,6 +39,11 @@ public class Main Socket socket = null; try { + /* + * Sets up a two-way data stream to the browser through the + * process I/O streams. This converts between JSON data used by + * the browser to serializable Java objects used by the interface. + */ logger.debug("Connecting to browser"); browserLink = new BrowserLink("BrowserLink"); try @@ -37,6 +52,10 @@ public class Main socket = new Socket(BrowserConstants.IP, BrowserConstants.PORT); logger.debug("Connection established"); + /* + * Sets up the data stream between this application and the + * interface. + */ Socket finalSocket = socket; interfaceLink = new MessageHandler("InterfaceHandler", finalSocket.getInputStream(), finalSocket.getOutputStream()) { @@ -47,7 +66,7 @@ public class Main { /* * How many milliseconds must pass between browser - * pings. + * pings before this stream shuts down. */ final long PING_RATE = 5000; if (!finalSocket.isConnected() || finalSocket.isClosed() || finalSocket.isInputShutdown() || finalSocket.isOutputShutdown()) @@ -56,7 +75,9 @@ public class Main return true; } /* - * Make sure that it is active. + * Make sure that it is active, either with logs from + * the browser or just with ping messages sent from + * here. */ if (QueueAppender.hasLogs()) { @@ -92,7 +113,9 @@ public class Main logger.debug("Connection received"); /* * Pretty much just forwards any messages to the browser and - * returns their value. + * returns their value. This is primarily a one-way + * relationship, where the interface sends commands, and the + * browser returns updates and responses. */ browserLink.addUpdateListener((update, link) -> { @@ -107,6 +130,9 @@ public class Main return returnValue; }); + /* + * Sets up both streams on their own threads. + */ browserThread = new Thread(browserLink); interfaceThread = new Thread(interfaceLink); @@ -114,6 +140,9 @@ public class Main browserThread.start(); interfaceThread.start(); logger.debug("Joining threads."); + /* + * Waits for both threads to shut down. + */ try { browserThread.join();