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

Last change on this file since 32366 was 32366, checked in by kjdon, 6 years ago

instead of blindly copying the paramList into the new pageRequest element going into the page response, look through the paramLIst/param elements - if any have SENSITIVE attribute, remove them from the list. prevent password info being stored in the page response.

  • Property svn:keywords set to Author Date Id Revision
File size: 12.2 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 // load up the actions
136 Element action_list = (Element) GSXML.getChildByTagName(config_elem, GSXML.ACTION_ELEM + GSXML.LIST_MODIFIER);
137 NodeList actions = action_list.getElementsByTagName(GSXML.ACTION_ELEM);
138
139 for (int i = 0; i < actions.getLength(); i++)
140 {
141 Element action = (Element) actions.item(i);
142 String class_name = action.getAttribute("class");
143 String action_name = action.getAttribute("name");
144 Action ac = null;
145 try
146 {
147 ac = (Action) Class.forName("org.greenstone.gsdl3.action." + class_name).newInstance();
148 }
149 catch (Exception e)
150 {
151 logger.error(" couldn't load in action " + class_name);
152 e.printStackTrace();
153 continue;
154 }
155 ac.setConfigParams(this.config_params);
156 ac.setMessageRouter(this.mr);
157 ac.configure();
158 ac.addActionParameters(this.params);
159 this.action_map.put(action_name, ac);
160 }
161
162 this.language_list = (Element) GSXML.getChildByTagName(config_elem, "languageList");
163 if (language_list == null)
164 {
165 logger.error(" didn't find a language list in the config file!!");
166 }
167
168 return true;
169 }
170
171 public String process(String xml_in)
172 {
173
174 Node message_node = this.converter.getDOM(xml_in);
175 Node page = process(message_node);
176 return this.converter.getString(page);
177 }
178
179 /**
180 * process - produce a page of data in response to a request if something
181 * goes wrong, it returns null - TODO: return a suitable message to the user
182 */
183 public Node process(Node message_node)
184 {
185 Element message = GSXML.nodeToElement(message_node);
186
187 // get the request out of the message - assume that there is only one
188 Element request = (Element) GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
189 if (request == null)
190 {
191 logger.error(" message had no request!");
192 return null;
193 }
194 // check the request type
195 String type = request.getAttribute(GSXML.TYPE_ATT); // returns "" if no att of this name
196 if (type.equals(GSXML.REQUEST_TYPE_SECURITY))
197 {
198 return this.mr.process(message);
199 }
200
201 if (!type.equals(GSXML.REQUEST_TYPE_PAGE))
202 {
203 // now Receptionist forwards non-page requests straight to the MR, and returns the responses
204 logger.debug(" request type is not '" + GSXML.REQUEST_TYPE_PAGE + "', but it is '" + type + "', so forwarding the message to the MR!");
205 // process the whole message - mr needs <message> tags, and
206 // in this case, there may be more than one request in the message
207 return this.mr.process(message);
208 }
209 // work out which action to pass to
210 String action = request.getAttribute(GSXML.ACTION_ATT);
211 if (action.equals(""))
212 {
213 logger.error(" no action specified in the request!");
214 return null;
215 }
216
217 // find the appropriate action
218 Action a = this.action_map.get(action);
219
220 String action_name = null;
221 if (a == null)
222 { // not in the map yet
223 // try to load a new action
224 try
225 {
226 action_name = action.substring(0, 1).toUpperCase() + action.substring(1) + "Action";
227 Action ac = (Action) Class.forName("org.greenstone.gsdl3.action." + action_name).newInstance();
228 ac.setConfigParams(this.config_params);
229 ac.setMessageRouter(this.mr);
230 ac.configure();
231 ac.addActionParameters(this.params);
232 this.action_map.put(action, ac);
233 a = ac;
234 }
235 catch (Exception e)
236 {
237
238 logger.error(" a new action (" + action_name + ") was specified and it couldn't be created. Error message:" + e.getMessage());
239 return null;
240 }
241 }
242 // transform the request in some way -- does nothing!
243 preProcessRequest(request);
244 // set up the page
245 Document doc = XMLConverter.newDOM();
246 Element page = doc.createElement(GSXML.PAGE_ELEM);
247 page.setAttribute(GSXML.LANG_ATT, request.getAttribute(GSXML.LANG_ATT));
248 // just in case these namespaces end up in the page and we want to display the XML
249 GSXML.addGSNamespaces(page, false);
250
251 //logger.info(a+" mesa=" + this.converter.getPrettyString(message));
252 // get the page data from the action
253
254 Node action_response = a.process(message);
255 boolean response_only = false;
256 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
257 if (param_list != null)
258 {
259 Element param = GSXML.getNamedElement(param_list, GSXML.PARAM_ELEM, GSXML.NAME_ATT, "ro");
260 if (param != null)
261 {
262 String value = param.getAttribute("value");
263 if (value.equals("1"))
264 {
265 response_only = true;
266 }
267 }
268 }
269 if (response_only)
270 {
271 // only the response from the action is sent back
272 return action_response;
273 }
274
275 // the request is part of the page
276 page.appendChild(duplicateRequest(doc, request));
277 // add the response too
278 Element page_response = GSXML.duplicateWithNewName(doc, (Element) GSXML.getChildByTagName(action_response, GSXML.RESPONSE_ELEM), GSXML.PAGE_RESPONSE_ELEM, true);
279 page.appendChild(page_response);
280
281 //logger.info(" raw page="+this.converter.getString(page));
282 // transform the result in some way
283 //Element resulting_page = postProcessPage(page);
284
285 Node resulting_page = postProcessPage(page);
286
287 //logger.debug("receptionist returned response");
288 //logger.error("receptionist returned response");
289 //logger.debug(this.converter.getString(resulting_page));
290 //logger.error(this.converter.getString(resulting_page));
291 // logger.info("receptionist returned response");
292 // logger.info(this.converter.getString(resulting_page));
293 return resulting_page;
294 }
295
296 // This is pretty much a straight copy of the Element, with a new top root node name, but also, removing any NOSAVE parameters.
297 protected Element duplicateRequest(Document owner, Element request) {
298
299 Element duplicate;
300 duplicate = owner.createElement(GSXML.PAGE_REQUEST_ELEM);
301 // Copy element attributes
302 NamedNodeMap attributes = request.getAttributes();
303 for (int i = 0; i < attributes.getLength(); i++)
304 {
305 Node attribute = attributes.item(i);
306 duplicate.setAttribute(attribute.getNodeName(), attribute.getNodeValue());
307 }
308 // Copy element children
309 NodeList children = request.getChildNodes();
310 for (int i = 0; i < children.getLength(); i++)
311 {
312 Node child = children.item(i);
313 if (child.getNodeName().equals(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER)) {
314 Element param_list = (Element)owner.importNode(child, true);
315 NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
316 for (int j=params.getLength()-1; j>=0; j--) {
317 Element p = (Element)params.item(j);
318 if (!p.getAttribute(GSXML.SENSITIVE_ATT).equals("")) {
319 logger.error("removing param "+p.getAttribute("name"));
320 param_list.removeChild(p);
321 }
322 }
323 duplicate.appendChild(param_list);
324 } else {
325 duplicate.appendChild(owner.importNode(child, true));
326 }
327 }
328
329
330 return duplicate;
331
332
333
334
335 }
336 protected boolean setUpBaseInterface(String base_interface)
337 {
338 if (base_interface == null || base_interface.equals(""))
339 {
340 // there was no base interface, the list remains null
341 return true;
342 }
343 // foreach base interface
344 while (!base_interface.equals(""))
345 {
346 // find the base interface config file
347 File base_interface_config_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), base_interface)));
348 if (!base_interface_config_file.exists())
349 {
350 logger.error(" base interface config file: " + base_interface_config_file.getPath() + " not found!");
351 return false;
352 }
353 // the interface name is valid, add it to the list
354 if (base_interfaces == null)
355 {
356 base_interfaces = new ArrayList<String>();
357 }
358 base_interfaces.add(base_interface);
359 this.config_params.put(GSConstants.BASE_INTERFACES, base_interfaces);
360 // now see if this has a base interface
361 Document config_doc = this.converter.getDOM(base_interface_config_file);
362 if (config_doc == null)
363 {
364 logger.error(" could not parse base interface config file: " + base_interface_config_file.getPath());
365 return false;
366 }
367 Element config_elem = config_doc.getDocumentElement();
368 base_interface = config_elem.getAttribute("baseInterface");
369 }
370 return true;
371 }
372
373 protected boolean setUpInterfaceOptions(Element config_elem)
374 {
375 Element option_list = (Element) GSXML.getChildByTagName(config_elem, "optionList");
376 if (option_list != null)
377 {
378 logger.debug("found an interface optionList");
379 // we set any options in the config params
380 NodeList options = option_list.getElementsByTagName("option");
381 for (int i = 0; i < options.getLength(); i++)
382 {
383 Element option = (Element) options.item(i);
384 String name = option.getAttribute(GSXML.NAME_ATT);
385 String value = option.getAttribute(GSXML.VALUE_ATT);
386 logger.debug("option: " + name + ", " + value);
387 if (!name.equals("") && !value.equals(""))
388 {
389 this.config_params.put(name, value);
390 }
391 }
392 }
393
394 return true;
395 }
396
397 protected void preProcessRequest(Element request)
398 {
399 return;
400 }
401
402 protected Node postProcessPage(Element page)
403 {
404 return page;
405 }
406
407}
Note: See TracBrowser for help on using the repository browser.