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

Last change on this file since 16374 was 16374, checked in by davidb, 16 years ago

Change to Skin code (returning Node note Element) so XSLT encodes its DocType -- important information for IE to render resultant HTML correctly. This also required Skin.java to be changed from using DomResult to StreamResult. The former is known to have a problem with loosing its DocType info, and as it's then read-only, has no elegant way to put back this info.

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