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

Last change on this file was 38731, checked in by davidb, 3 months ago

Allow GS3 runtime to skip over temporary backup versions of XSL files. This can happen if running emacs, for example, while working on XSL files and testing them out in Tomcat

  • Property svn:keywords set to Author Date Id Revision
File size: 43.8 KB
Line 
1package org.greenstone.gsdl3.core;
2
3import java.io.File;
4import java.io.FileReader;
5import java.io.Serializable;
6import java.io.StringWriter;
7import java.util.ArrayList;
8import java.util.HashMap;
9import java.util.HashSet;
10import java.util.regex.Pattern;
11import java.util.regex.Matcher;
12
13import javax.xml.transform.Transformer;
14import javax.xml.transform.TransformerException;
15import javax.xml.transform.TransformerFactory;
16import javax.xml.transform.dom.DOMSource;
17import javax.xml.transform.stream.StreamResult;
18
19import org.apache.commons.lang3.StringUtils;
20import org.apache.log4j.Logger;
21import org.apache.xerces.parsers.DOMParser;
22import org.greenstone.gsdl3.action.Action;
23import org.greenstone.gsdl3.util.GSConstants;
24import org.greenstone.gsdl3.util.GSFile;
25import org.greenstone.gsdl3.util.GSParams;
26import org.greenstone.gsdl3.util.GSXML;
27import org.greenstone.gsdl3.util.GSXSLT;
28import org.greenstone.gsdl3.util.UserContext;
29import org.greenstone.gsdl3.util.XMLConverter;
30import org.greenstone.gsdl3.util.XMLTransformer;
31import org.greenstone.gsdl3.util.XSLTUtil;
32import org.greenstone.util.GlobalProperties;
33import org.w3c.dom.Comment;
34import org.w3c.dom.Document;
35import org.w3c.dom.Element;
36import org.w3c.dom.Node;
37import org.w3c.dom.NodeList;
38import org.w3c.dom.Text;
39import org.xml.sax.InputSource;
40
41/**
42 * A receptionist that uses xslt to transform the page_data before returning it.
43 * . Receives requests consisting of an xml representation of cgi args, and
44 * returns the page of data - in html by default. The requests are processed by
45 * the appropriate action class
46 *
47 * @see Action
48 */
49public class TransformingReceptionist extends Receptionist
50{
51 protected static final String EXPAND_GSF_FILE = "expand-gsf.xsl";
52 protected static final String EXPAND_GSF_PASS1_FILE = "expand-gsf-pass1.xsl";
53 protected static final String EXPAND_GSLIB_FILE = "expand-gslib.xsl";
54 protected static final String GSLIB_FILE = "gslib.xsl";
55
56 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.TransformingReceptionist.class.getName());
57
58 /** The expand-gslib.xsl file is in a fixed location */
59 static final String expand_gslib_filepath = GlobalProperties.getGSDL3Home() + File.separatorChar + "interfaces" + File.separatorChar + "core" + File.separatorChar + "transform" + File.separatorChar + EXPAND_GSLIB_FILE;
60
61 /** the list of xslt to use for actions */
62 protected HashMap<String, String> xslt_map = null;
63
64 /** a transformer class to transform xml using xslt */
65 protected XMLTransformer transformer = null;
66
67 protected TransformerFactory transformerFactory = null;
68 protected DOMParser parser = null;
69
70 protected HashMap<String, ArrayList<String>> _metadataRequiredMap = new HashMap<String, ArrayList<String>>();
71
72 boolean _debug = true;
73
74 public TransformingReceptionist()
75 {
76 super();
77 this.xslt_map = new HashMap<String, String>();
78 this.transformer = new XMLTransformer();
79 try
80 {
81 transformerFactory = org.apache.xalan.processor.TransformerFactoryImpl.newInstance();
82 this.converter = new XMLConverter();
83 //transformerFactory.setURIResolver(new MyUriResolver()) ;
84
85 parser = new DOMParser();
86 parser.setFeature("http://xml.org/sax/features/validation", false);
87 // 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.
88 parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
89 // a performance test showed that having this on lead to increased
90 // memory use for small-medium docs, and not much gain for large
91 // docs.
92 // http://www.sosnoski.com/opensrc/xmlbench/conclusions.html
93 parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
94 parser.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true);
95 // setting a handler for when fatal errors, errors or warnings happen during xml parsing
96 // call XMLConverter's getParseErrorMessage() to get the errorstring that can be rendered as web page
97 this.parser.setErrorHandler(new XMLConverter.ParseErrorHandler());
98 }
99 catch (Exception e)
100 {
101 e.printStackTrace();
102 }
103 }
104
105 /** configures the receptionist - adding in setting up the xslt map */
106 public boolean configure()
107 {
108 if (!super.configure()) {
109
110 return false;
111 }
112
113 logger.info("configuring the TransformingReceptionist");
114
115 // find the config file containing a list of actions
116 File interface_config_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.INTERFACE_NAME))));
117 Document config_doc = this.converter.getDOM(interface_config_file, "UTF-8");
118 Element config_elem = config_doc.getDocumentElement();
119
120 // Find the actions again so that we can set up the xslt map
121 Element action_list = (Element) GSXML.getChildByTagName(config_elem, GSXML.ACTION_ELEM + GSXML.LIST_MODIFIER);
122 NodeList actions = action_list.getElementsByTagName(GSXML.ACTION_ELEM);
123
124 for (int i = 0; i < actions.getLength(); i++)
125 {
126 Element action = (Element) actions.item(i);
127 String class_name = action.getAttribute("class");
128 String action_name = action.getAttribute("name");
129
130 // now do the xslt map
131 String xslt = action.getAttribute("xslt");
132 if (!xslt.equals(""))
133 {
134 this.xslt_map.put(action_name, xslt);
135 }
136 NodeList subactions = action.getElementsByTagName(GSXML.SUBACTION_ELEM);
137 for (int j = 0; j < subactions.getLength(); j++)
138 {
139 Element subaction = (Element) subactions.item(j);
140 String subname = subaction.getAttribute(GSXML.NAME_ATT);
141 String subxslt = subaction.getAttribute("xslt");
142
143 String map_key = action_name + ":" + subname;
144 logger.debug("adding in to xslt map, " + map_key + "->" + subxslt);
145 this.xslt_map.put(map_key, subxslt);
146 }
147 }
148
149 getRequiredMetadataNamesFromXSLFiles();
150
151 return true;
152 }
153
154 protected void getRequiredMetadataNamesFromXSLFiles()
155 {
156 ArrayList<File> xslFiles = GSFile.getAllXSLFiles((String) this.config_params.get(GSConstants.SITE_NAME));
157
158 HashMap<String, ArrayList<String>> includes = new HashMap<String, ArrayList<String>>();
159 HashMap<String, ArrayList<File>> files = new HashMap<String, ArrayList<File>>();
160 HashMap<String, ArrayList<String>> metaNames = new HashMap<String, ArrayList<String>>();
161
162 //First exploratory pass
163 for (File currentFile : xslFiles)
164 {
165
166 String full_filename = currentFile.getPath();
167 int sep_pos = full_filename.lastIndexOf(File.separator)+1;
168 String local_filename = full_filename.substring(sep_pos);
169 if (local_filename.startsWith(".")) {
170 logger.warn("Greenstone does not normally rely on 'dot' files for XSL transformations.\n Is the following file intended to be part of the digital library installation?\n XSL File being read in:\n " + currentFile.getPath());
171 }
172
173 Document currentDoc = this.converter.getDOM(currentFile);
174 if (currentDoc == null)
175 {
176 // Can happen if an editor creates an auto-save temporary file
177 // (such as #header.xsl#) that is not well formed XML
178 logger.warn("Skipping XSL file. DOM returned was null for:\n " + currentFile.getPath());
179 continue;
180 }
181
182 HashSet<String> extra_meta_names = new HashSet<String>();
183 GSXSLT.findExtraMetadataNames(currentDoc.getDocumentElement(), extra_meta_names);
184 ArrayList<String> names = new ArrayList<String>(extra_meta_names);
185
186 metaNames.put(currentFile.getAbsolutePath(), names);
187
188 NodeList includeElems = currentDoc.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "include");
189 NodeList importElems = currentDoc.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "import");
190
191
192 ArrayList<String> includeAndImportList = new ArrayList<String>();
193 for (int i = 0; i < includeElems.getLength(); i++)
194 {
195 includeAndImportList.add(((Element) includeElems.item(i)).getAttribute(GSXML.HREF_ATT));
196 }
197 for (int i = 0; i < importElems.getLength(); i++)
198 {
199 includeAndImportList.add(((Element) importElems.item(i)).getAttribute(GSXML.HREF_ATT));
200 }
201 includes.put(currentFile.getAbsolutePath(), includeAndImportList);
202
203 String filename = currentFile.getName();
204 if (files.get(filename) == null)
205 {
206 ArrayList<File> fileList = new ArrayList<File>();
207 fileList.add(currentFile);
208 files.put(currentFile.getName(), fileList);
209 }
210 else
211 {
212 ArrayList<File> fileList = files.get(filename);
213 fileList.add(currentFile);
214 }
215 }
216
217 //Second pass
218 for (File currentFile : xslFiles)
219 {
220 ArrayList<File> filesToGet = new ArrayList<File>();
221 filesToGet.add(currentFile);
222
223 ArrayList<String> fullNameList = new ArrayList<String>();
224
225 while (filesToGet.size() > 0)
226 {
227 File currentFileTemp = filesToGet.remove(0);
228
229 //Add the names from this file
230 ArrayList<String> currentNames = metaNames.get(currentFileTemp.getAbsolutePath());
231 if (currentNames == null)
232 {
233 continue;
234 }
235
236 fullNameList.addAll(currentNames);
237
238 ArrayList<String> includedHrefs = includes.get(currentFileTemp.getAbsolutePath());
239
240 for (String href : includedHrefs)
241 {
242 int lastSepIndex = href.lastIndexOf("/");
243 if (lastSepIndex != -1)
244 {
245 href = href.substring(lastSepIndex + 1);
246 }
247
248 ArrayList<File> filesToAdd = files.get(href);
249 if (filesToAdd != null)
250 {
251 filesToGet.addAll(filesToAdd);
252 }
253 }
254 }
255
256 _metadataRequiredMap.put(currentFile.getAbsolutePath(), fullNameList);
257 }
258 }
259
260 protected void preProcessRequest(Element request)
261 {
262 String action = request.getAttribute(GSXML.ACTION_ATT);
263 String subaction = request.getAttribute(GSXML.SUBACTION_ATT);
264
265 String name = null;
266 if (!subaction.equals(""))
267 {
268 String key = action + ":" + subaction;
269 name = this.xslt_map.get(key);
270 }
271 // try the action by itself
272 if (name == null)
273 {
274 name = this.xslt_map.get(action);
275 }
276
277 Element cgi_param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
278 String collection = "";
279
280 if (cgi_param_list != null)
281 {
282 // Don't waste time getting all the parameters
283 HashMap<String, Serializable> params = GSXML.extractParams(cgi_param_list, false);
284 collection = (String) params.get(GSParams.COLLECTION);
285 if (collection == null)
286 {
287 collection = "";
288 }
289 }
290
291 ArrayList<File> stylesheets = GSFile.getStylesheetFiles(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, name);
292
293 Document doc = XMLConverter.newDOM();
294 Element extraMetadataList = doc.createElement(GSXML.EXTRA_METADATA + GSXML.LIST_MODIFIER);
295 HashSet<String> name_set = new HashSet<String>();
296 for (File stylesheet : stylesheets)
297 {
298 ArrayList<String> requiredMetadata = _metadataRequiredMap.get(stylesheet.getAbsolutePath());
299
300 if (requiredMetadata != null)
301 {
302 for (String metadataString : requiredMetadata)
303 {
304 if (!name_set.contains(metadataString)) {
305 name_set.add(metadataString);
306 Element metadataElem = doc.createElement(GSXML.EXTRA_METADATA);
307 metadataElem.setAttribute(GSXML.NAME_ATT, metadataString);
308 extraMetadataList.appendChild(metadataElem);
309 }
310 }
311 }
312 }
313 request.appendChild(request.getOwnerDocument().importNode(extraMetadataList, true));
314 }
315
316 protected Node postProcessPage(Element page)
317 {
318 // might need to add some data to the page
319 addExtraInfo(page);
320
321
322 // transform the page using xslt
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 boolean useClientXSLT = (Boolean) config_params.get(GSConstants.USE_CLIENT_SIDE_XSLT);
330 //logger.info("Client side transforms allowed? " + allowsClientXSLT);
331
332 if (useClientXSLT)
333 {
334 // if not specified, output defaults to 'html', but this isn't what we want when useClientXSLT is on
335 if (output.equals("html")) {
336 output = "xsltclient";
337 }
338 }
339 Node transformed_page = transformPage(page,currentInterface,output);
340
341 if (useClientXSLT) {
342 return transformed_page;
343 }
344 // if the user has specified they want only a part of the full page then subdivide it
345 boolean subdivide = false;
346 String excerptID = null;
347 String excerptIDText = null;
348 String excerptTag = null;
349 Element cgi_param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
350
351 // **** Now that the number of cases handled has risen to 3, the following would be worth refactoring ****
352 if (cgi_param_list != null)
353 {
354 HashMap<String, Serializable> params = GSXML.extractParams(cgi_param_list, false);
355 if ((excerptID = (String) params.get(GSParams.EXCERPT_ID)) != null)
356 {
357 subdivide = true;
358 }
359 if ((excerptIDText = (String) params.get(GSParams.EXCERPT_ID_TEXT)) != null)
360 {
361 subdivide = true;
362 }
363 if ((excerptTag = (String) params.get(GSParams.EXCERPT_TAG)) != null)
364 {
365 subdivide = true;
366 }
367 }
368
369 if (subdivide)
370 {
371 Node subdivided_page = subdivide(transformed_page, excerptID, excerptIDText, excerptTag);
372 if (subdivided_page != null)
373 {
374 return subdivided_page;
375 }
376 else return null;
377 }
378
379 return transformed_page;
380 }
381
382 protected Node subdivide(Node transformed_page, String excerptID, String excerptIDText, String excerptTag)
383 {
384 if (excerptID != null)
385 {
386 Node selectedElement = getNodeByIdRecursive(transformed_page, excerptID);
387 modifyNodesByTagRecursive(selectedElement, "a");
388 return selectedElement;
389 }
390 if (excerptIDText != null)
391 {
392 Node selectedElement = getNodeByIdRecursive(transformed_page, excerptIDText);
393
394 String selectedTextString = selectedElement.getTextContent();
395 Document forexcerptid_doc = XMLConverter.newDOM();
396 Node selectedElementChildTextNode = forexcerptid_doc.createTextNode(selectedTextString);
397
398 return selectedElementChildTextNode;
399 }
400 else if (excerptTag != null)
401 {
402 Node selectedElement = getNodeByTagRecursive(transformed_page, excerptTag);
403 return selectedElement;
404 }
405 return transformed_page;
406 }
407
408 protected Node getNodeByIdRecursive(Node parent, String id)
409 {
410 if (parent.hasAttributes() && ((Element) parent).getAttribute("id").equals(id))
411 {
412 return parent;
413 }
414
415 NodeList children = parent.getChildNodes();
416 for (int i = 0; i < children.getLength(); i++)
417 {
418 Node result = null;
419 if ((result = getNodeByIdRecursive(children.item(i), id)) != null)
420 {
421 return result;
422 }
423 }
424 return null;
425 }
426
427 protected Node getNodeByTagRecursive(Node parent, String tag)
428 {
429 if (parent.getNodeType() == Node.ELEMENT_NODE && ((Element) parent).getTagName().equals(tag))
430 {
431 return parent;
432 }
433
434 NodeList children = parent.getChildNodes();
435 for (int i = 0; i < children.getLength(); i++)
436 {
437 Node result = null;
438 if ((result = getNodeByTagRecursive(children.item(i), tag)) != null)
439 {
440 return result;
441 }
442 }
443 return null;
444 }
445
446 protected Node modifyNodesByTagRecursive(Node parent, String tag)
447 {
448 if (parent == null || (parent.getNodeType() == Node.ELEMENT_NODE && ((Element) parent).getTagName().equals(tag)))
449 {
450 return parent;
451 }
452
453 NodeList children = parent.getChildNodes();
454 for (int i = 0; i < children.getLength(); i++)
455 {
456 Node result = null;
457 if ((result = modifyNodesByTagRecursive(children.item(i), tag)) != null)
458 {
459 //TODO: DO SOMETHING HERE?
460 }
461 }
462 return null;
463 }
464
465 protected void replaceNodeWithInterfaceText(Document doc, String interface_name, String lang,
466 Element elem, String attr_name, String attr_val)
467 {
468 String pattern_str_3arg = "util:getInterfaceText\\([^,]+,[^,]+,\\s*'(.+?)'\\s*\\)";
469 String pattern_str_4arg = "util:getInterfaceText\\([^,]+,[^,]+,\\s*'(.+?)'\\s*,\\s*(.+?)\\s*\\)$";
470
471 Pattern pattern3 = Pattern.compile(pattern_str_3arg);
472 Matcher matcher3 = pattern3.matcher(attr_val);
473 if (matcher3.find()) {
474 String dict_key = matcher3.group(1);
475 String dict_val = XSLTUtil.getInterfaceText(interface_name,lang,dict_key);
476
477 Node parent_node = elem.getParentNode();
478
479 Text replacement_text_node = doc.createTextNode(dict_val);
480 parent_node.replaceChild(replacement_text_node,elem);
481 }
482 else {
483 Pattern pattern4 = Pattern.compile(pattern_str_4arg);
484 Matcher matcher4 = pattern4.matcher(attr_val);
485 StringBuffer string_buffer4 = new StringBuffer();
486
487 if (matcher4.find()) {
488 String dict_key = matcher4.group(1);
489 String args = matcher4.group(2);
490 args = args.replaceAll("\\$","\\\\\\$");
491
492 String dict_val = XSLTUtil.getInterfaceText(interface_name,lang,dict_key);
493
494 matcher4.appendReplacement(string_buffer4, "js:getInterfaceTextSubstituteArgs('"+dict_val+"',string("+args+"))");
495 matcher4.appendTail(string_buffer4);
496
497 attr_val = string_buffer4.toString();
498 elem.setAttribute(attr_name,attr_val);
499 }
500 else {
501 logger.error("Failed to find match in attribute: " + attr_name + "=\"" + attr_val + "\"");
502 attr_val = attr_val.replaceAll("util:getInterfaceText\\(.+?,.+?,\\s*(.+?)\\s*\\)","$1");
503 elem.setAttribute(attr_name,attr_val);
504 }
505 }
506
507 }
508
509 protected void resolveExtendedNamespaceAttributesXSLT(Document doc, String interface_name, String lang)
510 {
511 String[] attr_list = new String[] {"select","test"};
512
513 // http://stackoverflow.com/questions/13220520/javascript-replace-child-loop-issue
514 // go through nodeList in reverse to avoid the 'skipping' problem, due to
515 // replaceChild() calls removing items from the "live" nodeList
516
517 NodeList nodeList = doc.getElementsByTagName("*");
518 for (int i=nodeList.getLength()-1; i>=0; i--) {
519 Node node = nodeList.item(i);
520 if (node.getNodeType() == Node.ELEMENT_NODE) {
521 Element elem = (Element)node;
522 for (String attr_name : attr_list) {
523 if (elem.hasAttribute(attr_name)) {
524 String attr_val = elem.getAttribute(attr_name);
525
526 if (attr_val.startsWith("util:getInterfaceText(")) {
527 // replace the node with dictionary lookup
528 replaceNodeWithInterfaceText(doc, interface_name,lang, elem,attr_name,attr_val);
529 }
530 else if (attr_val.contains("util:")) {
531
532 attr_val = attr_val.replaceAll("util:getInterfaceStringsAsJavascript\\(.+?,.+?,\\s*(.+?)\\)","$1");
533
534 //attr_val = attr_val.replaceAll("util:escapeNewLinesAndQuotes\\(\\s*(.+?)\\s*\\)","'escapeNLandQ $1'");
535 //attr_val = attr_val.replaceAll("util:escapeNewLinesAndQuotes\\(\\s*(.+?)\\s*\\)","$1");
536
537 // 'contains()' supported in XSLT 1.0, so OK to change any util:contains() into contains()
538 attr_val = attr_val.replaceAll("util:(contains\\(.+?\\))","$1");
539
540 elem.setAttribute(attr_name,attr_val);
541 }
542
543 if (attr_val.contains("java:")) {
544 if (attr_val.indexOf("getInterfaceTextSubstituteArgs")>=4) {
545
546 attr_val = attr_val.replaceAll("java:.+?\\.(\\w+)\\((.*?)\\)$","js:$1($2)");
547 }
548
549 elem.setAttribute(attr_name,attr_val);
550 }
551 }
552 }
553
554 }
555 }
556 }
557
558
559 protected void resolveExtendedNamespaceAttributesXML(Document doc, String interface_name, String lang)
560 {
561 String[] attr_list = new String[] {"src", "href"};
562
563 // http://stackoverflow.com/questions/13220520/javascript-replace-child-loop-issue
564 // go through nodeList in reverse to avoid the 'skipping' problem, due to
565 // replaceChild() calls removing items from the "live" nodeList
566
567 NodeList nodeList = doc.getElementsByTagName("*");
568 for (int i=nodeList.getLength()-1; i>=0; i--) {
569 Node node = nodeList.item(i);
570 if (node.getNodeType() == Node.ELEMENT_NODE) {
571 Element elem = (Element)node;
572 for (String attr_name : attr_list) {
573 if (elem.hasAttribute(attr_name)) {
574 String attr_val = elem.getAttribute(attr_name);
575
576 if (attr_val.contains("util:getInterfaceText(")) {
577 String pattern_str_3arg = "util:getInterfaceText\\([^,]+,[^,]+,\\s*'(.+?)'\\s*\\)";
578 Pattern pattern3 = Pattern.compile(pattern_str_3arg);
579 Matcher matcher3 = pattern3.matcher(attr_val);
580
581 StringBuffer string_buffer3 = new StringBuffer();
582
583 boolean found_match = false;
584
585 while (matcher3.find()) {
586 found_match = true;
587 String dict_key = matcher3.group(1);
588 String dict_val = XSLTUtil.getInterfaceText(interface_name,lang,dict_key);
589
590 matcher3.appendReplacement(string_buffer3, dict_val);
591 }
592 matcher3.appendTail(string_buffer3);
593
594 if (found_match) {
595 attr_val = string_buffer3.toString();
596 elem.setAttribute(attr_name,attr_val);
597 }
598 else {
599 logger.error("Failed to find match in attribute: " + attr_name + "=\"" + attr_val + "\"");
600 attr_val = attr_val.replaceAll("util:getInterfaceText\\(.+?,.+?,\\s*(.+?)\\s*\\)","$1");
601 elem.setAttribute(attr_name,attr_val);
602 }
603 }
604 else if (attr_val.contains("util:")) {
605
606 logger.error("Encountered unexpected 'util:' prefix exension: " + attr_name + "=\"" + attr_val + "\"");
607 }
608
609 if (attr_val.contains("java:")) {
610 // make anything java: safe from the point of an XSLT without extensions
611 logger.error("Encountered unexpected 'java:' prefix exension: " + attr_name + "=\"" + attr_val + "\"");
612
613 }
614 }
615 }
616
617 }
618 }
619 }
620
621
622
623 /**
624 * overwrite this to add any extra info that might be needed in the page
625 * before transformation
626 */
627 protected void addExtraInfo(Element page)
628 {
629 }
630
631 /**
632 * transform the page using xslt.
633 * we need to get any format element out of the page and add it to the xslt before transforming
634 */
635 protected Node transformPage(Element page_xml, String currentInterface, String output)
636 {
637 _debug = false;
638
639 Element request = (Element) GSXML.getChildByTagName(page_xml, GSXML.PAGE_REQUEST_ELEM);
640
641 //logger.info("Current output mode is: " + output + ", current interface name is: " + currentInterface);
642
643 if (output.equals("xsltclient"))
644 {
645 return generateXSLTClientOutput(request);
646 }
647
648 String action = request.getAttribute(GSXML.ACTION_ATT);
649 String subaction = request.getAttribute(GSXML.SUBACTION_ATT);
650
651 // we should choose how to transform the data based on output, eg diff
652 // choice for html, and wml??
653 // for now, if output=xml, we don't transform the page, we just return
654 // the page xml
655 Document page_with_xslt_params_doc = null;
656
657 if (output.equals("xml") || (output.equals("json")) || output.equals("clientside"))
658 {
659 // Append the xsltparams to the page
660 page_with_xslt_params_doc = converter.newDOM();
661 // Import into new document first!
662 Node page_with_xslt_params = page_with_xslt_params_doc.importNode(page_xml, true);
663 page_with_xslt_params_doc.appendChild(page_with_xslt_params);
664 Element xslt_params = page_with_xslt_params_doc.createElement("xsltparams");
665 page_with_xslt_params.appendChild(xslt_params);
666
667 GSXML.addParameter2ToList(xslt_params, "library_name", (String) config_params.get(GSConstants.LIBRARY_NAME));
668 GSXML.addParameter2ToList(xslt_params, "interface_name", (String) config_params.get(GSConstants.INTERFACE_NAME));
669 GSXML.addParameter2ToList(xslt_params, "site_name", (String) config_params.get(GSConstants.SITE_NAME));
670 GSXML.addParameter2ToList(xslt_params, "cookie_consent", (String) config_params.get(GSConstants.COOKIE_CONSENT));
671 Boolean useClientXSLT = (Boolean) config_params.get(GSConstants.USE_CLIENT_SIDE_XSLT);
672 GSXML.addParameter2ToList(xslt_params, "use_client_side_xslt", useClientXSLT.toString());
673 GSXML.addParameter2ToList(xslt_params, "filepath", GlobalProperties.getGSDL3Home());
674
675 if ((output.equals("xml")) || output.equals("json"))
676 {
677 // Just return the page XML
678 // in the case of "json", calling method responsible for converting to JSON-string
679 return page_with_xslt_params_doc.getDocumentElement();
680 }
681 // in the case of client side, later on we'll use this doc with xslt params added,
682 // along with the xsl.
683 }
684
685 Element cgi_param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
686 String collection = "";
687 String inline_template = "";
688 if (cgi_param_list != null)
689 {
690 // Don't waste time getting all the parameters
691 HashMap<String, Serializable> params = GSXML.extractParams(cgi_param_list, false);
692 collection = (String) params.get(GSParams.COLLECTION);
693 if (collection == null)
694 {
695 collection = "";
696 }
697
698 inline_template = (String) params.get(GSParams.INLINE_TEMPLATE);
699 String debug_p = (String) params.get(GSParams.DEBUG);
700 if (debug_p != null && (debug_p.equals("on") || debug_p.equals("1") || debug_p.equals("true")))
701 {
702 String[] groups = new UserContext(request).getGroups();
703
704 boolean found = false;
705 for (String g : groups)
706 {
707 if (g.equals("administrator"))
708 {
709 found = true;
710 break;
711 }
712 if (!collection.equals("")) {
713 if (g.equals("all-collections-editor")) {
714 found = true;
715 break;
716 }
717
718 if (g.equals(collection+"-collection-editor")) {
719 found = true;
720 break;
721 }
722 }
723 }
724 if (found)
725 {
726 _debug = true;
727 }
728 }
729 }
730
731 config_params.put("collName", collection);
732
733 // find the appropriate stylesheet (based on action/subaction) - eg a=p&sa=home will be home.xsl
734 // This mapping is defined in interfaceConfig.xsl
735 // All versions of the stylesheet (base interface, interface, site, collection) are
736 // merged together into one document
737 Document page_xsl = getXSLTDocument(action, subaction, collection);
738 String page_xsl_filename = getXSLTFilename(action, subaction); // for debug purposes
739 if (page_xsl == null)
740 {
741 logger.error("Couldn't find and/or load the stylesheet ("+page_xsl_filename+") for a="+action+", sa="+subaction+", in collection="+collection);
742 return XMLTransformer.constructErrorXHTMLPage("Couldn't find and/or load the stylesheet \""+page_xsl_filename+"\" for a="+action+", sa="+subaction+", in collection="+collection);
743 }
744
745 if (output.equals("xsl1")) {
746 // if we just output the page_xsl directly then there may be unescaped & in the javascript,
747 // and the page won't display properly
748 return converter.getDOM(getStringFromDocument(page_xsl));
749 }
750
751
752 // put the page into a document - this is necessary for xslt to get
753 // the paths right if you have paths relative to the document root
754 // eg /page.
755 Document page_xml_doc = XMLConverter.newDOM();
756 page_xml_doc.appendChild(page_xml_doc.importNode(page_xml, true));
757 Element page_response = (Element) GSXML.getChildByTagName(page_xml, GSXML.PAGE_RESPONSE_ELEM);
758 Element format_elem = (Element) GSXML.getChildByTagName(page_response, GSXML.FORMAT_ELEM);
759
760 if (output.equals("format1"))
761 {
762 return format_elem;
763 }
764
765 // do we have language attribute for page?
766 String lang_att = page_xml.getAttribute(GSXML.LANG_ATT);
767 if (lang_att != null && lang_att.length() > 0)
768 {
769 config_params.put("lang", lang_att);
770 }
771
772 if (format_elem != null)
773 {
774 //page_response.removeChild(format_elem);
775
776 // need to transform the format info
777 // run expand-gsf.xsl over the format_elem. We need to do this now to turn
778 // eg gsf:template into xsl:template so that the merging works properly.
779 // xsl:templates will get merged
780 // into the main stylesheet, but gsf:templates won't.
781
782 Document format_doc = XMLConverter.newDOM();
783 format_doc.appendChild(format_doc.importNode(format_elem, true));
784
785 if (_debug) {
786
787 String siteHome = GSFile.siteHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME));
788 GSXSLT.insertDebugElements(format_doc, GSFile.collectionConfigFile(siteHome, collection));
789 }
790
791 // should we be doing the double pass here too?
792 Node result = transformGSFElements(collection, format_doc, EXPAND_GSF_FILE);
793 // Since we started creating documents with DocTypes, we can end up with
794 // Document objects here. But we will be working with an Element instead,
795 // so we grab the DocumentElement() of the Document object in such a case.
796 Element new_format;
797 if (result.getNodeType() == Node.DOCUMENT_NODE)
798 {
799 new_format = ((Document) result).getDocumentElement();
800 }
801 else
802 {
803 new_format = (Element) result;
804 }
805
806 if (output.equals("format"))
807 {
808 return new_format;
809 }
810
811 // add the extracted format statements in to the main stylesheet
812 if (_debug)
813 {
814 String siteHome = GSFile.siteHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME));
815 GSXSLT.mergeStylesheetsDebug(page_xsl, new_format, true, true, "OTHER1", GSFile.collectionConfigFile(siteHome, collection));
816 }
817 else
818 {
819 GSXSLT.mergeStylesheets(page_xsl, new_format, true);
820 }
821
822
823 }
824
825 if (output.equals("xsl2")) {
826 return converter.getDOM(getStringFromDocument(page_xsl));
827 }
828
829 Document inline_template_doc = null;
830 if (inline_template != null)
831 {
832 try
833 {
834 inline_template_doc = this.converter.getDOM("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xsl:stylesheet version=\"1.0\" "+GSXML.ALL_NAMESPACES_ATTS + ">" + inline_template + "</xsl:stylesheet>", "UTF-8");
835
836 if (_debug)
837 {
838 GSXSLT.mergeStylesheetsDebug(page_xsl, inline_template_doc.getDocumentElement(), true, true, "OTHER2", "INLINE");
839 }
840 else
841 {
842 //GSXSLT.mergeStylesheets(skinAndLibraryDoc, inlineTemplateDoc.getDocumentElement(), true);
843 GSXSLT.mergeStylesheets(page_xsl, inline_template_doc.getDocumentElement(), true);
844 }
845 }
846 catch (Exception ex)
847 {
848 ex.printStackTrace();
849 }
850 }
851
852
853 if (output.equals("ilt")) {
854 return converter.getDOM(getStringFromDocument(inline_template_doc));
855 }
856 if (output.equals("xsl3")) {
857 return converter.getDOM(getStringFromDocument(page_xsl));
858 }
859
860 // once we are here, have got the main page xsl loaded up. Have added in any format statements from the source xml, and added in any inline template which came through cgi params.
861
862 // next we load in the import and include files. - these, too, go through the inheritance cascade (base interface, interface, site, collection) before being added into the main document
863
864 if (_debug)
865 {
866 GSXSLT.inlineImportAndIncludeFilesDebug(page_xsl, null, _debug, page_xsl_filename, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
867 }
868 else
869 {
870 GSXSLT.inlineImportAndIncludeFiles(page_xsl, null, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
871
872 }
873
874 if (output.equals("xsl4")) {
875 return converter.getDOM(getStringFromDocument(page_xsl));
876 }
877
878 // The next step is to process the page_xsl + gslib_xsl by
879 // expand-gslib.xsl to expand all the gslib elements
880
881 Document expand_gslib_xsl_doc;
882 try
883 {
884 // interfaces/core/transform/expand-gslib.xsl
885 // this takes skinandLibraryXsl, copies skinXSL, merges elements of libraryXsl into it, and replaces gslib elements
886 expand_gslib_xsl_doc = getDoc(expand_gslib_filepath);
887 String errMsg = ((XMLConverter.ParseErrorHandler) parser.getErrorHandler()).getErrorMessage();
888 if (errMsg != null)
889 {
890 return XMLTransformer.constructErrorXHTMLPage("error loading file: " + expand_gslib_filepath + "\n" + errMsg);
891 }
892 }
893 catch (java.io.FileNotFoundException e)
894 {
895 return fileNotFoundErrorPage(e.getMessage());
896 }
897 catch (Exception e)
898 {
899 e.printStackTrace();
900 System.out.println("error loading "+expand_gslib_filepath);
901 return XMLTransformer.constructErrorXHTMLPage("Error loading file: "+ expand_gslib_filepath+"\n" + e.getMessage());
902 }
903
904 // gslib.xsl
905 Document gslib_xsl_doc = null;
906 try
907 {
908 gslib_xsl_doc = GSXSLT.mergedXSLTDocumentCascade(GSLIB_FILE, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, _debug);
909 }
910 catch (Exception e)
911 {
912 e.printStackTrace();
913 System.out.println("error loading gslib xslt");
914 return XMLTransformer.constructErrorXHTMLPage("error loading gslib xslt\n" + e.getMessage());
915 }
916
917 if (output.equals("gslib-expander")) {
918 return converter.getDOM(getStringFromDocument(expand_gslib_xsl_doc));
919 }
920 if (output.equals("gslib1")) {
921 return converter.getDOM(getStringFromDocument(gslib_xsl_doc));
922 }
923 // Combine the skin file and library variables/templates into one document.
924 // Please note: We dont just use xsl:import because the preprocessing stage
925 // needs to know what's available in the library.
926
927
928 // add in all gslib.xsl's include and import files
929 // debug?? use debug method?? or does it not make sense here??
930 GSXSLT.inlineImportAndIncludeFiles(gslib_xsl_doc, null, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
931 if (output.equals("gslib")) {
932 return converter.getDOM(getStringFromDocument(gslib_xsl_doc));
933 }
934
935 // if the page xsl or gslib xsl uses namespaces that are not listed in
936 // expand_gslib, then they will be ignored. So just check through and add
937 // any in that are missing.
938 GSXML.addMissingNamespaceAttributes(expand_gslib_xsl_doc.getDocumentElement(), page_xsl.getDocumentElement());
939 GSXML.addMissingNamespaceAttributes(expand_gslib_xsl_doc.getDocumentElement(), gslib_xsl_doc.getDocumentElement());
940
941 Document pageAndGslibXsl = null;
942 Document pageAndGslibDoc = converter.newDOM();
943
944 // now, we transform all the gslib elements
945 {
946
947
948 pageAndGslibXsl = converter.newDOM();
949 Element root = pageAndGslibXsl.createElement("pageAndGslibXsl");
950 pageAndGslibXsl.appendChild(root);
951
952 Element s = pageAndGslibXsl.createElement("pageXsl");
953 s.appendChild(pageAndGslibXsl.importNode(page_xsl.getDocumentElement(), true));
954 root.appendChild(s);
955
956 Element l = pageAndGslibXsl.createElement("gslibXsl");
957 if (gslib_xsl_doc != null)
958 {
959 Element gslib_xsl_el = gslib_xsl_doc.getDocumentElement();
960 l.appendChild(pageAndGslibXsl.importNode(gslib_xsl_el, true));
961 }
962 root.appendChild(l);
963
964 if (output.equals("xsl5")) {
965 return converter.getDOM(getStringFromDocument(pageAndGslibXsl));
966 }
967 // actually merge the gslib file with the page
968 XMLTransformer preProcessor = new XMLTransformer();
969 preProcessor.transform_withResultNode(expand_gslib_xsl_doc, pageAndGslibXsl, pageAndGslibDoc);
970 }
971 if (output.equals("xsl6")) {
972 return converter.getDOM(getStringFromDocument(pageAndGslibDoc));
973 }
974
975 pageAndGslibDoc = (Document) transformGSFElements(collection, pageAndGslibDoc, EXPAND_GSF_PASS1_FILE);
976
977 if (output.equals("xsl7")) {
978 return converter.getDOM(getStringFromDocument(pageAndGslibDoc));
979 }
980
981 pageAndGslibDoc = (Document) transformGSFElements(collection, pageAndGslibDoc, EXPAND_GSF_FILE);
982
983 if (output.equals("xsl") || output.equals("skinandlibdocfinal"))
984 {
985 return converter.getDOM(getStringFromDocument(pageAndGslibDoc));
986 }
987
988 if (output.equals("clientside"))
989 {
990
991 // Go through and 'fix up' any 'util:...' or 'java:...' attributes the pageAndGslibDoc has
992 String lang = (String)config_params.get("lang");
993 resolveExtendedNamespaceAttributesXSLT(pageAndGslibDoc,currentInterface,lang); // test= and select= attributes
994 resolveExtendedNamespaceAttributesXML(pageAndGslibDoc,currentInterface,lang); // href= and src= attributes
995 Node skinAndLibFinal = converter.getDOM(getStringFromDocument(pageAndGslibDoc));
996
997 // Send XML and skinandlibdoc down the line together
998 Document finalDoc = converter.newDOM();
999 Node finalDocSkin = finalDoc.importNode(pageAndGslibDoc.getDocumentElement(), true);
1000 Node finalDocXML = finalDoc.importNode(page_with_xslt_params_doc.getDocumentElement(), true);
1001 Element root = finalDoc.createElement("skinlibfinalPlusXML");
1002 root.appendChild(finalDocSkin);
1003 root.appendChild(finalDocXML);
1004 finalDoc.appendChild(root);
1005 return (Node) finalDoc.getDocumentElement();
1006 }
1007
1008 ///logger.debug("final xml is ");
1009 ///logger.debug(XMLConverter.getPrettyString(page_xml_doc));
1010
1011 ///logger.debug("final xsl is");
1012 ///logger.debug(XMLConverter.getPrettyString(pageAndGslibDoc));
1013
1014 // The transformer will now work out the resulting doctype from any set in the (merged) stylesheets and
1015 // will set this in the output document it creates. So don't pass in any docWithDocType to the transformer
1016
1017 // Here, we finally transform the page xml source with the complete xsl file
1018 Node finalResult = this.transformer.transform(pageAndGslibDoc, page_xml_doc, config_params);
1019
1020 if (_debug)
1021 {
1022 GSXSLT.fixTables((Document) finalResult);
1023 }
1024
1025 return finalResult;
1026
1027 }
1028
1029 protected Node generateXSLTClientOutput(Element request) {
1030
1031 // DocType defaults in case the skin doesn't have an "xsl:output" element
1032 String qualifiedName = "html";
1033 String publicID = "-//W3C//DTD HTML 4.01 Transitional//EN";
1034 String systemID = "http://www.w3.org/TR/html4/loose.dtd";
1035
1036 // We need to create an empty document with a predefined DocType,
1037 // that will then be used for the transformation by the DOMResult
1038 Document docWithDoctype = converter.newDOM(qualifiedName, publicID, systemID);
1039 String baseURL = request.getAttribute(GSXML.BASE_URL);
1040
1041 // If you're just getting the client-side transform page, why bother with the rest of this?
1042 Element html = docWithDoctype.createElement("html");
1043 Element img = docWithDoctype.createElement("img");
1044 img.setAttribute("src", "loading.gif"); // Make it dynamic
1045 img.setAttribute("alt", "Please wait...");
1046 Text title_text = docWithDoctype.createTextNode("Please wait..."); // Make this language dependent
1047 Element head = docWithDoctype.createElement("head");
1048
1049 // e.g., <base href="http://localhost:8383/greenstone3/" /><!-- [if lte IE 6]></base><![endif] -->
1050 Element base = docWithDoctype.createElement("base");
1051 base.setAttribute("href",baseURL);
1052 Comment opt_end_base = docWithDoctype.createComment("[if lte IE 6]></base><![endif]");
1053
1054 Element title = docWithDoctype.createElement("title");
1055 title.appendChild(title_text);
1056
1057 Element body = docWithDoctype.createElement("body");
1058
1059 Element jquery_script = docWithDoctype.createElement("script");
1060 jquery_script.setAttribute("src", "jquery-3.6.0.min.js");
1061 jquery_script.setAttribute("type", "text/javascript");
1062 Comment jquery_comment = docWithDoctype.createComment("jQuery");
1063 jquery_script.appendChild(jquery_comment);
1064
1065 Element saxonce_script = docWithDoctype.createElement("script");
1066 saxonce_script.setAttribute("src", "Saxonce/Saxonce.nocache.js");
1067 saxonce_script.setAttribute("type", "text/javascript");
1068 Comment saxonce_comment = docWithDoctype.createComment("SaxonCE");
1069 saxonce_script.appendChild(saxonce_comment);
1070
1071 Element xsltutil_script = docWithDoctype.createElement("script");
1072 xsltutil_script.setAttribute("src", "xslt-util.js");
1073 xsltutil_script.setAttribute("type", "text/javascript");
1074 Comment xsltutil_comment = docWithDoctype.createComment("JavaScript version of XSLTUtil.java");
1075 xsltutil_script.appendChild(xsltutil_comment);
1076
1077 Element script = docWithDoctype.createElement("script");
1078 Comment script_comment = docWithDoctype.createComment("Filler for browser");
1079 script.setAttribute("src", "client-side-xslt.js");
1080 script.setAttribute("type", "text/javascript");
1081 script.appendChild(script_comment);
1082
1083 Element pagevar = docWithDoctype.createElement("script");
1084 Element style = docWithDoctype.createElement("style");
1085 style.setAttribute("type", "text/css");
1086 Text style_text = docWithDoctype.createTextNode("body { text-align: center; padding: 50px; font: 14pt Arial, sans-serif; font-weight: bold; }");
1087 pagevar.setAttribute("type", "text/javascript");
1088 Text page_var_text = docWithDoctype.createTextNode("var placeholder = true;");
1089
1090 html.appendChild(head);
1091 head.appendChild(base); head.appendChild(opt_end_base);
1092 head.appendChild(title);
1093 head.appendChild(style);
1094 style.appendChild(style_text);
1095 html.appendChild(body);
1096 head.appendChild(pagevar);
1097 head.appendChild(jquery_script);
1098 head.appendChild(saxonce_script);
1099 head.appendChild(xsltutil_script);
1100 head.appendChild(script);
1101 pagevar.appendChild(page_var_text);
1102
1103 body.appendChild(img);
1104 docWithDoctype.appendChild(html);
1105
1106 return (Node) docWithDoctype;
1107
1108 }
1109
1110 // transform the xsl with xsl to replace all gsf elements. We do this in 2 stages -
1111 // first do just a text pass, that way we can have gsf elements in the text content
1112 protected Node transformGSFElements(String collection, Document source_xsl, String expand_gsf_filename) {
1113
1114 String expand_gsf_file = GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, expand_gsf_filename);
1115 Document expand_gsf_doc = this.converter.getDOM(new File(expand_gsf_file));
1116
1117 if (expand_gsf_doc != null)
1118 {
1119 return this.transformer.transform(expand_gsf_doc, source_xsl, config_params);
1120 }
1121 return source_xsl;
1122
1123 }
1124
1125 // method to convert Document to a proper XML string for debug purposes only
1126 protected String getStringFromDocument(Document doc)
1127 {
1128 String content = "";
1129 try
1130 {
1131 DOMSource domSource = new DOMSource(doc);
1132 StringWriter writer = new StringWriter();
1133 StreamResult result = new StreamResult(writer);
1134 TransformerFactory tf = TransformerFactory.newInstance();
1135 Transformer transformer = tf.newTransformer();
1136 transformer.transform(domSource, result);
1137 content = writer.toString();
1138 System.out.println("Change the & to &Amp; for proper debug display");
1139 content = StringUtils.replace(content, "&", "&amp;");
1140 writer.flush();
1141 }
1142 catch (TransformerException ex)
1143 {
1144 ex.printStackTrace();
1145 return null;
1146 }
1147 return content;
1148 }
1149
1150 protected synchronized Document getDoc(String docName) throws Exception
1151 {
1152 File xslt_file = new File(docName);
1153
1154 FileReader reader = new FileReader(xslt_file);
1155 InputSource xml_source = new InputSource(reader);
1156 this.parser.parse(xml_source);
1157 Document doc = this.parser.getDocument();
1158
1159 return doc;
1160 }
1161
1162 protected String getXSLTFilename(String action, String subaction) {
1163 String name = null;
1164 if (!subaction.equals(""))
1165 {
1166 String key = action + ":" + subaction;
1167 name = this.xslt_map.get(key);
1168 }
1169 // try the action by itself
1170 if (name == null)
1171 {
1172 name = this.xslt_map.get(action);
1173 }
1174 if (name == null)
1175 {
1176 // so we can reandomly create any named page
1177 if (action.equals("p") && !subaction.equals(""))
1178 {
1179 // TODO: pages/ won't work for interface other than default!!
1180 name = "pages/" + subaction + ".xsl";
1181 }
1182
1183 }
1184 return name;
1185 }
1186
1187
1188 protected Document getXSLTDocument(String action, String subaction, String collection)
1189 {
1190 String name = getXSLTFilename(action, subaction);
1191 Document finalDoc = null;
1192 if(name != null)
1193 {
1194 // this finds all the stylesheets named "name" and merges them together, in the order of
1195 // base interface, current interface, site, collection - the latter overriding the former.
1196 // templates with the same name will replace earlier versions
1197 finalDoc = GSXSLT.mergedXSLTDocumentCascade(name, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, _debug);
1198 }
1199 return finalDoc;
1200 }
1201
1202 // returns the path to the gslib.xsl file that is applicable for the current interface
1203 protected String getGSLibXSLFilename()
1204 {
1205 return GSFile.xmlTransformDir(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.INTERFACE_NAME))) + File.separatorChar + "gslib.xsl";
1206 }
1207
1208 // Call this when a FileNotFoundException could be thrown when loading an xsl (xml) file.
1209 // Returns an error xhtml page indicating which xsl (or other xml) file is missing.
1210 protected Document fileNotFoundErrorPage(String filenameMessage)
1211 {
1212 String errorMessage = "ERROR missing file: " + filenameMessage;
1213 Element errPage = XMLTransformer.constructErrorXHTMLPage(errorMessage);
1214 logger.error(errorMessage);
1215 return errPage.getOwnerDocument();
1216 }
1217}
Note: See TracBrowser for help on using the repository browser.