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

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

Created the gs variable in Javascript as well as gsf:variable that creates a variable in both XSLT and Javascript. Also, can now be accessed in config_format.xsl

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