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

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

Adding in the DocumentBasket functionality and also the new cascading way of handling xsl files which will look in the collect/site/interface/base interface places in that order

  • 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.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.