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 #include "globus_soap_message.h"
19 #include "globus_i_soap_message.h"
20 #include "xsd_anyAttributes.h"
21
22 typedef struct
23 {
24     xsd_QName                           qname;
25     char *                              value;
26 } xsd_l_anyAttributes_element_t;
27
28 int
29 xsd_anyAttributes_size(
30     xsd_anyAttributes_t                 attrs)
31 25 {
32 25     return globus_hashtable_size(&attrs);
33 }
34
35 const char *
36 xsd_anyAttributes_lookup(
37     xsd_anyAttributes_t                 attrs,
38     const xsd_QName *                   name)
39 0 {
40 0     xsd_l_anyAttributes_element_t *     element;
41
42 0     element = (xsd_l_anyAttributes_element_t *)
43         globus_hashtable_lookup(&attrs, (void *) name);
44 0     if(!element)
45     {
46 0         return NULL;
47     }
48
49 0     return element->value;
50 }
51
52 int
53 xsd_anyAttributes_insert(
54     xsd_anyAttributes_t                 attrs,
55     const xsd_QName *                   name,
56     const char *                        value)
57 0 {
58 0     xsd_l_anyAttributes_element_t *     element;
59
60 0     element = (xsd_l_anyAttributes_element_t *)
61         globus_malloc(sizeof(xsd_l_anyAttributes_element_t));
62 0     xsd_QName_copy_contents(&element->qname, name);
63 0     element->value = globus_libc_strdup(value);
64
65 0     return globus_hashtable_insert(&attrs, &element->qname, element);
66 }
67
68 static
69 void
70 xsd_anyAttributes_element_delete(
71     void *                              value)
72 958 {
73 958     xsd_l_anyAttributes_element_t *     element;
74     
75 958     element = (xsd_l_anyAttributes_element_t *) value;
76     
77 958     if(element)
78     {
79 958         xsd_QName_destroy_contents(&element->qname);
80 958         if(element->value)
81         {
82 958             globus_free(element->value);
83         }
84 958         globus_free(element);
85     }
86 }
87
88 int
89 xsd_anyAttributes_remove(
90     xsd_anyAttributes_t                 attrs,
91     const xsd_QName *                   name)
92 0 {
93 0     void *                              element;
94
95 0     element = globus_hashtable_remove(&attrs, (void *) name);
96 0     if(!element)
97     {
98 0         return GLOBUS_FAILURE;
99     }
100     
101 0     xsd_anyAttributes_element_delete(element);
102 0     return GLOBUS_SUCCESS;
103 }
104
105 void
106 xsd_anyAttributes_destroy(
107     xsd_anyAttributes_t                 attrs)
108 53417 {
109 53417     if(attrs)
110     {
111 41431         globus_hashtable_destroy_all(&attrs, xsd_anyAttributes_element_delete);
112     }
113 }
114
115 globus_result_t
116 xsd_anyAttributes_init(
117     xsd_anyAttributes_t *               attrs)
118 26807 {
119 26807     return globus_hashtable_init(attrs, 10, xsd_QName_hash, xsd_QName_keyeq);
120 }
121
122 static
123 int
124 xsd_QName_compare(
125     void *                              a,
126     void *                              b,
127     void *                              args)
128 0 {
129 0     int                                 res;
130 0     xsd_QName *                         qa;
131 0     xsd_QName *                         qb;
132
133     
134 0     if(!a)
135     {
136 0         return 1;
137     }
138
139 0     if(!b)
140     {
141 0         return 0;
142     }
143
144 0     qa = (xsd_QName *)a;
145 0     qb = (xsd_QName *)b;
146
147 0     if(!qa->Namespace && !qb->Namespace)
148     {
149 0         globus_assert_string(qa->local && qb->local, 
150                              "QName structs must have valid local values");
151         
152 0         if(strcmp(qa->local, qb->local) <= 0)
153         {
154 0             return 1;
155         }
156         
157 0         return 0;
158     }
159
160 0     if(qa->Namespace && qb->Namespace)
161     {
162 0         res = strcmp(qa->Namespace, qb->Namespace);
163 0         if(res == 0)
164         {
165 0             if(strcmp(qa->local, qb->local) <= 0)
166             {
167 0                 return 1;
168             }
169
170 0             return 0;
171         }
172         
173 0         if(res < 0)
174         {
175 0             return 1;
176         }
177
178 0         return 0;
179     }
180          
181 0     if((!qa->Namespace) && qb->Namespace)
182     {
183 0         return 1;
184     }
185
186 0     if((!qb->Namespace) && qa->Namespace)
187     {
188 0         return 0;
189     }
190
191 0     return 1;
192 }
193
194 globus_list_t *
195 xsd_anyAttributes_lex_sort(
196     xsd_anyAttributes_t                 attrs)
197 8 {
198 8     xsd_l_anyAttributes_element_t *     element;
199 8     globus_list_t *                     keys = NULL;
200     
201 8     element = (xsd_l_anyAttributes_element_t *) globus_hashtable_first(&attrs);
202 8     while(element)
203     {
204 0         globus_list_insert(&keys, &element->qname);
205 0         element = (xsd_l_anyAttributes_element_t *) 
206             globus_hashtable_next(&attrs);
207     }
208
209 8     keys = globus_list_sort(keys, xsd_QName_compare, NULL);
210
211 8     return keys;
212 }
213
214 globus_result_t
215 xsd_anyAttributes_namespace_set(
216     globus_soap_message_handle_t        message,
217     const xsd_QName *                   element_qname,
218     xsd_anyAttributes_t                 attrs,
219     globus_xsd_element_options_t *      options)
220 26038 {
221 26038     globus_result_t                     result = GLOBUS_SUCCESS;
222 26038     xsd_l_anyAttributes_element_t *     element;
223 26038     if(attrs)
224     {
225 8         element = globus_hashtable_first(&attrs);
226 8         while(element)
227         {
228 0             result = globus_soap_message_attribute_ns_set(
229                 message,
230                 element_qname,
231                 element->qname.Namespace,
232                 options);
233 0             if(result != GLOBUS_SUCCESS)
234             {
235 0                 xsd_QName *             eqn = &element->qname;
236 0                 result = GlobusSoapMessageErrorSerializeFailed(
237                     result, NULL, eqn);
238 0                 goto exit;
239             }
240
241 0             element = globus_hashtable_next(&attrs);
242         }
243     }
244
245 exit:
246     
247 26038     return result;
248 }
249 globus_result_t
250 xsd_anyAttributes_namespace_add(
251     globus_soap_message_handle_t        message,
252     const xsd_QName *                   element_qname,
253     xsd_anyAttributes_t                 attrs,
254     globus_xsd_element_options_t *      options)
255 26038 {
256 26038     globus_result_t                     result = GLOBUS_SUCCESS;
257 26038     xsd_l_anyAttributes_element_t *     element;
258 26038     if(attrs)
259     {
260 8         element = globus_hashtable_first(&attrs);
261 8         while(element)
262         {
263 0             result = globus_soap_message_attribute_ns_add(
264                 message,
265                 element_qname,
266                 element->qname.Namespace,
267                 options);
268 0             if(result != GLOBUS_SUCCESS)
269             {
270 0                 xsd_QName *             eqn = &element->qname;
271 0                 result = GlobusSoapMessageErrorSerializeFailed(
272                     result, NULL, eqn);
273 0                 goto exit;
274             }
275
276 0             element = globus_hashtable_next(&attrs);
277         }
278     }
279
280 exit:
281     
282 26038     return result;
283 }
284
285 globus_result_t
286 xsd_anyAttributes_namespace_remove(
287     globus_soap_message_handle_t        message,
288     xsd_anyAttributes_t                 attrs,
289     globus_xsd_element_options_t *      options)
290 26038 {
291 26038     globus_result_t                     result = GLOBUS_SUCCESS;
292 26038     xsd_l_anyAttributes_element_t *     element;
293 26038     if(attrs)
294     {
295 8         element = globus_hashtable_first(&attrs);
296 8         while(element)
297         {
298 0             globus_soap_message_attribute_ns_remove(
299                 message,
300                 element->qname.Namespace,
301                 options);
302 0             if(result != GLOBUS_SUCCESS)
303             {
304 0                 xsd_QName *             eqn = &element->qname;
305 0                 result = GlobusSoapMessageErrorSerializeFailed(
306                     result, NULL, eqn);
307 0                 goto exit;
308             }
309
310 0             element = globus_hashtable_next(&attrs);
311         }
312     }
313
314 exit:
315     
316 26038     return result;
317 }
318
319 globus_result_t
320 xsd_anyAttributes_serialize(
321     globus_soap_message_handle_t        message,
322     xsd_anyAttributes_t                 attrs)
323 0 {
324 0     globus_list_t *                     lex_sorted_keys;
325 0     globus_result_t                     result = GLOBUS_SUCCESS;
326 0     xsd_l_anyAttributes_element_t *     element;
327 0     xsd_QName *                         key;
328
329 0     lex_sorted_keys = xsd_anyAttributes_lex_sort(attrs);
330
331 0     key = globus_list_first(lex_sorted_keys);
332 0     while(key)
333     {
334 0         lex_sorted_keys = globus_list_rest(lex_sorted_keys);
335 0         element = (xsd_l_anyAttributes_element_t *) 
336             globus_hashtable_lookup(&attrs, key);
337 0         if(!element)
338         {
339 0             result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
340                 result, "Null element in attributes list");
341 0             goto exit;
342         }
343         
344 0         result = xsd_string_serialize_attribute(
345             &element->qname, &element->value, message, 0);
346 0         if(result != GLOBUS_SUCCESS)
347         {
348 0             result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
349                 result, "Failed to serialize any attribute");
350 0             goto exit;
351         }
352      
353 0         key = globus_list_first(lex_sorted_keys);
354     }
355
356  exit:
357
358 0     return result;
359 }
360
361 globus_result_t
362 xsd_anyAttributes_serialize_lex_before(
363     globus_soap_message_handle_t        message,
364     globus_list_t **                    lex_sorted_keys,
365     xsd_anyAttributes_t                 attrs,
366     xsd_QName *                         comparable_value)
367 0 {
368 0     globus_result_t                     result = GLOBUS_SUCCESS;
369 0     xsd_l_anyAttributes_element_t *     element;
370 0     xsd_QName *                         key;
371
372 0     while(*lex_sorted_keys)
373     {
374 0         key = globus_list_first(*lex_sorted_keys);
375         
376 0         if(!xsd_QName_compare(comparable_value, key, NULL))
377         {
378 0     break;
379         } 
380          
381 0         element = (xsd_l_anyAttributes_element_t *) 
382             globus_hashtable_lookup(&attrs, key);
383 0         if(!element)
384         {
385 0             result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
386                 result, "Null element in attributes list");
387 0             goto exit;
388         }
389         
390 0         result = xsd_string_serialize_attribute(
391             &element->qname, &element->value, message, 0);
392 0         if(result != GLOBUS_SUCCESS)
393         {
394 0             result = GlobusSoapMessageErrorSerializeAnyAttrsFailed(
395                 result, "Failed to serialize any attribute");
396 0             goto exit;
397         }
398      
399 0         *lex_sorted_keys = globus_list_rest(*lex_sorted_keys);
400     }
401
402  exit:
403
404 0     return result;
405 }
406
407 static
408 void
409 xsd_anyAttributes_QName_copy_callback(
410     void **                             dest_key,
411     void **                             dest_datum,
412     void *                              src_key,
413     void *                              src_datum)
414 12 {
415 12     xsd_l_anyAttributes_element_t *     dest_element;
416 12     xsd_l_anyAttributes_element_t *     src_element;
417
418 12     src_element = (xsd_l_anyAttributes_element_t *) src_datum;
419
420 12     dest_element = (xsd_l_anyAttributes_element_t *)
421         globus_malloc(sizeof(xsd_l_anyAttributes_element_t));
422
423 12     xsd_QName_copy_contents(&dest_element->qname, (const xsd_QName *) src_key);
424 12     dest_element->value = globus_libc_strdup(src_element->value);
425
426 12     *dest_datum = dest_element;
427 12     *dest_key = &dest_element->qname;
428 }
429
430 globus_result_t
431 xsd_anyAttributes_copy(
432     xsd_anyAttributes_t *               dest_attrs,
433     const xsd_anyAttributes_t           src_attrs)
434 14728 {
435 14728     globus_result_t                     result = GLOBUS_SUCCESS;
436
437 14728     result = globus_hashtable_copy(
438             dest_attrs,
439             (xsd_anyAttributes_t *) &src_attrs,
440             xsd_anyAttributes_QName_copy_callback);
441     
442 14728     return result;
443 }
444
445 globus_result_t
446 xsd_anyAttributes_deserialize(
447     globus_soap_message_handle_t        message,
448     xsd_anyAttributes_t                 attrs)
449 26807 {
450 26807     globus_result_t                     result = GLOBUS_SUCCESS;
451 26807     int                                 res = 0;
452
453 26807     res = xmlTextReaderMoveToFirstAttribute(message->reader);
454 26807     if(res < 0)
455     {
456 0         result = GlobusSoapMessageErrorDeserializeAnyAttrsFailed(
457             message->result, NULL);
458
459 0         goto exit;
460     }
461
462 46371     while(res)
463     {
464 19564         xmlNodePtr                      attrNode;
465 19564         xsd_l_anyAttributes_element_t * element;
466         
467 19564         attrNode = xmlTextReaderCurrentNode(message->reader);
468 19564         if(attrNode->type == XML_ATTRIBUTE_NODE)
469         {
470 946             element = (xsd_l_anyAttributes_element_t *)
471                 globus_malloc(sizeof(xsd_l_anyAttributes_element_t));
472 946             element->qname.local = xmlTextReaderLocalName(message->reader);
473 946             element->qname.Namespace =
474                 xmlTextReaderNamespaceUri(message->reader);
475 946             element->value = xmlTextReaderValue(message->reader);
476             
477 946             globus_hashtable_insert(&attrs, &element->qname, element);
478         }
479
480 19564         res = xmlTextReaderMoveToNextAttribute(message->reader);
481 19564         if(res == -1)
482         {
483 0             result = GlobusSoapMessageErrorDeserializeAnyAttrsFailed(
484                 message->result, NULL);
485 0             goto exit;
486         }
487     }
488
489 26807     res = xmlTextReaderMoveToElement(message->reader);
490 26807     if(res < 0)
491     {
492 0         result = GlobusSoapMessageErrorDeserializeAnyAttrsFailed(
493             message->result, NULL);
494
495         goto exit;
496     }
497
498  exit:
499
500 26807     return result;