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

Last change on this file since 33045 was 33045, checked in by ak19, 5 years ago
  1. Dr Bainbridge's fix for the Windows encoding issue when online doc editing Title meta containing non-ASCII/non-basic unicode chars, was to URL encode the QUERY_STRING so that CGI.pm would then do the right thing. This was because the problem had turned out not to be env vars on Windows, which could set and recall unicode and win-1252 chars just fine and therefore retained what was entered. The problem was that on Windows, the perl did not get the actual chars transmitted in the case of UTF-8 whereas win-1252 was received looking apparently like a unicode codepoint, but then in the latter case the utf82unicode call in metadataaction would then clobber the codepoint in attempting to do utf82unicode on it. On linux, perl happened to receive the chars as utf8-encoded bytes and so utf82unicode worked (to make them unicode aware strings?). The real problem was that it could go wrong in different ways on windows, since utf8 chars weren't even received properly by perl/CGI, so we didn't even need to start worrying about them getting sometimes clobbered in metadataaction. URL encoding the QUERY_STRING was meant to solve this. Except that URL encoding the whole QUERY_STRING made CGI.pm choke on the equals signs between param name and param value and possibly other chars. I don't know why. I found that URL encoding just the param values in the QUERY_STRING works, so I am committing that. 2. Renaming the recently introduced string2hex() in JavaScript to debug_unicode_string and stringToHex() in Java to debugUnicodeString() to be more consistent with the perl variant, debug_unicode_string. Also like in the perl, the JavaScript and Java now print the unicode value inside curly braces for better legibility. 3. Leaving in some commented out encoding debugging statements in the Java and JavaScript code, but not committing the debugging on the perl side. 4. Some further improvements to overloaded functions in GSXML using debug_unicode_string for converting XML elements or printing them to logs.
  • Property svn:keywords set to Author Date Id Revision
File size: 51.8 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 java.io.Serializable;
22import java.io.StringWriter;
23import java.util.ArrayList;
24import java.util.HashMap;
25import java.util.Iterator;
26import java.util.Map;
27import java.util.Set;
28import java.util.Vector;
29
30import javax.xml.transform.OutputKeys;
31import javax.xml.transform.Transformer;
32import javax.xml.transform.TransformerFactory;
33import javax.xml.transform.dom.DOMSource;
34import javax.xml.transform.stream.StreamResult;
35
36import org.apache.log4j.Logger;
37import org.w3c.dom.Document;
38import org.w3c.dom.Element;
39import org.w3c.dom.NamedNodeMap;
40import org.w3c.dom.Node;
41import org.w3c.dom.NodeList;
42import org.w3c.dom.Text;
43
44import org.greenstone.gsdl3.util.MyNodeList;
45import org.greenstone.util.Misc;
46
47/** various functions for extracting info out of GS XML */
48public class GSXML
49{
50
51 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GSXML.class.getName());
52
53 // greenstone message xml elements
54 public static final String MESSAGE_ELEM = "message";
55 public static final String REQUEST_ELEM = "request";
56 public static final String RESPONSE_ELEM = "response";
57 public static final String COLLECTION_ELEM = "collection";
58 public static final String SERVICE_ELEM = "service";
59 public static final String CLUSTER_ELEM = "serviceCluster";
60 public static final String SITE_ELEM = "site";
61 public static final String PARAM_ELEM = "param";
62 public static final String PARAM_OPTION_ELEM = "option";
63 public static final String LIBRARY_PARAM_ELEM = "libraryParam";
64 public static final String CONTENT_ELEM = "content";
65 public static final String RESOURCE_ELEM = "resource";
66 public static final String DOCUMENT_ELEM = "document";
67 public static final String METADATA_ELEM = "metadata";
68 public static final String SERVICE_CLASS_ELEM = "serviceRack";
69 public static final String CLASSIFIER_ELEM = "classifier";
70 public static final String APPLET_ELEM = "applet";
71 public static final String APPLET_DATA_ELEM = "appletData";
72 public static final String CONFIGURE_ELEM = "configure";
73 public static final String STATUS_ELEM = "status";
74 public static final String ERROR_ELEM = "error";
75 public static final String DEFAULT_ELEM = "default";
76 public static final String STYLESHEET_ELEM = "format";//"stylesheet"; // any additional stylesheet stuff is carried in the message inside this elem
77 public static final String FORMAT_ELEM = "format"; // config files use format - should we use this instead of stylesheet??
78 public static final String GLOBAL_FORMAT_ELEM = "globalFormat";
79 public static final String TERM_ELEM = "term";
80 public static final String STOPWORD_ELEM = "stopword";
81 public static final String FACET_ELEM = "facet";
82 public static final String COUNT_ELEM = "count";
83 public static final String SYSTEM_ELEM = "system";
84 public static final String FORMAT_STRING_ELEM = "formatString";
85 public static final String EXTRA_METADATA = "extraMetadata";
86 public static final String PATH_ELEM = "path";
87
88 //config file elems
89 public static final String COLLECTION_CONFIG_ELEM = "collectionConfig";
90 public static final String COLLECTION_BUILD_ELEM = "buildConfig";
91 public static final String COLLECTION_INIT_ELEM = "collectionInit";
92 public static final String RECOGNISE_ELEM = "recognise";
93 public static final String DOC_TYPE_ELEM = "docType";
94 public static final String SEARCH_ELEM = "search";
95 public static final String INFODB_ELEM = "infodb";
96 public static final String INDEX_ELEM = "index";
97 public static final String INDEX_STEM_ELEM = "indexStem";
98 public static final String INDEX_OPTION_ELEM = "indexOption";
99 public static final String PARAM_DEFAULT_ELEM = "paramDefault";
100 public static final String BROWSE_ELEM = "browse";
101 public static final String DISPLAY_ELEM = "display";
102 public static final String LEVEL_ELEM = "level";
103 public static final String REPLACE_ELEM = "replace";
104 public static final String EXTRA_INFO_ELEM = "extraInfo";
105 public static final String DBINFO_ELEM = "dbInfo";
106 public static final String DBNAME_ATT = "dbname";
107 public static final String DBPATH_ATT = "dbpath";
108 public static final String SQLSTATE_ATT = "sqlstate";
109 public static final String DATABASE_TYPE_ELEM = "databaseType";
110 public static final String SHORTNAME_ATT = "shortname";
111 public static final String NOTIFY_ELEM = "notify";
112 public static final String NOTIFY_HOST_ATT = "host";
113
114 //doc.xml file elems
115 public static final String DOCXML_SECTION_ELEM = "Section";
116 public static final String DOCXML_DESCRIPTION_ELEM = "Description";
117 public static final String DOCXML_METADATA_ELEM = "Metadata";
118 public static final String DOCXML_CONTENT_ELEM = "Content";
119
120 // elems for the pages to be processed by xslt
121 public final static String PAGE_ELEM = "page";
122 public final static String CONFIGURATION_ELEM = "config";
123 public final static String PAGE_REQUEST_ELEM = "pageRequest";
124 public final static String PAGE_RESPONSE_ELEM = "pageResponse";
125 public final static String PAGE_EXTRA_ELEM = "pageExtra";
126
127 //public final static String DESCRIPTION_ELEM = "description";
128
129 public static final String ACTION_ELEM = "action";
130 public static final String SUBACTION_ELEM = "subaction";
131
132 // add on to another elem type to get a list of that type
133 public static final String LIST_MODIFIER = "List";
134 // used to refer back to another element type
135 public static final String REF_MODIFIER = "Ref";
136 // greenstone xml attributes
137 public static final String COLLECTION_ATT = "collection";
138 public static final String NAME_ATT = "name";
139 public static final String MATCH_ATT = "match";
140 public static final String TO_ATT = "to";
141 public static final String USER_ID_ATT = "uid";
142 public static final String FROM_ATT = "from";
143 public static final String LANG_ATT = "lang";
144 public static final String KEY_ATT = "key";
145 public static final String DICTIONARY_ATT = "dictionary";
146 public static final String HREF_ATT = "href";
147 public static final String TYPE_ATT = "type";
148 public static final String DB_TYPE_ATT = "dbType";
149 public static final String VALUE_ATT = "value";
150 public static final String DEFAULT_ATT = "default";
151 public static final String INFO_ATT = "info";
152 public static final String ACTION_ATT = "action";
153 public static final String SUBACTION_ATT = "subaction";
154 public static final String OUTPUT_ATT = "output";
155 public static final String ADDRESS_ATT = "address";
156 public static final String LOCAL_SITE_ATT = "localSite";
157 public static final String LOCAL_SITE_NAME_ATT = "localSiteName";
158 public static final String STATUS_ERROR_CODE_ATT = "code";
159 public static final String STATUS_PROCESS_ID_ATT = "pid";
160 public static final String PARAM_SHORTNAME_ATT = "shortname";
161 public static final String PARAM_IGNORE_POS_ATT = "ignore";
162 public static final String CLASSIFIER_CONTENT_ATT = "content";
163 public static final String ERROR_TYPE_ATT = "type";
164 public static final String COLLECT_TYPE_ATT = "ct";
165 public static final String HIDDEN_ATT = "hidden";
166 public static final String FACET_ATT = "facet";
167 public static final String PATH_ATT = "path";
168 public static final String SENSITIVE_ATT = "sensitive";
169 public static final String NO_ARCHIVES_ATT = "no_archives";
170 // document stuff
171 public static final String DOC_TYPE_ATT = "docType";
172 public static final String DOC_NODE_ELEM = "documentNode";
173 public static final String NODE_CONTENT_ELEM = "nodeContent";
174 public static final String NODE_STRUCTURE_ELEM = "nodeStructure";
175 public static final String NODE_ID_ATT = "nodeID";
176 public static final String HREF_ID_ATT = "hrefId"; // for ids that need translating
177 public static final String HL_SNIPPET_ELEM = "highlightSnippet";
178 public static final String ID_MOD_ATT = "idMod"; // might hold .rt etc for hrefIds
179 public static final String NODE_OID = "oid";
180 public static final String NODE_NAME_ATT = "nodeName";
181 public static final String NODE_TYPE_ATT = "nodeType";
182 public static final String NODE_RANK_ATT = "rank";
183 public static final String NODE_TYPE_ROOT = "root";
184 public static final String NODE_TYPE_INTERNAL = "internal";
185 public static final String NODE_TYPE_LEAF = "leaf";
186
187 public static final String DOC_TYPE_SIMPLE = "simple";
188 public static final String DOC_TYPE_PAGED = "paged";
189 public static final String DOC_TYPE_HIERARCHY = "hierarchy";
190 public static final String DOC_TYPE_PAGED_HIERARCHY = "pagedhierarchy";
191
192 public static final String SESSION_EXPIRATION = "session_expiration";
193 public static final String USER_SESSION_CACHE_ATT = "user_session_cache";
194
195 // classifier stuff
196 public static final String CLASS_NODE_ELEM = "classifierNode";
197 public static final String CLASS_NODE_ORIENTATION_ATT = "orientation";
198
199 // parameter types
200 public static final String PARAM_TYPE_INTEGER = "integer";
201 public static final String PARAM_TYPE_BOOLEAN = "boolean";
202 public static final String PARAM_TYPE_ENUM_START = "enum";
203 public static final String PARAM_TYPE_ENUM_SINGLE = "enum_single";
204 public static final String PARAM_TYPE_ENUM_MULTI = "enum_multi";
205 public static final String PARAM_TYPE_STRING = "string";
206 public static final String PARAM_TYPE_TEXT = "text";
207 public static final String PARAM_TYPE_MULTI = "multi";
208 public static final String PARAM_TYPE_FILE = "file";
209 public static final String PARAM_TYPE_INVISIBLE = "invisible";
210 public static final String PARAM_TYPE_CHECKBOX_LIST = "checkbox_list";
211 // stuff for text strings
212 public static final String DISPLAY_TEXT_ELEM = "displayItem";
213 // the following are used for the name attributes
214 public static final String DISPLAY_TEXT_NAME = "name";
215 public static final String DISPLAY_TEXT_SUBMIT = "submit";
216 public static final String DISPLAY_TEXT_DESCRIPTION = "description";
217
218 // request types
219 // get the module description
220 public static final String REQUEST_TYPE_DESCRIBE = "describe";
221 // startup a process
222 public static final String REQUEST_TYPE_PROCESS = "process";
223 // get the status of an ongoing process
224 public static final String REQUEST_TYPE_STATUS = "status";
225 // system type request - eg reload a collection
226 public static final String REQUEST_TYPE_SYSTEM = "system";
227 // page requests to the Receptionist/Actions
228 public static final String REQUEST_TYPE_PAGE = "page"; // used to be cgi
229 // get any format info for a service
230 public static final String REQUEST_TYPE_FORMAT = "format";
231 // modify the requests
232 public static final String REQUEST_TYPE_MESSAGING = "messaging";
233 // save the format string
234 public static final String REQUEST_TYPE_FORMAT_STRING = "formatString";
235 // check credentials
236 public static final String REQUEST_TYPE_SECURITY = "security";
237
238 // service types
239 public static final String SERVICE_TYPE_QUERY = "query";
240 public static final String SERVICE_TYPE_RETRIEVE = "retrieve";
241 public static final String SERVICE_TYPE_BROWSE = "browse";
242 public static final String SERVICE_TYPE_GROUPINFO = "groupinfo";
243 public static final String SERVICE_TYPE_APPLET = "applet";
244 public static final String SERVICE_TYPE_PROCESS = "process";
245 public static final String SERVICE_TYPE_ENRICH = "enrich";
246 public static final String SERVICE_TYPE_OAI = "oai";
247 public static final String FLAX_PAGE = "flaxPage";
248 public static final String FLAX_PAGE_GENERATION = "FlaxPageGeneration";
249
250 // system command types and attributes
251 public static final String SYSTEM_TYPE_CONFIGURE = "configure";
252 public static final String SYSTEM_TYPE_ACTIVATE = "activate";
253 public static final String SYSTEM_TYPE_DEACTIVATE = "deactivate";
254 public static final String SYSTEM_TYPE_PING = "ping";
255 public static final String SYSTEM_TYPE_AUTHENTICATED_PING = "authenticated-ping";
256 //public static final String SYSTEM_TYPE_ISPERSISTENT = "is-persistent";
257
258 public static final String SYSTEM_SUBSET_ATT = "subset";
259 public static final String SYSTEM_MODULE_TYPE_ATT = "moduleType";
260 public static final String SYSTEM_MODULE_NAME_ATT = "moduleName";
261
262 // communicator types
263 public static final String COMM_TYPE_SOAP_JAVA = "soap";
264
265 // error types
266 public static final String ERROR_TYPE_SYNTAX = "syntax";
267 public static final String ERROR_TYPE_SYSTEM = "system";
268 public static final String ERROR_TYPE_INVALID_ID = "invalid_id";
269 public static final String ERROR_TYPE_OTHER = "other";
270
271 // some system wide param names
272 public static final String SUBSET_PARAM = "subset";
273
274 //for plugin
275 public static final String PLUGIN_ELEM = "plugin";
276 public static final String IMPORT_ELEM = "import";
277
278 //for authentication
279 public static final String AUTHEN_NODE_ELEM = "authenticationNode";
280 public static final String USER_NODE_ELEM = "userNode";
281
282 //for configure action results
283 public static final String SUCCESS = "success";
284 public static final String ERROR = "error";
285
286 //security tags and attributes
287 public static final String SECURITY_ELEM = "security";
288 public static final String DISABLED_ATT = "disabled";
289 public static final String SCOPE_ATT = "scope";
290 public static final String DEFAULT_ACCESS_ATT = "default_access";
291 public static final String EXCEPTION_ELEM = "exception";
292 public static final String DOCUMENT_SET_ELEM = "documentSet";
293 public static final String GROUP_ELEM = "group";
294 public static final String MATCH_ELEM = "match";
295 public static final String FIELD_ATT = "field";
296 public static final String USER_INFORMATION_ELEM = "userInformation";
297 public static final String USERNAME_ATT = "username";
298 public static final String GROUPS_ATT = "groups";
299 public static final String BASE_URL = "baseURL";
300
301 // only for authenticated-ping
302 public static final String PASSWORD_ATT = "password";
303
304 //for classifiers
305 public static final String CHILD_TYPE_ATT = "childType";
306 public static final String CLASSIFIER_STYLE_ATT = "classifierStyle";
307 public static final String HLIST = "HList";
308 public static final String VLIST = "VList";
309
310 //for namespaces
311 public static final String XSL_NAMESPACE = "http://www.w3.org/1999/XSL/Transform";
312 public static final String GSF_NAMESPACE = "http://www.greenstone.org/greenstone3/schema/ConfigFormat";
313 public static final String GSLIB_NAMESPACE = "http://www.greenstone.org/skinning";
314 public static final String JAVA_NAMESPACE = "http://xml.apache.org/xslt/java";
315 public static final String UTIL_NAMESPACE = "xalan://org.greenstone.gsdl3.util.XSLTUtil";
316
317 // all the namespaces in a string for easy addition to a string
318 public static final String ALL_NAMESPACES_ATTS = "xmlns:gsf='" + GSF_NAMESPACE + "' xmlns:xsl='" + XSL_NAMESPACE + "' xmlns:gslib='" + GSLIB_NAMESPACE + "' xmlns:java='" + JAVA_NAMESPACE + "' xmlns:util='" + UTIL_NAMESPACE +"' ";
319 public static final String STD_NAMESPACES_ATTS = "xmlns:gsf='" + GSF_NAMESPACE + "' xmlns:xsl='" + XSL_NAMESPACE + "' xmlns:gslib='" + GSLIB_NAMESPACE +"' ";
320
321 //Groups configuration
322 public static final String HIERARCHY_ELEM = "hierarchy";
323 public static final String GROUP_DESC_ELEM = "groupDescriptions";
324 public static final String TITLE_ELEM = "title";
325 public static final String DESCRIPTION_ELEM = "description";
326 public static final String SHORT_DESCRIPTION_ELEM = "shortDescription";
327 public static final String BACKGROUND_IMAGE_ELEM = "backgroundImage";
328 public static final String POSITION_ATT = "position";
329
330 /**
331 * takes a list of elements, and returns an array of strings of the values
332 * of attribute att_name
333 */
334 public static String[] getAttributeValuesFromList(Element list, String att_name)
335 {
336
337 NodeList children = list.getChildNodes();
338
339 int num_nodes = children.getLength();
340 String[] ids = new String[num_nodes];
341 for (int i = 0; i < num_nodes; i++)
342 {
343 Element e = (Element) children.item(i);
344 String id = e.getAttribute(att_name);
345 ids[i] = id;
346 }
347
348 return ids;
349 }
350
351 public static HashMap<String, String> getParamMap(NodeList params) {
352 HashMap<String, String> map = new HashMap<String, String>();
353 for(int i=0; i<params.getLength(); i++) {
354 Element param = (Element)params.item(i);
355 String param_name = param.getAttribute(NAME_ATT);
356 String param_value = param.getAttribute(VALUE_ATT);
357 map.put(param_name, param_value);
358 }
359 return map;
360 }
361
362 public static HashMap<String, Serializable> extractParams(Element xml, boolean deep)
363 {
364 return extractParams(xml, deep, null);
365 }
366
367 /**
368 * takes a paramList element, and gets a HashMap of name-value pairs if
369 * deep=true, extracts embedded params, otherwise just top level params
370 */
371 public static HashMap<String, Serializable> extractParams(Element xml, boolean deep, String toFind)
372 {
373 if (xml == null)
374 {
375 return null;
376 }
377
378 if (!xml.getNodeName().equals(PARAM_ELEM + LIST_MODIFIER))
379 {
380 logger.error("paramList element should have been passed to extractParams, instead it was " + xml.getNodeName());
381 return null;
382 }
383
384 NodeList params = null;
385 if (deep)
386 { // get all the nested ones
387 params = xml.getElementsByTagName(PARAM_ELEM);
388 }
389 else
390 { // just get the top level ones
391 params = xml.getChildNodes();
392 }
393 HashMap<String, Serializable> param_map = new HashMap<String, Serializable>();
394 for (int i = 0; i < params.getLength(); i++)
395 {
396 if (params.item(i).getNodeName().equals(PARAM_ELEM))
397 {
398 Element param = (Element) params.item(i);
399 String name = param.getAttribute(NAME_ATT);
400 String value = getValue(param); //att or content
401
402 // For only one parameter
403 if (toFind != null && name.equals(toFind))
404 {
405 param_map.put(name, value);
406 return param_map;
407 }
408 else if (toFind != null)
409 continue;
410
411 int pos = name.indexOf('.');
412 if (pos == -1)
413 { // a base param
414 param_map.put(name, value);
415 }
416 else
417 { // a namespaced param
418
419 String namespace = name.substring(0, pos);
420 name = name.substring(pos + 1);
421 HashMap<String, String> map = (HashMap<String, String>) param_map.get(namespace);
422 if (map == null)
423 {
424 map = new HashMap<String, String>();
425 param_map.put(namespace, map);
426 }
427 map.put(name, value);
428 }
429 }
430 }
431 return param_map;
432 }
433
434 /** gets the value att or the text content */
435 public static String getValue(Element e)
436 {
437 String val = e.getAttribute(VALUE_ATT);
438 if (val == null || val.equals(""))
439 {
440 // have to get it out of the text
441 val = getNodeText(e);
442
443 }
444 else
445 {
446 // unescape the xml stuff
447 val = unXmlSafe(val);
448 }
449 return val;
450 }
451
452 /** extracts the text out of a node */
453 public static Node getNodeTextNode(Element param)
454 {
455 param.normalize();
456 Node n = param.getFirstChild();
457 while (n != null && n.getNodeType() != Node.TEXT_NODE)
458 {
459 n = n.getNextSibling();
460 }
461 return n;
462 }
463
464 /** extracts the text out of a node */
465 public static String getNodeText(Element param)
466 {
467 Node text_node = getNodeTextNode(param);
468 if (text_node == null)
469 {
470 return "";
471 }
472 return text_node.getNodeValue();
473 }
474
475 public static void setNodeText(Element elem, String text)
476 {
477 Node old_text_node = getNodeTextNode(elem);
478 if (old_text_node != null)
479 {
480 elem.removeChild(old_text_node);
481 }
482 Text t = elem.getOwnerDocument().createTextNode(text);
483 elem.appendChild(t);
484 }
485
486 /** add text to a document/subsection element */
487 public static boolean addDocText(Element doc, String text)
488 {
489
490 Element content = doc.getOwnerDocument().createElement(NODE_CONTENT_ELEM);
491 Text t = doc.getOwnerDocument().createTextNode(text);
492 content.appendChild(t);
493 doc.appendChild(content);
494 return true;
495 }
496
497 /** add an error message, unknown error type */
498 public static boolean addError(Element doc, String text)
499 {
500 return addError(doc, text, ERROR_TYPE_OTHER);
501 }
502
503 /** add an error message */
504 public static boolean addError(Element doc, String text, String error_type)
505 {
506
507 Element content = doc.getOwnerDocument().createElement(ERROR_ELEM);
508 content.setAttribute(ERROR_TYPE_ATT, error_type);
509 Text t = doc.getOwnerDocument().createTextNode(text);
510 content.appendChild(t);
511 doc.appendChild(content);
512 return true;
513 }
514
515 /** add an error message */
516 public static boolean addError(Element doc, Throwable error)
517 {
518 return addError(doc, error, ERROR_TYPE_OTHER);
519 }
520
521 /** add an error message */
522 public static boolean addError(Element doc, Throwable error, String error_type)
523 {
524 error.printStackTrace();
525 return addError(doc, error.toString(), error_type);
526 }
527
528 public static boolean addGSNamespaces(Element elem, boolean include_extension_ns) {
529 if (elem == null) {
530 return false;
531 }
532 elem.setAttribute("xmlns:gsf", GSF_NAMESPACE);
533 elem.setAttribute("xmlns:xsl", XSL_NAMESPACE);
534 elem.setAttribute("xmlns:gslib", GSLIB_NAMESPACE);
535 if (include_extension_ns) {
536 elem.setAttribute("xmlns:util", UTIL_NAMESPACE);
537 elem.setAttribute("xmlns:java", JAVA_NAMESPACE);
538 }
539 return true;
540 }
541 public static Element createMetadataParamList(Document owner, Vector meta_values)
542 {
543
544 Element meta_param_list = owner.createElement(PARAM_ELEM + LIST_MODIFIER);
545 Iterator i = meta_values.iterator();
546 while (i.hasNext())
547 {
548 String next = (String) i.next();
549 Element meta_param = owner.createElement(PARAM_ELEM);
550 meta_param_list.appendChild(meta_param);
551 meta_param.setAttribute(NAME_ATT, "metadata");
552 meta_param.setAttribute(VALUE_ATT, next);
553 }
554 return meta_param_list;
555 }
556
557 /** adds a metadata elem to a list */
558 public static boolean addMetadata(Element list, String meta_name, String meta_value)
559 {
560 if (meta_value == null || meta_value.equals(""))
561 {
562 return false;
563 }
564 Document owner = list.getOwnerDocument();
565 Element data = owner.createElement(METADATA_ELEM);
566 data.setAttribute(NAME_ATT, meta_name);
567 Text t = owner.createTextNode(meta_value);
568 data.appendChild(t);
569 list.appendChild(data);
570 return true;
571
572 }
573
574 /**
575 * copies the metadata out of the metadataList of 'from' into the
576 * metadataList of 'to'
577 */
578 public static boolean mergeMetadataLists(Node to, Node from) {
579 return mergeSpecifiedLists(to, from, METADATA_ELEM);
580 }
581
582 /** copies metadata from meta_list into the metadataList of to **/
583 public static boolean mergeMetadataFromList(Node to, Node meta_list) {
584 return mergeSpecifiedFromList(to, meta_list, METADATA_ELEM);
585 }
586
587
588 public static boolean mergeSpecifiedLists(Node to, Node from, String element_name) {
589 // find the list in the from element
590 Node from_list = getChildByTagName(from, element_name+LIST_MODIFIER);
591 if (from_list == null) {
592 // nothing to copy
593 return false;
594 }
595
596 return mergeSpecifiedFromList(to, from_list, element_name);
597 }
598 public static boolean mergeSpecifiedFromList(Node to, Node from_list, String element_name) {
599 if (from_list == null) {
600 return false;
601 }
602 Document to_owner = to.getOwnerDocument();
603 Node to_list = getChildByTagName(to, element_name+LIST_MODIFIER);
604 if (to_list == null) {
605 // just copy over the whole list
606 to.appendChild(to_owner.importNode(from_list, true));
607 return true;
608 }
609 // otherwise we copy all the elements
610 NodeList from_items = ((Element) from_list).getElementsByTagName(element_name);
611
612 for (int i = 0; i < from_items.getLength(); i++)
613 {
614 to_list.appendChild(to_owner.importNode(from_items.item(i), true));
615 }
616 return true;
617
618 }
619
620 /** copies all the children from from to to */
621 public static boolean mergeElements(Element to, Element from)
622 {
623
624 Document owner = to.getOwnerDocument();
625 Node child = from.getFirstChild();
626 while (child != null)
627 {
628 to.appendChild(owner.importNode(child, true));
629 child = child.getNextSibling();
630 }
631 return true;
632 }
633
634 /** returns the (first) element child of the node n */
635 public static Element getFirstElementChild(Node n)
636 {
637
638 Node child = n.getFirstChild();
639 while (child != null)
640 {
641 if (child.getNodeType() == Node.ELEMENT_NODE)
642 {
643 return (Element) child;
644 }
645 child = child.getNextSibling();
646 }
647 return null; //no element child found
648 }
649
650 /** returns the (first) child element with the given name */
651 public static Node getChildByTagName(Node n, String name)
652 {
653 if (n != null)
654 { // this line is an attempted solution to the NullPointerException mentioned
655 // in trac bug ticket #225. If n is null can't do n.getFirstChild() below. As per bug #225:
656 // getNodeByPath() is called by GS2BrowseAction, which then calls this method.
657 // If n is null, null will be returned which GS2BrowseAction already checks for. It's here
658 // that the NullPointerException was thrown.
659
660 Node child = n.getFirstChild();
661 while (child != null)
662 {
663 if (child.getNodeName().equals(name))
664 {
665 return child;
666 }
667 child = child.getNextSibling();
668 }
669 }
670 return null; //not found
671 }
672
673 /**
674 * returns the (nth) child element with the given name index numbers start
675 * at 0
676 */
677 public static Node getChildByTagNameIndexed(Node n, String name, int index)
678 {
679 if (index == -1)
680 {
681 return getChildByTagName(n, name);
682 }
683 int count = 0;
684 Node child = n.getFirstChild();
685 while (child != null)
686 {
687 if (child.getNodeName().equals(name))
688 {
689 if (count == index)
690 {
691 return child;
692 }
693 else
694 {
695 count++;
696 }
697 }
698 child = child.getNextSibling();
699 }
700 return null; //not found
701 }
702
703 /**
704 * takes an xpath type expression of the form name/name/... and returns the
705 * first node that matches, or null if not found
706 */
707 public static Node getNodeByPath(Node n, String path)
708 {
709
710 String link = GSPath.getFirstLink(path);
711 path = GSPath.removeFirstLink(path);
712 while (!link.equals(""))
713 {
714 n = getChildByTagName(n, link);
715 if (n == null)
716 {
717 return null;
718 }
719 link = GSPath.getFirstLink(path);
720 path = GSPath.removeFirstLink(path);
721 }
722 return n;
723 }
724
725 /**
726 * takes an xpath type expression of the form name/name/... and returns the
727 * first node that matches, or null if not found can include [i] indices.
728 * index numbers start at 0
729 */
730 public static Node getNodeByPathIndexed(Node n, String path)
731 {
732
733 String link = GSPath.getFirstLink(path);
734 int index = GSPath.getIndex(link);
735 if (index != -1)
736 {
737 link = GSPath.removeIndex(link);
738 }
739 path = GSPath.removeFirstLink(path);
740 while (!link.equals(""))
741 {
742 n = getChildByTagNameIndexed(n, link, index);
743 if (n == null)
744 {
745 return null;
746 }
747 link = GSPath.getFirstLink(path);
748 index = GSPath.getIndex(link);
749 if (index != -1)
750 {
751 link = GSPath.removeIndex(link);
752 }
753 path = GSPath.removeFirstLink(path);
754 }
755 return n;
756 }
757
758 public static HashMap<String, Node> getChildrenMap(Node n)
759 {
760
761 HashMap<String, Node> map = new HashMap<String, Node>();
762 Node child = n.getFirstChild();
763 while (child != null)
764 {
765 String name = child.getNodeName();
766 map.put(name, child);
767 child = child.getNextSibling();
768 }
769 return map;
770 }
771
772 public static NodeList getChildrenByTagName(Node n, String name)
773 {
774 MyNodeList node_list = new MyNodeList();
775 Node child = n.getFirstChild();
776 while (child != null)
777 {
778 if (child.getNodeName().equals(name))
779 {
780 node_list.addNode(child);
781 }
782 child = child.getNextSibling();
783 }
784 return node_list;
785 }
786
787 public static NodeList getChildrenByTagNameNS(Node n, String namespace, String local_name)
788 {
789 MyNodeList node_list = new MyNodeList();
790 Node child = n.getFirstChild();
791 while (child != null)
792 {
793 if (child.getNodeType() == Node.ELEMENT_NODE && child.getNamespaceURI() != null && child.getNamespaceURI().equals(namespace) && child.getLocalName() != null && child.getLocalName().equals(local_name))
794 {
795 node_list.addNode(child);
796 }
797 child = child.getNextSibling();
798 }
799 return node_list;
800 }
801
802 /** Duplicates an element, but gives it a new name */
803 public static Element duplicateWithNewName(Document owner, Element element, String element_name, boolean with_attributes)
804 {
805 return duplicateWithNewNameNS(owner, element, element_name, null, with_attributes);
806 }
807
808 /** Duplicates an element, but gives it a new name */
809 public static Element duplicateWithNewNameNS(Document owner, Element element, String element_name, String namespace_uri, boolean with_attributes)
810 {
811 Element duplicate;
812 if (namespace_uri == null)
813 {
814 duplicate = owner.createElement(element_name);
815 }
816 else
817 {
818 duplicate = owner.createElementNS(namespace_uri, element_name);
819 }
820
821 // Copy element attributes
822 if (with_attributes)
823 {
824 NamedNodeMap attributes = element.getAttributes();
825 for (int i = 0; i < attributes.getLength(); i++)
826 {
827 Node attribute = attributes.item(i);
828 duplicate.setAttribute(attribute.getNodeName(), attribute.getNodeValue());
829 }
830 }
831
832 // Copy element children
833 NodeList children = element.getChildNodes();
834 for (int i = 0; i < children.getLength(); i++)
835 {
836 Node child = children.item(i);
837 duplicate.appendChild(owner.importNode(child, true));
838 }
839
840 return duplicate;
841 }
842
843 public static void copyAllChildren(Element to, Element from)
844 {
845
846 Document to_doc = to.getOwnerDocument();
847 Node child = from.getFirstChild();
848 while (child != null)
849 {
850 to.appendChild(to_doc.importNode(child, true));
851 child = child.getNextSibling();
852 }
853 }
854
855 public static void copyNode(Element to_elem, Node original_element) {
856 to_elem.appendChild(to_elem.getOwnerDocument().importNode(original_element, true));
857
858 }
859
860 public static void copyNamedElement(Element to, Element from, String elem_name) {
861
862 Document to_doc = to.getOwnerDocument();
863 Node child = from.getFirstChild();
864 while (child != null) {
865 if (child.getNodeName().equals(elem_name)) {
866 to.appendChild(to_doc.importNode(child, true));
867 return;
868 }
869 child = child.getNextSibling();
870 }
871 }
872
873 /* Have an element with a set of children, attributes name="x". Replace the specified item in the list with new_item. */
874 /* this assumes we only have children of the same node name. if going tro have mixed lists, need to test on node name as well */
875 public static void replaceNamedItemInList(Element item_list, String item_node_name, String name_att, String item_name, Element new_item) {
876 Node child = item_list.getFirstChild();
877 while(child != null) {
878 if (child.getNodeName().equals(item_node_name) && ((Element)child).getAttribute(name_att).equals(item_name)) {
879 //replace the element
880 item_list.insertBefore(item_list.getOwnerDocument().importNode(new_item, true), child);
881 item_list.removeChild(child);
882 return;
883 }
884 child = child.getNextSibling();
885 }
886
887 }
888 /**
889 * Given a Node representing an Element or Document, will return the
890 * Element/docroot Element. Returns null if the Node was not an element.
891 */
892 public static Element nodeToElement(Node node)
893 {
894 if (node == null)
895 {
896 return null;
897 }
898 short nodeType = node.getNodeType();
899
900 if (nodeType == Node.DOCUMENT_NODE)
901 {
902 Document docNode = (Document) node;
903 return docNode.getDocumentElement();
904 }
905 else if (nodeType == Node.ELEMENT_NODE)
906 {
907 return (Element) node;
908 }
909 else
910 {
911 String message = "Expecting Document or Element node type but got " + node.getNodeName() + "\nReturning null";
912 System.err.println(message);
913 logger.warn(message);
914 return null;
915 }
916 }
917
918
919 /** returns a basic request message */
920 public static Element createBasicRequest(Document owner, String request_type, String to, UserContext userContext)
921 {
922 Element request = owner.createElement(REQUEST_ELEM);
923 request.setAttribute(TO_ATT, to);
924 request.setAttribute(TYPE_ATT, request_type);
925 if (userContext != null) { // should we allow this??
926 request.setAttribute(LANG_ATT, userContext._lang);
927 Element userContextElem = owner.createElement("userContext");
928 request.appendChild(userContextElem);
929 userContextElem.setAttribute(LANG_ATT, userContext._lang);
930 userContextElem.setAttribute(USERNAME_ATT, userContext._username);
931 userContextElem.setAttribute(USER_ID_ATT, userContext._userID);
932
933 if (userContext._groups != null)
934 {
935 String groupString = "";
936 for (int i = 0; i < userContext._groups.length; i++)
937 {
938 groupString += userContext._groups[i];
939 if (i != userContext._groups.length - 1)
940 {
941 groupString += ",";
942 }
943 }
944
945 if (groupString.length() > 0)
946 {
947 userContextElem.setAttribute(GROUPS_ATT, groupString);
948 }
949 }
950 }
951 return request;
952 }
953
954 public static Element createBasicResponse(Document owner, String from)
955 {
956 Element response = owner.createElement(RESPONSE_ELEM);
957 response.setAttribute(FROM_ATT, from);
958 response.setAttribute(TYPE_ATT, REQUEST_TYPE_PROCESS);
959 return response;
960 }
961
962 public static Element createMetadataElement(Document owner, String name, String value)
963 {
964 Element metaElem = owner.createElement(METADATA_ELEM);
965 metaElem.setAttribute(NAME_ATT, name);
966 metaElem.setAttribute(VALUE_ATT, value);
967 return metaElem;
968 }
969
970 public static Element createTextElement(Document owner, String elem_name, String text)
971 {
972 Element e = owner.createElement(elem_name);
973 Text t = owner.createTextNode(text);
974 e.appendChild(t);
975 return e;
976
977 }
978
979 public static Element createTextElement(Document owner, String elem_name, String text, String att_name, String att_value)
980 {
981 Element e = owner.createElement(elem_name);
982 e.setAttribute(att_name, att_value);
983 Text t = owner.createTextNode(text);
984 e.appendChild(t);
985 return e;
986
987 }
988
989 public static Element createDisplayTextElement(Document owner, String text_name, String text)
990 {
991 Element e = owner.createElement(DISPLAY_TEXT_ELEM);
992 e.setAttribute(NAME_ATT, text_name);
993 Text t = owner.createTextNode(text);
994 e.appendChild(t);
995 return e;
996
997 }
998
999 public static Element createParameter(Document owner, String name, String value)
1000 {
1001 Element param = owner.createElement(PARAM_ELEM);
1002 param.setAttribute(NAME_ATT, name);
1003 param.setAttribute(VALUE_ATT, value);
1004 return param;
1005 }
1006
1007 public static void addParameterToList(Element param_list, String name, String value) {
1008 Element p = createParameter(param_list.getOwnerDocument(), name, value);
1009 param_list.appendChild(p);
1010 }
1011 public static void addParametersToList(Element param_list, HashMap params)
1012 {
1013 if (params == null)
1014 {
1015 return;
1016 }
1017
1018 Set items = params.entrySet();
1019 Iterator i = items.iterator();
1020 Document owner = param_list.getOwnerDocument();
1021 while (i.hasNext())
1022 {
1023 Map.Entry m = (Map.Entry) i.next();
1024 param_list.appendChild(createParameter(owner, (String) m.getKey(), (String) m.getValue()));
1025 }
1026
1027 }
1028
1029 public static Element createParameterDescription(Document owner, String id, String display_name, String type, String default_value, String[] option_ids, String[] option_names)
1030 {
1031
1032 Element p = owner.createElement(PARAM_ELEM);
1033 p.setAttribute(NAME_ATT, id);
1034 p.setAttribute(TYPE_ATT, type);
1035 p.appendChild(createDisplayTextElement(owner, DISPLAY_TEXT_NAME, display_name));
1036
1037 if (default_value != null)
1038 {
1039 p.setAttribute(DEFAULT_ATT, default_value);
1040 }
1041 if (option_ids != null && option_names != null)
1042 {
1043 for (int i = 0; i < option_ids.length; i++)
1044 {
1045 Element e = owner.createElement(PARAM_OPTION_ELEM);
1046 e.setAttribute(NAME_ATT, option_ids[i]);
1047 e.appendChild(createDisplayTextElement(owner, DISPLAY_TEXT_NAME, option_names[i]));
1048 p.appendChild(e);
1049 }
1050 }
1051 return p;
1052 }
1053
1054 public static Element createParameterDescription2(Document owner, String id, String display_name, String type, String default_value, ArrayList<String> option_ids, ArrayList<String> option_names)
1055 {
1056
1057 Element p = owner.createElement(PARAM_ELEM);
1058 p.setAttribute(NAME_ATT, id);
1059 p.setAttribute(TYPE_ATT, type);
1060 p.appendChild(createDisplayTextElement(owner, DISPLAY_TEXT_NAME, display_name));
1061 if (default_value != null)
1062 {
1063 p.setAttribute(DEFAULT_ATT, default_value);
1064 }
1065 if (option_ids != null && option_names != null)
1066 {
1067 for (int i = 0; i < option_ids.size(); i++)
1068 {
1069 Element e = owner.createElement(PARAM_OPTION_ELEM);
1070 e.setAttribute(NAME_ATT, option_ids.get(i));
1071 e.appendChild(createDisplayTextElement(owner, DISPLAY_TEXT_NAME, option_names.get(i)));
1072 p.appendChild(e);
1073 }
1074 }
1075 return p;
1076 }
1077
1078 /** returns the element parent/node_name[@attribute_name='attribute_value']
1079 if attribute_value is null, just returns the first one with that attribute */
1080 public static Element getNamedElement(Element parent, String node_name, String attribute_name, String attribute_value)
1081 {
1082
1083 NodeList children = parent.getChildNodes();
1084 for (int i = 0; i < children.getLength(); i++)
1085 {
1086 Node child = children.item(i);
1087 if (child.getNodeName().equals(node_name))
1088 {
1089 String att_val = ((Element) child).getAttribute(attribute_name);
1090 if (!att_val.equals("") ) {
1091 if (attribute_value == null || att_val.equals(attribute_value)) {
1092 return (Element) child;
1093 }
1094 }
1095 }
1096 } // for each child
1097 // not found
1098 return null;
1099 }
1100
1101 public static Element getNamedElementNS(Element parent, String namespace_uri, String node_local_name, String attribute_name, String attribute_value)
1102 {
1103 NodeList children = parent.getChildNodes();
1104 for (int i = 0; i < children.getLength(); i++)
1105 {
1106 Node child = children.item(i);
1107 if (child.getNodeType() == Node.ELEMENT_NODE && child.getNamespaceURI() != null && child.getNamespaceURI().equals(namespace_uri) && child.getLocalName().equals(node_local_name))
1108 {
1109 if (((Element) child).getAttribute(attribute_name).equals(attribute_value))
1110 return (Element) child;
1111 }
1112 }
1113 // not found
1114 return null;
1115 }
1116
1117 public static NodeList getNamedElementsNS(Element parent, String namespace_uri, String node_local_name, String attribute_name, String attribute_value)
1118 {
1119 MyNodeList result = new MyNodeList();
1120 NodeList children = parent.getChildNodes();
1121 for (int i = 0; i < children.getLength(); i++)
1122 {
1123 Node child = children.item(i);
1124 if (child.getNodeType() == Node.ELEMENT_NODE && child.getNamespaceURI() != null && child.getNamespaceURI().equals(namespace_uri) && child.getLocalName().equals(node_local_name))
1125 {
1126 if (((Element) child).getAttribute(attribute_name).equals(attribute_value))
1127 result.addNode(child);
1128 }
1129 }
1130 return result;
1131 }
1132
1133 public static NodeList getElementsWithAttributesNS(Element parent, String namespace_uri, String node_local_name, String[] attribute_names, String[] attribute_values)
1134 {
1135 if (attribute_names.length == 0 || attribute_names.length != attribute_values.length)
1136 {
1137 return new MyNodeList();
1138 }
1139
1140 MyNodeList result = new MyNodeList();
1141
1142 NodeList matchingNodes = getNamedElementsNS(parent, namespace_uri, node_local_name, attribute_names[0], attribute_values[0]);
1143 for (int i = 0; i < matchingNodes.getLength(); i++)
1144 {
1145 Element current = (Element) matchingNodes.item(i);
1146 boolean nodeMatches = true;
1147 for (int j = 1; j < attribute_names.length; j++)
1148 {
1149 String currentName = attribute_names[j];
1150 String currentValue = attribute_values[j];
1151 if (!current.getAttribute(currentName).equals(currentValue))
1152 {
1153 nodeMatches = false;
1154 break;
1155 }
1156 }
1157
1158 if (nodeMatches)
1159 {
1160 result.addNode(current);
1161 }
1162 }
1163
1164 return result;
1165 }
1166
1167 public static void removeElementsWithAttributesNS(Element parent, String namespace_uri, String node_local_name, String[] attribute_names, String[] attribute_values)
1168 {
1169 NodeList matchingNodes = getElementsWithAttributesNS(parent, namespace_uri, node_local_name, attribute_names, attribute_values);
1170 for (int i = 0; i < matchingNodes.getLength(); i++)
1171 {
1172 parent.removeChild(matchingNodes.item(i));
1173 }
1174 }
1175
1176 // In element main, tries to find any previous occurrence of elements with xsl-template-name=templateName,
1177 // and whose named attribute (attributeName) has the same value as the same attribute in node.
1178 // If this is the case, such a previous occurrence is removed from element main, since
1179 // the new node will contain a more specific redefinition of this element.
1180 public static void removeNamedElementNS(Element parent, String namespace_uri, String node_local_name, String attribute_name, String attribute_value)
1181 {
1182 if (attribute_value.equals(""))
1183 {
1184 // it has no identifying attribute, so we can't find any matches
1185 return;
1186 }
1187
1188 Element old_elem = getNamedElementNS(parent, namespace_uri, node_local_name, attribute_name, attribute_value);
1189 if (old_elem != null)
1190 {
1191 parent.removeChild(old_elem);
1192 }
1193 }
1194
1195 public static void removeNamedElementsNS(Element parent, String namespace, String node_local_name, String attribute_name, String attribute_value)
1196 {
1197 if (attribute_value.equals(""))
1198 {
1199 // it has no identifying attribute, so we can't find any matches
1200 return;
1201 }
1202
1203 NodeList children = parent.getChildNodes();
1204 for (int i = children.getLength() - 1; i >= 0; i--)
1205 {
1206 Node child = children.item(i);
1207 if (child.getNodeType() == Node.ELEMENT_NODE && child.getNamespaceURI() != null && child.getNamespaceURI().equals(namespace) && child.getLocalName() != null && child.getLocalName().equals(node_local_name))
1208 {
1209 if (((Element) child).getAttribute(attribute_name).equals(attribute_value))
1210 parent.removeChild(child);
1211 }
1212 }
1213 }
1214
1215 /**
1216 * returns a NodeList of elements:
1217 * ancestor/node_name[@attribute_name='attribute_value']
1218 */
1219 public static NodeList getNamedElements(Element ancestor, String node_name, String attribute_name, String attribute_value)
1220 {
1221 MyNodeList node_list = new MyNodeList();
1222 NodeList children = ancestor.getElementsByTagName(node_name);
1223
1224 if (children != null && children.getLength() > 0)
1225 {
1226
1227 for (int i = 0; i < children.getLength(); i++)
1228 {
1229 Node child = children.item(i);
1230 if (child.getNodeName().equals(node_name))
1231 {
1232 if (((Element) child).getAttribute(attribute_name).equals(attribute_value))
1233 node_list.addNode(child);
1234 }
1235 }
1236 }
1237 return node_list;
1238 }
1239
1240 public static Element getLastElementByTagNameNS(Element main, String namespace, String node_name)
1241 {
1242 NodeList nodes = main.getElementsByTagNameNS(namespace, node_name);
1243 int len = nodes.getLength();
1244 if (len == 0)
1245 {
1246 return null;
1247 }
1248 return (Element) nodes.item(len - 1);
1249 }
1250
1251 public static int SORT_TYPE_STRING = 0;
1252 public static int SORT_TYPE_INT = 1;
1253 public static int SORT_TYPE_FLOAT = 2;
1254
1255 // sort type:
1256 public static Element insertIntoOrderedList(Element parent_node, String node_name, Element start_from_elem, Element new_elem, String sort_att, boolean descending)
1257 {
1258 if (new_elem == null)
1259 return null;
1260 Element cloned_elem = (Element) parent_node.getOwnerDocument().importNode(new_elem, true);
1261 if (start_from_elem == null)
1262 {
1263 parent_node.appendChild(cloned_elem);
1264 return cloned_elem;
1265 }
1266
1267 Node current_node = start_from_elem;
1268 String insert_att = cloned_elem.getAttribute(sort_att);
1269 String list_att = start_from_elem.getAttribute(sort_att);
1270 while ((!descending && list_att.compareTo(insert_att) < 0) || (descending && list_att.compareTo(insert_att) > 0))
1271 {
1272 current_node = current_node.getNextSibling();
1273 if (current_node == null)
1274 break; // end of the list
1275 if (!current_node.getNodeName().equals(node_name))
1276 {
1277 continue; // not a valid node
1278 }
1279 list_att = ((Element) current_node).getAttribute(sort_att);
1280 }
1281
1282 parent_node.insertBefore(cloned_elem, current_node);
1283 return cloned_elem;
1284 }
1285
1286 public static String getMetadataValue(Element metadata_list, String name) {
1287 Element meta = getNamedElement(metadata_list, METADATA_ELEM, NAME_ATT, name);
1288 if (meta == null) {
1289 return "";
1290 }
1291 String att_value = meta.getAttribute(VALUE_ATT);
1292 if (att_value.equals("")) {
1293 // try the text
1294 att_value = getNodeText(meta);
1295 }
1296 return att_value;
1297 }
1298
1299 // replaces < > " ' & in the original with their entities
1300 public static String xmlSafe(String original)
1301 {
1302
1303 StringBuffer filtered = new StringBuffer(original.length());
1304 char c;
1305 for (int i = 0; i < original.length(); i++)
1306 {
1307 c = original.charAt(i);
1308 if (c == '>')
1309 {
1310 filtered.append("&gt;");
1311 }
1312 else if (c == '<')
1313 {
1314 filtered.append("&lt;");
1315 }
1316 else if (c == '"')
1317 {
1318 filtered.append("&quot;");
1319 }
1320 else if (c == '&')
1321 {
1322 filtered.append("&amp;");
1323 }
1324 else if (c == '\'')
1325 {
1326 filtered.append("&apos;");
1327 }
1328 else
1329 {
1330 filtered.append(c);
1331 }
1332 }
1333 return filtered.toString();
1334 }
1335
1336 // replaces < > " ' & entities with their originals
1337 public static String unXmlSafe(String original)
1338 {
1339
1340 StringBuffer filtered = new StringBuffer(original.length());
1341 char c;
1342 for (int i = 0; i < original.length(); i++)
1343 {
1344 c = original.charAt(i);
1345 if (c == '&')
1346 {
1347 int pos = original.indexOf(";", i);
1348 String entity = original.substring(i + 1, pos);
1349 if (entity.equals("gt"))
1350 {
1351 filtered.append(">");
1352 }
1353 else if (entity.equals("lt"))
1354 {
1355 filtered.append("<");
1356 }
1357 else if (entity.equals("apos"))
1358 {
1359 filtered.append("'");
1360 }
1361 else if (entity.equals("amp"))
1362 {
1363 filtered.append("&");
1364 }
1365 else if (entity.equals("quot"))
1366 {
1367 filtered.append("\"");
1368 }
1369 else
1370 {
1371 filtered.append("&" + entity + ";");
1372 }
1373 i = pos;
1374 }
1375 else
1376 {
1377 filtered.append(c);
1378 }
1379 }
1380 return filtered.toString();
1381 }
1382
1383 public static void printXMLNode(Node e, boolean printText)
1384 {
1385 printXMLNode(e, 0, printText);
1386 }
1387
1388 public static String xmlNodeToString(Node e)
1389 {
1390 StringBuffer sb = new StringBuffer("");
1391 xmlNodeToString(sb, e, true, "\t", 0);
1392 return sb.toString();
1393 }
1394
1395 public static void xmlNodeToString(StringBuffer sb, Node e, boolean indent, String indentString, int depth)
1396 {
1397 if (e.getNodeType() == Node.TEXT_NODE)
1398 {
1399 if (e.getNodeValue() != "")
1400 {
1401 String text = e.getNodeValue();
1402 if (text != null)
1403 {
1404 text = text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("^[\\n\\r\\t\\s]*", "").replaceAll("[\\n\\r\\t\\s]*$", "");
1405 sb.append(text);
1406 }
1407 }
1408 return;
1409 }
1410
1411 if (e.getNodeType() == Node.COMMENT_NODE)
1412 {
1413 if (e.getNodeValue() != "")
1414 {
1415 sb.append("<!--" + e.getNodeValue() + "-->");
1416 }
1417 return;
1418 }
1419
1420 if (indent)
1421 {
1422 for (int i = 0; i < depth; i++)
1423 {
1424 sb.append(indentString);
1425 }
1426 }
1427
1428 sb.append('<');
1429 sb.append(e.getNodeName());
1430 NamedNodeMap attrs = e.getAttributes();
1431 if (attrs != null)
1432 {
1433 for (int i = 0; i < attrs.getLength(); i++)
1434 {
1435 Node attr = attrs.item(i);
1436 sb.append(' ');
1437 sb.append(attr.getNodeName());
1438 sb.append("=\"");
1439 sb.append(attr.getNodeValue().replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"));
1440 sb.append('"');
1441 }
1442 }
1443
1444 if (e.hasChildNodes())
1445 {
1446 boolean hasElements = false;
1447 boolean indentSwapped = false;
1448
1449 Node child = e.getFirstChild();
1450 do
1451 {
1452 if (child.getNodeType() == Node.ELEMENT_NODE)
1453 {
1454 hasElements = true;
1455 }
1456 if (child.getNodeType() == Node.TEXT_NODE && indent)
1457 {
1458 if (child.getNodeValue() != null && child.getNodeValue().trim().length() > 0)
1459 {
1460 indentSwapped = true;
1461 indent = false;
1462 }
1463 }
1464 } while ((child = child.getNextSibling()) != null);
1465
1466 sb.append(">");
1467 if (hasElements && indent)
1468 {
1469 sb.append("\n");
1470 }
1471
1472 child = e.getFirstChild();
1473 do
1474 {
1475 xmlNodeToString(sb, child, indent, indentString, depth + 1);
1476 } while ((child = child.getNextSibling()) != null);
1477
1478 if (indent)
1479 {
1480 for (int i = 0; i < depth; i++)
1481 {
1482 sb.append(indentString);
1483 }
1484 }
1485
1486 sb.append("</" + e.getNodeName() + ">");
1487
1488 if ((hasElements && indent) || indentSwapped)
1489 {
1490 sb.append("\n");
1491 }
1492 }
1493 else
1494 {
1495 sb.append("/>");
1496
1497 if (indent)
1498 {
1499 sb.append("\n");
1500 }
1501 }
1502
1503 /*
1504 boolean hasElements = false;
1505 boolean indentSwapped = false;
1506 for (int i = 0; i < children.getLength(); i++)
1507 {
1508 if (children.item(i).getNodeType() == Node.ELEMENT_NODE)
1509 {
1510 hasElements = true;
1511 }
1512 if (children.item(i).getNodeType() == Node.TEXT_NODE && indent)
1513 {
1514 if (children.item(i).getNodeValue() != null && children.item(i).getNodeValue().trim().length() > 0)
1515 {
1516 indentSwapped = true;
1517 indent = false;
1518 }
1519 }
1520 }
1521
1522 if (children == null || children.getLength() == 0)
1523 {
1524 sb.append("/>");
1525
1526 if (indent)
1527 {
1528 sb.append("\n");
1529 }
1530 }
1531 else
1532 {
1533 sb.append(">");
1534 if (hasElements && indent)
1535 {
1536 sb.append("\n");
1537 }
1538
1539 int len = children.getLength();
1540 for (int i = 0; i < len; i++)
1541 {
1542 xmlNodeToString(sb, children.item(i), indent, indentString, depth + 1);
1543 }
1544
1545 if (indent)
1546 {
1547 for (int i = 0; i < depth; i++)
1548 {
1549 sb.append(indentString);
1550 }
1551 }
1552
1553 sb.append("</" + e.getNodeName() + ">");
1554
1555 if ((hasElements && indent) || indentSwapped)
1556 {
1557 sb.append("\n");
1558 }
1559 }
1560 */
1561 }
1562
1563 public static void printXMLNode(Node e, int depth, boolean printText)
1564 { //recursive method call using DOM API...
1565
1566 if (e == null)
1567 {
1568 return;
1569 }
1570
1571 for (int i = 0; i < depth; i++)
1572 System.out.print(' ');
1573
1574 if (e.getNodeType() == Node.TEXT_NODE)
1575 {
1576 if (printText)
1577 {
1578 System.out.println(e.getNodeValue());
1579 }
1580 else
1581 {
1582 System.out.println("text");
1583 }
1584 return;
1585 }
1586
1587 System.out.print('<');
1588 System.out.print(e.getNodeName());
1589 NamedNodeMap attrs = e.getAttributes();
1590
1591 if (attrs != null)
1592 {
1593 for (int i = 0; i < attrs.getLength(); i++)
1594 {
1595 Node attr = attrs.item(i);
1596 System.out.print(' ');
1597 System.out.print(attr.getNodeName());
1598 System.out.print("=\"");
1599 System.out.print(attr.getNodeValue());
1600 System.out.print('"');
1601 }
1602 }
1603
1604 NodeList children = e.getChildNodes();
1605
1606 if (children == null || children.getLength() == 0)
1607 System.out.println("/>");
1608 else
1609 {
1610
1611 System.out.println('>');
1612
1613 int len = children.getLength();
1614 for (int i = 0; i < len; i++)
1615 {
1616 printXMLNode(children.item(i), depth + 1, printText);
1617 }
1618
1619 for (int i = 0; i < depth; i++)
1620 System.out.print(' ');
1621
1622 System.out.println("</" + e.getNodeName() + ">");
1623 }
1624 }
1625
1626 private static void elementToLogAsString(String prefix, Element e, boolean indent, boolean debugEncoding)
1627 {
1628 String str = prefix + "\n" + elementToString(e, indent, debugEncoding);
1629 System.err.println(str);
1630 logger.info(str);
1631 }
1632
1633 // hex/unicode codepoint used only for those chars that are beyond printable/basic ASCII
1634 public static void elementToLogAsUnicodeDebugString(String prefix, Element e, boolean indent)
1635 {
1636 elementToLogAsString(prefix, e, indent, true);
1637 }
1638
1639 public static void elementToLogAsString(String prefix, Element e, boolean indent)
1640 {
1641 elementToLogAsString(prefix, e, indent, false);
1642 }
1643
1644 // pass in debugEncoding=true to investigate encoding issues. This function will then return non-basic ASCII characters in hex
1645 private static String elementToString(Element e, boolean indent, boolean debugEncoding)
1646 {
1647 String str = "";
1648 try
1649 {
1650 TransformerFactory tf = TransformerFactory.newInstance();
1651 Transformer trans = tf.newTransformer();
1652 StringWriter sw = new StringWriter();
1653 if (indent)
1654 {
1655 trans.setOutputProperty(OutputKeys.INDENT, "yes");
1656 }
1657 else
1658 {
1659 trans.setOutputProperty(OutputKeys.INDENT, "no");
1660 }
1661 trans.transform(new DOMSource(e), new StreamResult(sw));
1662 str += sw.toString();
1663
1664 // if debugging encoding issues, then encode unicode code pts as hex for all but non-alphanumeric and space/tab/newline chars
1665 if(debugEncoding) str = Misc.debugUnicodeString(str);
1666 }
1667 catch (Exception ex)
1668 {
1669 str += "Exception: couldn't write " + e + " to log";
1670 }
1671 finally
1672 {
1673 return str;
1674 }
1675 }
1676
1677 public static String elementToString(Element e, boolean indent)
1678 {
1679 return elementToString(e, indent, false);
1680 }
1681
1682 // hex/unicode codepoint used only for those chars that are beyond printable/basic ASCII
1683 public static String elementToUnicodeDebugString(Element e, boolean indent)
1684 {
1685 return elementToString(e, indent, true);
1686 }
1687
1688 public static ArrayList<String> getGroupsFromSecurityResponse(Element securityResponse)
1689 {
1690 ArrayList<String> groups = new ArrayList<String>();
1691
1692 Element groupList = (Element) getChildByTagName(securityResponse, GROUP_ELEM + LIST_MODIFIER);
1693 if (groupList == null)
1694 {
1695 return groups;
1696 }
1697
1698 NodeList groupElems = getChildrenByTagName(groupList, GROUP_ELEM);
1699
1700 for (int i = 0; i < groupElems.getLength(); i++)
1701 {
1702 Element groupElem = (Element) groupElems.item(i);
1703 // an empty attribute will return "". some code depends on having "" for groups, so leave it in for now.
1704 groups.add(groupElem.getAttribute(NAME_ATT));
1705 }
1706
1707 return groups;
1708 }
1709
1710}
Note: See TracBrowser for help on using the repository browser.