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

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

undoing last commit which was made in error

  • Property svn:keywords set to Author Date Id Revision
File size: 47.8 KB
Line 
1package org.greenstone.gsdl3.core;
2
3import java.io.File;
4import java.io.FileReader;
5import java.io.Serializable;
6import java.io.StringWriter;
7import java.util.ArrayList;
8import java.util.HashMap;
9import java.util.HashSet;
10import java.util.regex.Pattern;
11import java.util.regex.Matcher;
12
13import javax.xml.transform.Transformer;
14import javax.xml.transform.TransformerException;
15import javax.xml.transform.TransformerFactory;
16import javax.xml.transform.dom.DOMSource;
17import javax.xml.transform.stream.StreamResult;
18
19import org.apache.commons.lang3.StringUtils;
20import org.apache.log4j.Logger;
21import org.apache.xerces.parsers.DOMParser;
22import org.greenstone.gsdl3.action.Action;
23import org.greenstone.gsdl3.util.GSConstants;
24import org.greenstone.gsdl3.util.GSFile;
25import org.greenstone.gsdl3.util.GSParams;
26import org.greenstone.gsdl3.util.GSXML;
27import org.greenstone.gsdl3.util.GSXSLT;
28import org.greenstone.gsdl3.util.UserContext;
29import org.greenstone.gsdl3.util.XMLConverter;
30import org.greenstone.gsdl3.util.XMLTransformer;
31import org.greenstone.gsdl3.util.XSLTUtil;
32import org.greenstone.util.GlobalProperties;
33import org.w3c.dom.Comment;
34import org.w3c.dom.Document;
35import org.w3c.dom.Element;
36import org.w3c.dom.Node;
37import org.w3c.dom.NodeList;
38import org.w3c.dom.Text;
39import org.xml.sax.InputSource;
40
41/**
42 * A receptionist that uses xslt to transform the page_data before returning it.
43 * . Receives requests consisting of an xml representation of cgi args, and
44 * returns the page of data - in html by default. The requests are processed by
45 * the appropriate action class
46 *
47 * @see Action
48 */
49public class TransformingReceptionist extends Receptionist
50{
51 protected static final 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 return page;
929 }
930
931 // put the page into a document - this is necessary for xslt to get
932 // the paths right if you have paths relative to the document root
933 // eg /page.
934 Document doc = XMLConverter.newDOM();
935 doc.appendChild(doc.importNode(page, true));
936 Element page_response = (Element) GSXML.getChildByTagName(page, GSXML.PAGE_RESPONSE_ELEM);
937 Element format_elem = (Element) GSXML.getChildByTagName(page_response, GSXML.FORMAT_ELEM);
938
939 NodeList pageElems = doc.getElementsByTagName("page");
940 if (pageElems.getLength() > 0)
941 {
942 Element pageElem = (Element) pageElems.item(0);
943 String langAtt = pageElem.getAttribute(GSXML.LANG_ATT);
944
945 if (langAtt != null && langAtt.length() > 0)
946 {
947 config_params.put("lang", langAtt);
948 }
949 }
950
951 if (output.equals("formatelem"))
952 {
953 return format_elem;
954 }
955 if (format_elem != null)
956 {
957 //page_response.removeChild(format_elem);
958 logger.debug("format elem=" + this.converter.getPrettyStringLogger(format_elem, logger));
959 // need to transform the format info
960 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");
961 Document configStylesheet_doc = this.converter.getDOM(new File(configStylesheet_file));
962
963 if (configStylesheet_doc != null)
964 {
965 Document format_doc = XMLConverter.newDOM();
966 format_doc.appendChild(format_doc.importNode(format_elem, true));
967
968 if (_debug)
969 {
970 String siteHome = GSFile.siteHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME));
971 GSXSLT.insertDebugElements(format_doc, GSFile.collectionConfigFile(siteHome, collection));
972 }
973
974 Node result = this.transformer.transform(configStylesheet_doc, format_doc, config_params); // Needs addressing <-
975
976 // Since we started creating documents with DocTypes, we can end up with
977 // Document objects here. But we will be working with an Element instead,
978 // so we grab the DocumentElement() of the Document object in such a case.
979 Element new_format;
980 if (result.getNodeType() == Node.DOCUMENT_NODE)
981 {
982 new_format = ((Document) result).getDocumentElement();
983 }
984 else
985 {
986 new_format = (Element) result;
987 }
988 logger.debug("new format elem=" + this.converter.getPrettyStringLogger(new_format, logger));
989 if (output.equals("newformat"))
990 {
991 return new_format;
992 }
993
994 // add extracted GSF statements in to the main stylesheet
995 if (_debug)
996 {
997 String siteHome = GSFile.siteHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME));
998 GSXSLT.mergeStylesheetsDebug(style_doc, new_format, true, true, "OTHER1", GSFile.collectionConfigFile(siteHome, collection));
999 }
1000 else
1001 {
1002 GSXSLT.mergeStylesheets(style_doc, new_format, true);
1003 }
1004 //System.out.println("added extracted GSF statements into the main stylesheet") ;
1005
1006 // add extracted GSF statements in to the debug test stylesheet
1007 //GSXSLT.mergeStylesheets(oldStyle_doc, new_format);
1008 }
1009 else
1010 {
1011 logger.error(" couldn't parse the config_format stylesheet, adding the format info as is");
1012 GSXSLT.mergeStylesheets(style_doc, format_elem, true);
1013 //GSXSLT.mergeStylesheets(oldStyle_doc, format_elem);
1014 }
1015 logger.debug("the converted stylesheet is:");
1016 logger.debug(this.converter.getPrettyStringLogger(style_doc.getDocumentElement(), logger));
1017 }
1018
1019 //for debug purposes only
1020 Document oldStyle_doc = style_doc;
1021 Document preprocessingXsl;
1022 try
1023 {
1024 preprocessingXsl = getDoc(preprocess_xsl_filename);
1025 String errMsg = ((XMLConverter.ParseErrorHandler) parser.getErrorHandler()).getErrorMessage();
1026 if (errMsg != null)
1027 {
1028 return XMLTransformer.constructErrorXHTMLPage("error loading preprocess xslt file: " + preprocess_xsl_filename + "\n" + errMsg);
1029 }
1030 }
1031 catch (java.io.FileNotFoundException e)
1032 {
1033 return fileNotFoundErrorPage(e.getMessage());
1034 }
1035 catch (Exception e)
1036 {
1037 e.printStackTrace();
1038 System.out.println("error loading preprocess xslt");
1039 return XMLTransformer.constructErrorXHTMLPage("error loading preprocess xslt\n" + e.getMessage());
1040 }
1041
1042 Document libraryXsl = null;
1043 try
1044 {
1045 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);
1046 }
1047 catch (Exception e)
1048 {
1049 e.printStackTrace();
1050 System.out.println("error loading gslib xslt");
1051 return XMLTransformer.constructErrorXHTMLPage("error loading gslib xslt\n" + e.getMessage());
1052 }
1053
1054 // Combine the skin file and library variables/templates into one document.
1055 // Please note: We dont just use xsl:import because the preprocessing stage
1056 // needs to know what's available in the library.
1057
1058 Document skinAndLibraryXsl = null;
1059 Document skinAndLibraryDoc = converter.newDOM();
1060
1061 // Applying the preprocessing XSLT - in its own block {} to allow use of non-unique variable names
1062 {
1063
1064 skinAndLibraryXsl = converter.newDOM();
1065 Element root = skinAndLibraryXsl.createElement("skinAndLibraryXsl");
1066 skinAndLibraryXsl.appendChild(root);
1067
1068 Element s = skinAndLibraryXsl.createElement("skinXsl");
1069 s.appendChild(skinAndLibraryXsl.importNode(style_doc.getDocumentElement(), true));
1070 root.appendChild(s);
1071
1072 Element l = skinAndLibraryXsl.createElement("libraryXsl");
1073 if (libraryXsl != null)
1074 {
1075 Element libraryXsl_el = libraryXsl.getDocumentElement();
1076 l.appendChild(skinAndLibraryXsl.importNode(libraryXsl_el, true));
1077 }
1078 root.appendChild(l);
1079
1080 //System.out.println("Skin and Library XSL are now together") ;
1081
1082 //System.out.println("Pre-processing the skin file...") ;
1083
1084 //pre-process the skin style sheet
1085 //In other words, apply the preProcess.xsl to 'skinAndLibraryXsl' in order to
1086 //expand all GS-Lib statements into complete XSL statements and also to create
1087 //a valid xsl style sheet document.
1088
1089 XMLTransformer preProcessor = new XMLTransformer();
1090 // Perform the transformation, by passing in:
1091 // preprocess-stylesheet, source-xsl (skinAndLibraryXsl), and the node that should
1092 // be in the result (skinAndLibraryDoc)
1093 preProcessor.transform_withResultNode(preprocessingXsl, skinAndLibraryXsl, skinAndLibraryDoc);
1094 //System.out.println("GS-Lib statements are now expanded") ;
1095 }
1096
1097 // there is a thing called a URIResolver which you can set for a
1098 // transformer or transformer factory. may be able to use this
1099 // instead of this absoluteIncludepaths hack
1100
1101 //GSXSLT.absoluteIncludePaths(skinAndLibraryDoc, GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
1102
1103 //Same but for the debug version when we want the do the transformation like we use to do
1104 //without any gslib elements.
1105 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);
1106
1107 //Send different stages of the skin xslt to the browser for debug purposes only
1108 //using &o=skindoc or &o=skinandlib etc...
1109 if (output.equals("skindoc"))
1110 {
1111 return converter.getDOM(getStringFromDocument(style_doc));
1112 }
1113 if (output.equals("skinandlib"))
1114 {
1115 return converter.getDOM(getStringFromDocument(skinAndLibraryXsl));
1116 }
1117 if (output.equals("skinandlibdoc"))
1118 {
1119
1120 Node skinAndLib = converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
1121 return skinAndLib;
1122 }
1123 if (output.equals("oldskindoc"))
1124 {
1125 return converter.getDOM(getStringFromDocument(oldStyle_doc));
1126 }
1127
1128 // We now no longer create a document with doctype before the transformation
1129 // We let the XMLTransformer do the work of first working out the doctype from any
1130 // that may be set in the (merged) stylesheets and then setting the doctype when transforming
1131
1132 /*
1133 // Try to get the system and public ID from the current skin xsl document
1134 // otherwise keep the default values.
1135 Element root = skinAndLibraryDoc.getDocumentElement();
1136 NodeList nodes = root.getElementsByTagName("xsl:output");
1137 // If there is at least one "xsl:output" command in the final xsl then...
1138 if (nodes.getLength() != 0)
1139 {
1140 // There should be only one element called xsl:output,
1141 // but if this is not the case get the last one
1142 Element xsl_output = (Element) nodes.item(nodes.getLength() - 1);
1143 if (xsl_output != null)
1144 {
1145 // Qualified name will always be html even for xhtml pages
1146 //String attrValue = xsl_output.getAttribute("method");
1147 //qualifiedName = attrValue.equals("") ? qualifiedName : attrValue;
1148
1149 String attrValue = xsl_output.getAttribute("doctype-system");
1150 systemID = attrValue.equals("") ? systemID : attrValue;
1151
1152 attrValue = xsl_output.getAttribute("doctype-public");
1153 publicID = attrValue.equals("") ? publicID : attrValue;
1154 }
1155 }
1156
1157 //System.out.println(converter.getPrettyString(docWithDoctype));
1158 //System.out.println("Doctype vals: " + qualifiedName + " " + publicID + " " + systemID) ;
1159
1160 docWithDoctype = converter.newDOM(qualifiedName, publicID, systemID);
1161 */
1162
1163 //System.out.println("Generate final HTML from current skin") ;
1164 //Transformation of the XML message from the receptionist to HTML with doctype
1165
1166 if (inlineTemplate != null)
1167 {
1168 try
1169 {
1170 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");
1171
1172 if (_debug)
1173 {
1174 GSXSLT.mergeStylesheetsDebug(skinAndLibraryDoc, inlineTemplateDoc.getDocumentElement(), true, true, "OTHER2", "INLINE");
1175 }
1176 else
1177 {
1178 GSXSLT.mergeStylesheets(skinAndLibraryDoc, inlineTemplateDoc.getDocumentElement(), true);
1179 }
1180 }
1181 catch (Exception ex)
1182 {
1183 ex.printStackTrace();
1184 }
1185 }
1186
1187 if (_debug)
1188 {
1189 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);
1190 }
1191 else
1192 {
1193 GSXSLT.inlineImportAndIncludeFiles(skinAndLibraryDoc, null, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces);
1194 }
1195 skinAndLibraryDoc = (Document) performFormatPass(collection, skinAndLibraryDoc, doc, new UserContext(request), TEXT_PASS);
1196 skinAndLibraryDoc = (Document) performFormatPass(collection, skinAndLibraryDoc, doc, new UserContext(request), CONFIG_PASS);
1197
1198 if (output.equals("xmlfinal"))
1199 {
1200 return doc;
1201 }
1202
1203 if (output.equals("skinandlibdocfinal") || output.equals("clientside"))
1204 {
1205 if (output.equals("skinandlibdocfinal"))
1206 {
1207 Node skinAndLibFinal = converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
1208 return skinAndLibFinal;
1209 }
1210 else
1211 {
1212 // Go through and 'fix up' any 'util:...' or 'java:...' attributes the skinAndLibraryDoc has
1213 String lang = (String)config_params.get("lang");
1214 resolveExtendedNamespaceAttributesXSLT(skinAndLibraryDoc,currentInterface,lang); // test= and select= attributes
1215 resolveExtendedNamespaceAttributesXML(skinAndLibraryDoc,currentInterface,lang); // href= and src= attributes
1216 Node skinAndLibFinal = converter.getDOM(getStringFromDocument(skinAndLibraryDoc));
1217
1218 // Send XML and skinandlibdoc down the line together
1219 Document finalDoc = converter.newDOM();
1220 Node finalDocSkin = finalDoc.importNode(skinAndLibraryDoc.getDocumentElement(), true);
1221 Node finalDocXML = finalDoc.importNode(theXML.getDocumentElement(), true);
1222 Element root = finalDoc.createElement("skinlibfinalPlusXML");
1223 root.appendChild(finalDocSkin);
1224 root.appendChild(finalDocXML);
1225 finalDoc.appendChild(root);
1226 return (Node) finalDoc.getDocumentElement();
1227 }
1228
1229
1230
1231
1232 }
1233
1234 // The transformer will now work out the resulting doctype from any set in the (merged) stylesheets and
1235 // will set this in the output document it creates. So don't pass in any docWithDocType to the transformer
1236 //Node finalResult = this.transformer.transform(skinAndLibraryDoc, doc, config_params, docWithDoctype);
1237 Node finalResult = this.transformer.transform(skinAndLibraryDoc, doc, config_params);
1238
1239 if (_debug)
1240 {
1241 GSXSLT.fixTables((Document) finalResult);
1242 }
1243
1244 return finalResult;
1245
1246 // The line below will do the transformation like we use to do before having Skin++ implemented,
1247 // it will not contain any GS-Lib statements expanded, and the result will not contain any doctype.
1248
1249 //return (Element)this.transformer.transform(style_doc, doc, config_params);
1250 //return null; // For now - change later
1251 }
1252
1253 protected Node performFormatPass(String collection, Document skinAndLibraryDoc, Document doc, UserContext userContext, int pass)
1254 {
1255 String formatFile;
1256 if (pass == CONFIG_PASS)
1257 {
1258 formatFile = "config_format.xsl";
1259 }
1260 else
1261 {
1262 formatFile = "text_fragment_format.xsl";
1263 }
1264
1265 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);
1266 Document configStylesheet_doc = this.converter.getDOM(new File(configStylesheet_file));
1267
1268 if (configStylesheet_doc != null)
1269 {
1270 return this.transformer.transform(configStylesheet_doc, skinAndLibraryDoc, config_params);
1271 }
1272 return skinAndLibraryDoc;
1273 }
1274
1275 // method to convert Document to a proper XML string for debug purposes only
1276 protected String getStringFromDocument(Document doc)
1277 {
1278 String content = "";
1279 try
1280 {
1281 DOMSource domSource = new DOMSource(doc);
1282 StringWriter writer = new StringWriter();
1283 StreamResult result = new StreamResult(writer);
1284 TransformerFactory tf = TransformerFactory.newInstance();
1285 Transformer transformer = tf.newTransformer();
1286 transformer.transform(domSource, result);
1287 content = writer.toString();
1288 System.out.println("Change the & to &Amp; for proper debug display");
1289 content = StringUtils.replace(content, "&", "&amp;");
1290 writer.flush();
1291 }
1292 catch (TransformerException ex)
1293 {
1294 ex.printStackTrace();
1295 return null;
1296 }
1297 return content;
1298 }
1299
1300 protected synchronized Document getDoc(String docName) throws Exception
1301 {
1302 File xslt_file = new File(docName);
1303
1304 FileReader reader = new FileReader(xslt_file);
1305 InputSource xml_source = new InputSource(reader);
1306 this.parser.parse(xml_source);
1307 Document doc = this.parser.getDocument();
1308
1309 return doc;
1310 }
1311
1312 protected Document getXSLTDocument(String action, String subaction, String collection)
1313 {
1314 String name = null;
1315 if (!subaction.equals(""))
1316 {
1317 String key = action + ":" + subaction;
1318 name = this.xslt_map.get(key);
1319 }
1320 // try the action by itself
1321 if (name == null)
1322 {
1323 name = this.xslt_map.get(action);
1324 }
1325 if (name == null)
1326 {
1327 // so we can reandomly create any named page
1328 if (action.equals("p") && !subaction.equals(""))
1329 {
1330 // TODO: pages/ won't work for interface other than default!!
1331 name = "pages/" + subaction + ".xsl";
1332 }
1333
1334 }
1335
1336 Document finalDoc = null;
1337 if(name != null)
1338 {
1339 finalDoc = GSXSLT.mergedXSLTDocumentCascade(name, (String) this.config_params.get(GSConstants.SITE_NAME), collection, (String) this.config_params.get(GSConstants.INTERFACE_NAME), base_interfaces, _debug);
1340 }
1341 return finalDoc;
1342 }
1343
1344 // returns the path to the gslib.xsl file that is applicable for the current interface
1345 protected String getGSLibXSLFilename()
1346 {
1347 return GSFile.xmlTransformDir(GSFile.interfaceHome(GlobalProperties.getGSDL3Home(), (String) this.config_params.get(GSConstants.INTERFACE_NAME))) + File.separatorChar + "gslib.xsl";
1348 }
1349
1350 // Call this when a FileNotFoundException could be thrown when loading an xsl (xml) file.
1351 // Returns an error xhtml page indicating which xsl (or other xml) file is missing.
1352 protected Document fileNotFoundErrorPage(String filenameMessage)
1353 {
1354 String errorMessage = "ERROR missing file: " + filenameMessage;
1355 Element errPage = XMLTransformer.constructErrorXHTMLPage(errorMessage);
1356 logger.error(errorMessage);
1357 return errPage.getOwnerDocument();
1358 }
1359}
Note: See TracBrowser for help on using the repository browser.