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 = Logger.getLogger("org.evergreen_ils.hatch");
33 /** Root directory for all FileIO operations */
34 private static String profileDirectory = null;
35 private static String defaultDirectory = null;
36 private static boolean migrateProfileData = false;
38 private void configure() {
40 if (profileDirectory != null) {
41 return; // Already loaded
44 String home = System.getProperty("user.home");
45 defaultDirectory = new File(home, ".evergreen").getPath();
46 profileDirectory = Hatch.getProp("data.directory");
48 // Find the profile directory.
49 // The profile directory + origin string represent the base
50 // directory for all file I/O for this session.
51 if (profileDirectory == null) {
52 profileDirectory = defaultDirectory;
54 migrateProfileData = true;
57 logger.info("Using data directory: " + profileDirectory);
59 if (profileDirectory == null) {
60 logger.warning("Unable to set profile directory");
66 * Unpack a JSON request and send it to the necessary Hatch handler.
68 * @return True if the calling code should avoid calling reply() with
69 * the response object.
71 private boolean dispatchRequest(
72 JSONObject request, JSONObject response) throws JSONException {
74 String action = request.getString("action");
75 String origin = request.getString("origin");
77 logger.info("Received message id=" +
78 response.get("msgid") + " action=" + action);
80 if ("".equals(origin)) {
81 response.put("status", 404);
82 response.put("message", "'origin' parameter required");
87 String content = null;
88 FileIO fileIO = new FileIO(profileDirectory, origin);
90 if (migrateProfileData) {
91 fileIO.migrateProfileData(profileDirectory, defaultDirectory, origin);
97 response.put("content",
98 new PrintManager().getPrintersAsMaps());
101 case "printer-options":
103 String printer = request.optString("printer", null);
105 new PrintManager().getPrintersOptions(printer);
107 if (options == null) {
108 response.put("status", 400);
109 if (printer == null) {
110 response.put("message", "No default printer found");
112 response.put("message", "No such printer: " + printer);
115 response.put("content", options);
121 // Confirm a minimal data set to enqueue print requests.
122 content = request.getString("content");
123 String contentType = request.getString("contentType");
125 if (content == null || "".equals(content)) {
126 response.put("status", 400);
127 response.put("message", "Empty print message");
130 Hatch.enqueuePrintRequest(request);
131 // Responses to print requests are generated asynchronously
132 // and delivered from the FX print thread via reply().
136 case "keys": // Return stored keys
137 key = request.optString("key");
138 response.put("content", fileIO.keys(key));
142 key = request.getString("key");
143 String val = fileIO.get(key);
146 // Translate the JSON string stored by set() into a
147 // Java object that can be added to the response.
148 Object jsonBlob = new JSONTokener(val).nextValue();
149 response.put("content", jsonBlob);
154 key = request.getString("key");
156 // JSON-ify the thing stored under "content"
157 String json = JSONObject.valueToString(request.get("content"));
159 if (!fileIO.set(key, json)) {
160 response.put("status", 500);
161 response.put("message", "Unable to set key: " + key);
166 key = request.getString("key");
168 if (!fileIO.remove(key)) {
169 response.put("status", 500);
170 response.put("message", "Unable to remove key: " + key);
175 response.put("status", 404);
176 response.put("message", "Action not found: " + action);
183 * Most replies are delivered from within dispatchRequest, but some
184 * like printing require the reply be delivered from another thread.
186 protected static void reply(JSONObject response) {
187 io.sendMessage(response);
193 io.listen(); // STDIN/STDOUT handler
197 boolean skipReply = false;
198 JSONObject response = new JSONObject();
200 // Status values overidden as needed by the dispatch handler.
201 response.put("status", 200);
202 response.put("message", "OK");
205 JSONObject request = io.recvMessage();
207 response.put("clientid", request.getLong("clientid"));
208 response.put("msgid", request.getLong("msgid"));
210 skipReply = dispatchRequest(request, response);
212 } catch (JSONException je) {
213 response.put("status", 400);
214 response.put("message", "Bad Request: " + je.toString());
217 if (!skipReply) reply(response);