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