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

Last change on this file since 37471 was 37471, checked in by davidb, 14 months ago

small tweak to logger message to make what is happening with 'collection' clearer in terms of the value it is set to

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