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

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

Fixing an error with excerptid and also changed GSXML.xmlNodeToString to have a parameter that controls whether or not to print XML text

  • 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 return null;
304 }
305
306 /**
307 * overwrite this to add any extra info that might be needed in the page
308 * before transformation
309 */
310 protected void addExtraInfo(Element page)
311 {
312 }
313
314 /**
315 * transform the page using xslt we need to get any format element out of
316 * the page and add it to the xslt before transforming
317 */
318 protected Node transformPage(Element page)
319 {
320 boolean allowsClientXSLT = (Boolean) config_params.get(GSConstants.ALLOW_CLIENT_SIDE_XSLT);
321 //System.out.println("Client side transforms allowed? " + allowsClientXSLT);
322
323 String currentInterface = (String) config_params.get(GSConstants.INTERFACE_NAME);
324
325 Element request = (Element) GSXML.getChildByTagName(page, GSXML.PAGE_REQUEST_ELEM);
326 String output = request.getAttribute(GSXML.OUTPUT_ATT);
327
328 //System.out.println("Current output mode is: " + output + ", current interface name is: " + currentInterface);
329
330 if (allowsClientXSLT)
331 {
332 if (!currentInterface.endsWith(GSConstants.CLIENT_SIDE_XSLT_INTERFACE_SUFFIX) && output.equals("html"))
333 {
334 System.out.println("output is html and we are not currently using a client side version, switching");
335 // Switch the interface
336 config_params.put(GSConstants.INTERFACE_NAME, currentInterface.concat(GSConstants.CLIENT_SIDE_XSLT_INTERFACE_SUFFIX));
337 }
338 else if ((currentInterface.endsWith(GSConstants.CLIENT_SIDE_XSLT_INTERFACE_SUFFIX) && !output.equals("html")) || output.equals("server"))
339 {
340 // The reverse needs to happen too
341 config_params.put(GSConstants.INTERFACE_NAME, currentInterface.substring(0, currentInterface.length() - GSConstants.CLIENT_SIDE_XSLT_INTERFACE_SUFFIX.length()));
342 }
343 }
344 else if (currentInterface.endsWith(GSConstants.CLIENT_SIDE_XSLT_INTERFACE_SUFFIX))
345 {
346 config_params.put(GSConstants.INTERFACE_NAME, currentInterface.substring(0, currentInterface.length() - GSConstants.CLIENT_SIDE_XSLT_INTERFACE_SUFFIX.length()));
347 }
348
349 // DocType defaults in case the skin doesn't have an "xsl:output" element
350 String qualifiedName = "html";
351 String publicID = "-//W3C//DTD HTML 4.01 Transitional//EN";
352 String systemID = "http://www.w3.org/TR/html4/loose.dtd";
353
354 // We need to create an empty document with a predefined DocType,
355 // that will then be used for the transformation by the DOMResult
356 Document docWithDoctype = converter.newDOM(qualifiedName, publicID, systemID);
357
358 if (output.equals("xsltclient"))
359 {
360 // If you're just getting the client-side transform page, why bother with the rest of this?
361 Element html = docWithDoctype.createElement("html");
362 Element img = docWithDoctype.createElement("img");
363 img.setAttribute("src", "interfaces/default/images/loading.gif"); // Make it dynamic
364 img.setAttribute("alt", "Please wait...");
365 Text title_text = docWithDoctype.createTextNode("Please wait..."); // Make this language dependent
366 Element head = docWithDoctype.createElement("head");
367 Element title = docWithDoctype.createElement("title");
368 title.appendChild(title_text);
369 Element body = docWithDoctype.createElement("body");
370 Element script = docWithDoctype.createElement("script");
371 Element jquery = docWithDoctype.createElement("script");
372 jquery.setAttribute("src", "jquery.js");
373 jquery.setAttribute("type", "text/javascript");
374 Comment jquery_comment = docWithDoctype.createComment("jQuery");
375 Comment script_comment = docWithDoctype.createComment("Filler for browser");
376 script.setAttribute("src", "test.js");
377 script.setAttribute("type", "text/javascript");
378 Element pagevar = docWithDoctype.createElement("script");
379 Element style = docWithDoctype.createElement("style");
380 style.setAttribute("type", "text/css");
381 Text style_text = docWithDoctype.createTextNode("body { text-align: center; padding: 50px; font: 14pt Arial, sans-serif; font-weight: bold; }");
382 pagevar.setAttribute("type", "text/javascript");
383 Text page_var_text = docWithDoctype.createTextNode("var placeholder = true;");
384
385 html.appendChild(head);
386 head.appendChild(title);
387 head.appendChild(style);
388 style.appendChild(style_text);
389 html.appendChild(body);
390 head.appendChild(pagevar);
391 head.appendChild(jquery);
392 head.appendChild(script);
393 pagevar.appendChild(page_var_text);
394 jquery.appendChild(jquery_comment);
395 script.appendChild(script_comment);
396 body.appendChild(img);
397 docWithDoctype.appendChild(html);
398
399 return (Node) docWithDoctype;
400 }
401
402 // 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
403 logger.debug("page before transforming:");
404 logger.debug(this.converter.getPrettyStringLogger(page, logger));
405
406 String action = request.getAttribute(GSXML.ACTION_ATT);
407 String subaction = request.getAttribute(GSXML.SUBACTION_ATT);
408
409 // we should choose how to transform the data based on output, eg diff
410 // choice for html, and wml??
411 // for now, if output=xml, we don't transform the page, we just return
412 // the page xml
413 Document theXML = null;
414
415 if (output.equals("xml") || output.equals("clientside"))
416 {
417 // Append some bits and pieces first...
418 theXML = converter.newDOM();
419 // Import into new document first!
420 Node newPage = theXML.importNode(page, true);
421 theXML.appendChild(newPage);
422 Element root = theXML.createElement("xsltparams");
423 newPage.appendChild(root);
424
425 Element libname = theXML.createElement("param");
426 libname.setAttribute("name", "library_name");
427 Text libnametext = theXML.createTextNode((String) config_params.get(GSConstants.LIBRARY_NAME));
428 libname.appendChild(libnametext);
429
430 Element intname = theXML.createElement("param");
431 intname.setAttribute("name", "interface_name");
432 Text intnametext = theXML.createTextNode((String) config_params.get(GSConstants.INTERFACE_NAME));
433 intname.appendChild(intnametext);
434
435 Element filepath = theXML.createElement("param");
436 filepath.setAttribute("name", "filepath");
437 Text filepathtext = theXML.createTextNode(GlobalProperties.getGSDL3Home());
438 filepath.appendChild(filepathtext);
439
440 root.appendChild(libname);
441 root.appendChild(intname);
442 root.appendChild(filepath);
443
444 if (output.equals("xml"))
445 return theXML.getDocumentElement();
446 }
447
448 Element cgi_param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
449 String collection = "";
450 if (cgi_param_list != null)
451 {
452 // Don't waste time getting all the parameters
453 HashMap params = GSXML.extractParams(cgi_param_list, false, GSParams.COLLECTION);
454 collection = (String) params.get(GSParams.COLLECTION);
455 if (collection == null)
456 collection = "";
457 }
458
459 Document style_doc = getXSLTDocument(action, subaction, collection);
460 if (style_doc == null)
461 {
462 String errorPage = this.converter.getParseErrorMessage();
463 if (errorPage != null)
464 {
465 return XMLTransformer.constructErrorXHTMLPage("Cannot parse the xslt file\n" + errorPage);
466 }
467 return page;
468 }
469
470 // put the page into a document - this is necessary for xslt to get
471 // the paths right if you have paths relative to the document root
472 // eg /page.
473 Document doc = this.converter.newDOM();
474 doc.appendChild(doc.importNode(page, true));
475 Element page_response = (Element) GSXML.getChildByTagName(page, GSXML.PAGE_RESPONSE_ELEM);
476 Element format_elem = (Element) GSXML.getChildByTagName(page_response, GSXML.FORMAT_ELEM);
477 if (output.equals("formatelem"))
478 {
479 return format_elem;
480 }
481 if (format_elem != null)
482 {
483 //page_response.removeChild(format_elem);
484 logger.debug("format elem=" + this.converter.getPrettyStringLogger(format_elem, logger));
485 // need to transform the format info
486 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");
487 Document configStylesheet_doc = this.converter.getDOM(new File(configStylesheet_file));
488
489 if (configStylesheet_doc != null)
490 {
491 Document format_doc = this.converter.newDOM();
492 format_doc.appendChild(format_doc.importNode(format_elem, true));
493 Node result = this.transformer.transform(configStylesheet_doc, format_doc, config_params); // Needs addressing <-
494
495 // Since we started creating documents with DocTypes, we can end up with
496 // Document objects here. But we will be working with an Element instead,
497 // so we grab the DocumentElement() of the Document object in such a case.
498 Element new_format;
499 if (result.getNodeType() == Node.DOCUMENT_NODE)
500 {
501 new_format = ((Document) result).getDocumentElement();
502 }
503 else
504 {
505 new_format = (Element) result;
506 }
507 logger.debug("new format elem=" + this.converter.getPrettyStringLogger(new_format, logger));
508 if (output.equals("newformat"))
509 {
510 return new_format;
511 }
512
513 // add extracted GSF statements in to the main stylesheet
514 GSXSLT.mergeStylesheets(style_doc, new_format);
515 //System.out.println("added extracted GSF statements into the main stylesheet") ;
516
517 // add extracted GSF statements in to the debug test stylesheet
518 //GSXSLT.mergeStylesheets(oldStyle_doc, new_format);
519 }
520 else
521 {
522 logger.error(" couldn't parse the config_format stylesheet, adding the format info as is");
523 GSXSLT.mergeStylesheets(style_doc, format_elem);
524 //GSXSLT.mergeStylesheets(oldStyle_doc, format_elem);
525 }
526 logger.debug("the converted stylesheet is:");
527 logger.debug(this.converter.getPrettyStringLogger(style_doc.getDocumentElement(), logger));
528 }
529
530 //for debug purposes only
531 Document oldStyle_doc = style_doc;
532
533 Document preprocessingXsl;
534 try
535 {
536 preprocessingXsl = getPreprocessDoc();
537 String errMsg = ((XMLConverter.ParseErrorHandler) parser.getErrorHandler()).getErrorMessage();
538 if (errMsg != null)
539 {
540 return XMLTransformer.constructErrorXHTMLPage("error loading preprocess xslt file: " + preprocess_xsl_filename + "\n" + errMsg);
541 }
542 }
543 catch (java.io.FileNotFoundException e)
544 {
545 return fileNotFoundErrorPage(e.getMessage());
546 }
547 catch (Exception e)
548 {
549 e.printStackTrace();
550 System.out.println("error loading preprocess xslt");
551 return XMLTransformer.constructErrorXHTMLPage("error loading preprocess xslt\n" + e.getMessage());
552 }
553
554 Document libraryXsl = null;
555 try
556 {
557 libraryXsl = getLibraryDoc();
558 String errMsg = ((XMLConverter.ParseErrorHandler) parser.getErrorHandler()).getErrorMessage();
559 if (errMsg != null)
560 {
561 return XMLTransformer.constructErrorXHTMLPage("Error loading xslt file: " + this.getLibraryXSLFilename() + "\n" + errMsg);
562 }
563 }
564 catch (java.io.FileNotFoundException e)
565 {
566 return fileNotFoundErrorPage(e.getMessage());
567 }
568 catch (Exception e)
569 {
570 e.printStackTrace();
571 System.out.println("error loading library xslt");
572 return XMLTransformer.constructErrorXHTMLPage("error loading library xslt\n" + e.getMessage());
573 }
574
575 // Combine the skin file and library variables/templates into one document.
576 // Please note: We dont just use xsl:import because the preprocessing stage
577 // needs to know what's available in the library.
578
579 Document skinAndLibraryXsl = null;
580 Document skinAndLibraryDoc = converter.newDOM();
581 try
582 {
583
584 skinAndLibraryXsl = converter.newDOM();
585 Element root = skinAndLibraryXsl.createElement("skinAndLibraryXsl");
586 skinAndLibraryXsl.appendChild(root);
587
588 Element s = skinAndLibraryXsl.createElement("skinXsl");
589 s.appendChild(skinAndLibraryXsl.importNode(style_doc.getDocumentElement(), true));
590 root.appendChild(s);
591
592 Element l = skinAndLibraryXsl.createElement("libraryXsl");
593 Element libraryXsl_el = libraryXsl.getDocumentElement();
594 l.appendChild(skinAndLibraryXsl.importNode(libraryXsl_el, true));
595 root.appendChild(l);
596 //System.out.println("Skin and Library XSL are now together") ;
597
598 //System.out.println("Pre-processing the skin file...") ;
599
600 //pre-process the skin style sheet
601 //In other words, apply the preProcess.xsl to 'skinAndLibraryXsl' in order to
602 //expand all GS-Lib statements into complete XSL statements and also to create
603 //a valid xsl style sheet document.
604
605 Transformer preProcessor = transformerFactory.newTransformer(new DOMSource(preprocessingXsl));
606 preProcessor.setErrorListener(new XMLTransformer.TransformErrorListener());
607 DOMResult result = new DOMResult();
608 result.setNode(skinAndLibraryDoc);
609 preProcessor.transform(new DOMSource(skinAndLibraryXsl), result);
610 //System.out.println("GS-Lib statements are now expanded") ;
611
612 }
613 catch (TransformerException e)
614 {
615 e.printStackTrace();
616 System.out.println("TransformerException while preprocessing the skin xslt");
617 return XMLTransformer.constructErrorXHTMLPage(e.getMessage());
618 }
619 catch (Exception e)
620 {
621 e.printStackTrace();
622 System.out.println("Error while preprocessing the skin xslt");
623 return XMLTransformer.constructErrorXHTMLPage(e.getMessage());
624 }
625
626 //The following code is to be uncommented if we need to append the extracted GSF statements
627 //after having extracted the GSLib elements. In case of a problem during postprocessing.
628 /*
629 * // put the page into a document - this is necessary for xslt to get
630 * // the paths right if you have paths relative to the document root //
631 * eg /page. Document doc = this.converter.newDOM();
632 * doc.appendChild(doc.importNode(page, true)); Element page_response =
633 * (Element)GSXML.getChildByTagName(page, GSXML.PAGE_RESPONSE_ELEM);
634 * Element format_elem = (Element)GSXML.getChildByTagName(page_response,
635 * GSXML.FORMAT_ELEM); if (output.equals("formatelem")) { return
636 * format_elem; } if (format_elem != null) {
637 * //page_response.removeChild(format_elem);
638 * logger.debug("format elem="+
639 * this.converter.getPrettyString(format_elem)); // need to transform
640 * the format info String configStylesheet_file =
641 * GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(),
642 * (String)this.config_params.get(GSConstants.SITE_NAME), collection,
643 * (String)this.config_params.get(GSConstants.INTERFACE_NAME),
644 * base_interfaces, "config_format.xsl"); Document configStylesheet_doc
645 * = this.converter.getDOM(new File(configStylesheet_file)); if
646 * (configStylesheet_doc != null) { Document format_doc =
647 * this.converter.newDOM();
648 * format_doc.appendChild(format_doc.importNode(format_elem, true));
649 * Node result = this.transformer.transform(configStylesheet_doc,
650 * format_doc);
651 *
652 * // Since we started creating documents with DocTypes, we can end up
653 * with // Document objects here. But we will be working with an Element
654 * instead, // so we grab the DocumentElement() of the Document object
655 * in such a case. Element new_format; if(result.getNodeType() ==
656 * Node.DOCUMENT_NODE) { new_format =
657 * ((Document)result).getDocumentElement(); } else { new_format =
658 * (Element)result; }
659 * logger.debug("new format elem="+this.converter.getPrettyString
660 * (new_format)); if (output.equals("newformat")) { return new_format; }
661 *
662 * // add extracted GSF statements in to the main stylesheet
663 * GSXSLT.mergeStylesheets(skinAndLibraryDoc, new_format);
664 * //System.out.println
665 * ("added extracted GSF statements into the main stylesheet") ;
666 *
667 * // add extracted GSF statements in to the debug test stylesheet
668 * //GSXSLT.mergeStylesheets(oldStyle_doc, new_format); } else {
669 * logger.error(
670 * " couldn't parse the config_format stylesheet, adding the format info as is"
671 * ); GSXSLT.mergeStylesheets(skinAndLibraryDoc, format_elem); //
672 * GSXSLT.mergeStylesheets(oldStyle_doc, format_elem); }
673 * logger.debug("the converted stylesheet is:");
674 * logger.debug(this.converter
675 * .getPrettyString(skinAndLibraryDoc.getDocumentElement())); }
676 */
677
678 // there is a thing called a URIResolver which you can set for a
679 // transformer or transformer factory. may be able to use this
680 // instead of this absoluteIncludepaths hack
681
682 GSXSLT.absoluteIncludePaths(skinAndLibraryDoc, GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
683
684 //Same but for the debug version when we want the do the transformation like we use to do
685 //without any gslib elements.
686 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);
687
688 //Send different stages of the skin xslt to the browser for debug purposes only
689 //using &o=skindoc or &o=skinandlib etc...
690 if (output.equals("skindoc"))
691 {
692 return converter.getDOM(getStringFromDocument(style_doc));
693 }
694 if (output.equals("skinandlib"))
695 {
696 return converter.getDOM(getStringFromDocument(skinAndLibraryXsl));
697 }
698 if (output.equals("skinandlibdoc") || output.equals("clientside"))
699 {
700
701 Node skinAndLib = converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
702
703 if (output.equals("skinandlibdoc"))
704 {
705 return skinAndLib;
706 }
707 else
708 {
709 // Send XML and skinandlibdoc down the line together
710 Document finalDoc = converter.newDOM();
711 Node finalDocSkin = finalDoc.importNode(skinAndLibraryDoc.getDocumentElement(), true);
712 Node finalDocXML = finalDoc.importNode(theXML.getDocumentElement(), true);
713 Element root = finalDoc.createElement("skinlibPlusXML");
714 root.appendChild(finalDocSkin);
715 root.appendChild(finalDocXML);
716 finalDoc.appendChild(root);
717 return (Node) finalDoc.getDocumentElement();
718 }
719 }
720 if (output.equals("oldskindoc"))
721 {
722 return converter.getDOM(getStringFromDocument(oldStyle_doc));
723 }
724
725 // Try to get the system and public ID from the current skin xsl document
726 // otherwise keep the default values.
727 Element root = skinAndLibraryDoc.getDocumentElement();
728 NodeList nodes = root.getElementsByTagName("xsl:output");
729 // If there is at least one "xsl:output" command in the final xsl then...
730 if (nodes.getLength() != 0)
731 {
732 // There should be only one element called xsl:output,
733 // but if this is not the case get the last one
734 Element xsl_output = (Element) nodes.item(nodes.getLength() - 1);
735 if (xsl_output != null)
736 {
737 // Qualified name will always be html even for xhtml pages
738 //String attrValue = xsl_output.getAttribute("method");
739 //qualifiedName = attrValue.equals("") ? qualifiedName : attrValue;
740
741 String attrValue = xsl_output.getAttribute("doctype-system");
742 systemID = attrValue.equals("") ? systemID : attrValue;
743
744 attrValue = xsl_output.getAttribute("doctype-public");
745 publicID = attrValue.equals("") ? publicID : attrValue;
746 }
747 }
748
749 //System.out.println(converter.getPrettyString(docWithDoctype));
750 //System.out.println("Doctype vals: " + qualifiedName + " " + publicID + " " + systemID) ;
751
752 docWithDoctype = converter.newDOM(qualifiedName, publicID, systemID);
753
754 //System.out.println("Generate final HTML from current skin") ;
755 //Transformation of the XML message from the receptionist to HTML with doctype
756
757 return this.transformer.transform(skinAndLibraryDoc, doc, config_params, docWithDoctype); // The default
758
759 // The line below will do the transformation like we use to do before having Skin++ implemented,
760 // it will not contain any GS-Lib statements expanded, and the result will not contain any doctype.
761
762 //return (Element)this.transformer.transform(style_doc, doc, config_params);
763 //return null; // For now - change later
764 }
765
766 // method to convert Document to a proper XML string for debug purposes only
767 protected String getStringFromDocument(Document doc)
768 {
769 String content = "";
770 try
771 {
772 DOMSource domSource = new DOMSource(doc);
773 StringWriter writer = new StringWriter();
774 StreamResult result = new StreamResult(writer);
775 TransformerFactory tf = TransformerFactory.newInstance();
776 Transformer transformer = tf.newTransformer();
777 transformer.transform(domSource, result);
778 content = writer.toString();
779 System.out.println("Change the & to &Amp; for proper debug dispay");
780 content = StringUtils.replace(content, "&", "&amp;");
781 writer.flush();
782 }
783 catch (TransformerException ex)
784 {
785 ex.printStackTrace();
786 return null;
787 }
788 return content;
789 }
790
791 protected Document getPreprocessDoc() throws Exception
792 {
793
794 File xslt_file = new File(preprocess_xsl_filename);
795
796 FileReader reader = new FileReader(xslt_file);
797 InputSource xml_source = new InputSource(reader);
798 this.parser.parse(xml_source);
799 Document doc = this.parser.getDocument();
800
801 return doc;
802 }
803
804 protected Document getLibraryDoc() throws Exception
805 {
806 Document doc = null;
807 File xslt_file = new File(this.getLibraryXSLFilename());
808
809 FileReader reader = new FileReader(xslt_file);
810 InputSource xml_source = new InputSource(reader);
811 this.parser.parse(xml_source);
812
813 doc = this.parser.getDocument();
814 return doc;
815 }
816
817 protected Document getXSLTDocument(String action, String subaction, String collection)
818 {
819 String name = null;
820 if (!subaction.equals(""))
821 {
822 String key = action + ":" + subaction;
823 name = (String) this.xslt_map.get(key);
824 }
825 // try the action by itself
826 if (name == null)
827 {
828 name = (String) this.xslt_map.get(action);
829 }
830 // now find the absolute path
831 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);
832
833 if (stylesheets.size() == 0)
834 {
835 logger.error(" Can't find stylesheet for " + name);
836 return null;
837 }
838 logger.debug("Stylesheet: " + name);
839
840 Document finalDoc = this.converter.getDOM(stylesheets.get(stylesheets.size() -1), "UTF-8");
841 if(finalDoc == null)
842 {
843 return null;
844 }
845
846 for(int i = stylesheets.size() - 2; i >= 0; i--)
847 {
848 Document currentDoc = this.converter.getDOM(stylesheets.get(i), "UTF-8");
849 if(currentDoc == null)
850 {
851 return null;
852 }
853
854 GSXSLT.mergeStylesheets(finalDoc, currentDoc.getDocumentElement());
855 }
856
857 return finalDoc;
858 }
859
860 // returns the library.xsl path of the library file that is applicable for the current interface
861 protected String getLibraryXSLFilename()
862 {
863 return GSFile.xmlTransformDir(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.INTERFACE_NAME))) + File.separatorChar + "library.xsl";
864 }
865
866 // Call this when a FileNotFoundException could be thrown when loading an xsl (xml) file.
867 // Returns an error xhtml page indicating which xsl (or other xml) file is missing.
868 protected Document fileNotFoundErrorPage(String filenameMessage)
869 {
870 String errorMessage = "ERROR missing file: " + filenameMessage;
871 Element errPage = XMLTransformer.constructErrorXHTMLPage(errorMessage);
872 logger.error(errorMessage);
873 return errPage.getOwnerDocument();
874 }
875}
Note: See TracBrowser for help on using the repository browser.