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

Last change on this file since 30553 was 30553, checked in by kjdon, 8 years ago

added ability for teh collectionConfig.xml file to carry additional stuff. Can have extraInfo element at the top level (inside collectionConfig). For now this is used to add extra items to the navigation bar (<navigationTab type=external-link

  • Property svn:keywords set to Author Date Id Revision
File size: 47.9 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 int CONFIG_PASS = 1;
52 protected static final int TEXT_PASS = 2;
53
54 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.core.TransformingReceptionist.class.getName());
55
56 /** The preprocess.xsl file is in a fixed location */
57 static final String preprocess_xsl_filename = GlobalProperties.getGSDL3Home() + File.separatorChar + "interfaces" + File.separatorChar + "core" + File.separatorChar + "transform" + File.separatorChar + "preProcess.xsl";
58
59 /** the list of xslt to use for actions */
60 protected HashMap<String, String> xslt_map = null;
61
62 /** a transformer class to transform xml using xslt */
63 protected XMLTransformer transformer = null;
64
65 protected TransformerFactory transformerFactory = null;
66 protected DOMParser parser = null;
67
68 protected HashMap<String, ArrayList<String>> _metadataRequiredMap = new HashMap<String, ArrayList<String>>();
69
70 boolean _debug = true;
71
72 public TransformingReceptionist()
73 {
74 super();
75 this.xslt_map = new HashMap<String, String>();
76 this.transformer = new XMLTransformer();
77 try
78 {
79 transformerFactory = org.apache.xalan.processor.TransformerFactoryImpl.newInstance();
80 this.converter = new XMLConverter();
81 //transformerFactory.setURIResolver(new MyUriResolver()) ;
82
83 parser = new DOMParser();
84 parser.setFeature("http://xml.org/sax/features/validation", false);
85 // 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.
86 parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
87 // a performance test showed that having this on lead to increased
88 // memory use for small-medium docs, and not much gain for large
89 // docs.
90 // http://www.sosnoski.com/opensrc/xmlbench/conclusions.html
91 parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
92 parser.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true);
93 // setting a handler for when fatal errors, errors or warnings happen during xml parsing
94 // call XMLConverter's getParseErrorMessage() to get the errorstring that can be rendered as web page
95 this.parser.setErrorHandler(new XMLConverter.ParseErrorHandler());
96 }
97 catch (Exception e)
98 {
99 e.printStackTrace();
100 }
101 }
102
103 /** configures the receptionist - overwrite this to set up the xslt map */
104 public boolean configure()
105 {
106 if (this.config_params == null)
107 {
108 logger.error(" config variables must be set before calling configure");
109 return false;
110 }
111 if (this.mr == null)
112 {
113 logger.error(" message router must be set before calling configure");
114 return false;
115 }
116
117 // find the config file containing a list of actions
118 File interface_config_file = new File(GSFile.interfaceConfigFile(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.INTERFACE_NAME))));
119 if (!interface_config_file.exists())
120 {
121 logger.error(" interface config file: " + interface_config_file.getPath() + " not found!");
122 return false;
123 }
124 Document config_doc = this.converter.getDOM(interface_config_file, "utf-8");
125 if (config_doc == null)
126 {
127 logger.error(" could not parse interface config file: " + interface_config_file.getPath());
128 return false;
129 }
130 Element config_elem = config_doc.getDocumentElement();
131 String base_interface = config_elem.getAttribute("baseInterface");
132 setUpBaseInterface(base_interface);
133 setUpInterfaceOptions(config_elem);
134
135 Element action_list = (Element) GSXML.getChildByTagName(config_elem, GSXML.ACTION_ELEM + GSXML.LIST_MODIFIER);
136 NodeList actions = action_list.getElementsByTagName(GSXML.ACTION_ELEM);
137
138 for (int i = 0; i < actions.getLength(); i++)
139 {
140 Element action = (Element) actions.item(i);
141 String class_name = action.getAttribute("class");
142 String action_name = action.getAttribute("name");
143 Action ac = null;
144 try
145 {
146 ac = (Action) Class.forName("org.greenstone.gsdl3.action." + class_name).newInstance();
147 }
148 catch (Exception e)
149 {
150 logger.error(" couldn't load in action " + class_name);
151 e.printStackTrace();
152 continue;
153 }
154 ac.setConfigParams(this.config_params);
155 ac.setMessageRouter(this.mr);
156 ac.configure();
157 ac.addActionParameters(this.params);
158 this.action_map.put(action_name, ac);
159
160 // now do the xslt map
161 String xslt = action.getAttribute("xslt");
162 if (!xslt.equals(""))
163 {
164 this.xslt_map.put(action_name, xslt);
165 }
166 NodeList subactions = action.getElementsByTagName(GSXML.SUBACTION_ELEM);
167 for (int j = 0; j < subactions.getLength(); j++)
168 {
169 Element subaction = (Element) subactions.item(j);
170 String subname = subaction.getAttribute(GSXML.NAME_ATT);
171 String subxslt = subaction.getAttribute("xslt");
172
173 String map_key = action_name + ":" + subname;
174 logger.debug("adding in to xslt map, " + map_key + "->" + subxslt);
175 this.xslt_map.put(map_key, subxslt);
176 }
177 }
178 Element lang_list = (Element) GSXML.getChildByTagName(config_elem, "languageList");
179 if (lang_list == null)
180 {
181 logger.error(" didn't find a language list in the config file!!");
182 }
183 else
184 {
185 //this.language_list = (Element) this.doc.importNode(lang_list, true);
186 this.language_list = lang_list;
187 }
188
189 getRequiredMetadataNamesFromXSLFiles();
190
191 return true;
192 }
193
194 protected void getRequiredMetadataNamesFromXSLFiles()
195 {
196 ArrayList<File> xslFiles = GSFile.getAllXSLFiles((String) this.config_params.get((String) this.config_params.get(GSConstants.SITE_NAME)));
197
198 HashMap<String, ArrayList<String>> includes = new HashMap<String, ArrayList<String>>();
199 HashMap<String, ArrayList<File>> files = new HashMap<String, ArrayList<File>>();
200 HashMap<String, ArrayList<String>> metaNames = new HashMap<String, ArrayList<String>>();
201
202 //First exploratory pass
203 for (File currentFile : xslFiles)
204 {
205
206 String full_filename = currentFile.getPath();
207 int sep_pos = full_filename.lastIndexOf(File.separator)+1;
208 String local_filename = full_filename.substring(sep_pos);
209 if (local_filename.startsWith(".")) {
210 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());
211 }
212
213 Document currentDoc = this.converter.getDOM(currentFile);
214 if (currentDoc == null)
215 {
216 // Can happen if an editor creates an auto-save temporary file
217 // (such as #header.xsl#) that is not well formed XML
218 continue;
219 }
220
221 NodeList metadataElems = currentDoc.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "metadata"); //gsf:metadata
222 NodeList foreachMetadataElems = currentDoc.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "foreach-metadata"); //gsf:foreach-metadata
223 NodeList imageElems = currentDoc.getElementsByTagNameNS(GSXML.GSF_NAMESPACE, "image"); //gsf:image
224 NodeList includeElems = currentDoc.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "include");
225 NodeList importElems = currentDoc.getElementsByTagNameNS(GSXML.XSL_NAMESPACE, "import");
226
227 ArrayList<String> names = new ArrayList<String>();
228 for (int i = 0; i < metadataElems.getLength(); i++)
229 {
230 Element current = (Element) metadataElems.item(i);
231 String name = current.getAttribute(GSXML.NAME_ATT);
232 if (name != null && name.length() > 0 && !names.contains(name))
233 {
234 names.add(name);
235 }
236 }
237
238 for (int i = 0; i < foreachMetadataElems.getLength(); i++)
239 {
240 Element current = (Element) foreachMetadataElems.item(i);
241 String name = current.getAttribute(GSXML.NAME_ATT);
242 if (name != null && name.length() > 0 && !names.contains(name))
243 {
244 names.add(name);
245 }
246 }
247
248 for (int i = 0; i < imageElems.getLength(); i++)
249 {
250 Element current = (Element) imageElems.item(i);
251 String type = current.getAttribute(GSXML.TYPE_ATT);
252 if (type == null || type.length() == 0)
253 {
254 continue;
255 }
256
257 if (type.equals("source"))
258 {
259 String[] standardSourceMeta = new String[] { "SourceFile", "ImageHeight", "ImageWidth", "ImageType", "srcicon" };
260 for (String meta : standardSourceMeta)
261 {
262 if (!names.contains(meta))
263 {
264 names.add(meta);
265 }
266 }
267 }
268 else if (type.equals("screen"))
269 {
270 String[] standardScreenMeta = new String[] { "Screen", "ScreenHeight", "ScreenWidth", "ScreenType", "screenicon" };
271 for (String meta : standardScreenMeta)
272 {
273 if (!names.contains(meta))
274 {
275 names.add(meta);
276 }
277 }
278 }
279 else if (type.equals("thumb"))
280 {
281 String[] standardThumbMeta = new String[] { "Thumb", "ThumbHeight", "ThumbWidth", "ThumbType", "thumbicon" };
282 for (String meta : standardThumbMeta)
283 {
284 if (!names.contains(meta))
285 {
286 names.add(meta);
287 }
288 }
289 }
290 }
291
292 metaNames.put(currentFile.getAbsolutePath(), names);
293
294 ArrayList<String> includeAndImportList = new ArrayList<String>();
295 for (int i = 0; i < includeElems.getLength(); i++)
296 {
297 includeAndImportList.add(((Element) includeElems.item(i)).getAttribute(GSXML.HREF_ATT));
298 }
299 for (int i = 0; i < importElems.getLength(); i++)
300 {
301 includeAndImportList.add(((Element) importElems.item(i)).getAttribute(GSXML.HREF_ATT));
302 }
303 includes.put(currentFile.getAbsolutePath(), includeAndImportList);
304
305 String filename = currentFile.getName();
306 if (files.get(filename) == null)
307 {
308 ArrayList<File> fileList = new ArrayList<File>();
309 fileList.add(currentFile);
310 files.put(currentFile.getName(), fileList);
311 }
312 else
313 {
314 ArrayList<File> fileList = files.get(filename);
315 fileList.add(currentFile);
316 }
317 }
318
319 //Second pass
320 for (File currentFile : xslFiles)
321 {
322 ArrayList<File> filesToGet = new ArrayList<File>();
323 filesToGet.add(currentFile);
324
325 ArrayList<String> fullNameList = new ArrayList<String>();
326
327 while (filesToGet.size() > 0)
328 {
329 File currentFileTemp = filesToGet.remove(0);
330
331 //Add the names from this file
332 ArrayList<String> currentNames = metaNames.get(currentFileTemp.getAbsolutePath());
333 if (currentNames == null)
334 {
335 continue;
336 }
337
338 fullNameList.addAll(currentNames);
339
340 ArrayList<String> includedHrefs = includes.get(currentFileTemp.getAbsolutePath());
341
342 for (String href : includedHrefs)
343 {
344 int lastSepIndex = href.lastIndexOf("/");
345 if (lastSepIndex != -1)
346 {
347 href = href.substring(lastSepIndex + 1);
348 }
349
350 ArrayList<File> filesToAdd = files.get(href);
351 if (filesToAdd != null)
352 {
353 filesToGet.addAll(filesToAdd);
354 }
355 }
356 }
357
358 _metadataRequiredMap.put(currentFile.getAbsolutePath(), fullNameList);
359 }
360 }
361
362 protected void preProcessRequest(Element request)
363 {
364 String action = request.getAttribute(GSXML.ACTION_ATT);
365 String subaction = request.getAttribute(GSXML.SUBACTION_ATT);
366
367 String name = null;
368 if (!subaction.equals(""))
369 {
370 String key = action + ":" + subaction;
371 name = this.xslt_map.get(key);
372 }
373 // try the action by itself
374 if (name == null)
375 {
376 name = this.xslt_map.get(action);
377 }
378
379 Element cgi_param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
380 String collection = "";
381
382 if (cgi_param_list != null)
383 {
384 // Don't waste time getting all the parameters
385 HashMap<String, Serializable> params = GSXML.extractParams(cgi_param_list, false);
386 collection = (String) params.get(GSParams.COLLECTION);
387 if (collection == null)
388 {
389 collection = "";
390 }
391 }
392
393 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);
394
395 Document doc = XMLConverter.newDOM();
396 Element extraMetadataList = doc.createElement(GSXML.EXTRA_METADATA + GSXML.LIST_MODIFIER);
397 HashSet<String> name_set = new HashSet<String>();
398 for (File stylesheet : stylesheets)
399 {
400 ArrayList<String> requiredMetadata = _metadataRequiredMap.get(stylesheet.getAbsolutePath());
401
402 if (requiredMetadata != null)
403 {
404 for (String metadataString : requiredMetadata)
405 {
406 if (!name_set.contains(metadataString)) {
407 name_set.add(metadataString);
408 Element metadataElem = doc.createElement(GSXML.EXTRA_METADATA);
409 metadataElem.setAttribute(GSXML.NAME_ATT, metadataString);
410 extraMetadataList.appendChild(metadataElem);
411 }
412 }
413 }
414 }
415 request.appendChild(request.getOwnerDocument().importNode(extraMetadataList, true));
416 }
417
418 protected Node postProcessPage(Element page)
419 {
420 // might need to add some data to the page
421 addExtraInfo(page);
422
423
424 // transform the page using xslt
425
426 String currentInterface = (String) config_params.get(GSConstants.INTERFACE_NAME);
427
428 Element request = (Element) GSXML.getChildByTagName(page, GSXML.PAGE_REQUEST_ELEM);
429 String output = request.getAttribute(GSXML.OUTPUT_ATT);
430
431 boolean useClientXSLT = (Boolean) config_params.get(GSConstants.USE_CLIENT_SIDE_XSLT);
432 //logger.info("Client side transforms allowed? " + allowsClientXSLT);
433
434 if (useClientXSLT)
435 {
436 // if not specified, output defaults to 'html', but this isn't what we want when useClientXSLT is on
437 if (output.equals("html")) {
438 output = "xsltclient";
439 }
440 }
441 Node transformed_page = transformPage(page,currentInterface,output);
442
443 if (useClientXSLT) {
444 return transformed_page;
445 }
446 // if the user has specified they want only a part of the full page then subdivide it
447 boolean subdivide = false;
448 String excerptID = null;
449 String excerptTag = null;
450 Element cgi_param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
451 if (cgi_param_list != null)
452 {
453 HashMap<String, Serializable> params = GSXML.extractParams(cgi_param_list, false);
454 if ((excerptID = (String) params.get(GSParams.EXCERPT_ID)) != null)
455 {
456 subdivide = true;
457 }
458 if ((excerptTag = (String) params.get(GSParams.EXCERPT_TAG)) != null)
459 {
460 subdivide = true;
461 }
462 }
463
464 if (subdivide)
465 {
466 Node subdivided_page = subdivide(transformed_page, excerptID, excerptTag);
467 if (subdivided_page != null)
468 {
469 return subdivided_page;
470 }
471 else return null;
472 }
473
474 return transformed_page;
475 }
476
477 protected Node subdivide(Node transformed_page, String excerptID, String excerptTag)
478 {
479 if (excerptID != null)
480 {
481 Node selectedElement = getNodeByIdRecursive(transformed_page, excerptID);
482 modifyNodesByTagRecursive(selectedElement, "a");
483 return selectedElement;
484 }
485 else if (excerptTag != null)
486 {
487 Node selectedElement = getNodeByTagRecursive(transformed_page, excerptTag);
488 return selectedElement;
489 }
490 return transformed_page;
491 }
492
493 protected Node getNodeByIdRecursive(Node parent, String id)
494 {
495 if (parent.hasAttributes() && ((Element) parent).getAttribute("id").equals(id))
496 {
497 return parent;
498 }
499
500 NodeList children = parent.getChildNodes();
501 for (int i = 0; i < children.getLength(); i++)
502 {
503 Node result = null;
504 if ((result = getNodeByIdRecursive(children.item(i), id)) != null)
505 {
506 return result;
507 }
508 }
509 return null;
510 }
511
512 protected Node getNodeByTagRecursive(Node parent, String tag)
513 {
514 if (parent.getNodeType() == Node.ELEMENT_NODE && ((Element) parent).getTagName().equals(tag))
515 {
516 return parent;
517 }
518
519 NodeList children = parent.getChildNodes();
520 for (int i = 0; i < children.getLength(); i++)
521 {
522 Node result = null;
523 if ((result = getNodeByTagRecursive(children.item(i), tag)) != null)
524 {
525 return result;
526 }
527 }
528 return null;
529 }
530
531 protected Node modifyNodesByTagRecursive(Node parent, String tag)
532 {
533 if (parent == null || (parent.getNodeType() == Node.ELEMENT_NODE && ((Element) parent).getTagName().equals(tag)))
534 {
535 return parent;
536 }
537
538 NodeList children = parent.getChildNodes();
539 for (int i = 0; i < children.getLength(); i++)
540 {
541 Node result = null;
542 if ((result = modifyNodesByTagRecursive(children.item(i), tag)) != null)
543 {
544 //TODO: DO SOMETHING HERE?
545 }
546 }
547 return null;
548 }
549
550 protected void replaceNodeWithInterfaceText(Document doc, String interface_name, String lang,
551 Element elem, String attr_name, String attr_val)
552 {
553 String pattern_str_3arg = "util:getInterfaceText\\([^,]+,[^,]+,\\s*'(.+?)'\\s*\\)";
554 String pattern_str_4arg = "util:getInterfaceText\\([^,]+,[^,]+,\\s*'(.+?)'\\s*,\\s*(.+?)\\s*\\)$";
555
556 Pattern pattern3 = Pattern.compile(pattern_str_3arg);
557 Matcher matcher3 = pattern3.matcher(attr_val);
558 if (matcher3.find()) {
559 String dict_key = matcher3.group(1);
560 String dict_val = XSLTUtil.getInterfaceText(interface_name,lang,dict_key);
561
562 Node parent_node = elem.getParentNode();
563
564 Text replacement_text_node = doc.createTextNode(dict_val);
565 parent_node.replaceChild(replacement_text_node,elem);
566 }
567 else {
568 Pattern pattern4 = Pattern.compile(pattern_str_4arg);
569 Matcher matcher4 = pattern4.matcher(attr_val);
570 StringBuffer string_buffer4 = new StringBuffer();
571
572 if (matcher4.find()) {
573 String dict_key = matcher4.group(1);
574 String args = matcher4.group(2);
575 args = args.replaceAll("\\$","\\\\\\$");
576
577 String dict_val = XSLTUtil.getInterfaceText(interface_name,lang,dict_key);
578
579 matcher4.appendReplacement(string_buffer4, "js:getInterfaceTextSubstituteArgs('"+dict_val+"',string("+args+"))");
580 matcher4.appendTail(string_buffer4);
581
582 attr_val = string_buffer4.toString();
583 elem.setAttribute(attr_name,attr_val);
584 }
585 else {
586 logger.error("Failed to find match in attribute: " + attr_name + "=\"" + attr_val + "\"");
587 attr_val = attr_val.replaceAll("util:getInterfaceText\\(.+?,.+?,\\s*(.+?)\\s*\\)","$1");
588 elem.setAttribute(attr_name,attr_val);
589 }
590 }
591
592 }
593
594 protected void resolveExtendedNamespaceAttributesXSLT(Document doc, String interface_name, String lang)
595 {
596 String[] attr_list = new String[] {"select","test"};
597
598 // http://stackoverflow.com/questions/13220520/javascript-replace-child-loop-issue
599 // go through nodeList in reverse to avoid the 'skipping' problem, due to
600 // replaceChild() calls removing items from the "live" nodeList
601
602 NodeList nodeList = doc.getElementsByTagName("*");
603 for (int i=nodeList.getLength()-1; i>=0; i--) {
604 Node node = nodeList.item(i);
605 if (node.getNodeType() == Node.ELEMENT_NODE) {
606 Element elem = (Element)node;
607 for (String attr_name : attr_list) {
608 if (elem.hasAttribute(attr_name)) {
609 String attr_val = elem.getAttribute(attr_name);
610
611 if (attr_val.startsWith("util:getInterfaceText(")) {
612 // replace the node with dictionary lookup
613 replaceNodeWithInterfaceText(doc, interface_name,lang, elem,attr_name,attr_val);
614 }
615 else if (attr_val.contains("util:")) {
616
617 attr_val = attr_val.replaceAll("util:getInterfaceStringsAsJavascript\\(.+?,.+?,\\s*(.+?)\\)","$1");
618
619 //attr_val = attr_val.replaceAll("util:escapeNewLinesAndQuotes\\(\\s*(.+?)\\s*\\)","'escapeNLandQ $1'");
620 //attr_val = attr_val.replaceAll("util:escapeNewLinesAndQuotes\\(\\s*(.+?)\\s*\\)","$1");
621
622 // 'contains()' supported in XSLT 1.0, so OK to change any util:contains() into contains()
623 attr_val = attr_val.replaceAll("util:(contains\\(.+?\\))","$1");
624
625 elem.setAttribute(attr_name,attr_val);
626 }
627
628 if (attr_val.contains("java:")) {
629 if (attr_val.indexOf("getInterfaceTextSubstituteArgs")>=4) {
630
631 attr_val = attr_val.replaceAll("java:.+?\\.(\\w+)\\((.*?)\\)$","js:$1($2)");
632 }
633
634 elem.setAttribute(attr_name,attr_val);
635 }
636 }
637 }
638
639 }
640 }
641 }
642
643
644 protected void resolveExtendedNamespaceAttributesXML(Document doc, String interface_name, String lang)
645 {
646 String[] attr_list = new String[] {"src", "href"};
647
648 // http://stackoverflow.com/questions/13220520/javascript-replace-child-loop-issue
649 // go through nodeList in reverse to avoid the 'skipping' problem, due to
650 // replaceChild() calls removing items from the "live" nodeList
651
652 NodeList nodeList = doc.getElementsByTagName("*");
653 for (int i=nodeList.getLength()-1; i>=0; i--) {
654 Node node = nodeList.item(i);
655 if (node.getNodeType() == Node.ELEMENT_NODE) {
656 Element elem = (Element)node;
657 for (String attr_name : attr_list) {
658 if (elem.hasAttribute(attr_name)) {
659 String attr_val = elem.getAttribute(attr_name);
660
661 if (attr_val.contains("util:getInterfaceText(")) {
662 String pattern_str_3arg = "util:getInterfaceText\\([^,]+,[^,]+,\\s*'(.+?)'\\s*\\)";
663 Pattern pattern3 = Pattern.compile(pattern_str_3arg);
664 Matcher matcher3 = pattern3.matcher(attr_val);
665
666 StringBuffer string_buffer3 = new StringBuffer();
667
668 boolean found_match = false;
669
670 while (matcher3.find()) {
671 found_match = true;
672 String dict_key = matcher3.group(1);
673 String dict_val = XSLTUtil.getInterfaceText(interface_name,lang,dict_key);
674
675 matcher3.appendReplacement(string_buffer3, dict_val);
676 }
677 matcher3.appendTail(string_buffer3);
678
679 if (found_match) {
680 attr_val = string_buffer3.toString();
681 elem.setAttribute(attr_name,attr_val);
682 }
683 else {
684 logger.error("Failed to find match in attribute: " + attr_name + "=\"" + attr_val + "\"");
685 attr_val = attr_val.replaceAll("util:getInterfaceText\\(.+?,.+?,\\s*(.+?)\\s*\\)","$1");
686 elem.setAttribute(attr_name,attr_val);
687 }
688 }
689 else if (attr_val.contains("util:")) {
690
691 logger.error("Encountered unexpected 'util:' prefix exension: " + attr_name + "=\"" + attr_val + "\"");
692 }
693
694 if (attr_val.contains("java:")) {
695 // make anything java: safe from the point of an XSLT without extensions
696 logger.error("Encountered unexpected 'java:' prefix exension: " + attr_name + "=\"" + attr_val + "\"");
697
698 }
699 }
700 }
701
702 }
703 }
704 }
705
706
707
708 /**
709 * overwrite this to add any extra info that might be needed in the page
710 * before transformation
711 */
712 protected void addExtraInfo(Element page)
713 {
714 }
715
716 /**
717 * transform the page using xslt we need to get any format element out of
718 * the page and add it to the xslt before transforming
719 */
720 protected Node transformPage(Element page,String currentInterface,String output)
721 {
722 _debug = false;
723
724 Element request = (Element) GSXML.getChildByTagName(page, GSXML.PAGE_REQUEST_ELEM);
725
726 //logger.info("Current output mode is: " + output + ", current interface name is: " + currentInterface);
727
728 // DocType defaults in case the skin doesn't have an "xsl:output" element
729 String qualifiedName = "html";
730 String publicID = "-//W3C//DTD HTML 4.01 Transitional//EN";
731 String systemID = "http://www.w3.org/TR/html4/loose.dtd";
732
733 // We need to create an empty document with a predefined DocType,
734 // that will then be used for the transformation by the DOMResult
735 Document docWithDoctype = converter.newDOM(qualifiedName, publicID, systemID);
736
737 if (output.equals("xsltclient"))
738 {
739 String baseURL = request.getAttribute(GSXML.BASE_URL);
740
741 // If you're just getting the client-side transform page, why bother with the rest of this?
742 Element html = docWithDoctype.createElement("html");
743 Element img = docWithDoctype.createElement("img");
744 img.setAttribute("src", "loading.gif"); // Make it dynamic
745 img.setAttribute("alt", "Please wait...");
746 Text title_text = docWithDoctype.createTextNode("Please wait..."); // Make this language dependent
747 Element head = docWithDoctype.createElement("head");
748
749 // e.g., <base href="http://localhost:8383/greenstone3/" /><!-- [if lte IE 6]></base><![endif] -->
750 Element base = docWithDoctype.createElement("base");
751 base.setAttribute("href",baseURL);
752 Comment opt_end_base = docWithDoctype.createComment("[if lte IE 6]></base><![endif]");
753
754 Element title = docWithDoctype.createElement("title");
755 title.appendChild(title_text);
756
757 Element body = docWithDoctype.createElement("body");
758
759 Element jquery_script = docWithDoctype.createElement("script");
760 jquery_script.setAttribute("src", "jquery-1.10-min.js");
761 jquery_script.setAttribute("type", "text/javascript");
762 Comment jquery_comment = docWithDoctype.createComment("jQuery");
763 jquery_script.appendChild(jquery_comment);
764
765 Element saxonce_script = docWithDoctype.createElement("script");
766 saxonce_script.setAttribute("src", "Saxonce/Saxonce.nocache.js");
767 saxonce_script.setAttribute("type", "text/javascript");
768 Comment saxonce_comment = docWithDoctype.createComment("SaxonCE");
769 saxonce_script.appendChild(saxonce_comment);
770
771 Element xsltutil_script = docWithDoctype.createElement("script");
772 xsltutil_script.setAttribute("src", "xslt-util.js");
773 xsltutil_script.setAttribute("type", "text/javascript");
774 Comment xsltutil_comment = docWithDoctype.createComment("JavaScript version of XSLTUtil.java");
775 xsltutil_script.appendChild(xsltutil_comment);
776
777 Element script = docWithDoctype.createElement("script");
778 Comment script_comment = docWithDoctype.createComment("Filler for browser");
779 script.setAttribute("src", "client-side-xslt.js");
780 script.setAttribute("type", "text/javascript");
781 script.appendChild(script_comment);
782
783 Element pagevar = docWithDoctype.createElement("script");
784 Element style = docWithDoctype.createElement("style");
785 style.setAttribute("type", "text/css");
786 Text style_text = docWithDoctype.createTextNode("body { text-align: center; padding: 50px; font: 14pt Arial, sans-serif; font-weight: bold; }");
787 pagevar.setAttribute("type", "text/javascript");
788 Text page_var_text = docWithDoctype.createTextNode("var placeholder = true;");
789
790 html.appendChild(head);
791 head.appendChild(base); head.appendChild(opt_end_base);
792 head.appendChild(title);
793 head.appendChild(style);
794 style.appendChild(style_text);
795 html.appendChild(body);
796 head.appendChild(pagevar);
797 head.appendChild(jquery_script);
798 head.appendChild(saxonce_script);
799 head.appendChild(xsltutil_script);
800 head.appendChild(script);
801 pagevar.appendChild(page_var_text);
802
803 body.appendChild(img);
804 docWithDoctype.appendChild(html);
805
806 return (Node) docWithDoctype;
807 }
808
809 // Passing in the pretty string here means it needs to be generated even when not debugging; so use custom function to return blank when debug is off
810 logger.debug("page before transforming:");
811 logger.debug(this.converter.getPrettyStringLogger(page, logger));
812
813 String action = request.getAttribute(GSXML.ACTION_ATT);
814 String subaction = request.getAttribute(GSXML.SUBACTION_ATT);
815
816 // we should choose how to transform the data based on output, eg diff
817 // choice for html, and wml??
818 // for now, if output=xml, we don't transform the page, we just return
819 // the page xml
820 Document theXML = null;
821
822 if (output.equals("xml") || (output.equals("json")) || output.equals("clientside"))
823 {
824 // Append some bits and pieces first...
825 theXML = converter.newDOM();
826 // Import into new document first!
827 Node newPage = theXML.importNode(page, true);
828 theXML.appendChild(newPage);
829 Element root = theXML.createElement("xsltparams");
830 newPage.appendChild(root);
831
832 Element libname = theXML.createElement("param");
833 libname.setAttribute("name", "library_name");
834 Text libnametext = theXML.createTextNode((String) config_params.get(GSConstants.LIBRARY_NAME));
835 libname.appendChild(libnametext);
836
837 Element intname = theXML.createElement("param");
838 intname.setAttribute("name", "interface_name");
839 Text intnametext = theXML.createTextNode((String) config_params.get(GSConstants.INTERFACE_NAME));
840 intname.appendChild(intnametext);
841
842 Element siteName = theXML.createElement("param");
843 siteName.setAttribute("name", "site_name");
844 Text siteNameText = theXML.createTextNode((String) config_params.get(GSConstants.SITE_NAME));
845 siteName.appendChild(siteNameText);
846
847 Element clientSideXSLTName = theXML.createElement("param");
848 clientSideXSLTName.setAttribute("name", "use_client_side_xslt");
849 Boolean useClientXSLT = (Boolean) config_params.get(GSConstants.USE_CLIENT_SIDE_XSLT);
850 Text clientSideXSLTNameText = theXML.createTextNode(useClientXSLT.toString());
851 clientSideXSLTName.appendChild(clientSideXSLTNameText);
852
853 Element filepath = theXML.createElement("param");
854 filepath.setAttribute("name", "filepath");
855 Text filepathtext = theXML.createTextNode(GlobalProperties.getGSDL3Home());
856 filepath.appendChild(filepathtext);
857
858 root.appendChild(libname);
859 root.appendChild(intname);
860 root.appendChild(siteName);
861 root.appendChild(clientSideXSLTName);
862 root.appendChild(filepath);
863
864 if ((output.equals("xml")) || output.equals("json"))
865 {
866 // in the case of "json", calling method responsible for converting to JSON-string
867 return theXML.getDocumentElement();
868 }
869 }
870
871 Element cgi_param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
872 String collection = "";
873 String inlineTemplate = "";
874 if (cgi_param_list != null)
875 {
876 // Don't waste time getting all the parameters
877 HashMap<String, Serializable> params = GSXML.extractParams(cgi_param_list, false);
878 collection = (String) params.get(GSParams.COLLECTION);
879 if (collection == null)
880 {
881 collection = "";
882 }
883
884 inlineTemplate = (String) params.get(GSParams.INLINE_TEMPLATE);
885 String debug_p = (String) params.get(GSParams.DEBUG);
886 if (debug_p != null && (debug_p.equals("on") || debug_p.equals("1") || debug_p.equals("true")))
887 {
888 String[] groups = new UserContext(request).getGroups();
889
890 boolean found = false;
891 for (String g : groups)
892 {
893 if (g.equals("administrator"))
894 {
895 found = true;
896 break;
897 }
898 if (!collection.equals("")) {
899 if (g.equals("all-collections-editor")) {
900 found = true;
901 break;
902 }
903
904 if (g.equals(collection+"-collection-editor")) {
905 found = true;
906 break;
907 }
908 }
909 }
910 if (found)
911 {
912 _debug = true;
913 }
914 }
915 }
916
917 config_params.put("collName", collection);
918
919 Document style_doc = getXSLTDocument(action, subaction, collection);
920 if (style_doc == null)
921 {
922 // this getParseErrorMessage may have originally worked, but now it doesn't.
923 // //String errorPage = this.converter.getParseErrorMessage();
924 // if (errorPage != null)
925 // {
926 // return XMLTransformer.constructErrorXHTMLPage("Cannot parse the xslt file\n");// + errorPage);
927 // }
928 logger.error("style_doc is null, returning the page");
929 return page;
930 }
931
932 // put the page into a document - this is necessary for xslt to get
933 // the paths right if you have paths relative to the document root
934 // eg /page.
935 Document doc = XMLConverter.newDOM();
936 doc.appendChild(doc.importNode(page, true));
937 Element page_response = (Element) GSXML.getChildByTagName(page, GSXML.PAGE_RESPONSE_ELEM);
938 Element format_elem = (Element) GSXML.getChildByTagName(page_response, GSXML.FORMAT_ELEM);
939
940 NodeList pageElems = doc.getElementsByTagName("page");
941 if (pageElems.getLength() > 0)
942 {
943 Element pageElem = (Element) pageElems.item(0);
944 String langAtt = pageElem.getAttribute(GSXML.LANG_ATT);
945
946 if (langAtt != null && langAtt.length() > 0)
947 {
948 config_params.put("lang", langAtt);
949 }
950 }
951
952 if (output.equals("formatelem"))
953 {
954 return format_elem;
955 }
956 if (format_elem != null)
957 {
958 //page_response.removeChild(format_elem);
959 logger.debug("format elem=" + this.converter.getPrettyStringLogger(format_elem, logger));
960 // need to transform the format info
961 String configStylesheet_file = GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, "config_format.xsl");
962 Document configStylesheet_doc = this.converter.getDOM(new File(configStylesheet_file));
963
964 if (configStylesheet_doc != null)
965 {
966 Document format_doc = XMLConverter.newDOM();
967 format_doc.appendChild(format_doc.importNode(format_elem, true));
968
969 if (_debug)
970 {
971 String siteHome = GSFile.siteHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME));
972 GSXSLT.insertDebugElements(format_doc, GSFile.collectionConfigFile(siteHome, collection));
973 }
974
975 Node result = this.transformer.transform(configStylesheet_doc, format_doc, config_params); // Needs addressing <-
976
977 // Since we started creating documents with DocTypes, we can end up with
978 // Document objects here. But we will be working with an Element instead,
979 // so we grab the DocumentElement() of the Document object in such a case.
980 Element new_format;
981 if (result.getNodeType() == Node.DOCUMENT_NODE)
982 {
983 new_format = ((Document) result).getDocumentElement();
984 }
985 else
986 {
987 new_format = (Element) result;
988 }
989 logger.debug("new format elem=" + this.converter.getPrettyStringLogger(new_format, logger));
990 if (output.equals("newformat"))
991 {
992 return new_format;
993 }
994
995 // add extracted GSF statements in to the main stylesheet
996 if (_debug)
997 {
998 String siteHome = GSFile.siteHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME));
999 GSXSLT.mergeStylesheetsDebug(style_doc, new_format, true, true, "OTHER1", GSFile.collectionConfigFile(siteHome, collection));
1000 }
1001 else
1002 {
1003 GSXSLT.mergeStylesheets(style_doc, new_format, true);
1004 }
1005 //System.out.println("added extracted GSF statements into the main stylesheet") ;
1006
1007 // add extracted GSF statements in to the debug test stylesheet
1008 //GSXSLT.mergeStylesheets(oldStyle_doc, new_format);
1009 }
1010 else
1011 {
1012 logger.error(" couldn't parse the config_format stylesheet, adding the format info as is");
1013 GSXSLT.mergeStylesheets(style_doc, format_elem, true);
1014 //GSXSLT.mergeStylesheets(oldStyle_doc, format_elem);
1015 }
1016 logger.debug("the converted stylesheet is:");
1017 logger.debug(this.converter.getPrettyStringLogger(style_doc.getDocumentElement(), logger));
1018 }
1019
1020 //for debug purposes only
1021 Document oldStyle_doc = style_doc;
1022 Document preprocessingXsl;
1023 try
1024 {
1025 preprocessingXsl = getDoc(preprocess_xsl_filename);
1026 String errMsg = ((XMLConverter.ParseErrorHandler) parser.getErrorHandler()).getErrorMessage();
1027 if (errMsg != null)
1028 {
1029 return XMLTransformer.constructErrorXHTMLPage("error loading preprocess xslt file: " + preprocess_xsl_filename + "\n" + errMsg);
1030 }
1031 }
1032 catch (java.io.FileNotFoundException e)
1033 {
1034 return fileNotFoundErrorPage(e.getMessage());
1035 }
1036 catch (Exception e)
1037 {
1038 e.printStackTrace();
1039 System.out.println("error loading preprocess xslt");
1040 return XMLTransformer.constructErrorXHTMLPage("error loading preprocess xslt\n" + e.getMessage());
1041 }
1042
1043 Document libraryXsl = null;
1044 try
1045 {
1046 libraryXsl = GSXSLT.mergedXSLTDocumentCascade("gslib.xsl", (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, _debug);
1047 }
1048 catch (Exception e)
1049 {
1050 e.printStackTrace();
1051 System.out.println("error loading gslib xslt");
1052 return XMLTransformer.constructErrorXHTMLPage("error loading gslib xslt\n" + e.getMessage());
1053 }
1054
1055 // Combine the skin file and library variables/templates into one document.
1056 // Please note: We dont just use xsl:import because the preprocessing stage
1057 // needs to know what's available in the library.
1058
1059 Document skinAndLibraryXsl = null;
1060 Document skinAndLibraryDoc = converter.newDOM();
1061
1062 // Applying the preprocessing XSLT - in its own block {} to allow use of non-unique variable names
1063 {
1064
1065 skinAndLibraryXsl = converter.newDOM();
1066 Element root = skinAndLibraryXsl.createElement("skinAndLibraryXsl");
1067 skinAndLibraryXsl.appendChild(root);
1068
1069 Element s = skinAndLibraryXsl.createElement("skinXsl");
1070 s.appendChild(skinAndLibraryXsl.importNode(style_doc.getDocumentElement(), true));
1071 root.appendChild(s);
1072
1073 Element l = skinAndLibraryXsl.createElement("libraryXsl");
1074 if (libraryXsl != null)
1075 {
1076 Element libraryXsl_el = libraryXsl.getDocumentElement();
1077 l.appendChild(skinAndLibraryXsl.importNode(libraryXsl_el, true));
1078 }
1079 root.appendChild(l);
1080
1081 //System.out.println("Skin and Library XSL are now together") ;
1082
1083 //System.out.println("Pre-processing the skin file...") ;
1084
1085 //pre-process the skin style sheet
1086 //In other words, apply the preProcess.xsl to 'skinAndLibraryXsl' in order to
1087 //expand all GS-Lib statements into complete XSL statements and also to create
1088 //a valid xsl style sheet document.
1089
1090 XMLTransformer preProcessor = new XMLTransformer();
1091 // Perform the transformation, by passing in:
1092 // preprocess-stylesheet, source-xsl (skinAndLibraryXsl), and the node that should
1093 // be in the result (skinAndLibraryDoc)
1094 preProcessor.transform_withResultNode(preprocessingXsl, skinAndLibraryXsl, skinAndLibraryDoc);
1095 //System.out.println("GS-Lib statements are now expanded") ;
1096 }
1097
1098 // there is a thing called a URIResolver which you can set for a
1099 // transformer or transformer factory. may be able to use this
1100 // instead of this absoluteIncludepaths hack
1101
1102 //GSXSLT.absoluteIncludePaths(skinAndLibraryDoc, GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
1103
1104 //Same but for the debug version when we want the do the transformation like we use to do
1105 //without any gslib elements.
1106 GSXSLT.absoluteIncludePaths(oldStyle_doc, GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
1107
1108 //Send different stages of the skin xslt to the browser for debug purposes only
1109 //using &o=skindoc or &o=skinandlib etc...
1110 if (output.equals("skindoc"))
1111 {
1112 return converter.getDOM(getStringFromDocument(style_doc));
1113 }
1114 if (output.equals("skinandlib"))
1115 {
1116 return converter.getDOM(getStringFromDocument(skinAndLibraryXsl));
1117 }
1118 if (output.equals("skinandlibdoc"))
1119 {
1120
1121 Node skinAndLib = converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
1122 return skinAndLib;
1123 }
1124 if (output.equals("oldskindoc"))
1125 {
1126 return converter.getDOM(getStringFromDocument(oldStyle_doc));
1127 }
1128
1129 // We now no longer create a document with doctype before the transformation
1130 // We let the XMLTransformer do the work of first working out the doctype from any
1131 // that may be set in the (merged) stylesheets and then setting the doctype when transforming
1132
1133 /*
1134 // Try to get the system and public ID from the current skin xsl document
1135 // otherwise keep the default values.
1136 Element root = skinAndLibraryDoc.getDocumentElement();
1137 NodeList nodes = root.getElementsByTagName("xsl:output");
1138 // If there is at least one "xsl:output" command in the final xsl then...
1139 if (nodes.getLength() != 0)
1140 {
1141 // There should be only one element called xsl:output,
1142 // but if this is not the case get the last one
1143 Element xsl_output = (Element) nodes.item(nodes.getLength() - 1);
1144 if (xsl_output != null)
1145 {
1146 // Qualified name will always be html even for xhtml pages
1147 //String attrValue = xsl_output.getAttribute("method");
1148 //qualifiedName = attrValue.equals("") ? qualifiedName : attrValue;
1149
1150 String attrValue = xsl_output.getAttribute("doctype-system");
1151 systemID = attrValue.equals("") ? systemID : attrValue;
1152
1153 attrValue = xsl_output.getAttribute("doctype-public");
1154 publicID = attrValue.equals("") ? publicID : attrValue;
1155 }
1156 }
1157
1158 //System.out.println(converter.getPrettyString(docWithDoctype));
1159 //System.out.println("Doctype vals: " + qualifiedName + " " + publicID + " " + systemID) ;
1160
1161 docWithDoctype = converter.newDOM(qualifiedName, publicID, systemID);
1162 */
1163
1164 //System.out.println("Generate final HTML from current skin") ;
1165 //Transformation of the XML message from the receptionist to HTML with doctype
1166
1167 if (inlineTemplate != null)
1168 {
1169 try
1170 {
1171 Document inlineTemplateDoc = this.converter.getDOM("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"" + GSXML.XSL_NAMESPACE + "\" xmlns:java=\"" + GSXML.JAVA_NAMESPACE + "\" xmlns:util=\"" + GSXML.UTIL_NAMESPACE + "\" xmlns:gsf=\"" + GSXML.GSF_NAMESPACE + "\">" + inlineTemplate + "</xsl:stylesheet>", "UTF-8");
1172
1173 if (_debug)
1174 {
1175 GSXSLT.mergeStylesheetsDebug(skinAndLibraryDoc, inlineTemplateDoc.getDocumentElement(), true, true, "OTHER2", "INLINE");
1176 }
1177 else
1178 {
1179 GSXSLT.mergeStylesheets(skinAndLibraryDoc, inlineTemplateDoc.getDocumentElement(), true);
1180 }
1181 }
1182 catch (Exception ex)
1183 {
1184 ex.printStackTrace();
1185 }
1186 }
1187
1188 if (_debug)
1189 {
1190 GSXSLT.inlineImportAndIncludeFilesDebug(skinAndLibraryDoc, null, _debug, this.getGSLibXSLFilename(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
1191 }
1192 else
1193 {
1194 GSXSLT.inlineImportAndIncludeFiles(skinAndLibraryDoc, null, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
1195 }
1196 skinAndLibraryDoc = (Document) performFormatPass(collection, skinAndLibraryDoc, doc, new UserContext(request), TEXT_PASS);
1197 skinAndLibraryDoc = (Document) performFormatPass(collection, skinAndLibraryDoc, doc, new UserContext(request), CONFIG_PASS);
1198
1199 if (output.equals("xmlfinal"))
1200 {
1201 return doc;
1202 }
1203
1204 if (output.equals("skinandlibdocfinal") || output.equals("clientside"))
1205 {
1206 if (output.equals("skinandlibdocfinal"))
1207 {
1208 Node skinAndLibFinal = converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
1209 return skinAndLibFinal;
1210 }
1211 else
1212 {
1213 // Go through and 'fix up' any 'util:...' or 'java:...' attributes the skinAndLibraryDoc has
1214 String lang = (String)config_params.get("lang");
1215 resolveExtendedNamespaceAttributesXSLT(skinAndLibraryDoc,currentInterface,lang); // test= and select= attributes
1216 resolveExtendedNamespaceAttributesXML(skinAndLibraryDoc,currentInterface,lang); // href= and src= attributes
1217 Node skinAndLibFinal = converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
1218
1219 // Send XML and skinandlibdoc down the line together
1220 Document finalDoc = converter.newDOM();
1221 Node finalDocSkin = finalDoc.importNode(skinAndLibraryDoc.getDocumentElement(), true);
1222 Node finalDocXML = finalDoc.importNode(theXML.getDocumentElement(), true);
1223 Element root = finalDoc.createElement("skinlibfinalPlusXML");
1224 root.appendChild(finalDocSkin);
1225 root.appendChild(finalDocXML);
1226 finalDoc.appendChild(root);
1227 return (Node) finalDoc.getDocumentElement();
1228 }
1229
1230
1231
1232
1233 }
1234
1235 // The transformer will now work out the resulting doctype from any set in the (merged) stylesheets and
1236 // will set this in the output document it creates. So don't pass in any docWithDocType to the transformer
1237 //Node finalResult = this.transformer.transform(skinAndLibraryDoc, doc, config_params, docWithDoctype);
1238 Node finalResult = this.transformer.transform(skinAndLibraryDoc, doc, config_params);
1239
1240 if (_debug)
1241 {
1242 GSXSLT.fixTables((Document) finalResult);
1243 }
1244
1245 return finalResult;
1246
1247 // The line below will do the transformation like we use to do before having Skin++ implemented,
1248 // it will not contain any GS-Lib statements expanded, and the result will not contain any doctype.
1249
1250 //return (Element)this.transformer.transform(style_doc, doc, config_params);
1251 //return null; // For now - change later
1252 }
1253
1254 protected Node performFormatPass(String collection, Document skinAndLibraryDoc, Document doc, UserContext userContext, int pass)
1255 {
1256 String formatFile;
1257 if (pass == CONFIG_PASS)
1258 {
1259 formatFile = "config_format.xsl";
1260 }
1261 else
1262 {
1263 formatFile = "text_fragment_format.xsl";
1264 }
1265
1266 String configStylesheet_file = GSFile.stylesheetFile(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, formatFile);
1267 Document configStylesheet_doc = this.converter.getDOM(new File(configStylesheet_file));
1268
1269 if (configStylesheet_doc != null)
1270 {
1271 return this.transformer.transform(configStylesheet_doc, skinAndLibraryDoc, config_params);
1272 }
1273 return skinAndLibraryDoc;
1274 }
1275
1276 // method to convert Document to a proper XML string for debug purposes only
1277 protected String getStringFromDocument(Document doc)
1278 {
1279 String content = "";
1280 try
1281 {
1282 DOMSource domSource = new DOMSource(doc);
1283 StringWriter writer = new StringWriter();
1284 StreamResult result = new StreamResult(writer);
1285 TransformerFactory tf = TransformerFactory.newInstance();
1286 Transformer transformer = tf.newTransformer();
1287 transformer.transform(domSource, result);
1288 content = writer.toString();
1289 System.out.println("Change the & to &Amp; for proper debug display");
1290 content = StringUtils.replace(content, "&", "&amp;");
1291 writer.flush();
1292 }
1293 catch (TransformerException ex)
1294 {
1295 ex.printStackTrace();
1296 return null;
1297 }
1298 return content;
1299 }
1300
1301 protected synchronized Document getDoc(String docName) throws Exception
1302 {
1303 File xslt_file = new File(docName);
1304
1305 FileReader reader = new FileReader(xslt_file);
1306 InputSource xml_source = new InputSource(reader);
1307 this.parser.parse(xml_source);
1308 Document doc = this.parser.getDocument();
1309
1310 return doc;
1311 }
1312
1313 protected Document getXSLTDocument(String action, String subaction, String collection)
1314 {
1315 String name = null;
1316 if (!subaction.equals(""))
1317 {
1318 String key = action + ":" + subaction;
1319 name = this.xslt_map.get(key);
1320 }
1321 // try the action by itself
1322 if (name == null)
1323 {
1324 name = this.xslt_map.get(action);
1325 }
1326 if (name == null)
1327 {
1328 // so we can reandomly create any named page
1329 if (action.equals("p") && !subaction.equals(""))
1330 {
1331 // TODO: pages/ won't work for interface other than default!!
1332 name = "pages/" + subaction + ".xsl";
1333 }
1334
1335 }
1336
1337 Document finalDoc = null;
1338 if(name != null)
1339 {
1340 finalDoc = GSXSLT.mergedXSLTDocumentCascade(name, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, _debug);
1341 }
1342 return finalDoc;
1343 }
1344
1345 // returns the path to the gslib.xsl file that is applicable for the current interface
1346 protected String getGSLibXSLFilename()
1347 {
1348 return GSFile.xmlTransformDir(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.INTERFACE_NAME))) + File.separatorChar + "gslib.xsl";
1349 }
1350
1351 // Call this when a FileNotFoundException could be thrown when loading an xsl (xml) file.
1352 // Returns an error xhtml page indicating which xsl (or other xml) file is missing.
1353 protected Document fileNotFoundErrorPage(String filenameMessage)
1354 {
1355 String errorMessage = "ERROR missing file: " + filenameMessage;
1356 Element errPage = XMLTransformer.constructErrorXHTMLPage(errorMessage);
1357 logger.error(errorMessage);
1358 return errPage.getOwnerDocument();
1359 }
1360}
Note: See TracBrowser for help on using the repository browser.