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

Last change on this file since 28966 was 28966, checked in by kjdon, 10 years ago

Lots of changes. Mainly to do with removing this.doc from everywhere. Document is not thread safe. Now we tend to create a new Document everytime we are starting a new page/message etc. in service this.desc_doc is available as teh document to create service info stuff. But it should only be used for this and not for other messages. newDOM is now static for XMLConverter. method param changes for some GSXML methods.

  • Property svn:keywords set to Author Date Id Revision
File size: 11.0 KB
RevLine 
[3344]1package org.greenstone.gsdl3.core;
2
[26055]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;
[22085]14import org.greenstone.util.GlobalProperties;
[26055]15import org.w3c.dom.Document;
16import org.w3c.dom.Element;
[25090]17import org.w3c.dom.Node;
18import org.w3c.dom.NodeList;
[3344]19
[25090]20/**
21 * the most basic Receptionist, used for interface generation. Receives requests
22 * consisting of an xml representation of cgi args, and returns the page of
23 * data. The requests are processed by the appropriate action class
24 *
[3570]25 * @see Action
26 */
[25090]27public class Receptionist implements ModuleInterface
28{
[3344]29
[25090]30 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.Receptionist.class.getName());
[13124]31
[25090]32 /** the set up variables */
[27617]33 protected HashMap<String, Object> config_params = null;
[25090]34 /** container Document to create XML Nodes */
[28966]35 //protected Document doc = null;
[3344]36
[25090]37 /** a converter class to parse XML and create Docs */
38 protected XMLConverter converter = null;
[3344]39
[25090]40 /** the message router that the Receptionist and Actions will talk to */
41 protected ModuleInterface mr = null;
[5144]42
[25090]43 /** the list of actions */
[25635]44 protected HashMap<String, Action> action_map = null;
[3344]45
[25090]46 /** the list of params */
47 protected GSParams params = null;
48 protected Element language_list = null;
[3344]49
[25090]50 /** the list of interfaces this is based on */
[25635]51 protected ArrayList<String> base_interfaces = null;
[25090]52
53 public Receptionist()
54 {
55 this.converter = new XMLConverter();
[28966]56 //this.doc = XMLConverter.newDOM();
[25635]57 this.action_map = new HashMap<String, Action>();
[3344]58 }
[25090]59
60 public void cleanUp()
61 {
[25760]62 if (this.mr != null)
63 {
64 this.mr.cleanUp();
65 }
[3344]66 }
67
[25090]68 public void setParams(GSParams params)
69 {
70 this.params = params;
[4258]71 }
[25090]72
[27617]73 public void setConfigParams(HashMap<String, Object> params)
[25090]74 {
75 this.config_params = params;
[9874]76 }
[8831]77
[27617]78 public HashMap<String, Object> getConfigParams()
[25090]79 {
80 return this.config_params;
[4258]81 }
[3570]82
[25090]83 /**
84 * sets the message router - it should already be created and configured
85 * before being passed to the receptionist
86 */
87 public void setMessageRouter(ModuleInterface m)
88 {
89 this.mr = m;
[5144]90 }
[25255]91
[25254]92 /**
93 * gets the message router
94 */
95 public ModuleInterface getMessageRouter()
96 {
97 return this.mr;
98 }
[8831]99
[25090]100 /** configures the receptionist */
101 public boolean configure()
102 {
[16374]103
[25090]104 if (this.config_params == null)
105 {
106 logger.error(" config variables must be set before calling configure");
107 return false;
108 }
109 if (this.mr == null)
110 {
111 logger.error(" message router must be set before calling configure");
112 return false;
113 }
[3344]114
[25090]115 // find the config file containing a list of actions
116 File interface_config_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.INTERFACE_NAME))));
117 if (!interface_config_file.exists())
118 {
119 logger.error(" interface config file: " + interface_config_file.getPath() + " not found!");
120 return false;
121 }
[3570]122
[25090]123 Document config_doc = this.converter.getDOM(interface_config_file);
124 if (config_doc == null)
125 {
126 logger.error(" could not parse interface config file: " + interface_config_file.getPath());
127 return false;
128 }
129 Element config_elem = config_doc.getDocumentElement();
130 String base_interface = config_elem.getAttribute("baseInterface");
131 setUpBaseInterface(base_interface);
132 setUpInterfaceOptions(config_elem);
[16374]133
[25090]134 // load up the actions
135 Element action_list = (Element) GSXML.getChildByTagName(config_elem, GSXML.ACTION_ELEM + GSXML.LIST_MODIFIER);
136 NodeList actions = action_list.getElementsByTagName(GSXML.ACTION_ELEM);
[16374]137
[25090]138 for (int i = 0; i < actions.getLength(); i++)
139 {
140 Element action = (Element) actions.item(i);
141 String class_name = action.getAttribute("class");
142 String action_name = action.getAttribute("name");
143 Action ac = null;
144 try
145 {
146 ac = (Action) Class.forName("org.greenstone.gsdl3.action." + class_name).newInstance();
147 }
148 catch (Exception e)
149 {
150 logger.error(" couldn't load in action " + class_name);
151 e.printStackTrace();
152 continue;
153 }
154 ac.setConfigParams(this.config_params);
155 ac.setMessageRouter(this.mr);
156 ac.configure();
[25301]157 ac.addActionParameters(this.params);
[25090]158 this.action_map.put(action_name, ac);
159 }
[16374]160
[25090]161 this.language_list = (Element) GSXML.getChildByTagName(config_elem, "languageList");
162 if (language_list == null)
163 {
164 logger.error(" didn't find a language list in the config file!!");
165 }
[3570]166
[25090]167 return true;
168 }
[16688]169
[25090]170 public String process(String xml_in)
171 {
172
173 Node message_node = this.converter.getDOM(xml_in);
174 Node page = process(message_node);
175 return this.converter.getString(page);
[3344]176 }
[3363]177
[25090]178 /**
179 * process - produce a page of data in response to a request if something
180 * goes wrong, it returns null - TODO: return a suitable message to the user
181 */
182 public Node process(Node message_node)
183 {
[28966]184 Element message = GSXML.nodeToElement(message_node);
[25090]185
186 // get the request out of the message - assume that there is only one
187 Element request = (Element) GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
188 if (request == null)
189 {
190 logger.error(" message had no request!");
191 return null;
[4258]192 }
[25090]193 // check the request type
194 String type = request.getAttribute(GSXML.TYPE_ATT); // returns "" if no att of this name
[25255]195 if (type.equals(GSXML.REQUEST_TYPE_SECURITY))
[25092]196 {
197 return this.mr.process(message);
198 }
[25255]199
[25090]200 if (!type.equals(GSXML.REQUEST_TYPE_PAGE))
201 {
202 // now Receptionist forwards non-page requests straight to the MR, and returns the responses
[28248]203 logger.debug(" request type is not '" + GSXML.REQUEST_TYPE_PAGE + "', but it is '" + type + "', so forwarding the message to the MR!");
[25090]204 // process the whole message - mr needs <message> tags, and
205 // in this case, there may be more than one request in the message
206 return this.mr.process(message);
207 }
208 // work out which action to pass to
209 String action = request.getAttribute(GSXML.ACTION_ATT);
210 if (action.equals(""))
211 {
212 logger.error(" no action specified in the request!");
213 return null;
214 }
[4258]215
[25090]216 // find the appropriate action
[25635]217 Action a = this.action_map.get(action);
[16374]218
[25090]219 String action_name = null;
220 if (a == null)
221 { // not in the map yet
222 // try to load a new action
223 try
224 {
225 action_name = action.substring(0, 1).toUpperCase() + action.substring(1) + "Action";
226 Action ac = (Action) Class.forName("org.greenstone.gsdl3.action." + action_name).newInstance();
227 ac.setConfigParams(this.config_params);
228 ac.setMessageRouter(this.mr);
229 ac.configure();
[25301]230 ac.addActionParameters(this.params);
[25090]231 this.action_map.put(action, ac);
232 a = ac;
233 }
234 catch (Exception e)
235 {
[16374]236
[25090]237 logger.error(" a new action (" + action_name + ") was specified and it couldn't be created. Error message:" + e.getMessage());
238 return null;
239 }
240 }
241 // transform the request in some way -- does nothing!
242 preProcessRequest(request);
243 // set up the page
[28966]244 Document doc = XMLConverter.newDOM();
245 Element page = doc.createElement(GSXML.PAGE_ELEM);
[25090]246 page.setAttribute(GSXML.LANG_ATT, request.getAttribute(GSXML.LANG_ATT));
247 // just in case these namespaces end up in the page and we want to display the XML
[26055]248 page.setAttribute("xmlns:gsf", GSXML.GSF_NAMESPACE);
249 page.setAttribute("xmlns:xsl", GSXML.XSL_NAMESPACE);
[3344]250
[25090]251 //logger.info(a+" mesa=" + this.converter.getPrettyString(message));
252 // get the page data from the action
[25092]253
[25090]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
[28966]276 page.appendChild(GSXML.duplicateWithNewName(doc, request, GSXML.PAGE_REQUEST_ELEM, true));
[25090]277 // add the response too
[28966]278 Element page_response = GSXML.duplicateWithNewName(doc, (Element) GSXML.getChildByTagName(action_response, GSXML.RESPONSE_ELEM), GSXML.PAGE_RESPONSE_ELEM, true);
[25090]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
[25871]287 //logger.debug("receptionist returned response");
[25090]288 //logger.error("receptionist returned response");
[25871]289 //logger.debug(this.converter.getString(resulting_page));
[25090]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;
[8562]294 }
[25090]295
296 protected boolean setUpBaseInterface(String base_interface)
297 {
298 if (base_interface == null || base_interface.equals(""))
299 {
300 // there was no base interface, the list remains null
301 return true;
302 }
303 // foreach base interface
304 while (!base_interface.equals(""))
305 {
306 // find the base interface config file
307 File base_interface_config_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), base_interface)));
308 if (!base_interface_config_file.exists())
309 {
310 logger.error(" base interface config file: " + base_interface_config_file.getPath() + " not found!");
311 return false;
312 }
313 // the interface name is valid, add it to the list
314 if (base_interfaces == null)
315 {
[25635]316 base_interfaces = new ArrayList<String>();
[25090]317 }
318 base_interfaces.add(base_interface);
[27617]319 this.config_params.put(GSConstants.BASE_INTERFACES, base_interfaces);
[25090]320 // now see if this has a base interface
321 Document config_doc = this.converter.getDOM(base_interface_config_file);
322 if (config_doc == null)
323 {
324 logger.error(" could not parse base interface config file: " + base_interface_config_file.getPath());
325 return false;
326 }
327 Element config_elem = config_doc.getDocumentElement();
328 base_interface = config_elem.getAttribute("baseInterface");
329 }
330 return true;
[8562]331 }
[8921]332
[25090]333 protected boolean setUpInterfaceOptions(Element config_elem)
334 {
335 Element option_list = (Element) GSXML.getChildByTagName(config_elem, "optionList");
336 if (option_list != null)
337 {
338 logger.debug("found an interface optionList");
339 // we set any options in the config params
340 NodeList options = option_list.getElementsByTagName("option");
341 for (int i = 0; i < options.getLength(); i++)
342 {
343 Element option = (Element) options.item(i);
344 String name = option.getAttribute(GSXML.NAME_ATT);
345 String value = option.getAttribute(GSXML.VALUE_ATT);
346 logger.debug("option: " + name + ", " + value);
347 if (!name.equals("") && !value.equals(""))
348 {
349 this.config_params.put(name, value);
350 }
351 }
[8921]352 }
[25090]353
354 return true;
[8921]355 }
356
[25090]357 protected void preProcessRequest(Element request)
358 {
359 return;
360 }
[8921]361
[25090]362 protected Node postProcessPage(Element page)
363 {
364 return page;
365 }
[3344]366
367}
Note: See TracBrowser for help on using the repository browser.