]> git.evergreen-ils.org Git - working/Hatch.git/blob - src/org/evergreen_ils/hatch/RequestHandler.java
LP1825896 Migrate values to new data directory
[working/Hatch.git] / src / org / evergreen_ils / hatch / RequestHandler.java
1 /* -----------------------------------------------------------------------
2  * Copyright 2016 King County Library System
3  * Bill Erickson <berickxx@gmail.com>
4  *
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.
9  *
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  * -----------------------------------------------------------------------
15  */
16 package org.evergreen_ils.hatch;
17
18 import org.json.*;
19 import java.io.File;
20 import java.util.logging.*;
21
22 /**
23  * Dispatches requests received via MessageIO, sends responses back 
24  * via MessageIO.
25  */
26 public class RequestHandler extends Thread {
27
28     /** STDIN/STDOUT handler */
29     private static MessageIO io = new MessageIO();
30
31     static final Logger logger = Logger.getLogger("org.evergreen_ils.hatch");
32
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;
37
38     private void configure() {
39
40         if (profileDirectory != null) {
41             return; // Already loaded
42         }
43
44         String home = System.getProperty("user.home");
45         defaultDirectory = new File(home, ".evergreen").getPath();
46         profileDirectory = Hatch.getProp("data.directory");
47
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;
53         } else {
54             migrateProfileData = true;
55         }
56
57         logger.info("Using data directory: " + profileDirectory);
58
59         if (profileDirectory == null) {
60             logger.warning("Unable to set profile directory");
61             return;
62         }
63     }
64
65     /**
66      * Unpack a JSON request and send it to the necessary Hatch handler.
67      *
68      * @return True if the calling code should avoid calling reply() with
69      * the response object.
70      */
71     private boolean dispatchRequest(
72         JSONObject request, JSONObject response) throws JSONException {
73
74         String action = request.getString("action");
75         String origin = request.getString("origin");
76
77         logger.info("Received message id=" + 
78             response.get("msgid") + " action=" + action);
79
80         if ("".equals(origin)) {
81             response.put("status", 404); 
82             response.put("message", "'origin' parameter required");
83             return false;
84         }
85
86         String key = null;
87         String content = null;
88         FileIO fileIO = new FileIO(profileDirectory, origin);
89
90         if (migrateProfileData) {
91             fileIO.migrateProfileData(profileDirectory, defaultDirectory, origin);
92         }
93
94         switch (action) {
95
96             case "printers":
97                 response.put("content",
98                     new PrintManager().getPrintersAsMaps());
99                 break;
100
101             case "printer-options":
102
103                 String printer = request.optString("printer", null);
104                 JSONObject options = 
105                     new PrintManager().getPrintersOptions(printer);
106
107                 if (options == null) {
108                     response.put("status", 400); 
109                     if (printer == null) {
110                         response.put("message", "No default printer found");
111                     } else {
112                         response.put("message", "No such printer: " + printer);
113                     }
114                 } else {
115                     response.put("content", options);
116                 }
117
118                 break;
119
120             case "print":
121                 // Confirm a minimal data set to enqueue print requests.
122                 content = request.getString("content");
123                 String contentType = request.getString("contentType");
124
125                 if (content == null || "".equals(content)) {
126                     response.put("status", 400); 
127                     response.put("message", "Empty print message");
128
129                 } else {
130                     Hatch.enqueuePrintRequest(request);
131                     // Responses to print requests are generated asynchronously 
132                     // and delivered from the FX print thread via reply().
133                     return true;
134                 }
135
136             case "keys": // Return stored keys
137                 key = request.optString("key");
138                 response.put("content", fileIO.keys(key));
139                 break;
140             
141             case "get":
142                 key = request.getString("key");
143                 String val = fileIO.get(key);
144
145                 if (val != null) {
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);
150                 }
151                 break;
152
153             case "set" :
154                 key = request.getString("key");
155
156                 // JSON-ify the thing stored under "content"
157                 String json = JSONObject.valueToString(request.get("content"));
158
159                 if (!fileIO.set(key, json)) {
160                     response.put("status", 500);
161                     response.put("message", "Unable to set key: " + key);
162                 }
163                 break;
164
165             case "remove":
166                 key = request.getString("key");
167
168                 if (!fileIO.remove(key)) {
169                     response.put("status", 500);
170                     response.put("message", "Unable to remove key: " + key);
171                 }
172                 break;
173
174             default:
175                 response.put("status", 404); 
176                 response.put("message", "Action not found: " + action);
177         }
178
179         return false;
180     }
181
182     /**
183      * Most replies are delivered from within dispatchRequest, but some
184      * like printing require the reply be delivered from another thread.
185      */
186     protected static void reply(JSONObject response) {
187         io.sendMessage(response);
188     }
189
190     public void run() {
191
192         configure();
193         io.listen(); // STDIN/STDOUT handler
194
195         while (true) { 
196
197             boolean skipReply = false;
198             JSONObject response = new JSONObject();
199
200             // Status values overidden as needed by the dispatch handler.
201             response.put("status", 200); 
202             response.put("message", "OK");
203
204             try {
205                 JSONObject request = io.recvMessage();
206
207                 response.put("clientid", request.getLong("clientid"));
208                 response.put("msgid", request.getLong("msgid"));
209
210                 skipReply = dispatchRequest(request, response); 
211
212             } catch (JSONException je) {
213                 response.put("status", 400); 
214                 response.put("message", "Bad Request: " + je.toString());
215             }
216
217             if (!skipReply) reply(response);
218         }
219     }
220 }
221