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

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

Fixed a mistake in Greenstone3's build.xml file that was preventing non-jni versions of Greenstone3 compiling successfully on Windows

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