source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/Receptionist.java@ 32549

Last change on this file since 32549 was 32549, checked in by kjdon, 5 years ago

receptionist now passes languageList (from interfaceConfig) to teh actions, so an action can add it into the page response if it needs to, rather than the receptionist adding it in to every page. its only ever used in prefs page

  • Property svn:keywords set to Author Date Id Revision
File size: 12.3 KB
Line 
1package org.greenstone.gsdl3.core;
2
3import java.io.File;
4import java.util.ArrayList;
5import java.util.HashMap;
6
7import org.apache.log4j.Logger;
8import org.greenstone.gsdl3.action.Action;
9import org.greenstone.gsdl3.util.GSConstants;
10import org.greenstone.gsdl3.util.GSFile;
11import org.greenstone.gsdl3.util.GSParams;
12import org.greenstone.gsdl3.util.GSXML;
13import org.greenstone.gsdl3.util.XMLConverter;
14import org.greenstone.util.GlobalProperties;
15import org.w3c.dom.Document;
16import org.w3c.dom.Element;
17import org.w3c.dom.Node;
18import org.w3c.dom.NodeList;
19import org.w3c.dom.NamedNodeMap;
20
21/**
22 * the most basic Receptionist, used for interface generation. Receives requests
23 * consisting of an xml representation of cgi args, and returns the page of
24 * data. The requests are processed by the appropriate action class
25 *
26 * @see Action
27 */
28public class Receptionist implements ModuleInterface
29{
30
31 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.Receptionist.class.getName());
32
33 /** the set up variables */
34 protected HashMap<String, Object> config_params = null;
35 /** container Document to create XML Nodes */
36 //protected Document doc = null;
37
38 /** a converter class to parse XML and create Docs */
39 protected XMLConverter converter = null;
40
41 /** the message router that the Receptionist and Actions will talk to */
42 protected ModuleInterface mr = null;
43
44 /** the list of actions */
45 protected HashMap<String, Action> action_map = null;
46
47 /** the list of params */
48 protected GSParams params = null;
49 protected Element language_list = null;
50
51 /** the list of interfaces this is based on */
52 protected ArrayList<String> base_interfaces = null;
53
54 public Receptionist()
55 {
56 this.converter = new XMLConverter();
57 //this.doc = XMLConverter.newDOM();
58 this.action_map = new HashMap<String, Action>();
59 }
60
61 public void cleanUp()
62 {
63 if (this.mr != null)
64 {
65 this.mr.cleanUp();
66 }
67 }
68
69 public void setParams(GSParams params)
70 {
71 this.params = params;
72 }
73
74 public void setConfigParams(HashMap<String, Object> params)
75 {
76 this.config_params = params;
77 }
78
79 public HashMap<String, Object> getConfigParams()
80 {
81 return this.config_params;
82 }
83
84 /**
85 * sets the message router - it should already be created and configured
86 * before being passed to the receptionist
87 */
88 public void setMessageRouter(ModuleInterface m)
89 {
90 this.mr = m;
91 }
92
93 /**
94 * gets the message router
95 */
96 public ModuleInterface getMessageRouter()
97 {
98 return this.mr;
99 }
100
101 /** configures the receptionist */
102 public boolean configure()
103 {
104
105 if (this.config_params == null)
106 {
107 logger.error(" config variables must be set before calling configure");
108 return false;
109 }
110 if (this.mr == null)
111 {
112 logger.error(" message router must be set before calling configure");
113 return false;
114 }
115
116 // find the config file containing a list of actions
117 File interface_config_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.INTERFACE_NAME))));
118 if (!interface_config_file.exists())
119 {
120 logger.error(" interface config file: " + interface_config_file.getPath() + " not found!");
121 return false;
122 }
123
124 Document config_doc = this.converter.getDOM(interface_config_file);
125 if (config_doc == null)
126 {
127 logger.error(" could not parse interface config file: " + interface_config_file.getPath());
128 return false;
129 }
130 Element config_elem = config_doc.getDocumentElement();
131 String base_interface = config_elem.getAttribute("baseInterface");
132 setUpBaseInterface(base_interface);
133 setUpInterfaceOptions(config_elem);
134
135 this.language_list = (Element) GSXML.getChildByTagName(config_elem, "languageList");
136 if (this.language_list == null)
137 {
138 logger.error(" didn't find a language list in the config file!!");
139 }
140
141 // load up the actions
142 Element action_list = (Element) GSXML.getChildByTagName(config_elem, GSXML.ACTION_ELEM + GSXML.LIST_MODIFIER);
143 NodeList actions = action_list.getElementsByTagName(GSXML.ACTION_ELEM);
144
145 for (int i = 0; i < actions.getLength(); i++)
146 {
147 Element action = (Element) actions.item(i);
148 String class_name = action.getAttribute("class");
149 String action_name = action.getAttribute("name");
150 Action ac = null;
151 try
152 {
153 ac = (Action) Class.forName("org.greenstone.gsdl3.action." + class_name).newInstance();
154 }
155 catch (Exception e)
156 {
157 logger.error(" couldn't load in action " + class_name);
158 e.printStackTrace();
159 continue;
160 }
161 ac.setConfigParams(this.config_params);
162 ac.setMessageRouter(this.mr);
163 ac.configure();
164 ac.addActionParameters(this.params);
165 ac.setLanguageList(this.language_list);
166 this.action_map.put(action_name, ac);
167 }
168
169
170 return true;
171 }
172
173 public String process(String xml_in)
174 {
175
176 Node message_node = this.converter.getDOM(xml_in);
177 Node page = process(message_node);
178 return this.converter.getString(page);
179 }
180
181 /**
182 * process - produce a page of data in response to a request if something
183 * goes wrong, it returns null - TODO: return a suitable message to the user
184 */
185 public Node process(Node message_node)
186 {
187 Element message = GSXML.nodeToElement(message_node);
188
189 // get the request out of the message - assume that there is only one
190 Element request = (Element) GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
191 if (request == null)
192 {
193 logger.error(" message had no request!");
194 return null;
195 }
196 // check the request type
197 String type = request.getAttribute(GSXML.TYPE_ATT); // returns "" if no att of this name
198 if (type.equals(GSXML.REQUEST_TYPE_SECURITY))
199 {
200 return this.mr.process(message);
201 }
202
203 if (!type.equals(GSXML.REQUEST_TYPE_PAGE))
204 {
205 // now Receptionist forwards non-page requests straight to the MR, and returns the responses
206 logger.debug(" request type is not '" + GSXML.REQUEST_TYPE_PAGE + "', but it is '" + type + "', so forwarding the message to the MR!");
207 // process the whole message - mr needs <message> tags, and
208 // in this case, there may be more than one request in the message
209 return this.mr.process(message);
210 }
211 // work out which action to pass to
212 String action = request.getAttribute(GSXML.ACTION_ATT);
213 if (action.equals(""))
214 {
215 logger.error(" no action specified in the request!");
216 return null;
217 }
218
219 // find the appropriate action
220 Action a = this.action_map.get(action);
221
222 String action_name = null;
223 if (a == null)
224 { // not in the map yet
225 // try to load a new action
226 try
227 {
228 action_name = action.substring(0, 1).toUpperCase() + action.substring(1) + "Action";
229 Action ac = (Action) Class.forName("org.greenstone.gsdl3.action." + action_name).newInstance();
230 ac.setConfigParams(this.config_params);
231 ac.setMessageRouter(this.mr);
232 ac.configure();
233 ac.addActionParameters(this.params);
234 ac.setLanguageList(this.language_list);
235 this.action_map.put(action, ac);
236 a = ac;
237 }
238 catch (Exception e)
239 {
240
241 logger.error(" a new action (" + action_name + ") was specified and it couldn't be created. Error message:" + e.getMessage());
242 return null;
243 }
244 }
245 // transform the request in some way -- does nothing!
246 preProcessRequest(request);
247 // set up the page
248 Document doc = XMLConverter.newDOM();
249 Element page = doc.createElement(GSXML.PAGE_ELEM);
250 page.setAttribute(GSXML.LANG_ATT, request.getAttribute(GSXML.LANG_ATT));
251 // just in case these namespaces end up in the page and we want to display the XML
252 GSXML.addGSNamespaces(page, false);
253
254 //logger.info(a+" mesa=" + this.converter.getPrettyString(message));
255 // get the page data from the action
256
257 Node action_response = a.process(message);
258 boolean response_only = false;
259 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
260 if (param_list != null)
261 {
262 Element param = GSXML.getNamedElement(param_list, GSXML.PARAM_ELEM, GSXML.NAME_ATT, "ro");
263 if (param != null)
264 {
265 String value = param.getAttribute("value");
266 if (value.equals("1"))
267 {
268 response_only = true;
269 }
270 }
271 }
272 if (response_only)
273 {
274 // only the response from the action is sent back
275 return action_response;
276 }
277
278 // the request is part of the page
279 page.appendChild(duplicateRequest(doc, request));
280 // add the response too
281 Element page_response = GSXML.duplicateWithNewName(doc, (Element) GSXML.getChildByTagName(action_response, GSXML.RESPONSE_ELEM), GSXML.PAGE_RESPONSE_ELEM, true);
282 page.appendChild(page_response);
283
284 //logger.info(" raw page="+this.converter.getString(page));
285 // transform the result in some way
286 //Element resulting_page = postProcessPage(page);
287
288 Node resulting_page = postProcessPage(page);
289
290 //logger.debug("receptionist returned response");
291 //logger.error("receptionist returned response");
292 //logger.debug(this.converter.getString(resulting_page));
293 //logger.error(this.converter.getString(resulting_page));
294 // logger.info("receptionist returned response");
295 // logger.info(this.converter.getString(resulting_page));
296 return resulting_page;
297 }
298
299 // This is pretty much a straight copy of the Element, with a new top root node name, but also, removing any NOSAVE parameters.
300 protected Element duplicateRequest(Document owner, Element request) {
301
302 Element duplicate;
303 duplicate = owner.createElement(GSXML.PAGE_REQUEST_ELEM);
304 // Copy element attributes
305 NamedNodeMap attributes = request.getAttributes();
306 for (int i = 0; i < attributes.getLength(); i++)
307 {
308 Node attribute = attributes.item(i);
309 duplicate.setAttribute(attribute.getNodeName(), attribute.getNodeValue());
310 }
311 // Copy element children
312 NodeList children = request.getChildNodes();
313 for (int i = 0; i < children.getLength(); i++)
314 {
315 Node child = children.item(i);
316 if (child.getNodeName().equals(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER)) {
317 Element param_list = (Element)owner.importNode(child, true);
318 NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
319 for (int j=params.getLength()-1; j>=0; j--) {
320 Element p = (Element)params.item(j);
321 if (!p.getAttribute(GSXML.SENSITIVE_ATT).equals("")) {
322 logger.debug("removing param "+p.getAttribute("name"));
323 param_list.removeChild(p);
324 }
325 }
326 duplicate.appendChild(param_list);
327 } else {
328 duplicate.appendChild(owner.importNode(child, true));
329 }
330 }
331
332
333 return duplicate;
334
335
336
337
338 }
339 protected boolean setUpBaseInterface(String base_interface)
340 {
341 if (base_interface == null || base_interface.equals(""))
342 {
343 // there was no base interface, the list remains null
344 return true;
345 }
346 // foreach base interface
347 while (!base_interface.equals(""))
348 {
349 // find the base interface config file
350 File base_interface_config_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), base_interface)));
351 if (!base_interface_config_file.exists())
352 {
353 logger.error(" base interface config file: " + base_interface_config_file.getPath() + " not found!");
354 return false;
355 }
356 // the interface name is valid, add it to the list
357 if (base_interfaces == null)
358 {
359 base_interfaces = new ArrayList<String>();
360 }
361 base_interfaces.add(base_interface);
362 this.config_params.put(GSConstants.BASE_INTERFACES, base_interfaces);
363 // now see if this has a base interface
364 Document config_doc = this.converter.getDOM(base_interface_config_file);
365 if (config_doc == null)
366 {
367 logger.error(" could not parse base interface config file: " + base_interface_config_file.getPath());
368 return false;
369 }
370 Element config_elem = config_doc.getDocumentElement();
371 base_interface = config_elem.getAttribute("baseInterface");
372 }
373 return true;
374 }
375
376 protected boolean setUpInterfaceOptions(Element config_elem)
377 {
378 Element option_list = (Element) GSXML.getChildByTagName(config_elem, "optionList");
379 if (option_list != null)
380 {
381 logger.debug("found an interface optionList");
382 // we set any options in the config params
383 NodeList options = option_list.getElementsByTagName("option");
384 for (int i = 0; i < options.getLength(); i++)
385 {
386 Element option = (Element) options.item(i);
387 String name = option.getAttribute(GSXML.NAME_ATT);
388 String value = option.getAttribute(GSXML.VALUE_ATT);
389 logger.debug("option: " + name + ", " + value);
390 if (!name.equals("") && !value.equals(""))
391 {
392 this.config_params.put(name, value);
393 }
394 }
395 }
396
397 return true;
398 }
399
400 protected void preProcessRequest(Element request)
401 {
402 return;
403 }
404
405 protected Node postProcessPage(Element page)
406 {
407 return page;
408 }
409
410}
Note: See TracBrowser for help on using the repository browser.