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

Last change on this file since 24203 was 24203, checked in by sjb48, 13 years ago

Working on document-level format editting

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