1 /*
2 * Copyright 1999-2006 University of Chicago
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /**
18 * @defgroup xsd_anyAttributes C Binding for the xsd:anyAttribute schema type
19 * @ingroup xsd_types
20 *
21 * The xsd_anyAttribute datatype represents a collection of attributes for
22 * an element.
23 */
24
25 #include "globus_soap_message.h"
26 #include "globus_i_soap_message.h"
27 #include "xsd_anyAttributes.h"
28
29 typedef struct
30 {
31 xsd_QName qname;
32 globus_xsd_type_info_t any_info;
33 void * value;
34 } xsd_l_anyAttributes_element_t;
35
36 /**
37 * Return the number of attributes in an anyAttribute collection
38 * @ingroup xsd_anyAttributes
39 *
40 * @param attrs
41 * The anyAttribute set to count.
42 *
43 * @return
44 * Returns the number of attributes in the attribute collection.
45 */
46 int
47 xsd_anyAttributes_size(
48 xsd_anyAttributes_t attrs)
49 2638793 {
50 2638793 if (attrs == NULL)
51 {
52 0 return 0;
53 }
54 2638793 return globus_hashtable_size(&attrs);
55 }
56
57 /**
58 * Look up the content of an attribute in an anyAttributes collection
59 * @ingroup xsd_anyAttributes
60 *
61 * @param attrs
62 * The anyAttribute collection to search.
63 * @param name
64 * QName of the attribute to return
65 * @param any_info
66 * Pointer to be set to the type information for this any value.
67 * @param value
68 * Pointer to the set to the current value of the attribute. Caller must
69 * free this value by calling the @a destroy function in the @a any_info
70 * pointer.
71 *
72 * @return
73 * Returns the unparsed content of the named attribute if it is present;
74 * NULL otherwise.
75 */
76 globus_result_t
77 xsd_anyAttributes_lookup(
78 xsd_anyAttributes_t attrs,
79 const xsd_QName * name,
80 globus_xsd_type_info_t * any_info,
81 void ** value)
82 15 {
83 xsd_l_anyAttributes_element_t * element;
84 globus_result_t result;
85
86 15 if (attrs == NULL || name == NULL || any_info == NULL || value == NULL)
87 {
88 0 return GlobusSoapMessageErrorNullParam;
89 }
90 15 element = (xsd_l_anyAttributes_element_t *)
91 globus_hashtable_lookup(&attrs, (void *) name);
92 15 if (!element)
93 {
94 3 return GlobusSoapMessageErrorAttributeNotFound(GLOBUS_TRUE, name);
95 }
96
97 12 *any_info = element->any_info;
98
99 12 result = (*any_info)->copy(value, element->value);
100
101 12 return result;
102 }
103 /* xsd_anyAttributes_lookup() */
104
105 /**
106 * Insert an attribute into an anyAttributes collection
107 * @ingroup xsd_anyAttributes
108 *
109 * @param attrs
110 * The anyAttribute collection to insert into.
111 * @param name
112 * Qualified name of the attribute to insert.
113 * @param any_info
114 * Type info containing pointers to serialization and deserialization
115 * functions.
116 * @param value
117 * Content of the attribute.
118 *
119 * @return
120 * Returns GLOBUS_SUCCESS if the attribute is inserted successfully;
121 * GLOBUS_FAILURE otherwise.
122 */
123 globus_result_t
124 xsd_anyAttributes_insert(
125 xsd_anyAttributes_t attrs,
126 const xsd_QName * name,
127 globus_xsd_type_info_t any_info,
128 void * value)
129 0 {
130 xsd_l_anyAttributes_element_t * element;
131 int rc;
132 globus_result_t result;
133
134 0 if (attrs == NULL || name == NULL || any_info == NULL || value == NULL)
135 {
136 0 return GlobusSoapMessageErrorNullParam;
137 }
138 0 element = malloc(sizeof(xsd_l_anyAttributes_element_t));
139 0 if (!element)
140 {
141 0 result = GlobusSoapMessageErrorOutOfMemory;
142
143 0 goto out;
144 }
145 0 element->any_info = any_info;
146
147 0 result = xsd_QName_copy_contents(&element->qname, name);
148 0 if (result != GLOBUS_SUCCESS)
149 {
150 0 goto free_element_out;
151 }
152
153 0 result = any_info->copy(&element->value, value);
154 0 if (result != GLOBUS_SUCCESS)
155 {
156 0 goto free_element_name_out;
157 }
158
159 0 rc = globus_hashtable_insert(&attrs, &element->qname, element);
160
161 0 if (rc != GLOBUS_SUCCESS)
162 {
163 0 any_info->destroy(element->value);
164 0 free_element_name_out:
165 0 xsd_QName_destroy_contents(&element->qname);
166 0 free_element_out:
167 0 free(element);
168 }
169 0 out:
170 0 return result;
171 }
172 /* xsd_anyAttributes_insert() */
173
174 static
175 void
176 xsd_anyAttributes_element_delete(
177 void * value)
178 3898 {
179 xsd_l_anyAttributes_element_t * element;
180
181 3898 element = (xsd_l_anyAttributes_element_t *) value;
182
183 3898 if (element)
184 {
185 3898 xsd_QName_destroy_contents(&element->qname);
186 3898 element->any_info->destroy(element->value);
187 3898 globus_free(element);
188 }
189 3898 }
190 /* xsd_anyAttributes_element_delete() */
191
192 /**
193 * Remove an attribute from an anyAttribute collection
194 * @ingroup xsd_anyAttributes
195 *
196 * @param attrs
197 * The anyAttribute collection to remove from.
198 * @param name
199 * Qualified name of the attribute to remove.
200 *
201 * @return
202 * Returns GLOBUS_SUCCESS if the element exists and was removed;
203 * an error otherwise
204 */
205 globus_result_t
206 xsd_anyAttributes_remove(
207 xsd_anyAttributes_t attrs,
208 const xsd_QName * name)
209 0 {
210 void * element;
211
212 0 if (attrs == NULL || name == NULL)
213 {
214 0 return GlobusSoapMessageErrorNullParam;
215 }
216 0 element = globus_hashtable_remove(&attrs, (void *) name);
217 0 if(!element)
218 {
219 0 return GlobusSoapMessageErrorAttributeNotFound(GLOBUS_TRUE, name);
220 }
221
222 0 xsd_anyAttributes_element_delete(element);
223 0 return GLOBUS_SUCCESS;
224 }
225 /* xsd_anyAttributes_remove() */
226
227 /**
228 * Destroy an anyAttributes atribute set
229 * @ingroup xsd_anyAttributes
230 *
231 * @param attrs
232 * The anyAttribute collection to destroy.
233 */
234 void
235 xsd_anyAttributes_destroy(
236 xsd_anyAttributes_t attrs)
237 5543680 {
238 5543680 if(attrs)
239 {
240 5486321 globus_hashtable_destroy_all(&attrs, xsd_anyAttributes_element_delete);
241 }
242 5543680 }
243 /* xsd_anyAttributes_destroy() */
244
245 /**
246 * Initialize an anyAttributes collection
247 * @ingroup xsd_anyAttributes
248 *
249 * @param attrs
250 * The anyAttribute collection to initialize.
251 *
252 * @retval GLOBUS_SUCCESS
253 * The anyAttribute collection initialized successfully.
254 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
255 * The @a attrs paramter is NULL.
256 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_INIT_FAILED
257 * Error initializing the anyAttribute.
258 */
259 globus_result_t
260 xsd_anyAttributes_init(
261 xsd_anyAttributes_t * attrs)
262 2760012 {
263 2760012 globus_result_t result = GLOBUS_SUCCESS;
264 int rc;
265
266 2760012 if (attrs == NULL)
267 {
268 0 result = GlobusSoapMessageErrorNullParam;
269
270 0 goto exit;
271 }
272 2760012 rc = globus_hashtable_init(attrs, 7, xsd_QName_hash, xsd_QName_keyeq);
273 2760012 if (rc != GLOBUS_SUCCESS)
274 {
275 0 result = GlobusSoapMessageErrorInitFailed("Initializing attrs");
276 }
277 2760012 exit:
278 2760012 return result;
279 }
280 /* xsd_anyAttributes_init() */
281
282 static
283 int
284 xsd_QName_compare(
285 void * a,
286 void * b,
287 void * args)
288 10 {
289 int res;
290 xsd_QName * qa;
291 xsd_QName * qb;
292
293
294 10 if(!a)
295 {
296 0 return 1;
297 }
298
299 10 if(!b)
300 {
301 0 return 0;
302 }
303
304 10 qa = (xsd_QName *)a;
305 10 qb = (xsd_QName *)b;
306
307 10 if (((!qa->Namespace) || (*qa->Namespace == '\0')) &&
308 ((!qb->Namespace) || (*qb->Namespace == '\0')))
309 {
310 10 globus_assert_string(qa->local && qb->local,
311 "QName structs must have valid local values");
312
313 10 if(strcmp(qa->local, qb->local) <= 0)
314 {
315 10 return 1;
316 }
317
318 0 return 0;
319 }
320
321 0 if(qa->Namespace && qb->Namespace)
322 {
323 0 res = strcmp(qa->Namespace, qb->Namespace);
324 0 if(res == 0)
325 {
326 0 if(strcmp(qa->local, qb->local) <= 0)
327 {
328 0 return 1;
329 }
330
331 0 return 0;
332 }
333
334 0 if(res < 0)
335 {
336 0 return 1;
337 }
338
339 0 return 0;
340 }
341
342 0 if((!qa->Namespace) && qb->Namespace)
343 {
344 0 return 0;
345 }
346
347 0 if((!qb->Namespace) && qa->Namespace)
348 {
349 0 return 0;
350 }
351
352 0 return 1;
353 }
354
355 /**
356 * Return a sorted list of attributes in an xsd_anyAttribute collection
357 * @ingroup xsd_anyAttributes
358 * Attributes are ordered by their namespace-URI, if present, and then
359 * by their local name.
360 *
361 * @param attrs
362 * The anyAttribute collection to query.
363 *
364 * @return
365 * Returns a sorted list of attribute QNames in the anyAttributes
366 * collection. If an error occurs, NULL will be returned. The caller
367 * must free this list by calling globus_list_frei();
368 */
369 globus_list_t *
370 xsd_anyAttributes_lex_sort(
371 xsd_anyAttributes_t attrs)
372 1935 {
373 xsd_l_anyAttributes_element_t * element;
374 int rc;
375 1935 globus_list_t * keys = NULL;
376
377 1935 if (attrs == NULL)
378 {
379 0 goto exit;
380 }
381 1935 element = (xsd_l_anyAttributes_element_t *) globus_hashtable_first(&attrs);
382 3880 while(element)
383 {
384 10 rc = globus_list_insert(&keys, &element->qname);
385
386 10 if (rc != 0)
387 {
388 0 globus_list_free(keys);
389 0 keys = NULL;
390
391 0 goto exit;
392 }
393 10 element = (xsd_l_anyAttributes_element_t *)
394 globus_hashtable_next(&attrs);
395 }
396
397 1935 keys = globus_list_sort(keys, xsd_QName_compare, NULL);
398
399 1935 exit:
400 1935 return keys;
401 }
402 /* xsd_anyAttributes_lex_sort() */
403
404 /**
405 * Create namespace prefix mappings for all namespaces used by the attributs in an anyAttributes collection
406 * @ingroup xsd_anyAttributes
407 * Creates prefix-to namespace mappings to be used when serializing a collection
408 * of anyAttributes. This should be called before the element is serialized to
409 * ensure that prefixes are defined for namespaces needed by the element. The
410 * prefix is not actually serialized by this function. Namespace set callouts
411 * will be called if this is the first time a namespace has been set for a
412 * particular element.
413 *
414 * @param message
415 * SOAP message to define the namespaces on.
416 * @param element_qname
417 * Element which will be serialized. This is used by the namespace set
418 * callouts.
419 * @param attrs
420 * Collection of anyAttributes to serialize the namespaces of.
421 * @param options
422 * Pointer to the serialization options to be used for this element. The
423 * options which are handled by this function are
424 * - GLOBUS_XSD_ELEMENT_ATTR_HAS_NULL_NAMESPACE
425 * - GLOBUS_XSD_ELEMENT_SET_DEFAULT_NS
426 * The GLOBUS_XSD_ELEMENT_ATTR_HAS_NULL_NAMESPACE flag will be cleared
427 * by this function.
428 *
429 * @retval GLOBUS_SUCCESS
430 * Namespace prefixes successfully defined for the attributes.
431 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
432 * One of @a handle, @a element_qname, or @a options is NULL.
433 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_SERIALIZE_FAILED
434 * Unable to define namespace prefix mapping.
435 */
436 globus_result_t
437 xsd_anyAttributes_namespace_set(
438 globus_soap_message_handle_t message,
439 const xsd_QName * element_qname,
440 xsd_anyAttributes_t attrs,
441 globus_xsd_element_options_t * options)
442 129603 {
443 129603 globus_result_t result = GLOBUS_SUCCESS;
444 xsd_l_anyAttributes_element_t * element;
445
446 129603 if(attrs)
447 {
448 1935 element = globus_hashtable_first(&attrs);
449 3880 while(element)
450 {
451 10 result = globus_soap_message_attribute_ns_set(
452 message,
453 element_qname,
454 element->qname.Namespace,
455 options);
456 10 if(result != GLOBUS_SUCCESS)
457 {
458 0 xsd_QName * eqn = &element->qname;
459 0 result = GlobusSoapMessageErrorSerializeFailed(
460 result, NULL, eqn);
461 0 goto exit;
462 }
463
464 10 if (element->any_info == &xsd_QName_info)
465 {
466 0 result = globus_soap_message_attribute_ns_set(
467 message,
468 element_qname,
469 ((xsd_QName *)(element->value))->Namespace,
470 options);
471 0 if(result != GLOBUS_SUCCESS)
472 {
473 0 xsd_QName * eqn = &element->qname;
474 0 result = GlobusSoapMessageErrorSerializeFailed(
475 result, NULL, eqn);
476 0 goto exit;
477 }
478 }
479
480 10 element = globus_hashtable_next(&attrs);
481 }
482 }
483
484 129603 exit:
485
486 129603 return result;
487 }
488 /* xsd_anyAttributes_namespace_set() */
489
490 /**
491 * Serialize XML namespaces definitions for an anyAttributes collection
492 * @ingroup xsd_anyAttributes
493 * Serializes the prefixes for the namespaces needed by the anyAttributes
494 * collection @a attrs for the named element. If this is the first time this
495 * has been called for a particular namespace in this subtree, the namespace
496 * prefix will be serialized; otherwise, a reference count for the namespace
497 * will be increased. The namespace add callouts will be called if this is the
498 * first time a namespace is serialized for a particular element.
499 *
500 * @param message
501 * SOAP message handle to serialize the namespaces on
502 * @param element_qname
503 * Name of the element which is being serialized.
504 * @param attrs
505 * The xsd_anyAttributes collection being serialized.
506 * @param options
507 * Pointer to the serialization options to be used for this element. The
508 * options which are handled by this function are
509 * - GLOBUS_XSD_ELEMENT_SET_DEFAULT_NS
510 * Both of these will be cleared by this function.
511 *
512 * @retval GLOBUS_SUCCESS
513 * Namespace prefixes have been serialized for @a Namespace if necessary.
514 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
515 * One of @a handle, @a element_qname, or @a options is NULL.
516 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_SERIALIZE_FAILED
517 * Unable to serialize namespace prefix mappings.
518 */
519 globus_result_t
520 xsd_anyAttributes_namespace_add(
521 globus_soap_message_handle_t message,
522 const xsd_QName * element_qname,
523 xsd_anyAttributes_t attrs,
524 globus_xsd_element_options_t * options)
525 129603 {
526 129603 globus_result_t result = GLOBUS_SUCCESS;
527 xsd_l_anyAttributes_element_t * element;
528 129603 if(attrs)
529 {
530 1935 element = globus_hashtable_first(&attrs);
531 3880 while(element)
532 {
533 10 result = globus_soap_message_attribute_ns_add(
534 message,
535 element_qname,
536 element->qname.Namespace,
537 options);
538 10 if(result != GLOBUS_SUCCESS)
539 {
540 0 xsd_QName * eqn = &element->qname;
541 0 result = GlobusSoapMessageErrorSerializeFailed(
542 result, NULL, eqn);
543 0 goto exit;
544 }
545 10 if (element->any_info == &xsd_QName_info)
546 {
547 0 result = globus_soap_message_attribute_ns_add(
548 message,
549 element_qname,
550 ((xsd_QName *)(element->value))->Namespace,
551 options);
552 0 if(result != GLOBUS_SUCCESS)
553 {
554 0 xsd_QName * eqn = &element->qname;
555 0 result = GlobusSoapMessageErrorSerializeFailed(
556 result, NULL, eqn);
557 0 goto exit;
558 }
559 }
560
561 10 element = globus_hashtable_next(&attrs);
562 }
563 }
564
565 129603 exit:
566
567 129603 return result;
568 }
569 /* xsd_anyAttributes_namespace_add() */
570
571
572 /**
573 * Decrement the reference count for the XML namespace prefixes used referenced by an anyAttributes set
574 * @ingroup xsd_anyAttributes
575 *
576 * @param message
577 * SOAP message handle to decrement the prefix reference count on.
578 * @param attrs
579 * Collection of anyAttributes whose namespaces should have their reference
580 * counts decremented.
581 * @param options
582 * IGNORED.
583 */
584 globus_result_t
585 xsd_anyAttributes_namespace_remove(
586 globus_soap_message_handle_t message,
587 xsd_anyAttributes_t attrs,
588 globus_xsd_element_options_t * options)
589 129603 {
590 129603 globus_result_t result = GLOBUS_SUCCESS;
591 xsd_l_anyAttributes_element_t * element;
592 129603 if(attrs)
593 {
594 1935 element = globus_hashtable_first(&attrs);
595 3880 while(element)
596 {
597 10 globus_soap_message_attribute_ns_remove(
598 message,
599 element->qname.Namespace,
600 options);
601 10 if(result != GLOBUS_SUCCESS)
602 {
603 0 xsd_QName * eqn = &element->qname;
604 0 result = GlobusSoapMessageErrorSerializeFailed(
605 result, NULL, eqn);
606 0 goto exit;
607 }
608 10 if (element->any_info == &xsd_QName_info)
609 {
610 0 globus_soap_message_attribute_ns_remove(
611 message,
612 ((xsd_QName *)(element->value))->Namespace,
613 options);
614 }
615
616 10 element = globus_hashtable_next(&attrs);
617 }
618 }
619
620 129603 exit:
621
622 129603 return result;
623 }
624 /* xsd_anyAttributes_namespace_remove() */
625
626 /**
627 * Serialize an anyAttributes collection
628 * @ingroup xsd_anyAttributes
629 * Serialize all of the attributes in an xsd_anyAttributes collection.
630 * The attributes are serialized in lexicographic order based on their
631 * namespaces (the primary key) and local attribute names (secondary key).
632 *
633 * @param message
634 * SOAP messages handle to serialize the attributes on.
635 * @param attrs
636 * Collection of anyAttributes to serialize.
637 *
638 * @retval GLOBUS_SUCCESS
639 * The anyAttributes collection was serialized successfully.
640 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
641 * One of @a message or @a attrs is NULL.
642 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_SERIALIZE_ANY_ATTRS_FAILED
643 * Error occurred serializing an attribute.
644 */
645 globus_result_t
646 xsd_anyAttributes_serialize(
647 globus_soap_message_handle_t message,
648 xsd_anyAttributes_t attrs)
649 1829 {
650 globus_list_t * lex_sorted_keys_save;
651 globus_list_t * lex_sorted_keys;
652 1829 globus_result_t result = GLOBUS_SUCCESS;
653 xsd_l_anyAttributes_element_t * element;
654 xsd_QName * key;
655
656 1829 if (message == NULL || attrs == NULL)
657 {
658 0 result = GlobusSoapMessageErrorNullParam;
659
660 0 goto exit;
661 }
662 1829 lex_sorted_keys = xsd_anyAttributes_lex_sort(attrs);
663 1829 if (lex_sorted_keys == NULL)
664 {
665 1829 goto exit;
666 }
667 0 lex_sorted_keys_save = lex_sorted_keys;
668
669 0 key = globus_list_first(lex_sorted_keys);
670 0 while(key)
671 {
672 0 lex_sorted_keys = globus_list_rest(lex_sorted_keys);
673 0 element = globus_hashtable_lookup(&attrs, key);
674 0 if(!element)
675 {
676 0 result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
677 result, "Null element in attributes list");
678 0 goto free_lex_sorted_keys_exit;
679 }
680 0 result = globus_soap_message_serialize_attribute(
681 message,
682 &element->qname);
683
684 0 if(result != GLOBUS_SUCCESS)
685 {
686 0 result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
687 result, "Failed to serialize any attribute");
688 0 goto free_lex_sorted_keys_exit;
689 }
690 0 result = element->any_info->serialize(
691 &element->qname,
692 element->value,
693 message,
694 GLOBUS_XSD_ELEMENT_CONTENTS_ONLY);
695 0 if(result != GLOBUS_SUCCESS)
696 {
697 0 result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
698 result, "Failed to serialize any attribute");
699 0 goto free_lex_sorted_keys_exit;
700 }
701
702 0 key = globus_list_first(lex_sorted_keys);
703 }
704
705 0 free_lex_sorted_keys_exit:
706 0 globus_list_free(lex_sorted_keys_save);
707 1829 exit:
708 1829 return result;
709 }
710 /* xsd_anyAttributes_serialize() */
711
712 /**
713 * Serialize attributes from an xsd_anyAttributes collection which occur before comparable_value
714 * @ingroup xsd_anyAttributes
715 * Serializes all attributes in the @a lex_sorted_keys list which occur before
716 * the @a comparable value in the lexicographic ordering defined by XML
717 * canonicalization.
718 *
719 * @param message
720 * SOAP messages handle to serialize the attributes on.
721 * @param lex_sorted_keys
722 * Sorted list of attribute names from the anyAttributes collection to
723 * serialize. This list is modified by this function.
724 * @param attrs
725 * Collection of anyAttributes to serialize.
726 * @param comparable_value
727 * QName to compare the attributes against. This function stops serializing
728 * from @a attrs once the head of @a lex_sorted_keys has a higher ordering
729 * value than this value.
730 *
731 * @retval GLOBUS_SUCCESS
732 * The anyAttributes collection was serialized successfully.
733 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
734 * One of @a message, @a lex_sorted_keys, @a attrs, or @a comparable_value
735 * is NULL.
736 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_SERIALIZE_ANY_ATTRS_FAILED
737 * Error occurred serializing an attribute.
738 */
739 globus_result_t
740 xsd_anyAttributes_serialize_lex_before(
741 globus_soap_message_handle_t message,
742 globus_list_t ** lex_sorted_keys,
743 xsd_anyAttributes_t attrs,
744 xsd_QName * comparable_value)
745 10 {
746 10 globus_result_t result = GLOBUS_SUCCESS;
747 xsd_l_anyAttributes_element_t * element;
748 xsd_QName * key;
749
750 10 if (message == NULL || lex_sorted_keys == NULL || attrs == NULL)
751 {
752 0 result = GlobusSoapMessageErrorNullParam;
753
754 0 goto exit;
755 }
756 30 while(*lex_sorted_keys)
757 {
758 10 key = globus_list_first(*lex_sorted_keys);
759
760 10 if(comparable_value &&
761 !xsd_QName_compare(comparable_value, key, NULL))
762 {
763 0 break;
764 }
765
766 10 element = globus_hashtable_lookup(&attrs, key);
767 10 if(!element)
768 {
769 0 result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
770 result, "Null element in attributes list");
771 0 goto exit;
772 }
773
774 10 if (xsd_QName_keyeq(comparable_value, &element->qname) != 0)
775 {
776 0 result = globus_soap_message_serialize_attribute(
777 message,
778 &element->qname);
779
780 0 if(result != GLOBUS_SUCCESS)
781 {
782 0 result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
783 result, "Failed to serialize any attribute");
784 0 goto exit;
785 }
786 0 result = element->any_info->serialize(
787 &element->qname,
788 element->value,
789 message,
790 GLOBUS_XSD_ELEMENT_CONTENTS_ONLY);
791 0 if(result != GLOBUS_SUCCESS)
792 {
793 0 result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
794 result, "Failed to serialize any attribute");
795 0 goto exit;
796 }
797 }
798
799 10 *lex_sorted_keys = globus_list_rest(*lex_sorted_keys);
800 }
801
802 10 exit:
803
804 10 return result;
805 }
806 /* xsd_anyAttributes_serialize_lex_before() */
807
808 static
809 void
810 xsd_anyAttributes_QName_copy_callback(
811 void ** dest_key,
812 void ** dest_datum,
813 void * src_key,
814 void * src_datum)
815 1604 {
816 xsd_l_anyAttributes_element_t * dest_element;
817 xsd_l_anyAttributes_element_t * src_element;
818 globus_result_t result;
819
820 1604 src_element = src_datum;
821
822 1604 dest_element = malloc(sizeof(xsd_l_anyAttributes_element_t));
823 1604 if (!dest_element)
824 {
825 0 goto out;
826 }
827
828 1604 result = xsd_QName_copy_contents(
829 &dest_element->qname, (const xsd_QName *) src_key);
830 1604 if (result != GLOBUS_SUCCESS)
831 {
832 0 goto free_dest_element_out;
833 }
834 1604 dest_element->any_info = src_element->any_info;
835
836 1604 result = dest_element->any_info->copy(
837 &dest_element->value, src_element->value);
838 1604 if (result != GLOBUS_SUCCESS)
839 {
840 0 goto free_dest_element_name_out;
841 }
842
843 1604 if (result != GLOBUS_SUCCESS)
844 {
845 0 free_dest_element_name_out:
846 0 xsd_QName_destroy_contents(&dest_element->qname);
847 0 free_dest_element_out:
848 0 free(dest_element);
849 0 dest_element = NULL;
850 }
851 1604 out:
852 1604 *dest_datum = dest_element;
853 1604 *dest_key = dest_element ? &dest_element->qname : NULL;
854 1604 }
855
856 /**
857 * Copy an xsd_anyAttributes collection
858 * @ingroup xsd_anyAttributes
859 * Copies all attributes from the @a src_attrs collection to @a dest_attrs.
860 * The caller is responsible for destroying @a dest_attrs.
861 *
862 * @param dest_attrs
863 * Pointer to an xsd_anyAttributes_t which will be set to contain a
864 * copy of the attributes in @a src_attrs.
865 * @param src_attrs
866 * Attribute set to copy.
867 *
868 * @retval GLOBUS_SUCCESS
869 * Attributes copied successfully.
870 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
871 * One of @a dest_attrs or @a src_attrs is NULL.
872 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
873 * Insufficient memory to copy the attributes.
874 */
875 globus_result_t
876 xsd_anyAttributes_copy(
877 xsd_anyAttributes_t * dest_attrs,
878 const xsd_anyAttributes_t src_attrs)
879 2729223 {
880 2729223 globus_result_t result = GLOBUS_SUCCESS;
881
882 2729223 if (dest_attrs == NULL || src_attrs == NULL)
883 {
884 0 result = GlobusSoapMessageErrorNullParam;
885 0 goto exit;
886 }
887
888 2729223 result = globus_hashtable_copy(
889 dest_attrs,
890 (xsd_anyAttributes_t *) &src_attrs,
891 xsd_anyAttributes_QName_copy_callback);
892 2729223 if (result != GLOBUS_SUCCESS)
893 {
894 0 result = GlobusSoapMessageErrorOutOfMemory;
895 0 goto exit;
896 }
897
898 2729223 exit:
899 2729223 return result;
900 }
901 /* xsd_anyAttributes_copy() */
902
903 /**
904 * Deserialize the attributes of an element into an anyAttributes collection
905 * @ingroup xsd_anyAttributes
906 *
907 * @param message
908 * SOAP message handle to deserialize attributes from.
909 * @param attrs
910 * Attribute collection to populate with the attributes of the element
911 * currently being deserialized.
912 * @param element_qname
913 * QName containing restrictions on the namespaces allowed for this
914 * attribute set. The namespace portion of the QName may be one of the
915 * following forms:
916 * - \#\#any
917 * - \#\#local
918 * - \#\#other{xml-namespace-string}
919 * If it is \#\#any, any namespace-qualified attribute is allowed. If it
920 * is \#\#local, then only non-namespace-qualified attributes are allowed.
921 * If it is \#\#other{xml-namespace-string} attribute-qualified namespaces
922 * that are not in the @a xml-namespace-string namespace area allowed.
923 *
924 *
925 * @retval GLOBUS_SUCCESS
926 * Attributes deserialized successfully.
927 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
928 * One of @a message or @a attrs is NULL.
929 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_DESERIALIZE_ANYATTRS_FAILED
930 * Unable to deserialize the attributes.
931 */
932 globus_result_t
933 xsd_anyAttributes_deserialize(
934 globus_soap_message_handle_t message,
935 xsd_anyAttributes_t attrs,
936 const xsd_QName * element_qname)
937 2760012 {
938 2760012 globus_result_t result = GLOBUS_SUCCESS;
939 2760012 int res = 0;
940
941 2760012 if (message == NULL || attrs == NULL)
942 {
943 0 result = GlobusSoapMessageErrorNullParam;
944 0 goto exit;
945 }
946 2760012 res = xmlTextReaderMoveToFirstAttribute(message->reader);
947 2760012 if(res < 0)
948 {
949 0 result = GlobusSoapMessageErrorDeserializeAnyAttrsFailed(
950 message->result, NULL);
951
952 0 goto exit;
953 }
954
955 14642273 while(res)
956 {
957 xmlNodePtr attrNode;
958 xsd_l_anyAttributes_element_t * element;
959
960 9122249 attrNode = xmlTextReaderCurrentNode(message->reader);
961 9122249 if(attrNode->type == XML_ATTRIBUTE_NODE)
962 {
963 const char * ns =
964 2136336 (const char *) xmlTextReaderConstNamespaceUri(message->reader);
965
966 2136336 if (ns == NULL)
967 {
968 /* No namespace present: only valid if ##any or ##local is
969 * allowed
970 */
971 2320 if (element_qname->Namespace == NULL ||
972 element_qname->Namespace[0] == 0 ||
973 strstr(element_qname->Namespace, "##any") ||
974 strstr(element_qname->Namespace, "##local"))
975 {
976 /* OK */
977 }
978 else
979 {
980 /* Skip */
981 0 goto next;
982 }
983 }
984 2134016 else if (strcmp(ns, XSI_NS) == 0)
985 {
986 /* skip xsi:type and xsi:nil */
987 2133611 goto next;
988 }
989 405 else if (element_qname->Namespace &&
990 strncmp(element_qname->Namespace, "##other{",8) == 0)
991 {
992 0 if (strncmp(element_qname->Namespace+8,
993 ns,
994 strlen(element_qname->Namespace+8)-1) != 0)
995 {
996 /* OK */
997 }
998 else
999 {
1000 /* skip */
1001 0 goto next;
1002 }
1003 }
1004 405 else if ((!element_qname->Namespace) ||
1005 element_qname->Namespace[0] == 0 ||
1006 strstr(element_qname->Namespace, "##any"))
1007 {
1008 /* OK */
1009 }
1010 0 else if (strstr(element_qname->Namespace, ns))
1011 {
1012 /* OK */
1013 }
1014 else
1015 {
1016 0 goto next;
1017 }
1018
1019 2725 element = malloc(sizeof(xsd_l_anyAttributes_element_t));
1020
1021 2725 if (element == NULL)
1022 {
1023 0 result = GlobusSoapMessageErrorOutOfMemory;
1024
1025 0 goto exit;
1026 }
1027 2725 element->qname.local = (char *)
1028 xmlTextReaderLocalName(message->reader);
1029 2725 if (element->qname.local == NULL)
1030 {
1031 0 result = GlobusSoapMessageErrorOutOfMemory;
1032
1033 0 goto exit;
1034 }
1035 2725 element->qname.Namespace = (char *)
1036 xmlTextReaderNamespaceUri(message->reader);
1037 2725 if (element->qname.Namespace == NULL && ns != NULL)
1038 {
1039 0 result = GlobusSoapMessageErrorOutOfMemory;
1040
1041 0 goto exit;
1042 }
1043
1044 2725 result = globus_xsd_type_registry_get_attribute(
1045 GLOBUS_GLOBAL_TYPE_REGISTRY,
1046 &element->qname,
1047 &element->any_info);
1048
1049 5444 if (result != GLOBUS_SUCCESS || element->any_info == NULL)
1050 {
1051 globus_xml_buffer * value;
1052 2719 element->any_info = &globus_xml_buffer_info;
1053
1054 2719 element->value = value = malloc(sizeof(globus_xml_buffer));
1055
1056 2719 result = xsd_string_deserialize_attribute(
1057 &element->qname, &value->buffer, message, 0);
1058 2719 if (result != GLOBUS_SUCCESS)
1059 {
1060 0 goto exit;
1061 }
1062 2719 value->length = strlen(value->buffer);
1063 }
1064 else
1065 {
1066 6 result = element->any_info->deserialize(
1067 &element->qname,
1068 &element->value,
1069 message,
1070 GLOBUS_XSD_ELEMENT_CONTENTS_ONLY|GLOBUS_XSD_ELEMENT_ATTRIBUTE);
1071 }
1072 2725 if (result != GLOBUS_SUCCESS)
1073 {
1074 0 goto exit;
1075 }
1076
1077 2725 res = globus_hashtable_insert(&attrs, &element->qname, element);
1078 2725 if (element->qname.local == NULL)
1079 {
1080 0 result = GlobusSoapMessageErrorOutOfMemory;
1081
1082 0 goto exit;
1083 }
1084 }
1085
1086 9122249 next:
1087 9122249 res = xmlTextReaderMoveToNextAttribute(message->reader);
1088 9122249 if(res == -1)
1089 {
1090 0 result = GlobusSoapMessageErrorDeserializeAnyAttrsFailed(
1091 message->result, NULL);
1092 0 goto exit;
1093 }
1094 }
1095
1096 2760012 res = xmlTextReaderMoveToElement(message->reader);
1097 2760012 if(res < 0)
1098 {
1099 0 result = GlobusSoapMessageErrorDeserializeAnyAttrsFailed(
1100 message->result, NULL);
1101
1102 0 goto exit;
1103 }
1104
1105 2760012 exit:
1106 2760012 return result;
1107 }