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

Last change on this file since 31871 was 31871, checked in by kjdon, 7 years ago

commented out some debug statements

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