source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/TransformingReceptionist.java@ 24522

Last change on this file since 24522 was 24522, checked in by sjm84, 13 years ago

Fixing a potential error

  • Property svn:keywords set to Author Date Id Revision
File size: 31.9 KB
Line 
1package org.greenstone.gsdl3.core;
2
3import org.greenstone.util.GlobalProperties;
4import org.greenstone.gsdl3.util.*;
5import org.greenstone.gsdl3.action.*;
6// XML classes
7import org.w3c.dom.Node;
8import org.w3c.dom.NodeList;
9import org.w3c.dom.Comment;
10import org.w3c.dom.Text;
11import org.w3c.dom.Document;
12import org.w3c.dom.Element;
13import org.xml.sax.InputSource;
14import org.w3c.dom.NamedNodeMap;
15
16// other java classes
17import java.io.File;
18import java.io.StringWriter;
19import java.io.FileReader;
20import java.io.FileNotFoundException;
21import java.util.ArrayList;
22import java.util.HashMap;
23import java.util.Enumeration;
24
25import javax.xml.parsers.*;
26import javax.xml.transform.*;
27import javax.xml.transform.dom.*;
28import javax.xml.transform.stream.*;
29import org.apache.log4j.*;
30import org.apache.xerces.dom.*;
31import org.apache.xerces.parsers.DOMParser;
32
33import org.apache.commons.lang3.StringUtils;
34
35/**
36 * A receptionist that uses xslt to transform the page_data before returning it.
37 * . Receives requests consisting of an xml representation of cgi args, and
38 * returns the page of data - in html by default. The requests are processed by
39 * the appropriate action class
40 *
41 * @see Action
42 */
43public class TransformingReceptionist extends Receptionist
44{
45
46 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.TransformingReceptionist.class.getName());
47
48 /** The preprocess.xsl file is in a fixed location */
49 static final String preprocess_xsl_filename = GlobalProperties.getGSDL3Home() + File.separatorChar + "ui" + File.separatorChar + "xslt" + File.separatorChar + "preProcess.xsl";
50
51 /** the list of xslt to use for actions */
52 protected HashMap xslt_map = null;
53
54 /** a transformer class to transform xml using xslt */
55 protected XMLTransformer transformer = null;
56
57 protected TransformerFactory transformerFactory = null;
58 protected DOMParser parser = null;
59
60 public TransformingReceptionist()
61 {
62 super();
63 this.xslt_map = new HashMap();
64 this.transformer = new XMLTransformer();
65 try
66 {
67 transformerFactory = org.apache.xalan.processor.TransformerFactoryImpl.newInstance();
68 this.converter = new XMLConverter();
69 //transformerFactory.setURIResolver(new MyUriResolver()) ;
70
71 parser = new DOMParser();
72 parser.setFeature("http://xml.org/sax/features/validation", false);
73 // don't try and load external DTD - no need if we are not validating, and may cause connection errors if a proxy is not set up.
74 parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
75 // a performance test showed that having this on lead to increased
76 // memory use for small-medium docs, and not much gain for large
77 // docs.
78 // http://www.sosnoski.com/opensrc/xmlbench/conclusions.html
79 parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
80 parser.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true);
81 // setting a handler for when fatal errors, errors or warnings happen during xml parsing
82 // call XMLConverter's getParseErrorMessage() to get the errorstring that can be rendered as web page
83 this.parser.setErrorHandler(new XMLConverter.ParseErrorHandler());
84 }
85 catch (Exception e)
86 {
87 e.printStackTrace();
88 }
89
90 }
91
92 /** configures the receptionist - overwrite this to set up the xslt map */
93 public boolean configure()
94 {
95
96 if (this.config_params == null)
97 {
98 logger.error(" config variables must be set before calling configure");
99 return false;
100 }
101 if (this.mr == null)
102 {
103 logger.error(" message router must be set before calling configure");
104 return false;
105 }
106
107 // find the config file containing a list of actions
108 File interface_config_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.INTERFACE_NAME))));
109 if (!interface_config_file.exists())
110 {
111 logger.error(" interface config file: " + interface_config_file.getPath() + " not found!");
112 return false;
113 }
114 Document config_doc = this.converter.getDOM(interface_config_file, "utf-8");
115 if (config_doc == null)
116 {
117 logger.error(" could not parse interface config file: " + interface_config_file.getPath());
118 return false;
119 }
120 Element config_elem = config_doc.getDocumentElement();
121 String base_interface = config_elem.getAttribute("baseInterface");
122 setUpBaseInterface(base_interface);
123 setUpInterfaceOptions(config_elem);
124
125 Element action_list = (Element) GSXML.getChildByTagName(config_elem, GSXML.ACTION_ELEM + GSXML.LIST_MODIFIER);
126 NodeList actions = action_list.getElementsByTagName(GSXML.ACTION_ELEM);
127
128 for (int i = 0; i < actions.getLength(); i++)
129 {
130 Element action = (Element) actions.item(i);
131 String class_name = action.getAttribute("class");
132 String action_name = action.getAttribute("name");
133 Action ac = null;
134 try
135 {
136 ac = (Action) Class.forName("org.greenstone.gsdl3.action." + class_name).newInstance();
137 }
138 catch (Exception e)
139 {
140 logger.error(" couldn't load in action " + class_name);
141 e.printStackTrace();
142 continue;
143 }
144 ac.setConfigParams(this.config_params);
145 ac.setMessageRouter(this.mr);
146 ac.configure();
147 ac.getActionParameters(this.params);
148 this.action_map.put(action_name, ac);
149
150 // now do the xslt map
151 String xslt = action.getAttribute("xslt");
152 if (!xslt.equals(""))
153 {
154 this.xslt_map.put(action_name, xslt);
155 }
156 NodeList subactions = action.getElementsByTagName(GSXML.SUBACTION_ELEM);
157 for (int j = 0; j < subactions.getLength(); j++)
158 {
159 Element subaction = (Element) subactions.item(j);
160 String subname = subaction.getAttribute(GSXML.NAME_ATT);
161 String subxslt = subaction.getAttribute("xslt");
162
163 String map_key = action_name + ":" + subname;
164 logger.debug("adding in to xslt map, " + map_key + "->" + subxslt);
165 this.xslt_map.put(map_key, subxslt);
166 }
167 }
168 Element lang_list = (Element) GSXML.getChildByTagName(config_elem, "languageList");
169 if (lang_list == null)
170 {
171 logger.error(" didn't find a language list in the config file!!");
172 }
173 else
174 {
175 this.language_list = (Element) this.doc.importNode(lang_list, true);
176 }
177
178 return true;
179 }
180
181 protected Node postProcessPage(Element page)
182 {
183 // might need to add some data to the page
184 addExtraInfo(page);
185 // transform the page using xslt
186 Node transformed_page = transformPage(page);
187
188 // if the user has specified they want only a part of the full page then subdivide it
189 boolean subdivide = false;
190 String excerptID = null;
191 String excerptTag = null;
192 Element request = (Element) GSXML.getChildByTagName(page, GSXML.PAGE_REQUEST_ELEM);
193 Element cgi_param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
194 if (cgi_param_list != null)
195 {
196 HashMap params = GSXML.extractParams(cgi_param_list, false);
197 if ((excerptID = (String) params.get(GSParams.EXCERPT_ID)) != null)
198 {
199 subdivide = true;
200 }
201 if ((excerptTag = (String) params.get(GSParams.EXCERPT_TAG)) != null)
202 {
203 subdivide = true;
204 }
205 }
206
207 if (subdivide)
208 {
209 Node subdivided_page = subdivide(transformed_page, excerptID, excerptTag);
210 if (subdivided_page != null)
211 {
212 return subdivided_page;
213 }
214 }
215
216 return transformed_page;
217 }
218
219 protected Node subdivide(Node transformed_page, String excerptID, String excerptTag)
220 {
221 if (excerptID != null)
222 {
223 Node selectedElement = getNodeByIdRecursive(transformed_page, excerptID);
224 modifyNodesByTagRecursive(selectedElement, "a");
225 return selectedElement;
226 }
227 else if (excerptTag != null)
228 {
229 /*
230 * // define a list
231 *
232 * Node selectedElement =
233 * modifyNodesByTagRecursive(transformed_page, excerptTag);
234 */
235
236 Node selectedElement = getNodeByTagRecursive(transformed_page, excerptTag);
237 return selectedElement;
238
239 }
240 return transformed_page;
241 }
242
243 protected Node getNodeByIdRecursive(Node parent, String id)
244 {
245 if (parent.hasAttributes() && ((Element) parent).getAttribute("id").equals(id))
246 {
247 return parent;
248 }
249
250 NodeList children = parent.getChildNodes();
251 for (int i = 0; i < children.getLength(); i++)
252 {
253 Node result = null;
254 if ((result = getNodeByIdRecursive(children.item(i), id)) != null)
255 {
256 return result;
257 }
258 }
259 return null;
260 }
261
262 protected Node getNodeByTagRecursive(Node parent, String tag)
263 {
264 if (parent.getNodeType() == Node.ELEMENT_NODE && ((Element) parent).getTagName().equals(tag))
265 {
266 return parent;
267 }
268
269 NodeList children = parent.getChildNodes();
270 for (int i = 0; i < children.getLength(); i++)
271 {
272 Node result = null;
273 if ((result = getNodeByTagRecursive(children.item(i), tag)) != null)
274 {
275 return result;
276 }
277 }
278 return null;
279 }
280
281 protected Node modifyNodesByTagRecursive(Node parent, String tag)
282 {
283 if (parent == null || (parent.getNodeType() == Node.ELEMENT_NODE && ((Element) parent).getTagName().equals(tag)))
284 {
285 return parent;
286 }
287
288 NodeList children = parent.getChildNodes();
289 for (int i = 0; i < children.getLength(); i++)
290 {
291 Node result = null;
292 if ((result = modifyNodesByTagRecursive(children.item(i), tag)) != null)
293 {
294 //return result;
295 //logger.error("Modify node value = "+result.getNodeValue()); //NamedItem("href"););
296 logger.error("BEFORE Modify node attribute = " + result.getAttributes().getNamedItem("href").getNodeValue());
297 String url = result.getAttributes().getNamedItem("href").getNodeValue();
298 //url = url + "&excerptid=results";
299 result.getAttributes().getNamedItem("href").setNodeValue(url);
300 logger.error("AFTER Modify node attribute = " + result.getAttributes().getNamedItem("href").getNodeValue());
301
302 }
303 }
304 return null;
305 }
306
307 /**
308 * overwrite this to add any extra info that might be needed in the page
309 * before transformation
310 */
311 protected void addExtraInfo(Element page)
312 {
313 }
314
315 /**
316 * transform the page using xslt we need to get any format element out of
317 * the page and add it to the xslt before transforming
318 */
319 protected Node transformPage(Element page)
320 {
321
322 boolean allowsClientXSLT = (Boolean) config_params.get(GSConstants.ALLOW_CLIENT_SIDE_XSLT);
323 //System.out.println("Client side transforms allowed? " + allowsClientXSLT);
324
325 String currentInterface = (String) config_params.get(GSConstants.INTERFACE_NAME);
326
327 Element request = (Element) GSXML.getChildByTagName(page, GSXML.PAGE_REQUEST_ELEM);
328 String output = request.getAttribute(GSXML.OUTPUT_ATT);
329
330 //System.out.println("Current output mode is: " + output + ", current interface name is: " + currentInterface);
331
332 if (allowsClientXSLT)
333 {
334 if (!currentInterface.endsWith(GSConstants.CLIENT_SIDE_XSLT_INTERFACE_SUFFIX) && output.equals("html"))
335 {
336 System.out.println("output is html and we are not currently using a client side version, switching");
337 // Switch the interface
338 config_params.put(GSConstants.INTERFACE_NAME, currentInterface.concat(GSConstants.CLIENT_SIDE_XSLT_INTERFACE_SUFFIX));
339 }
340 else if ((currentInterface.endsWith(GSConstants.CLIENT_SIDE_XSLT_INTERFACE_SUFFIX) && !output.equals("html")) || output.equals("server"))
341 {
342 // The reverse needs to happen too
343 config_params.put(GSConstants.INTERFACE_NAME, currentInterface.substring(0, currentInterface.length() - GSConstants.CLIENT_SIDE_XSLT_INTERFACE_SUFFIX.length()));
344 }
345 }
346 else if (currentInterface.endsWith(GSConstants.CLIENT_SIDE_XSLT_INTERFACE_SUFFIX))
347 {
348 config_params.put(GSConstants.INTERFACE_NAME, currentInterface.substring(0, currentInterface.length() - GSConstants.CLIENT_SIDE_XSLT_INTERFACE_SUFFIX.length()));
349 }
350
351 // DocType defaults in case the skin doesn't have an "xsl:output" element
352 String qualifiedName = "html";
353 String publicID = "-//W3C//DTD HTML 4.01 Transitional//EN";
354 String systemID = "http://www.w3.org/TR/html4/loose.dtd";
355
356 // We need to create an empty document with a predefined DocType,
357 // that will then be used for the transformation by the DOMResult
358 Document docWithDoctype = converter.newDOM(qualifiedName, publicID, systemID);
359
360 if (output.equals("xsltclient"))
361 {
362 // If you're just getting the client-side transform page, why bother with the rest of this?
363 Element html = docWithDoctype.createElement("html");
364 Element img = docWithDoctype.createElement("img");
365 img.setAttribute("src", "interfaces/default/images/loading.gif"); // Make it dynamic
366 img.setAttribute("alt", "Please wait...");
367 Text title_text = docWithDoctype.createTextNode("Please wait..."); // Make this language dependent
368 Element head = docWithDoctype.createElement("head");
369 Element title = docWithDoctype.createElement("title");
370 title.appendChild(title_text);
371 Element body = docWithDoctype.createElement("body");
372 Element script = docWithDoctype.createElement("script");
373 Element jquery = docWithDoctype.createElement("script");
374 jquery.setAttribute("src", "jquery.js");
375 jquery.setAttribute("type", "text/javascript");
376 Comment jquery_comment = docWithDoctype.createComment("jQuery");
377 Comment script_comment = docWithDoctype.createComment("Filler for browser");
378 script.setAttribute("src", "test.js");
379 script.setAttribute("type", "text/javascript");
380 Element pagevar = docWithDoctype.createElement("script");
381 Element style = docWithDoctype.createElement("style");
382 style.setAttribute("type", "text/css");
383 Text style_text = docWithDoctype.createTextNode("body { text-align: center; padding: 50px; font: 14pt Arial, sans-serif; font-weight: bold; }");
384 pagevar.setAttribute("type", "text/javascript");
385 Text page_var_text = docWithDoctype.createTextNode("var placeholder = true;");
386
387 html.appendChild(head);
388 head.appendChild(title);
389 head.appendChild(style);
390 style.appendChild(style_text);
391 html.appendChild(body);
392 head.appendChild(pagevar);
393 head.appendChild(jquery);
394 head.appendChild(script);
395 pagevar.appendChild(page_var_text);
396 jquery.appendChild(jquery_comment);
397 script.appendChild(script_comment);
398 body.appendChild(img);
399 docWithDoctype.appendChild(html);
400
401 return (Node) docWithDoctype;
402 }
403
404 // Passing in the pretty string here means it needs to be generated even when not debugging; so use custom function to return blank when debug is off
405 logger.debug("page before transforming:");
406 logger.debug(this.converter.getPrettyStringLogger(page, logger));
407
408 String action = request.getAttribute(GSXML.ACTION_ATT);
409 String subaction = request.getAttribute(GSXML.SUBACTION_ATT);
410
411 // we should choose how to transform the data based on output, eg diff
412 // choice for html, and wml??
413 // for now, if output=xml, we don't transform the page, we just return
414 // the page xml
415 Document theXML = null;
416
417 if (output.equals("xml") || output.equals("clientside"))
418 {
419 // Append some bits and pieces first...
420 theXML = converter.newDOM();
421 // Import into new document first!
422 Node newPage = theXML.importNode(page, true);
423 theXML.appendChild(newPage);
424 Element root = theXML.createElement("xsltparams");
425 newPage.appendChild(root);
426
427 Element libname = theXML.createElement("param");
428 libname.setAttribute("name", "library_name");
429 Text libnametext = theXML.createTextNode((String) config_params.get(GSConstants.LIBRARY_NAME));
430 libname.appendChild(libnametext);
431
432 Element intname = theXML.createElement("param");
433 intname.setAttribute("name", "interface_name");
434 Text intnametext = theXML.createTextNode((String) config_params.get(GSConstants.INTERFACE_NAME));
435 intname.appendChild(intnametext);
436
437 Element filepath = theXML.createElement("param");
438 filepath.setAttribute("name", "filepath");
439 Text filepathtext = theXML.createTextNode(GlobalProperties.getGSDL3Home());
440 filepath.appendChild(filepathtext);
441
442 root.appendChild(libname);
443 root.appendChild(intname);
444 root.appendChild(filepath);
445
446 if (output.equals("xml"))
447 return theXML.getDocumentElement();
448 }
449
450 Element cgi_param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
451 String collection = "";
452 if (cgi_param_list != null)
453 {
454 // Don't waste time getting all the parameters
455 HashMap params = GSXML.extractParams(cgi_param_list, false, GSParams.COLLECTION);
456 collection = (String) params.get(GSParams.COLLECTION);
457 if (collection == null)
458 collection = "";
459 }
460
461 Document style_doc = getXSLTDocument(action, subaction, collection);
462 if (style_doc == null)
463 {
464 String errorPage = this.converter.getParseErrorMessage();
465 if (errorPage != null)
466 {
467 return XMLTransformer.constructErrorXHTMLPage("Cannot parse the xslt file\n" + errorPage);
468 }
469 return page;
470 }
471
472 // put the page into a document - this is necessary for xslt to get
473 // the paths right if you have paths relative to the document root
474 // eg /page.
475 Document doc = this.converter.newDOM();
476 doc.appendChild(doc.importNode(page, true));
477 Element page_response = (Element) GSXML.getChildByTagName(page, GSXML.PAGE_RESPONSE_ELEM);
478 Element format_elem = (Element) GSXML.getChildByTagName(page_response, GSXML.FORMAT_ELEM);
479 if (output.equals("formatelem"))
480 {
481 return format_elem;
482 }
483 if (format_elem != null)
484 {
485 //page_response.removeChild(format_elem);
486 logger.debug("format elem=" + this.converter.getPrettyStringLogger(format_elem, logger));
487 // need to transform the format info
488 String configStylesheet_file = GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, "config_format.xsl");
489 Document configStylesheet_doc = this.converter.getDOM(new File(configStylesheet_file));
490
491 if (configStylesheet_doc != null)
492 {
493 Document format_doc = this.converter.newDOM();
494 format_doc.appendChild(format_doc.importNode(format_elem, true));
495 Node result = this.transformer.transform(configStylesheet_doc, format_doc, config_params); // Needs addressing <-
496
497 // Since we started creating documents with DocTypes, we can end up with
498 // Document objects here. But we will be working with an Element instead,
499 // so we grab the DocumentElement() of the Document object in such a case.
500 Element new_format;
501 if (result.getNodeType() == Node.DOCUMENT_NODE)
502 {
503 new_format = ((Document) result).getDocumentElement();
504 }
505 else
506 {
507 new_format = (Element) result;
508 }
509 logger.debug("new format elem=" + this.converter.getPrettyStringLogger(new_format, logger));
510 if (output.equals("newformat"))
511 {
512 return new_format;
513 }
514
515 // add extracted GSF statements in to the main stylesheet
516 GSXSLT.mergeStylesheets(style_doc, new_format);
517 //System.out.println("added extracted GSF statements into the main stylesheet") ;
518
519 // add extracted GSF statements in to the debug test stylesheet
520 //GSXSLT.mergeStylesheets(oldStyle_doc, new_format);
521 }
522 else
523 {
524 logger.error(" couldn't parse the config_format stylesheet, adding the format info as is");
525 GSXSLT.mergeStylesheets(style_doc, format_elem);
526 //GSXSLT.mergeStylesheets(oldStyle_doc, format_elem);
527 }
528 logger.debug("the converted stylesheet is:");
529 logger.debug(this.converter.getPrettyStringLogger(style_doc.getDocumentElement(), logger));
530 }
531
532 //for debug purposes only
533 Document oldStyle_doc = style_doc;
534
535 Document preprocessingXsl;
536 try
537 {
538 preprocessingXsl = getPreprocessDoc();
539 String errMsg = ((XMLConverter.ParseErrorHandler) parser.getErrorHandler()).getErrorMessage();
540 if (errMsg != null)
541 {
542 return XMLTransformer.constructErrorXHTMLPage("error loading preprocess xslt file: " + preprocess_xsl_filename + "\n" + errMsg);
543 }
544 }
545 catch (java.io.FileNotFoundException e)
546 {
547 return fileNotFoundErrorPage(e.getMessage());
548 }
549 catch (Exception e)
550 {
551 e.printStackTrace();
552 System.out.println("error loading preprocess xslt");
553 return XMLTransformer.constructErrorXHTMLPage("error loading preprocess xslt\n" + e.getMessage());
554 }
555
556 Document libraryXsl = null;
557 try
558 {
559 libraryXsl = getLibraryDoc();
560 String errMsg = ((XMLConverter.ParseErrorHandler) parser.getErrorHandler()).getErrorMessage();
561 if (errMsg != null)
562 {
563 return XMLTransformer.constructErrorXHTMLPage("Error loading xslt file: " + this.getLibraryXSLFilename() + "\n" + errMsg);
564 }
565 }
566 catch (java.io.FileNotFoundException e)
567 {
568 return fileNotFoundErrorPage(e.getMessage());
569 }
570 catch (Exception e)
571 {
572 e.printStackTrace();
573 System.out.println("error loading library xslt");
574 return XMLTransformer.constructErrorXHTMLPage("error loading library xslt\n" + e.getMessage());
575 }
576
577 // Combine the skin file and library variables/templates into one document.
578 // Please note: We dont just use xsl:import because the preprocessing stage
579 // needs to know what's available in the library.
580
581 Document skinAndLibraryXsl = null;
582 Document skinAndLibraryDoc = converter.newDOM();
583 try
584 {
585
586 skinAndLibraryXsl = converter.newDOM();
587 Element root = skinAndLibraryXsl.createElement("skinAndLibraryXsl");
588 skinAndLibraryXsl.appendChild(root);
589
590 Element s = skinAndLibraryXsl.createElement("skinXsl");
591 s.appendChild(skinAndLibraryXsl.importNode(style_doc.getDocumentElement(), true));
592 root.appendChild(s);
593
594 Element l = skinAndLibraryXsl.createElement("libraryXsl");
595 Element libraryXsl_el = libraryXsl.getDocumentElement();
596 l.appendChild(skinAndLibraryXsl.importNode(libraryXsl_el, true));
597 root.appendChild(l);
598 //System.out.println("Skin and Library XSL are now together") ;
599
600 //System.out.println("Pre-processing the skin file...") ;
601
602 //pre-process the skin style sheet
603 //In other words, apply the preProcess.xsl to 'skinAndLibraryXsl' in order to
604 //expand all GS-Lib statements into complete XSL statements and also to create
605 //a valid xsl style sheet document.
606
607 Transformer preProcessor = transformerFactory.newTransformer(new DOMSource(preprocessingXsl));
608 preProcessor.setErrorListener(new XMLTransformer.TransformErrorListener());
609 DOMResult result = new DOMResult();
610 result.setNode(skinAndLibraryDoc);
611 preProcessor.transform(new DOMSource(skinAndLibraryXsl), result);
612 //System.out.println("GS-Lib statements are now expanded") ;
613
614 }
615 catch (TransformerException e)
616 {
617 e.printStackTrace();
618 System.out.println("TransformerException while preprocessing the skin xslt");
619 return XMLTransformer.constructErrorXHTMLPage(e.getMessage());
620 }
621 catch (Exception e)
622 {
623 e.printStackTrace();
624 System.out.println("Error while preprocessing the skin xslt");
625 return XMLTransformer.constructErrorXHTMLPage(e.getMessage());
626 }
627
628 //The following code is to be uncommented if we need to append the extracted GSF statements
629 //after having extracted the GSLib elements. In case of a problem during postprocessing.
630 /*
631 * // put the page into a document - this is necessary for xslt to get
632 * // the paths right if you have paths relative to the document root //
633 * eg /page. Document doc = this.converter.newDOM();
634 * doc.appendChild(doc.importNode(page, true)); Element page_response =
635 * (Element)GSXML.getChildByTagName(page, GSXML.PAGE_RESPONSE_ELEM);
636 * Element format_elem = (Element)GSXML.getChildByTagName(page_response,
637 * GSXML.FORMAT_ELEM); if (output.equals("formatelem")) { return
638 * format_elem; } if (format_elem != null) {
639 * //page_response.removeChild(format_elem);
640 * logger.debug("format elem="+
641 * this.converter.getPrettyString(format_elem)); // need to transform
642 * the format info String configStylesheet_file =
643 * GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(),
644 * (String)this.config_params.get(GSConstants.SITE_NAME), collection,
645 * (String)this.config_params.get(GSConstants.INTERFACE_NAME),
646 * base_interfaces, "config_format.xsl"); Document configStylesheet_doc
647 * = this.converter.getDOM(new File(configStylesheet_file)); if
648 * (configStylesheet_doc != null) { Document format_doc =
649 * this.converter.newDOM();
650 * format_doc.appendChild(format_doc.importNode(format_elem, true));
651 * Node result = this.transformer.transform(configStylesheet_doc,
652 * format_doc);
653 *
654 * // Since we started creating documents with DocTypes, we can end up
655 * with // Document objects here. But we will be working with an Element
656 * instead, // so we grab the DocumentElement() of the Document object
657 * in such a case. Element new_format; if(result.getNodeType() ==
658 * Node.DOCUMENT_NODE) { new_format =
659 * ((Document)result).getDocumentElement(); } else { new_format =
660 * (Element)result; }
661 * logger.debug("new format elem="+this.converter.getPrettyString
662 * (new_format)); if (output.equals("newformat")) { return new_format; }
663 *
664 * // add extracted GSF statements in to the main stylesheet
665 * GSXSLT.mergeStylesheets(skinAndLibraryDoc, new_format);
666 * //System.out.println
667 * ("added extracted GSF statements into the main stylesheet") ;
668 *
669 * // add extracted GSF statements in to the debug test stylesheet
670 * //GSXSLT.mergeStylesheets(oldStyle_doc, new_format); } else {
671 * logger.error(
672 * " couldn't parse the config_format stylesheet, adding the format info as is"
673 * ); GSXSLT.mergeStylesheets(skinAndLibraryDoc, format_elem); //
674 * GSXSLT.mergeStylesheets(oldStyle_doc, format_elem); }
675 * logger.debug("the converted stylesheet is:");
676 * logger.debug(this.converter
677 * .getPrettyString(skinAndLibraryDoc.getDocumentElement())); }
678 */
679
680 // there is a thing called a URIResolver which you can set for a
681 // transformer or transformer factory. may be able to use this
682 // instead of this absoluteIncludepaths hack
683
684 GSXSLT.absoluteIncludePaths(skinAndLibraryDoc, GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
685
686 //Same but for the debug version when we want the do the transformation like we use to do
687 //without any gslib elements.
688 GSXSLT.absoluteIncludePaths(oldStyle_doc, GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
689
690 //Send different stages of the skin xslt to the browser for debug purposes only
691 //using &o=skindoc or &o=skinandlib etc...
692 if (output.equals("skindoc"))
693 {
694 return converter.getDOM(getStringFromDocument(style_doc));
695 }
696 if (output.equals("skinandlib"))
697 {
698 return converter.getDOM(getStringFromDocument(skinAndLibraryXsl));
699 }
700 if (output.equals("skinandlibdoc") || output.equals("clientside"))
701 {
702
703 Node skinAndLib = converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
704
705 if (output.equals("skinandlibdoc"))
706 {
707 return skinAndLib;
708 }
709 else
710 {
711 // Send XML and skinandlibdoc down the line together
712 Document finalDoc = converter.newDOM();
713 Node finalDocSkin = finalDoc.importNode(skinAndLibraryDoc.getDocumentElement(), true);
714 Node finalDocXML = finalDoc.importNode(theXML.getDocumentElement(), true);
715 Element root = finalDoc.createElement("skinlibPlusXML");
716 root.appendChild(finalDocSkin);
717 root.appendChild(finalDocXML);
718 finalDoc.appendChild(root);
719 return (Node) finalDoc.getDocumentElement();
720 }
721 }
722 if (output.equals("oldskindoc"))
723 {
724 return converter.getDOM(getStringFromDocument(oldStyle_doc));
725 }
726
727 // Try to get the system and public ID from the current skin xsl document
728 // otherwise keep the default values.
729 Element root = skinAndLibraryDoc.getDocumentElement();
730 NodeList nodes = root.getElementsByTagName("xsl:output");
731 // If there is at least one "xsl:output" command in the final xsl then...
732 if (nodes.getLength() != 0)
733 {
734 // There should be only one element called xsl:output,
735 // but if this is not the case get the last one
736 Element xsl_output = (Element) nodes.item(nodes.getLength() - 1);
737 if (xsl_output != null)
738 {
739 // Qualified name will always be html even for xhtml pages
740 //String attrValue = xsl_output.getAttribute("method");
741 //qualifiedName = attrValue.equals("") ? qualifiedName : attrValue;
742
743 String attrValue = xsl_output.getAttribute("doctype-system");
744 systemID = attrValue.equals("") ? systemID : attrValue;
745
746 attrValue = xsl_output.getAttribute("doctype-public");
747 publicID = attrValue.equals("") ? publicID : attrValue;
748 }
749 }
750
751 //System.out.println(converter.getPrettyString(docWithDoctype));
752 //System.out.println("Doctype vals: " + qualifiedName + " " + publicID + " " + systemID) ;
753
754 docWithDoctype = converter.newDOM(qualifiedName, publicID, systemID);
755
756 //System.out.println("Generate final HTML from current skin") ;
757 //Transformation of the XML message from the receptionist to HTML with doctype
758
759 return this.transformer.transform(skinAndLibraryDoc, doc, config_params, docWithDoctype); // The default
760
761 // The line below will do the transformation like we use to do before having Skin++ implemented,
762 // it will not contain any GS-Lib statements expanded, and the result will not contain any doctype.
763
764 //return (Element)this.transformer.transform(style_doc, doc, config_params);
765 //return null; // For now - change later
766 }
767
768 // method to convert Document to a proper XML string for debug purposes only
769 protected String getStringFromDocument(Document doc)
770 {
771 String content = "";
772 try
773 {
774 DOMSource domSource = new DOMSource(doc);
775 StringWriter writer = new StringWriter();
776 StreamResult result = new StreamResult(writer);
777 TransformerFactory tf = TransformerFactory.newInstance();
778 Transformer transformer = tf.newTransformer();
779 transformer.transform(domSource, result);
780 content = writer.toString();
781 System.out.println("Change the & to &Amp; for proper debug dispay");
782 content = StringUtils.replace(content, "&", "&amp;");
783 writer.flush();
784 }
785 catch (TransformerException ex)
786 {
787 ex.printStackTrace();
788 return null;
789 }
790 return content;
791 }
792
793 protected Document getPreprocessDoc() throws Exception
794 {
795
796 File xslt_file = new File(preprocess_xsl_filename);
797
798 FileReader reader = new FileReader(xslt_file);
799 InputSource xml_source = new InputSource(reader);
800 this.parser.parse(xml_source);
801 Document doc = this.parser.getDocument();
802
803 return doc;
804 }
805
806 protected Document getLibraryDoc() throws Exception
807 {
808 Document doc = null;
809 File xslt_file = new File(this.getLibraryXSLFilename());
810
811 FileReader reader = new FileReader(xslt_file);
812 InputSource xml_source = new InputSource(reader);
813 this.parser.parse(xml_source);
814
815 doc = this.parser.getDocument();
816 return doc;
817 }
818
819 protected Document getXSLTDocument(String action, String subaction, String collection)
820 {
821 String name = null;
822 if (!subaction.equals(""))
823 {
824 String key = action + ":" + subaction;
825 name = (String) this.xslt_map.get(key);
826 }
827 // try the action by itself
828 if (name == null)
829 {
830 name = (String) this.xslt_map.get(action);
831 }
832 // now find the absolute path
833 ArrayList<File> stylesheets = GSFile.getStylesheetFiles(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, name);
834
835 if (stylesheets.size() == 0)
836 {
837 logger.info(" Can't find stylesheet for " + name);
838 }
839 logger.debug("Stylesheet: " + name);
840
841 Document finalDoc = this.converter.getDOM(stylesheets.get(stylesheets.size() -1), "UTF-8");
842 if(finalDoc == null)
843 {
844 return null;
845 }
846
847 for(int i = stylesheets.size() - 2; i >= 0; i--)
848 {
849 Document currentDoc = this.converter.getDOM(stylesheets.get(i), "UTF-8");
850 if(currentDoc == null)
851 {
852 return null;
853 }
854
855 GSXSLT.mergeStylesheets(finalDoc, currentDoc.getDocumentElement());
856 }
857
858 return finalDoc;
859 }
860
861 // returns the library.xsl path of the library file that is applicable for the current interface
862 protected String getLibraryXSLFilename()
863 {
864 return GSFile.xmlTransformDir(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.INTERFACE_NAME))) + File.separatorChar + "library.xsl";
865 }
866
867 // Call this when a FileNotFoundException could be thrown when loading an xsl (xml) file.
868 // Returns an error xhtml page indicating which xsl (or other xml) file is missing.
869 protected Document fileNotFoundErrorPage(String filenameMessage)
870 {
871 String errorMessage = "ERROR missing file: " + filenameMessage;
872 Element errPage = XMLTransformer.constructErrorXHTMLPage(errorMessage);
873 logger.error(errorMessage);
874 return errPage.getOwnerDocument();
875 }
876}
Note: See TracBrowser for help on using the repository browser.