1 /*
2  * Portions of this file Copyright 1999-2005 University of Chicago
3  * Portions of this file Copyright 1999-2005 The University of Southern California.
4  *
5  * This file or a portion of this file is licensed under the
6  * terms of the Globus Toolkit Public License, found at
7  * http://www.globus.org/toolkit/download/license.html.
8  * If you redistribute this file, with or without
9  * modifications, you must include this notice in the file.
10  */
11
12 #include "globus_common.h"
13 #include "globus_i_xsd.h"
14 #include "globus_i_xsd_type_registry.h"
15 #include "globus_i_xsd_type_info.h"
16 #include "globus_soap_message_utils.h"
17 #include "globus_soap_message.h"
18
19 /**
20  * Initialize a new type registry.
21  *
22  * @param registry
23  *     New type registry.
24  *
25  * @retval GLOBUS_SUCCESS
26  *     Registry initialized.
27  * @retval GLOBUS_MESSAGE_ERROR_TYPE_NULL_PARAM
28  *     The @a registry parameter was NULL.
29  * @retval GLOBUS_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
30  *     Unable to allocate registry data.
31  *
32  * @see globus_xsd_type_registry_destroy()
33  */
34 globus_result_t
35 globus_xsd_type_registry_init(
36     globus_xsd_type_registry_t *        registry)
37 282 {
38 282     globus_result_t                     result;
39 282     struct globus_xsd_type_registry_s * p;
40 282     int                                 rc;
41 282     GlobusFuncName(globus_xsd_type_registry_init);
42 282     GlobusSoapMessageDebugEnter();
43
44 282     if (registry == NULL)
45     {
46 0         result = GlobusSoapMessageErrorNullParam;
47
48 0         goto error;
49     }
50 282     *registry = NULL;
51
52 282     p = globus_libc_malloc(sizeof(struct globus_xsd_type_registry_s));
53 282     if (p == NULL)
54     {
55 0         result = GlobusSoapMessageErrorOutOfMemory;
56
57 0         goto error;
58     }
59
60 282     rc = globus_hashtable_init(
61             &p->table,
62             257,
63             xsd_QName_hash,
64             xsd_QName_keyeq);
65
66 282     if (rc != GLOBUS_SUCCESS)
67     {
68 0         result = GlobusSoapMessageErrorOutOfMemory;
69
70 0         goto free_p_error;
71     }
72
73 282     p->default_mapping = &xsd_string_info;
74
75 282     globus_mutex_init(&p->lock, NULL);
76 282     *registry = p;
77
78 282     GlobusSoapMessageDebugExit();
79 282     return GLOBUS_SUCCESS;
80
81 free_p_error:
82 0     globus_libc_free(p);
83 error:
84 0     GlobusSoapMessageDebugExit();
85 0     return result;
86 }
87 /* globus_xsd_type_registry_init() */
88
89 /**
90  * Destroy a type registry.
91  *
92  * @param registry
93  *     Type registry to destroy.
94  *
95  * @retval GLOBUS_SUCCESS
96  *     Registry destroyed.
97  * @retval GLOBUS_MESSAGE_ERROR_TYPE_NULL_PARAM
98  *     The @a registry parameter was NULL.
99  *
100  * @see globus_xsd_type_registry_init()
101  * @see globus_xsd_type_registry_clear()
102  */
103 globus_result_t
104 globus_xsd_type_registry_destroy(
105     globus_xsd_type_registry_t          registry)
106 197 {
107 197     globus_result_t                     result;
108 197     GlobusFuncName(globus_xsd_type_registry_destroy);
109 197     GlobusSoapMessageDebugEnter();
110
111 197     result = globus_xsd_type_registry_clear(registry);
112
113 197     if (result == GLOBUS_SUCCESS)
114     {
115 197         globus_hashtable_destroy(&registry->table);
116 197         globus_mutex_destroy(&registry->lock);
117 197         globus_libc_free(registry);
118     }
119
120 197     GlobusSoapMessageDebugExit();
121 197     return result;
122 }
123 /* globus_xsd_type_registry_destroy() */
124
125 /**
126  * Insert a type into the registry.
127  *
128  * If an existing type mapping is registered for the specified type, it
129  * is replaced with the new type. The old type is returned in value pointed to
130  * by the @a old_info  parameter.
131  *
132  * @param registry
133  *     Registry to modify.
134  * @param info
135  *     Information about the type.
136  * @param old_info
137  *     Pointer to be set to the value of the previous info for this type.
138  *     May be NULL if the caller is not interested in this.
139  *
140  * @retval GLOBUS_SUCCESS
141  *     Type mapping added
142  * @retval GLOBUS_MESSAGE_ERROR_TYPE_NULL_PARAM
143  *     The @a registry or @a info  parameter was NULL.
144  *
145  * @see globus_xsd_type_registry_remove()
146  * @see globus_xsd_type_registry_get()
147  */
148 globus_result_t
149 globus_xsd_type_registry_insert(
150     globus_xsd_type_registry_t          registry,
151     globus_xsd_type_info_t              info,
152     globus_xsd_type_info_t *            old_info)
153 19680 {
154 19680     globus_result_t                     result;
155 19680     globus_xsd_type_info_t              p;
156 19680     int                                 rc;
157 19680     GlobusFuncName(globus_xsd_type_registry_insert);
158 19680     GlobusSoapMessageDebugEnter();
159
160 19680     if (registry == NULL || info == NULL)
161     {
162 0         result = GlobusSoapMessageErrorNullParam;
163
164 0         goto error;
165     }
166
167 19680     rc = globus_mutex_lock(&registry->lock);
168 19680     if (rc != GLOBUS_SUCCESS)
169     {
170 0         result = GlobusSoapMessageErrorOutOfMemory;
171
172 0         goto error;
173     }
174     
175 19680     p = globus_hashtable_lookup(&registry->table, info->type);
176 19680     if(p == info)
177     {
178 501         if(old_info)
179         {
180 0             *old_info = p;
181         }
182 0         goto exit;
183     }
184  
185 19179     p = globus_hashtable_remove(&registry->table, info->type);
186
187 19179     if (old_info)
188     {
189 0         *old_info = p;
190     }
191
192 19179     rc = globus_hashtable_insert(&registry->table, info->type, info);
193
194 19179     if (rc != GLOBUS_SUCCESS)
195     {
196 0         result = GlobusSoapMessageErrorOutOfMemory;
197
198 0         goto unlock_error;
199     }
200
201  exit:
202 19680     globus_mutex_unlock(&registry->lock);
203
204 19680     GlobusSoapMessageDebugExit();
205 19680     return GLOBUS_SUCCESS;
206
207 unlock_error:
208 0     globus_mutex_unlock(&registry->lock);
209 error:
210 0     GlobusSoapMessageDebugExit();
211 0     return result;
212 }
213 /* globus_xsd_type_registry_insert() */
214
215 /**
216  * Remove a type from the registry.
217  *
218  * @param registry
219  *     Registry to modify.
220  * @param name
221  *     Name of the type to be unregistered.
222  * @param info
223  *     Pointer to be set to the previously registred type information. May be
224  *     NULL if the caller doesn't want that type info.
225  *
226  * @retval GLOBUS_SUCCESS
227  *     Type mapping removed.
228  * @retval GLOBUS_MESSAGE_ERROR_TYPE_NULL_PARAM
229  *     The @a registry or @a name parameter was NULL.
230  *
231  * @see globus_xsd_type_registry_replace()
232  * @see globus_xsd_type_registry_remove()
233  * @see globus_xsd_type_registry_get()
234  */
235 globus_result_t
236 globus_xsd_type_registry_remove(
237     globus_xsd_type_registry_t          registry,
238     const xsd_QName *                   name,
239     globus_xsd_type_info_t *            info)
240 0 {
241 0     globus_result_t                     result;
242 0     globus_xsd_type_info_t              tmp;
243 0     GlobusFuncName(globus_xsd_type_registry_remove);
244 0     GlobusSoapMessageDebugEnter();
245
246 0     if (registry == NULL || name == NULL)
247     {
248 0         result = GlobusSoapMessageErrorNullParam;
249
250 0         goto error;
251     }
252
253 0     globus_mutex_lock(&registry->lock);
254 0     tmp = globus_hashtable_remove(&registry->table, (void *) name);
255
256 0     if (info != NULL)
257     {
258 0         *info = tmp;
259     }
260 0     globus_mutex_unlock(&registry->lock);
261     
262 0     GlobusSoapMessageDebugExit();
263 0     return GLOBUS_SUCCESS;
264 error:
265 0     GlobusSoapMessageDebugExit();
266 0     return result;
267 }
268 /* globus_xsd_type_registry_remove() */
269
270 globus_result_t
271 globus_xsd_type_registry_clear(
272     globus_xsd_type_registry_t          registry)
273 197 {
274 197     int                                 rc;
275 197     globus_result_t                     result;
276 197     globus_list_t *                     tmp_list;
277 197     globus_xsd_type_info_t              p;
278 197     GlobusFuncName(globus_xsd_type_registry_clear);
279 197     GlobusSoapMessageDebugEnter();
280
281 197     if (registry == NULL)
282     {
283 0         result = GlobusSoapMessageErrorNullParam;
284
285 0         goto error;
286     }
287 197     rc = globus_mutex_lock(&registry->lock);
288 197     if (rc != GLOBUS_SUCCESS)
289     {
290 0         result = GlobusSoapMessageErrorOutOfMemory;
291
292 0         goto error;
293     }
294 197     rc = globus_hashtable_to_list(&registry->table, &tmp_list);
295 197     if (rc != GLOBUS_SUCCESS)
296     {
297 0         result = GlobusSoapMessageErrorNullParam;
298
299 0         goto unlock_error;
300     }
301 12503     while (!globus_list_empty(tmp_list))
302     {
303 12306         p = globus_list_remove(&tmp_list, tmp_list);
304
305 12306         globus_assert(p);
306
307 12306         globus_hashtable_remove(&registry->table, p->type);
308     }
309
310 197     globus_mutex_unlock(&registry->lock);
311
312 197     GlobusSoapMessageDebugExit();
313 197     return GLOBUS_SUCCESS;
314
315
316 unlock_error:
317 0     globus_mutex_unlock(&registry->lock);
318 error:
319 0     GlobusSoapMessageDebugExit();
320 0     return result;
321 }
322 /* globus_xsd_type_registry_clear() */
323
324 globus_result_t
325 globus_xsd_type_registry_get(
326     globus_xsd_type_registry_t          registry,
327     const xsd_QName *                   name,
328     globus_xsd_type_info_t *            info)
329 498113 {
330 498113     globus_result_t                     result;
331 498113     int                                 rc;
332 498113     GlobusFuncName(globus_xsd_type_registry_get);
333 498113     GlobusSoapMessageDebugEnter();
334
335 498113     if (registry == NULL || name == NULL || info == NULL)
336     {
337 0         result = GlobusSoapMessageErrorNullParam;
338
339 0         goto error;
340     }
341 498113     rc = globus_mutex_lock(&registry->lock);
342 498113     if (rc != GLOBUS_SUCCESS)
343     {
344 0         result = GlobusSoapMessageErrorOutOfMemory;
345
346 0         goto error;
347     }
348 498113     *info = globus_hashtable_lookup(&registry->table, (void *) name);
349
350 498113     globus_mutex_unlock(&registry->lock);
351
352 498113     GlobusSoapMessageDebugExit();
353 498113     return GLOBUS_SUCCESS;
354 error:
355 0     GlobusSoapMessageDebugExit();
356 0     return result;
357 }
358 /* globus_xsd_type_registry_get() */
359
360 globus_result_t
361 globus_xsd_type_registry_set_default(
362     globus_xsd_type_registry_t          registry,
363     globus_xsd_type_info_t              info)
364 0 {
365 0     globus_result_t                     result;
366 0     GlobusFuncName(globus_xsd_type_registry_set_default);
367 0     GlobusSoapMessageDebugEnter();
368
369 0     if (registry == NULL || info == NULL)
370     {
371 0         result = GlobusSoapMessageErrorNullParam;
372
373 0         goto error;
374     }
375 0     globus_mutex_lock(&registry->lock);
376 0     registry->default_mapping = info;
377 0     globus_mutex_unlock(&registry->lock);
378
379 0     GlobusSoapMessageDebugExit();
380 0     return GLOBUS_SUCCESS;
381 error:
382 0     GlobusSoapMessageDebugExit();
383 0     return result;
384 }
385 /* globus_xsd_type_registry_set_default() */
386
387 globus_result_t
388 globus_xsd_type_registry_get_default(
389     globus_xsd_type_registry_t          registry,
390     globus_xsd_type_info_t *            info)
391 0 {
392 0     globus_result_t                     result;
393 0     GlobusFuncName(globus_xsd_type_registry_get_default);
394 0     GlobusSoapMessageDebugEnter();
395
396 0     if (registry == NULL || info == NULL)
397     {
398 0         result = GlobusSoapMessageErrorNullParam;
399
400 0         goto error;
401     }
402 0     globus_mutex_lock(&registry->lock);
403 0     *info = registry->default_mapping;
404 0     globus_mutex_unlock(&registry->lock);
405
406 0     GlobusSoapMessageDebugExit();
407 0     return GLOBUS_SUCCESS;
408 error:
409 0     GlobusSoapMessageDebugExit();
410 0     return result;
411 }
412 /* globus_xsd_type_registry_get_default() */
413
414
415 globus_result_t
416 globus_xsd_type_registry_add_base_types(
417     globus_xsd_type_registry_t          registry)
418 204 {
419 204     globus_result_t                     result = GLOBUS_SUCCESS;
420 204     GlobusFuncName(globus_xsd_type_registry_add_base_types);
421 204     GlobusSoapMessageDebugEnter();
422
423 204     result = globus_xsd_type_registry_insert(registry, &xsd_QName_info, NULL);
424 204     if(result != GLOBUS_SUCCESS)
425     {
426 0         goto exit;
427     }
428
429 204     result = globus_xsd_type_registry_insert(registry, &xsd_anyURI_info, NULL);
430 204     if(result != GLOBUS_SUCCESS)
431     {
432 0         goto exit;
433     }
434
435 204     result = globus_xsd_type_registry_insert(registry, &xsd_base64Binary_info, NULL);
436 204     if(result != GLOBUS_SUCCESS)
437     {
438 0         goto exit;
439     }
440
441 204     result = globus_xsd_type_registry_insert(registry, &xsd_boolean_info, NULL);
442 204     if(result != GLOBUS_SUCCESS)
443     {
444 0         goto exit;
445     }
446
447 204     result = globus_xsd_type_registry_insert(registry, &xsd_byte_info, NULL);
448 204     if(result != GLOBUS_SUCCESS)
449     {
450 0         goto exit;
451     }
452
453 204     result = globus_xsd_type_registry_insert(registry, &xsd_date_info, NULL);
454 204     if(result != GLOBUS_SUCCESS)
455     {
456 0         goto exit;
457     }
458
459 204     result = globus_xsd_type_registry_insert(registry, &xsd_dateTime_info, NULL);
460 204     if(result != GLOBUS_SUCCESS)
461     {
462 0         goto exit;
463     }
464
465 204     result = globus_xsd_type_registry_insert(registry, &xsd_decimal_info, NULL);
466 204     if(result != GLOBUS_SUCCESS)
467     {
468 0         goto exit;
469     }
470
471 204     result = globus_xsd_type_registry_insert(registry, &xsd_double_info, NULL);
472 204     if(result != GLOBUS_SUCCESS)
473     {
474 0         goto exit;
475     }
476
477 204     result = globus_xsd_type_registry_insert(registry, &xsd_duration_info, NULL);
478 204     if(result != GLOBUS_SUCCESS)
479     {
480 0         goto exit;
481     }
482
483 204     result = globus_xsd_type_registry_insert(registry, &xsd_float_info, NULL);
484 204     if(result != GLOBUS_SUCCESS)
485     {
486 0         goto exit;
487     }
488
489 204     result = globus_xsd_type_registry_insert(registry, &xsd_hexBinary_info, NULL);
490 204     if(result != GLOBUS_SUCCESS)
491     {
492 0         goto exit;
493     }
494
495 204     result = globus_xsd_type_registry_insert(registry, &xsd_int_info, NULL);
496 204     if(result != GLOBUS_SUCCESS)
497     {
498 0         goto exit;
499     }
500
501 204     result = globus_xsd_type_registry_insert(registry, &xsd_integer_info, NULL);
502 204     if(result != GLOBUS_SUCCESS)
503     {
504 0         goto exit;
505     }
506
507 204     result = globus_xsd_type_registry_insert(registry, &xsd_long_info, NULL);
508 204     if(result != GLOBUS_SUCCESS)
509     {
510 0         goto exit;
511     }
512
513 204     result = globus_xsd_type_registry_insert(registry, &xsd_negativeInteger_info, NULL);
514 204     if(result != GLOBUS_SUCCESS)
515     {
516 0         goto exit;
517     }
518
519 204     result = globus_xsd_type_registry_insert(registry, &xsd_nonNegativeInteger_info, NULL);
520 204     if(result != GLOBUS_SUCCESS)
521     {
522 0         goto exit;
523     }
524
525 204     result = globus_xsd_type_registry_insert(registry, &xsd_nonPositiveInteger_info, NULL);
526 204     if(result != GLOBUS_SUCCESS)
527     {
528 0         goto exit;
529     }
530
531 204     result = globus_xsd_type_registry_insert(registry, &xsd_positiveInteger_info, NULL);
532 204     if(result != GLOBUS_SUCCESS)
533     {
534 0         goto exit;
535     }
536
537 204     result = globus_xsd_type_registry_insert(registry, &xsd_short_info, NULL);
538 204     if(result != GLOBUS_SUCCESS)
539     {
540 0         goto exit;
541     }
542
543 204     result = globus_xsd_type_registry_insert(registry, &xsd_string_info, NULL);
544 204     if(result != GLOBUS_SUCCESS)
545     {
546 0         goto exit;
547     }
548
549 204     result = globus_xsd_type_registry_insert(registry, &xsd_time_info, NULL);
550 204     if(result != GLOBUS_SUCCESS)
551     {
552 0         goto exit;
553     }
554
555 204     result = globus_xsd_type_registry_insert(registry, &xsd_unsignedByte_info, NULL);
556 204     if(result != GLOBUS_SUCCESS)
557     {
558 0         goto exit;
559     }
560
561 204     result = globus_xsd_type_registry_insert(registry, &xsd_unsignedInt_info, NULL);
562 204     if(result != GLOBUS_SUCCESS)
563     {
564 0         goto exit;
565     }
566
567 204     result = globus_xsd_type_registry_insert(registry, &xsd_unsignedLong_info, NULL);
568 204     if(result != GLOBUS_SUCCESS)
569     {
570 0         goto exit;
571     }
572
573 204     result = globus_xsd_type_registry_insert(registry, &xsd_unsignedShort_info, NULL);
574 204     if(result != GLOBUS_SUCCESS)
575     {
576 204         goto exit;
577     }
578     
579  exit:
580
581 204     GlobusSoapMessageDebugExit();
582 204     return result;
583 }
584
585 globus_result_t
586 globus_xsd_type_registry_dump(
587     globus_xsd_type_registry_t               registry)
588 0 {
589 0     globus_result_t                     result = GLOBUS_SUCCESS;
590 0     globus_xsd_type_info_t              info;
591 0     int                                 rc = 0;
592 0     GlobusFuncName(globus_xsd_type_registry_dump);
593 0     GlobusSoapMessageDebugEnter();
594
595 0     rc = globus_mutex_lock(&registry->lock);
596 0     if (rc != GLOBUS_SUCCESS)
597     {
598 0         result = GlobusSoapMessageErrorOutOfMemory;
599 0         goto error;
600     }
601     
602 0     info = globus_hashtable_first(&registry->table);
603
604 0     while(info)
605     {
606 0         GlobusSoapMessageDebugPrintf(
607             GLOBUS_SOAP_MESSAGE_DEBUG_REGISTRY,
608             ("{%s}%s\n",
609             info->type->Namespace,
610             info->type->local));
611         
612 0         info = globus_hashtable_next(&registry->table);
613     }
614
615 0     rc = globus_mutex_unlock(&registry->lock);
616 0     if(rc != GLOBUS_SUCCESS)
617     {
618 0         result = GlobusSoapMessageErrorOutOfMemory;
619         goto error;
620     }
621
622  error:
623
624 0     GlobusSoapMessageDebugExit();
625 0     return result;