1 /* -----------------------------------------------------------------------
2 * Copyright 2016 King County Library System
3 * Bill Erickson <berickxx@gmail.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * -----------------------------------------------------------------------
16 package org.evergreen_ils.hatch;
20 import java.util.logging.*;
23 * Dispatches requests received via MessageIO, sends responses back
26 public class RequestHandler extends Thread {
28 /** STDIN/STDOUT handler */
29 private static MessageIO io = new MessageIO();
31 static final Logger logger = Hatch.getLogger();
33 /** Root directory for all FileIO operations */
34 private static String profileDirectory = null;
36 /** Origin host/domain used for segregating files by browser host */
37 private static String origin = null;
39 private void configure() {
41 // Find the profile directory.
42 // The profile directory + origin string represent the base
43 // directory for all file I/O for this session.
44 if (profileDirectory == null) { // TODO: make configurable
45 String home = System.getProperty("user.home");
46 profileDirectory = new File(home, ".evergreen").getPath();
47 if (profileDirectory == null) {
48 logger.warning("Unable to set profile directory");
54 * Unpack a JSON request and send it to the necessary Hatch handler.
56 * @return True if the calling code should avoid calling reply() with
57 * the response object.
59 private boolean dispatchRequest(
60 JSONObject request, JSONObject response) throws JSONException {
62 String action = request.getString("action");
64 logger.info("Received message id=" +
65 response.get("msgid") + " action=" + action);
67 // init must be called first to set the origin info
68 if (action.equals("init")) {
69 origin = request.getString("origin");
74 response.put("status", 400);
75 response.put("message", "'init' action must be called first!");
80 String content = null;
81 FileIO fileIO = new FileIO(profileDirectory, origin);
86 response.put("printers",
87 new PrintManager().getPrintersAsMaps());
91 // Confirm a minimal data set to enqueue print requests.
92 content = request.getString("content");
93 String contentType = request.getString("contentType");
95 if (content == null || "".equals(content)) {
96 response.put("status", 400);
97 response.put("message", "Empty print message");
100 Hatch.enqueuePrintRequest(request);
101 // Responses to print requests are generated asynchronously
102 // and delivered from the FX print thread via reply().
106 case "keys": // Return stored keys
107 String pfxKey = request.optString("key");
108 response.put("keys", fileIO.keys(pfxKey));
112 key = request.getString("key");
113 String val = fileIO.get(key);
116 // Translate the JSON string stored by set() into a
117 // Java object that can be added to the response.
118 Object jsonBlob = new JSONTokener(val).nextValue();
119 response.put("content", jsonBlob);
124 key = request.getString("key");
126 // JSON-ify the thing stored under "content"
127 String json = JSONObject.valueToString(request.get("content"));
129 if (!fileIO.set(key, json)) {
130 response.put("status", 500);
131 response.put("message", "Unable to set key: " + key);
136 key = request.getString("key");
138 if (!fileIO.remove(key)) {
139 response.put("status", 500);
140 response.put("message", "Unable to remove key: " + key);
145 response.put("status", 404);
146 response.put("message", "Action not found: " + action);
153 * Most replies are delivered from within dispatchRequest, but some
154 * like printing require the reply be delivered from another thread.
156 protected static void reply(JSONObject response) {
157 io.sendMessage(response);
163 io.listen(); // STDIN/STDOUT handler
167 boolean skipReply = false;
168 JSONObject response = new JSONObject();
170 // Status values overidden as needed by the dispatch handler.
171 response.put("status", 200);
172 response.put("message", "OK");
175 JSONObject request = io.recvMessage();
177 response.put("clientid", request.getLong("clientid"));
178 response.put("msgid", request.getLong("msgid"));
180 skipReply = dispatchRequest(request, response);
182 } catch (JSONException je) {
183 response.put("status", 400);
184 response.put("message", "Bad Request: " + je.toString());
187 if (!skipReply) reply(response);