import java.io.IOException;
import org.json.*;
-
+/**
+ * Reads and writes JSON strings from STDIN / to STDOUT.
+ *
+ * Each string is prefixed with a 4-byte message length header. All I/O
+ * occurs in a separate thread, so no blocking of the main thread occurs.
+ */
public class MessageIO {
private LinkedBlockingQueue<JSONObject> inQueue;
writer = new MessageWriter();
}
+ /**
+ * Starts the read and write threads.
+ */
public void listen() {
writer.start();
reader.start();
}
+ /**
+ * Receive one message from STDIN.
+ *
+ * This call blocks the current thread until a message is available.
+ */
public JSONObject recvMessage() {
while (true) {
try {
}
}
+ /**
+ * Queue a message for sending to STDOUT.
+ */
public void sendMessage(JSONObject msg) {
outQueue.offer(msg);
}
+ /**
+ * Thrown when STDIN or STDOUT are closed.
+ */
class EndOfStreamException extends IOException { }
+ /**
+ * Reads JSON-encoded strings from STDIN.
+ *
+ * As messages arrive, they are enqueued for access by recvMessage().
+ *
+ * Each message is prefixed with a 4-byte message length header.
+ */
class MessageReader extends Thread {
+ /**
+ * Converts a 4-byte array to its integer value.
+ */
private int bytesToInt(byte[] bytes) {
return
(bytes[3] << 24) & 0xff000000
| (bytes[0] << 0) & 0x000000ff;
}
+ /**
+ * Reads one message from STDIN.
+ *
+ * This method blocks until a message is available.
+ */
private String readOneMessage() throws EndOfStreamException, IOException {
byte[] lenBytes = new byte[4];
int bytesRead = System.in.read(lenBytes);
return message;
}
+ /**
+ * Read messages from STDIN until STDIN is closed or the application exits.
+ */
public void run() {
while (true) {
}
}
+ /**
+ * Writes JSON-encoded strings from STDOUT.
+ *
+ * As messages are queued for delivery, each is serialized as a JSON
+ * string and stamped with a 4-byte length header.
+ */
class MessageWriter extends Thread {
+ /**
+ * Returns the 4-byte array representation of an integer.
+ */
private byte[] intToBytes(int length) {
byte[] bytes = new byte[4];
bytes[0] = (byte) (length & 0xFF);
return bytes;
}
+ /**
+ * Encodes and writes one message to STDOUT.
+ */
public void writeOneMessage(String message) throws IOException {
System.out.write(intToBytes(message.length()));
System.out.write(message.getBytes("UTF-8"));
System.out.flush();
}
+ /**
+ * Waits for messages to be queued for delivery and writes
+ * each to STDOUT until STDOUT is closed or the application exits.
+ */
public void run() {
while (true) {
public Map<String,Object> configurePrinter(
Map<String,Object> params) throws IllegalArgumentException {
+ @SuppressWarnings("unchecked")
Map<String,Object> settings =
(Map<String,Object>) params.get("config");
Long msgid = (Long) params.get("msgid");
Boolean showDialog = (Boolean) params.get("showDialog");
+ @SuppressWarnings("unchecked")
Map<String,Object> settings =
(Map<String,Object>) params.get("config");
Map<String,Object> settings, Printer printer) {
// modify the default page layout with our settings
+ @SuppressWarnings("unchecked")
Map<String,Object> layoutMap =
(Map<String,Object>) settings.get("pageLayout");