source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GSXML.java@ 25445

Last change on this file since 25445 was 25445, checked in by ak19, 12 years ago

Error reporting is now improved again, much better than in previous commit: no longer just writes out the XSLT stylesheet to the log file, but follows Dr Bainbridge and Sam's suggestion of performing the transformation that failed again with physical files instead of in-memory as before. This points out the exact line location of errors.

  • Property svn:keywords set to Author Date Id Revision
File size: 36.7 KB
Line 
1/*
2 * GSXML.java
3 * Copyright (C) 2008 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.greenstone.gsdl3.util;
20
21import org.w3c.dom.NamedNodeMap;
22import org.w3c.dom.Node;
23import org.w3c.dom.Element;
24import org.w3c.dom.NodeList;
25import org.w3c.dom.Document;
26import org.w3c.dom.Text;
27
28import javax.xml.transform.TransformerFactory;
29import javax.xml.transform.Transformer;
30import java.io.StringWriter;
31import javax.xml.transform.stream.StreamResult;
32import javax.xml.transform.dom.DOMSource;
33import javax.xml.transform.OutputKeys;
34
35import java.util.Map;
36import java.util.Set;
37import java.util.HashMap;
38import java.util.Vector;
39import java.util.Iterator;
40import java.util.ArrayList;
41
42//import java.util.Locale;
43
44import org.apache.log4j.*;
45
46/** various functions for extracting info out of GS XML */
47public class GSXML
48{
49
50 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GSXML.class.getName());
51
52 // greenstone message xml elements
53 public static final String MESSAGE_ELEM = "message";
54 public static final String REQUEST_ELEM = "request";
55 public static final String RESPONSE_ELEM = "response";
56 public static final String COLLECTION_ELEM = "collection";
57 public static final String SERVICE_ELEM = "service";
58 public static final String CLUSTER_ELEM = "serviceCluster";
59 public static final String SITE_ELEM = "site";
60 public static final String PARAM_ELEM = "param";
61 public static final String PARAM_OPTION_ELEM = "option";
62 public static final String CONTENT_ELEM = "content";
63 public static final String RESOURCE_ELEM = "resource";
64 public static final String DOCUMENT_ELEM = "document";
65 public static final String METADATA_ELEM = "metadata";
66 public static final String SERVICE_CLASS_ELEM = "serviceRack";
67 public static final String CLASSIFIER_ELEM = "classifier";
68 public static final String APPLET_ELEM = "applet";
69 public static final String APPLET_DATA_ELEM = "appletData";
70 public static final String CONFIGURE_ELEM = "configure";
71 public static final String STATUS_ELEM = "status";
72 public static final String ERROR_ELEM = "error";
73 public static final String DEFAULT_ELEM = "default";
74 public static final String STYLESHEET_ELEM = "format";//"stylesheet"; // any additional stylesheet stuff is carried in the message inside this elem
75 public static final String FORMAT_ELEM = "format"; // config files use format - should we use this instead of stylesheet??
76 public static final String TERM_ELEM = "term";
77 public static final String STOPWORD_ELEM = "stopword";
78 public static final String SYSTEM_ELEM = "system";
79 public static final String FORMAT_STRING_ELEM = "formatString";
80
81 //config file elems
82 public static final String COLLECTION_CONFIG_ELEM = "collectionConfig";
83 public static final String COLLECTION_BUILD_ELEM = "buildConfig";
84 public static final String COLLECTION_INIT_ELEM = "collectionInit";
85 public static final String RECOGNISE_ELEM = "recognise";
86 public static final String DOC_TYPE_ELEM = "docType";
87 public static final String SEARCH_ELEM = "search";
88 public static final String INFODB_ELEM = "infodb";
89 public static final String INDEX_ELEM = "index";
90 public static final String INDEX_STEM_ELEM = "indexStem";
91 public static final String INDEX_OPTION_ELEM = "indexOption";
92 public static final String BROWSE_ELEM = "browse";
93 public static final String DISPLAY_ELEM = "display";
94 public static final String LEVEL_ELEM = "level";
95 public static final String REPLACE_ELEM = "replace";
96
97 public static final String DBINFO_ELEM = "dbInfo";
98 public static final String DBNAME_ATT = "dbname";
99 public static final String DBPATH_ATT = "dbpath";
100 public static final String SQLSTATE_ATT = "sqlstate";
101 public static final String DATABASE_TYPE_ELEM = "databaseType";
102 public static final String SHORTNAME_ATT = "shortname";
103 public static final String NOTIFY_ELEM = "notify";
104 public static final String NOTIFY_HOST_ATT = "host";
105
106 //doc.xml file elems
107 public static final String DOCXML_SECTION_ELEM = "Section";
108 public static final String DOCXML_DESCRIPTION_ELEM = "Description";
109 public static final String DOCXML_METADATA_ELEM = "Metadata";
110 public static final String DOCXML_CONTENT_ELEM = "Content";
111
112 // elems for the pages to be processed by xslt
113 public final static String PAGE_ELEM = "page";
114 public final static String CONFIGURATION_ELEM = "config";
115 public final static String PAGE_REQUEST_ELEM = "pageRequest";
116 public final static String PAGE_RESPONSE_ELEM = "pageResponse";
117 public final static String PAGE_EXTRA_ELEM = "pageExtra";
118
119 //public final static String DESCRIPTION_ELEM = "description";
120
121 public static final String ACTION_ELEM = "action";
122 public static final String SUBACTION_ELEM = "subaction";
123
124 // add on to another elem type to get a list of that type
125 public static final String LIST_MODIFIER = "List";
126 // used to refer back to another element type
127 public static final String REF_MODIFIER = "Ref";
128 // greenstone xml attributes
129 public static final String COLLECTION_ATT = "collection";
130 public static final String NAME_ATT = "name";
131 public static final String TO_ATT = "to";
132 public static final String USER_ID_ATT = "uid";
133 public static final String FROM_ATT = "from";
134 public static final String LANG_ATT = "lang";
135 public static final String TYPE_ATT = "type";
136 public static final String DB_TYPE_ATT = "dbType";
137 public static final String VALUE_ATT = "value";
138 public static final String DEFAULT_ATT = "default";
139 public static final String INFO_ATT = "info";
140 public static final String ACTION_ATT = "action";
141 public static final String SUBACTION_ATT = "subaction";
142 public static final String OUTPUT_ATT = "output";
143 public static final String ADDRESS_ATT = "address";
144 public static final String LOCAL_SITE_ATT = "localSite";
145 public static final String LOCAL_SITE_NAME_ATT = "localSiteName";
146 public static final String STATUS_ERROR_CODE_ATT = "code";
147 public static final String STATUS_PROCESS_ID_ATT = "pid";
148 public static final String PARAM_SHORTNAME_ATT = "shortname";
149 public static final String PARAM_IGNORE_POS_ATT = "ignore";
150 public static final String CLASSIFIER_CONTENT_ATT = "content";
151 public static final String ERROR_TYPE_ATT = "type";
152 public static final String COLLECT_TYPE_ATT = "ct";
153 public static final String HIDDEN_ATT = "hidden";
154
155 // document stuff
156 public static final String DOC_TYPE_ATT = "docType";
157 public static final String DOC_NODE_ELEM = "documentNode";
158 public static final String NODE_CONTENT_ELEM = "nodeContent";
159 public static final String NODE_STRUCTURE_ELEM = "nodeStructure";
160 public static final String NODE_ID_ATT = "nodeID";
161 public static final String HREF_ID_ATT = "hrefId"; // for ids that need translating
162 public static final String ID_MOD_ATT = "idMod"; // might hold .rt etc for hrefIds
163 public static final String NODE_OID = "oid";
164 public static final String NODE_NAME_ATT = "nodeName";
165 public static final String NODE_TYPE_ATT = "nodeType";
166 public static final String NODE_RANK_ATT = "rank";
167 public static final String NODE_TYPE_ROOT = "root";
168 public static final String NODE_TYPE_INTERNAL = "internal";
169 public static final String NODE_TYPE_LEAF = "leaf";
170
171 public static final String DOC_TYPE_SIMPLE = "simple";
172 public static final String DOC_TYPE_PAGED = "paged";
173 public static final String DOC_TYPE_HIERARCHY = "hierarchy";
174
175 public static final String SESSION_EXPIRATION = "session_expiration";
176 public static final String USER_SESSION_CACHE_ATT = "user_session_cache";
177
178 // classifier stuff
179 public static final String CLASS_NODE_ELEM = "classifierNode";
180 public static final String CLASS_NODE_ORIENTATION_ATT = "orientation";
181
182 // parameter types
183 public static final String PARAM_TYPE_INTEGER = "integer";
184 public static final String PARAM_TYPE_BOOLEAN = "boolean";
185 public static final String PARAM_TYPE_ENUM_START = "enum";
186 public static final String PARAM_TYPE_ENUM_SINGLE = "enum_single";
187 public static final String PARAM_TYPE_ENUM_MULTI = "enum_multi";
188 public static final String PARAM_TYPE_STRING = "string";
189 public static final String PARAM_TYPE_TEXT = "text";
190 public static final String PARAM_TYPE_MULTI = "multi";
191 public static final String PARAM_TYPE_FILE = "file";
192 public static final String PARAM_TYPE_INVISIBLE = "invisible";
193 // stuff for text strings
194 public static final String DISPLAY_TEXT_ELEM = "displayItem";
195 // the following are used for the name attributes
196 public static final String DISPLAY_TEXT_NAME = "name";
197 public static final String DISPLAY_TEXT_SUBMIT = "submit";
198 public static final String DISPLAY_TEXT_DESCRIPTION = "description";
199
200 // request types
201 // get the module description
202 public static final String REQUEST_TYPE_DESCRIBE = "describe";
203 // startup a process
204 public static final String REQUEST_TYPE_PROCESS = "process";
205 // get the status of an ongoing process
206 public static final String REQUEST_TYPE_STATUS = "status";
207 // system type request - eg reload a collection
208 public static final String REQUEST_TYPE_SYSTEM = "system";
209 // page requests to the Receptionist/Actions
210 public static final String REQUEST_TYPE_PAGE = "page"; // used to be cgi
211 // get any format info for a service
212 public static final String REQUEST_TYPE_FORMAT = "format";
213 // modify the requests
214 public static final String REQUEST_TYPE_MESSAGING = "messaging";
215 // save the format string
216 public static final String REQUEST_TYPE_FORMAT_STRING = "formatString";
217 // check credentials
218 public static final String REQUEST_TYPE_SECURITY = "security";
219
220 // service types
221 public static final String SERVICE_TYPE_QUERY = "query";
222 public static final String SERVICE_TYPE_RETRIEVE = "retrieve";
223 public static final String SERVICE_TYPE_BROWSE = "browse";
224 public static final String SERVICE_TYPE_APPLET = "applet";
225 public static final String SERVICE_TYPE_PROCESS = "process";
226 public static final String SERVICE_TYPE_ENRICH = "enrich";
227 public static final String SERVICE_TYPE_OAI = "oai";
228 public static final String FLAX_PAGE = "flaxPage";
229 public static final String FLAX_PAGE_GENERATION = "FlaxPageGeneration";
230
231 // system command types and attributes
232 public static final String SYSTEM_TYPE_CONFIGURE = "configure";
233 public static final String SYSTEM_TYPE_ACTIVATE = "activate";
234 public static final String SYSTEM_TYPE_DEACTIVATE = "deactivate";
235
236 public static final String SYSTEM_SUBSET_ATT = "subset";
237 public static final String SYSTEM_MODULE_TYPE_ATT = "moduleType";
238 public static final String SYSTEM_MODULE_NAME_ATT = "moduleName";
239
240 // communicator types
241 public static final String COMM_TYPE_SOAP_JAVA = "soap";
242
243 // error types
244 public static final String ERROR_TYPE_SYNTAX = "syntax";
245 public static final String ERROR_TYPE_SYSTEM = "system";
246 public static final String ERROR_TYPE_INVALID_ID = "invalid_id";
247 public static final String ERROR_TYPE_OTHER = "other";
248
249 // some system wide param names
250 public static final String SUBSET_PARAM = "subset";
251
252 //for plugin
253 public static final String PLUGIN_ELEM = "plugin";
254 public static final String IMPORT_ELEM = "import";
255
256 //for authentication
257 public static final String AUTHEN_NODE_ELEM = "authenticationNode";
258 public static final String USER_NODE_ELEM = "userNode";
259
260 //for configure action results
261 public static final String SUCCESS = "success";
262 public static final String ERROR = "error";
263
264 //security tags and attributes
265 public static final String SECURITY_ELEM = "security";
266 public static final String SCOPE_ATT = "scope";
267 public static final String DEFAULT_ACCESS_ATT = "default_access";
268 public static final String EXCEPTION_ELEM = "exception";
269 public static final String DOCUMENT_SET_ELEM = "documentSet";
270 public static final String GROUP_ELEM = "group";
271 public static final String MATCH_ELEM = "match";
272 public static final String FIELD_ATT = "field";
273 public static final String USER_INFORMATION_ELEM = "userInformation";
274 public static final String USERNAME_ATT = "username";
275 public static final String GROUPS_ATT = "groups";
276 public static final String BASE_URL = "baseURL";
277
278 /**
279 * takes a list of elements, and returns an array of strings of the values
280 * of attribute att_name
281 */
282 public static String[] getAttributeValuesFromList(Element list, String att_name)
283 {
284
285 NodeList children = list.getChildNodes();
286
287 int num_nodes = children.getLength();
288 String[] ids = new String[num_nodes];
289 for (int i = 0; i < num_nodes; i++)
290 {
291 Element e = (Element) children.item(i);
292 String id = e.getAttribute(att_name);
293 ids[i] = id;
294 }
295
296 return ids;
297 }
298
299 public static HashMap extractParams(Element xml, boolean deep)
300 {
301 return extractParams(xml, deep, null);
302 }
303
304 /**
305 * takes a paramList element, and gets a HashMap of name-value pairs if
306 * deep=true, extracts embedded params, otherwise just top level params
307 */
308 public static HashMap extractParams(Element xml, boolean deep, String toFind)
309 {
310
311 if (!xml.getNodeName().equals(PARAM_ELEM + LIST_MODIFIER))
312 {
313 logger.error("paramList element should have been passed to extractParams, instead it was " + xml.getNodeName());
314 return null;
315 }
316
317 NodeList params = null;
318 if (deep)
319 { // get all the nested ones
320 params = xml.getElementsByTagName(PARAM_ELEM);
321 }
322 else
323 { // just get the top level ones
324 params = xml.getChildNodes();
325 }
326 HashMap param_map = new HashMap();
327 for (int i = 0; i < params.getLength(); i++)
328 {
329 if (params.item(i).getNodeName().equals(PARAM_ELEM))
330 {
331 Element param = (Element) params.item(i);
332 String name = param.getAttribute(NAME_ATT);
333 String value = getValue(param); //att or content
334
335 // For only one parameter
336 if (toFind != null && name.equals(toFind))
337 {
338 param_map.put(name, value);
339 return param_map;
340 }
341 else if (toFind != null)
342 continue;
343
344 int pos = name.indexOf('.');
345 if (pos == -1)
346 { // a base param
347 param_map.put(name, value);
348 }
349 else
350 { // a namespaced param
351
352 String namespace = name.substring(0, pos);
353 name = name.substring(pos + 1);
354 HashMap map = (HashMap) param_map.get(namespace);
355 if (map == null)
356 {
357 map = new HashMap();
358 param_map.put(namespace, map);
359 }
360 map.put(name, value);
361 }
362 }
363 }
364 return param_map;
365 }
366
367 /** gets the value att or the text content */
368 public static String getValue(Element e)
369 {
370 String val = e.getAttribute(VALUE_ATT);
371 if (val == null || val.equals(""))
372 {
373 // have to get it out of the text
374 val = getNodeText(e);
375
376 }
377 else
378 {
379 // unescape the xml stuff
380 val = unXmlSafe(val);
381 }
382 return val;
383 }
384
385 /** extracts the text out of a node */
386 public static Node getNodeTextNode(Element param)
387 {
388 param.normalize();
389 Node n = param.getFirstChild();
390 while (n != null && n.getNodeType() != Node.TEXT_NODE)
391 {
392 n = n.getNextSibling();
393 }
394 return n;
395 }
396
397 /** extracts the text out of a node */
398 public static String getNodeText(Element param)
399 {
400 Node text_node = getNodeTextNode(param);
401 if (text_node == null)
402 {
403 return "";
404 }
405 return text_node.getNodeValue();
406 }
407
408 public static void setNodeText(Element elem, String text)
409 {
410 Node old_text_node = getNodeTextNode(elem);
411 if (old_text_node != null)
412 {
413 elem.removeChild(old_text_node);
414 }
415 Text t = elem.getOwnerDocument().createTextNode(text);
416 elem.appendChild(t);
417 }
418
419 /** add text to a document/subsection element */
420 public static boolean addDocText(Document owner, Element doc, String text)
421 {
422
423 Element content = owner.createElement(NODE_CONTENT_ELEM);
424 Text t = owner.createTextNode(text);
425 content.appendChild(t);
426 doc.appendChild(content);
427 return true;
428 }
429
430 /** add an error message, unknown error type */
431 public static boolean addError(Document owner, Element doc, String text)
432 {
433 return addError(owner, doc, text, ERROR_TYPE_OTHER);
434 }
435
436 /** add an error message */
437 public static boolean addError(Document owner, Element doc, String text, String error_type)
438 {
439
440 Element content = owner.createElement(ERROR_ELEM);
441 content.setAttribute(ERROR_TYPE_ATT, error_type);
442 Text t = owner.createTextNode(text);
443 content.appendChild(t);
444 doc.appendChild(content);
445 return true;
446 }
447
448 /** add an error message */
449 public static boolean addError(Document owner, Element doc, Throwable error)
450 {
451 return addError(owner, doc, error, ERROR_TYPE_OTHER);
452 }
453
454 /** add an error message */
455 public static boolean addError(Document owner, Element doc, Throwable error, String error_type)
456 {
457 error.printStackTrace();
458 return addError(owner, doc, error.toString(), error_type);
459 }
460
461 public static Element createMetadataParamList(Document owner, Vector meta_values)
462 {
463
464 Element meta_param_list = owner.createElement(PARAM_ELEM + LIST_MODIFIER);
465 Iterator i = meta_values.iterator();
466 while (i.hasNext())
467 {
468 String next = (String) i.next();
469 Element meta_param = owner.createElement(PARAM_ELEM);
470 meta_param_list.appendChild(meta_param);
471 meta_param.setAttribute(NAME_ATT, "metadata");
472 meta_param.setAttribute(VALUE_ATT, next);
473 }
474 return meta_param_list;
475 }
476
477 /** adds a metadata elem to a list */
478 public static boolean addMetadata(Document owner, Element list, String meta_name, String meta_value)
479 {
480 if (meta_value == null || meta_value.equals(""))
481 {
482 return false;
483 }
484 Element data = owner.createElement(METADATA_ELEM);
485 data.setAttribute(NAME_ATT, meta_name);
486 Text t = owner.createTextNode(meta_value);
487 data.appendChild(t);
488 list.appendChild(data);
489 return true;
490
491 }
492
493 /**
494 * copies the metadata out of the metadataList of 'from' into the
495 * metadataList of 'to'
496 */
497 public static boolean mergeMetadataLists(Node to, Node from)
498 {
499 Node from_meta = getChildByTagName(from, METADATA_ELEM + LIST_MODIFIER);
500 if (from_meta == null)
501 { // nothing to copy
502 return true;
503 }
504 return mergeMetadataFromList(to, from_meta);
505 }
506
507 /**
508 * copies the metadata out of the meta_list metadataList into the
509 * metadataList of 'to'
510 */
511 public static boolean mergeMetadataFromList(Node to, Node meta_list)
512 {
513 if (meta_list == null)
514 return false;
515 Node to_meta = getChildByTagName(to, METADATA_ELEM + LIST_MODIFIER);
516 Document to_owner = to.getOwnerDocument();
517 if (to_meta == null)
518 {
519 to.appendChild(to_owner.importNode(meta_list, true));
520 return true;
521 }
522 // copy individual metadata elements
523 NodeList meta_items = ((Element) meta_list).getElementsByTagName(METADATA_ELEM);
524 for (int i = 0; i < meta_items.getLength(); i++)
525 {
526 to_meta.appendChild(to_owner.importNode(meta_items.item(i), true));
527 }
528 return true;
529 }
530
531 /** copies all the children from from to to */
532 public static boolean mergeElements(Element to, Element from)
533 {
534
535 Document owner = to.getOwnerDocument();
536 Node child = from.getFirstChild();
537 while (child != null)
538 {
539 to.appendChild(owner.importNode(child, true));
540 child = child.getNextSibling();
541 }
542 return true;
543 }
544
545 /** returns the (first) element child of the node n */
546 public static Element getFirstElementChild(Node n)
547 {
548
549 Node child = n.getFirstChild();
550 while (child != null)
551 {
552 if (child.getNodeType() == Node.ELEMENT_NODE)
553 {
554 return (Element) child;
555 }
556 child = child.getNextSibling();
557 }
558 return null; //no element child found
559 }
560
561 /** returns the (first) child element with the given name */
562 public static Node getChildByTagName(Node n, String name)
563 {
564 if (n != null)
565 { // this line is an attempted solution to the NullPointerException mentioned
566 // in trac bug ticket #225. If n is null can't do n.getFirstChild() below. As per bug #225:
567 // GSXML.getNodeByPath() is called by GS2BrowseAction, which then calls this method.
568 // If n is null, null will be returned which GS2BrowseAction already checks for. It's here
569 // that the NullPointerException was thrown.
570
571 Node child = n.getFirstChild();
572 while (child != null)
573 {
574 if (child.getNodeName().equals(name))
575 {
576 return child;
577 }
578 child = child.getNextSibling();
579 }
580 }
581 return null; //not found
582 }
583
584 /**
585 * returns the (nth) child element with the given name index numbers start
586 * at 0
587 */
588 public static Node getChildByTagNameIndexed(Node n, String name, int index)
589 {
590 if (index == -1)
591 {
592 return getChildByTagName(n, name);
593 }
594 int count = 0;
595 Node child = n.getFirstChild();
596 while (child != null)
597 {
598 if (child.getNodeName().equals(name))
599 {
600 if (count == index)
601 {
602 return child;
603 }
604 else
605 {
606 count++;
607 }
608 }
609 child = child.getNextSibling();
610 }
611 return null; //not found
612 }
613
614 /**
615 * takes an xpath type expression of the form name/name/... and returns the
616 * first node that matches, or null if not found
617 */
618 public static Node getNodeByPath(Node n, String path)
619 {
620
621 String link = GSPath.getFirstLink(path);
622 path = GSPath.removeFirstLink(path);
623 while (!link.equals(""))
624 {
625 n = getChildByTagName(n, link);
626 if (n == null)
627 {
628 return null;
629 }
630 link = GSPath.getFirstLink(path);
631 path = GSPath.removeFirstLink(path);
632 }
633 return n;
634 }
635
636 /**
637 * takes an xpath type expression of the form name/name/... and returns the
638 * first node that matches, or null if not found can include [i] indices.
639 * index numbers start at 0
640 */
641 public static Node getNodeByPathIndexed(Node n, String path)
642 {
643
644 String link = GSPath.getFirstLink(path);
645 int index = GSPath.getIndex(link);
646 if (index != -1)
647 {
648 link = GSPath.removeIndex(link);
649 }
650 path = GSPath.removeFirstLink(path);
651 while (!link.equals(""))
652 {
653 n = getChildByTagNameIndexed(n, link, index);
654 if (n == null)
655 {
656 return null;
657 }
658 link = GSPath.getFirstLink(path);
659 index = GSPath.getIndex(link);
660 if (index != -1)
661 {
662 link = GSPath.removeIndex(link);
663 }
664 path = GSPath.removeFirstLink(path);
665 }
666 return n;
667 }
668
669 public static HashMap getChildrenMap(Node n)
670 {
671
672 HashMap map = new HashMap();
673 Node child = n.getFirstChild();
674 while (child != null)
675 {
676 String name = child.getNodeName();
677 map.put(name, child);
678 child = child.getNextSibling();
679 }
680 return map;
681 }
682
683 public static NodeList getChildrenByTagName(Node n, String name)
684 {
685 MyNodeList node_list = new MyNodeList();
686 Node child = n.getFirstChild();
687 while (child != null)
688 {
689 if (child.getNodeName().equals(name))
690 {
691 node_list.addNode(child);
692 }
693 child = child.getNextSibling();
694 }
695 return node_list;
696 }
697
698 /** Duplicates an element, but gives it a new name */
699 public static Element duplicateWithNewName(Document owner, Element element, String element_name, boolean with_attributes)
700 {
701 return duplicateWithNewNameNS(owner, element, element_name, null, with_attributes);
702 }
703
704 /** Duplicates an element, but gives it a new name */
705 public static Element duplicateWithNewNameNS(Document owner, Element element, String element_name, String namespace_uri, boolean with_attributes)
706 {
707 Element duplicate;
708 if (namespace_uri == null)
709 {
710 duplicate = owner.createElement(element_name);
711 }
712 else
713 {
714 duplicate = owner.createElementNS(namespace_uri, element_name);
715 }
716 // Copy element attributes
717 if (with_attributes)
718 {
719 NamedNodeMap attributes = element.getAttributes();
720 for (int i = 0; i < attributes.getLength(); i++)
721 {
722 Node attribute = attributes.item(i);
723 duplicate.setAttribute(attribute.getNodeName(), attribute.getNodeValue());
724 }
725 }
726
727 // Copy element children
728 NodeList children = element.getChildNodes();
729 for (int i = 0; i < children.getLength(); i++)
730 {
731 Node child = children.item(i);
732 duplicate.appendChild(owner.importNode(child, true));
733 }
734
735 return duplicate;
736 }
737
738 public static void copyAllChildren(Element to, Element from)
739 {
740
741 Document to_doc = to.getOwnerDocument();
742 Node child = from.getFirstChild();
743 while (child != null)
744 {
745 to.appendChild(to_doc.importNode(child, true));
746 child = child.getNextSibling();
747 }
748 }
749
750 /** returns a basic request message */
751 public static Element createBasicRequest(Document owner, String request_type, String to, UserContext userContext)
752 {
753 Element request = owner.createElement(REQUEST_ELEM);
754 request.setAttribute(TYPE_ATT, request_type);
755 request.setAttribute(LANG_ATT, userContext._lang);
756 request.setAttribute(TO_ATT, to);
757 request.setAttribute(USER_ID_ATT, userContext._userID);
758 return request;
759 }
760
761 public static Element createBasicResponse(Document owner, String from)
762 {
763 Element response = owner.createElement(GSXML.RESPONSE_ELEM);
764 response.setAttribute(GSXML.FROM_ATT, from);
765 response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
766 return response;
767 }
768
769 public static Element createMetadataElement(Document owner, String name, String value)
770 {
771 Element metaElem = owner.createElement(GSXML.METADATA_ELEM);
772 metaElem.setAttribute(GSXML.NAME_ATT, name);
773 metaElem.setAttribute(GSXML.VALUE_ATT, value);
774 return metaElem;
775 }
776
777 public static Element createTextElement(Document owner, String elem_name, String text)
778 {
779 Element e = owner.createElement(elem_name);
780 Text t = owner.createTextNode(text);
781 e.appendChild(t);
782 return e;
783
784 }
785
786 public static Element createTextElement(Document owner, String elem_name, String text, String att_name, String att_value)
787 {
788 Element e = owner.createElement(elem_name);
789 e.setAttribute(att_name, att_value);
790 Text t = owner.createTextNode(text);
791 e.appendChild(t);
792 return e;
793
794 }
795
796 public static Element createDisplayTextElement(Document owner, String text_name, String text)
797 {
798 Element e = owner.createElement(DISPLAY_TEXT_ELEM);
799 e.setAttribute(NAME_ATT, text_name);
800 Text t = owner.createTextNode(text);
801 e.appendChild(t);
802 return e;
803
804 }
805
806 public static Element createParameter(Document owner, String name, String value)
807 {
808 Element param = owner.createElement(PARAM_ELEM);
809 param.setAttribute(NAME_ATT, name);
810 param.setAttribute(VALUE_ATT, value);
811 return param;
812 }
813
814 public static void addParametersToList(Document owner, Element param_list, HashMap params)
815 {
816 if (params == null)
817 {
818 return;
819 }
820
821 Set items = params.entrySet();
822 Iterator i = items.iterator();
823 while (i.hasNext())
824 {
825 Map.Entry m = (Map.Entry) i.next();
826 param_list.appendChild(createParameter(owner, (String) m.getKey(), (String) m.getValue()));
827 }
828
829 }
830
831 public static Element createParameterDescription(Document owner, String id, String display_name, String type, String default_value, String[] option_ids, String[] option_names)
832 {
833
834 Element p = owner.createElement(PARAM_ELEM);
835 p.setAttribute(NAME_ATT, id);
836 p.setAttribute(TYPE_ATT, type);
837 p.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, display_name));
838
839 if (default_value != null)
840 {
841 p.setAttribute(DEFAULT_ATT, default_value);
842 }
843 if (option_ids != null && option_names != null)
844 {
845 for (int i = 0; i < option_ids.length; i++)
846 {
847 Element e = owner.createElement(PARAM_OPTION_ELEM);
848 e.setAttribute(NAME_ATT, option_ids[i]);
849 e.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, option_names[i]));
850 p.appendChild(e);
851 }
852 }
853 return p;
854 }
855
856 public static Element createParameterDescription2(Document owner, String id, String display_name, String type, String default_value, ArrayList option_ids, ArrayList option_names)
857 {
858
859 Element p = owner.createElement(PARAM_ELEM);
860 p.setAttribute(NAME_ATT, id);
861 p.setAttribute(TYPE_ATT, type);
862 p.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, display_name));
863 if (default_value != null)
864 {
865 p.setAttribute(DEFAULT_ATT, default_value);
866 }
867 if (option_ids != null && option_names != null)
868 {
869 for (int i = 0; i < option_ids.size(); i++)
870 {
871 Element e = owner.createElement(PARAM_OPTION_ELEM);
872 e.setAttribute(NAME_ATT, (String) option_ids.get(i));
873 e.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, (String) option_names.get(i)));
874 p.appendChild(e);
875 }
876 }
877 return p;
878 }
879
880 /** returns the element parent/node_name[@attribute_name='attribute_value'] */
881 public static Element getNamedElement(Element parent, String node_name, String attribute_name, String attribute_value)
882 {
883
884 NodeList children = parent.getChildNodes();
885 for (int i = 0; i < children.getLength(); i++)
886 {
887 Node child = children.item(i);
888 if (child.getNodeName().equals(node_name))
889 {
890 if (((Element) child).getAttribute(attribute_name).equals(attribute_value))
891 return (Element) child;
892 }
893 }
894 // not found
895 return null;
896 }
897
898 /**
899 * returns a NodeList of elements:
900 * ancestor/node_name[@attribute_name='attribute_value']
901 */
902 public static NodeList getNamedElements(Element ancestor, String node_name, String attribute_name, String attribute_value)
903 {
904 MyNodeList node_list = new MyNodeList();
905 NodeList children = ancestor.getElementsByTagName(node_name);
906
907 if (children != null && children.getLength() > 0)
908 {
909
910 for (int i = 0; i < children.getLength(); i++)
911 {
912 Node child = children.item(i);
913 if (child.getNodeName().equals(node_name))
914 {
915 if (((Element) child).getAttribute(attribute_name).equals(attribute_value))
916 node_list.addNode(child);
917 }
918 }
919 }
920 return node_list;
921 }
922
923 public static int SORT_TYPE_STRING = 0;
924 public static int SORT_TYPE_INT = 1;
925 public static int SORT_TYPE_FLOAT = 2;
926
927 // sort type:
928 public static Element insertIntoOrderedList(Element parent_node, String node_name, Element start_from_elem, Element new_elem, String sort_att, boolean descending)
929 {
930 if (new_elem == null)
931 return null;
932 Element cloned_elem = (Element) parent_node.getOwnerDocument().importNode(new_elem, true);
933 if (start_from_elem == null)
934 {
935 parent_node.appendChild(cloned_elem);
936 return cloned_elem;
937 }
938
939 Node current_node = start_from_elem;
940 String insert_att = cloned_elem.getAttribute(sort_att);
941 String list_att = start_from_elem.getAttribute(sort_att);
942 while ((!descending && list_att.compareTo(insert_att) < 0) || (descending && list_att.compareTo(insert_att) > 0))
943 {
944 current_node = current_node.getNextSibling();
945 if (current_node == null)
946 break; // end of the list
947 if (!current_node.getNodeName().equals(node_name))
948 {
949 continue; // not a valid node
950 }
951 list_att = ((Element) current_node).getAttribute(sort_att);
952 }
953
954 parent_node.insertBefore(cloned_elem, current_node);
955 return cloned_elem;
956 }
957
958 /**
959 * Returns the appropriate language element from a display elem, display is
960 * the containing element, name is the name of the element to look for, lang
961 * is the preferred language, lang_default is the fall back lang if neither
962 * lang is found, will return the first one it finds
963 */
964 public static String getDisplayText(Element display, String name, String lang, String lang_default)
965 {
966
967 String def = null;
968 String first = null;
969 NodeList elems = display.getElementsByTagName(DISPLAY_TEXT_ELEM);
970 if (elems.getLength() == 0)
971 return "";
972 for (int i = 0; i < elems.getLength(); i++)
973 {
974 Element e = (Element) elems.item(i);
975 String n = e.getAttribute(NAME_ATT);
976 if (name.equals(n))
977 {
978 String l = e.getAttribute(LANG_ATT);
979 if (lang.equals(l))
980 {
981 return getNodeText(e);
982 }
983 else if (lang_default.equals(l))
984 {
985 def = getNodeText(e);
986 }
987 else if (first == null)
988 {
989 first = getNodeText(e);
990 }
991 }
992 else
993 {
994 continue;
995 }
996 }
997
998 if (def != null)
999 {
1000 return def;
1001 }
1002 if (first != null)
1003 {
1004 return first;
1005 }
1006 return "";
1007 }
1008
1009 // replaces < > " ' & in the original with their entities
1010 public static String xmlSafe(String original)
1011 {
1012
1013 StringBuffer filtered = new StringBuffer(original.length());
1014 char c;
1015 for (int i = 0; i < original.length(); i++)
1016 {
1017 c = original.charAt(i);
1018 if (c == '>')
1019 {
1020 filtered.append("&gt;");
1021 }
1022 else if (c == '<')
1023 {
1024 filtered.append("&lt;");
1025 }
1026 else if (c == '"')
1027 {
1028 filtered.append("&quot;");
1029 }
1030 else if (c == '&')
1031 {
1032 filtered.append("&amp;");
1033 }
1034 else if (c == '\'')
1035 {
1036 filtered.append("&apos;");
1037 }
1038 else
1039 {
1040 filtered.append(c);
1041 }
1042 }
1043 return filtered.toString();
1044 }
1045
1046 // replaces < > " ' & entities with their originals
1047 public static String unXmlSafe(String original)
1048 {
1049
1050 StringBuffer filtered = new StringBuffer(original.length());
1051 char c;
1052 for (int i = 0; i < original.length(); i++)
1053 {
1054 c = original.charAt(i);
1055 if (c == '&')
1056 {
1057 int pos = original.indexOf(";", i);
1058 String entity = original.substring(i + 1, pos);
1059 if (entity.equals("gt"))
1060 {
1061 filtered.append(">");
1062 }
1063 else if (entity.equals("lt"))
1064 {
1065 filtered.append("<");
1066 }
1067 else if (entity.equals("apos"))
1068 {
1069 filtered.append("'");
1070 }
1071 else if (entity.equals("amp"))
1072 {
1073 filtered.append("&");
1074 }
1075 else if (entity.equals("quot"))
1076 {
1077 filtered.append("\"");
1078 }
1079 else
1080 {
1081 filtered.append("&" + entity + ";");
1082 }
1083 i = pos;
1084 }
1085 else
1086 {
1087 filtered.append(c);
1088 }
1089 }
1090 return filtered.toString();
1091 }
1092
1093 public static void printXMLNode(Node e, boolean printText)
1094 {
1095 printXMLNode(e, 0, printText);
1096 }
1097
1098 public static String xmlNodeToString(Node e)
1099 {
1100 StringBuffer sb = new StringBuffer("");
1101 xmlNodeToString(sb, e, 0, true);
1102 return sb.toString();
1103 }
1104
1105 public static String xmlNodeToString(Node e, boolean printText)
1106 {
1107 StringBuffer sb = new StringBuffer("");
1108 xmlNodeToString(sb, e, 0, printText);
1109 return sb.toString();
1110 }
1111
1112 private static void xmlNodeToString(StringBuffer sb, Node e, int depth, boolean printText)
1113 {
1114 if (e == null)
1115 {
1116 return;
1117 }
1118
1119 for (int i = 0; i < depth; i++)
1120 sb.append(' ');
1121
1122 if (e.getNodeType() == Node.TEXT_NODE)
1123 {
1124 if (printText)
1125 {
1126 sb.append(e.getNodeValue());
1127 }
1128 else
1129 {
1130 sb.append("text");
1131 }
1132 return;
1133 }
1134
1135 sb.append('<');
1136 sb.append(e.getNodeName());
1137 NamedNodeMap attrs = e.getAttributes();
1138 if (attrs != null)
1139 {
1140 for (int i = 0; i < attrs.getLength(); i++)
1141 {
1142 Node attr = attrs.item(i);
1143 sb.append(' ');
1144 sb.append(attr.getNodeName());
1145 sb.append("=\"");
1146 sb.append(attr.getNodeValue());
1147 sb.append('"');
1148 }
1149 }
1150
1151 NodeList children = e.getChildNodes();
1152
1153 if (children == null || children.getLength() == 0)
1154 sb.append("/>\n");
1155 else
1156 {
1157
1158 sb.append(">\n");
1159
1160 int len = children.getLength();
1161 for (int i = 0; i < len; i++)
1162 {
1163 xmlNodeToString(sb, children.item(i), depth + 1, printText);
1164 }
1165
1166 for (int i = 0; i < depth; i++)
1167 sb.append(' ');
1168
1169 sb.append("</" + e.getNodeName() + ">\n");
1170 }
1171
1172 }
1173
1174 public static void printXMLNode(Node e, int depth, boolean printText)
1175 { //recursive method call using DOM API...
1176
1177 if (e == null)
1178 {
1179 return;
1180 }
1181
1182 for (int i = 0; i < depth; i++)
1183 System.out.print(' ');
1184
1185 if (e.getNodeType() == Node.TEXT_NODE)
1186 {
1187 if (printText)
1188 {
1189 System.out.println(e.getNodeValue());
1190 }
1191 else
1192 {
1193 System.out.println("text");
1194 }
1195 return;
1196 }
1197
1198 System.out.print('<');
1199 System.out.print(e.getNodeName());
1200 NamedNodeMap attrs = e.getAttributes();
1201
1202 if (attrs != null)
1203 {
1204 for (int i = 0; i < attrs.getLength(); i++)
1205 {
1206 Node attr = attrs.item(i);
1207 System.out.print(' ');
1208 System.out.print(attr.getNodeName());
1209 System.out.print("=\"");
1210 System.out.print(attr.getNodeValue());
1211 System.out.print('"');
1212 }
1213 }
1214
1215 NodeList children = e.getChildNodes();
1216
1217 if (children == null || children.getLength() == 0)
1218 System.out.println("/>");
1219 else
1220 {
1221
1222 System.out.println('>');
1223
1224 int len = children.getLength();
1225 for (int i = 0; i < len; i++)
1226 {
1227 printXMLNode(children.item(i), depth + 1, printText);
1228 }
1229
1230 for (int i = 0; i < depth; i++)
1231 System.out.print(' ');
1232
1233 System.out.println("</" + e.getNodeName() + ">");
1234 }
1235 }
1236
1237 public static void elementToLogAsString(Element e, boolean indent)
1238 {
1239 String str = elementToString(e, indent);
1240 System.err.println(str);
1241 logger.error(str);
1242 }
1243
1244 public static String elementToString(Element e, boolean indent)
1245 {
1246 try {
1247 TransformerFactory tf = TransformerFactory.newInstance();
1248 Transformer trans = tf.newTransformer();
1249 StringWriter sw = new StringWriter();
1250 if(indent) {
1251 trans.setOutputProperty(OutputKeys.INDENT, "yes");
1252 } else {
1253 trans.setOutputProperty(OutputKeys.INDENT, "no");
1254 }
1255 trans.transform(new DOMSource(e), new StreamResult(sw));
1256 str += sw.toString();
1257 }
1258 catch (Exception ex) {
1259 str += "Exception: couldn't write " + e + " to log";
1260 }
1261 finally {
1262 return str;
1263 }
1264 }
1265
1266 public static ArrayList<String> getGroupsFromSecurityResponse(Element securityResponse)
1267 {
1268 ArrayList<String> groups = new ArrayList<String>();
1269
1270 Element groupList = (Element) GSXML.getChildByTagName(securityResponse, GSXML.GROUP_ELEM + GSXML.LIST_MODIFIER);
1271 if (groupList == null)
1272 {
1273 return groups;
1274 }
1275
1276 NodeList groupElems = GSXML.getChildrenByTagName(groupList, GSXML.GROUP_ELEM);
1277
1278 for (int i = 0; i < groupElems.getLength(); i++)
1279 {
1280 Element groupElem = (Element) groupElems.item(i);
1281 groups.add(groupElem.getAttribute(GSXML.NAME_ATT));
1282 }
1283
1284 return groups;
1285 }
1286}
Note: See TracBrowser for help on using the repository browser.