1 #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
2
3 #include "globus_i_notification_producer.h"
4 #include "wstop_TopicNamespaceType.h"
5 #include "wstop_TopicNamespaceType_Topic.h"
6 #include "wstop_TopicType.h"
7 #include "globus_xml_buffer.h"
8 #include "libxml/xpath.h"
9 #include "libxml/xpathInternals.h"
10 #include "xpath_TargetedXPathQueryType.h"
11 #include "xpath_NamespaceMappingType.h"
12 #include "wstop_TopicSet.h"
13 #include "wstop_SimpleTopicExpression.h"
14 #include "wstop_ConcreteTopicExpression.h"
15 #include "wstop_FullTopicExpression.h"
16 #include "globus_wsnt_topic_utils.h"
17 #include "globus_wsrf_core_tools.h"
18
19 #define SIMPLE_TOPIC_EXPRESSION \
20 "http://docs.oasis-open.org/wsn/t-1/TopicExpression/Simple"
21
22 #define CONCRETE_TOPIC_EXPRESSION \
23 "http://docs.oasis-open.org/wsn/t-1/TopicExpression/Concrete"
24
25 #define FULL_TOPIC_EXPRESSION \
26 "http://docs.oasis-open.org/wsn/t-1/TopicExpression/Full"
27
28 static
29 void
30 globus_l_notification_root_topic_destroy_contents(
31 wstop_TopicNamespaceType_Topic * topic);
32
33 static
34 void
35 globus_l_notification_topic_destroy_contents(
36 wstop_TopicType * topic);
37
38 static
39 void
40 globus_l_notification_topic_info_destroy(
41 globus_i_notification_producer_topic_t *
42 topic_info);
43
44 static
45 globus_result_t
46 globus_l_notification_topic_set_concrete_lookup(
47 globus_i_notification_topic_set_t topic_set,
48 const wsnt_TopicExpressionType * topic_expression,
49 globus_i_notification_producer_topic_t **
50 topic);
51
52 static
53 globus_result_t
54 globus_l_notification_topic_set_full_lookup(
55 globus_i_notification_topic_set_t topic_set,
56 const wsnt_TopicExpressionType * topic_expression,
57 globus_list_t ** topic_list);
58
59 static
60 globus_result_t
61 globus_l_notification_topic_set_xpath_lookup(
62 globus_i_notification_topic_set_t topic_set,
63 xpath_TargetedXPathQueryType * query,
64 globus_list_t ** topic_list);
65
66 static
67 globus_result_t
68 globus_l_notification_topic_set_to_dom(
69 xmlDocPtr * doc,
70 globus_i_notification_topic_set_t topic_set);
71
72 static
73 globus_result_t
74 globus_l_notification_topic_to_dom(
75 xmlDocPtr doc,
76 xmlNodePtr parent,
77 wstop_TopicType * child_topic);
78
79 static
80 wstop_TopicNamespaceType *
81 globus_l_topic_space_lookup(
82 globus_i_notification_topic_set_t topic_set,
83 xsd_anyURI Namespace);
84
85 static
86 globus_result_t
87 globus_l_topic_expression_to_xpath(
88 globus_wsnt_topic_value_t * topic_value,
89 xpath_TargetedXPathQueryType * query);
90 #endif
91
92 /**
93 * Enumerate the topics published by a notification producer
94 * @ingroup notification_topics
95 *
96 * @param resource_id
97 * Resource id associated with notification producer state.
98 * @param topics
99 * Pointer to an array of topic expressions. An element for each
100 * topic will be pushed onto this array if this function is successful.
101 * The caller must free this array.
102 *
103 * @retval GLOBUS_SUCCESS
104 * @retval GLOBUS_NOTIFICATION_PRODUCER_ERROR_TYPE_NULL_PARAMETER
105 * @retval GLOBUS_NOTIFICATION_PRODUCER_ERROR_TYPE_UNKNOWN_RESOURCE
106 * @retval GLOBUS_NOTIFICATION_PRODUCER_ERROR_TYPE_OUT_OF_MEMORY
107 */
108 globus_result_t
109 globus_notification_producer_topic_enumerate(
110 const char * resource_id,
111 wsnt_TopicExpressionType_array ** topics)
112 260 {
113 260 globus_result_t result = GLOBUS_SUCCESS;
114 globus_notification_producer_t producer;
115 wstop_TopicNamespaceType * topic_space;
116 globus_i_notification_producer_topic_t *
117 topic;
118 wsnt_TopicExpressionType * copy;
119 int i;
120 int j;
121
122 260 if (topics == NULL)
123 {
124 0 result = GLOBUS_NOTIFICATION_PRODUCER_NULL_PARAMETER();
125
126 0 goto out;
127 }
128
129 260 *topics = NULL;
130
131 260 if (resource_id == NULL)
132 {
133 0 result = GLOBUS_NOTIFICATION_PRODUCER_NULL_PARAMETER();
134
135 0 goto out;
136 }
137
138 260 GlobusNotificationProducerGlobalLock();
139
140 260 producer = globus_hashtable_lookup(
141 &globus_i_notification_producers,
142 (void *) resource_id);
143
144 260 if (producer == NULL)
145 {
146 0 result = GLOBUS_NOTIFICATION_PRODUCER_UNKNOWN_RESOURCE();
147
148 0 GlobusNotificationProducerGlobalUnlock();
149 0 goto out;
150 }
151 else
152 {
153 260 GlobusNotificationProducerLock(producer);
154 260 GlobusNotificationProducerGlobalUnlock();
155 }
156
157 260 wsnt_TopicExpressionType_array_init(topics);
158
159 /* Enumerate simple / concrete topics */
160 1220 for (i = 0; i < producer->topic_set->length; i++)
161 {
162 960 topic_space = &producer->topic_set->elements[i];
163
164 2740 for (j = 0; j < topic_space->Topic.length; j++)
165 {
166 1780 copy = wsnt_TopicExpressionType_array_push(*topics);
167 1780 if (copy == NULL)
168 {
169 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
170
171 0 goto destroy_topics_out;
172 }
173 1780 topic = topic_space->Topic.elements[j].any.elements[0].value;
174 1780 result = wsnt_TopicExpressionType_copy_contents(copy, &topic->topic);
175
176 1780 if (result != GLOBUS_SUCCESS)
177 {
178 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
179
180 0 goto destroy_topics_out;
181 }
182 }
183 }
184
185 260 destroy_topics_out:
186 260 if (result != GLOBUS_SUCCESS)
187 {
188 0 wsnt_TopicExpressionType_array_destroy(*topics);
189 0 *topics = NULL;
190 }
191 260 GlobusNotificationProducerUnlock(producer);
192 260 out:
193 260 return result;
194 }
195 /* globus_notification_producer_topic_enumerate() */
196
197 /**
198 * Enumerate the topics published by a notification producer
199 * @ingroup notification_topics
200 *
201 * @param resource_id
202 * Resource id associated with notification producer state.
203 * @param topic_set
204 * Pointer to a topic set. Will be initialized to contain the values of the
205 * topic set. The caller must free this by calling
206 * wtop_TopicSetType_destroy_contents().
207 *
208 * @retval GLOBUS_SUCCESS
209 * @retval GLOBUS_NOTIFICATION_PRODUCER_ERROR_TYPE_NULL_PARAMETER
210 * @retval GLOBUS_NOTIFICATION_PRODUCER_ERROR_TYPE_UNKNOWN_RESOURCE
211 * @retval GLOBUS_NOTIFICATION_PRODUCER_ERROR_TYPE_OUT_OF_MEMORY
212 */
213 globus_result_t
214 globus_notification_producer_get_topic_set(
215 const char * resource_id,
216 wstop_TopicSetType ** topic_set)
217 7 {
218 7 globus_result_t result = GLOBUS_SUCCESS;
219 globus_notification_producer_t producer;
220 xmlDocPtr doc;
221 xmlNodePtr child;
222 xmlBufferPtr buf;
223 xsd_any * any;
224 globus_xml_buffer * buffer;
225
226 7 if (topic_set == NULL)
227 {
228 0 result = GLOBUS_NOTIFICATION_PRODUCER_NULL_PARAMETER();
229
230 0 goto out;
231 }
232
233 7 *topic_set = NULL;
234
235 7 if (resource_id == NULL)
236 {
237 0 result = GLOBUS_NOTIFICATION_PRODUCER_NULL_PARAMETER();
238
239 0 goto out;
240 }
241
242 7 GlobusNotificationProducerGlobalLock();
243
244 7 producer = globus_hashtable_lookup(
245 &globus_i_notification_producers,
246 (void *) resource_id);
247
248 7 if (producer == NULL)
249 {
250 0 result = GLOBUS_NOTIFICATION_PRODUCER_UNKNOWN_RESOURCE();
251
252 0 GlobusNotificationProducerGlobalUnlock();
253 0 goto out;
254 }
255 else
256 {
257 7 GlobusNotificationProducerLock(producer);
258 7 GlobusNotificationProducerGlobalUnlock();
259 }
260
261 7 result = globus_l_notification_topic_set_to_dom(
262 &doc,
263 producer->topic_set);
264 7 if (result != GLOBUS_SUCCESS)
265 {
266 0 goto unlock_out;
267 }
268
269 7 buf = xmlBufferCreate();
270 7 if (buf == NULL)
271 {
272 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
273
274 0 goto free_doc_out;
275 }
276
277 7 for (child = xmlDocGetRootElement(doc)->children;
278 60 child != NULL;
279 46 child = child->next)
280 {
281 46 if (xmlNodeDump(buf, doc, child, 0, 0) == -1)
282 {
283 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
284
285 0 goto free_buf_out;
286 }
287 }
288
289 7 result = wstop_TopicSetType_init(topic_set);
290 7 if (result != GLOBUS_SUCCESS)
291 {
292 0 goto free_buf_out;
293 }
294 7 any = xsd_any_array_push(&(*topic_set)->any);
295 7 if (any == NULL)
296 {
297 0 goto free_topic_set_out;
298 }
299
300 7 any->any_info = &globus_xml_buffer_info;
301 7 any->element = NULL;
302 7 result = globus_xml_buffer_init(&buffer);
303 7 if (result != GLOBUS_SUCCESS)
304 {
305 0 goto free_topic_set_out;
306 }
307 7 any->value = buffer;
308
309 7 buffer->buffer = malloc(buf->use);
310 7 if (buffer->buffer == NULL)
311 {
312 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
313
314 0 goto free_topic_set_out;
315 }
316 7 buffer->length = buf->use;
317 7 memcpy(buffer->buffer, buf->content, buf->use);
318 7 buffer->length = buf->use;
319
320 7 if (result != GLOBUS_SUCCESS)
321 {
322 0 free_topic_set_out:
323 0 wstop_TopicSetType_destroy(*topic_set);
324 0 *topic_set = NULL;
325 }
326 7 free_buf_out:
327 7 xmlBufferFree(buf);
328 7 free_doc_out:
329 7 xmlFreeDoc(doc);
330 7 unlock_out:
331 7 GlobusNotificationProducerUnlock(producer);
332 7 out:
333 7 return result;
334 }
335 /* globus_notification_producer_get_topic_set() */
336
337 #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
338 /**
339 * @ingroup globus_i_notification_topic_set
340 */
341 globus_result_t
342 globus_i_notification_topic_set_init(
343 globus_i_notification_topic_set_t * topic_set)
344 0 {
345 globus_result_t result;
346
347 0 result = wstop_TopicNamespaceType_array_init(topic_set);
348
349 0 return result ? GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY() : GLOBUS_SUCCESS;
350 }
351 /* globus_i_notification_topic_set_init() */
352
353 /**
354 * @ingroup globus_i_notification_topic_set
355 */
356 void
357 globus_i_notification_topic_set_destroy(
358 globus_i_notification_topic_set_t topic_set)
359 0 {
360 0 wstop_TopicNamespaceType_array_destroy(topic_set);
361 0 }
362 /* globus_i_notification_topic_set_destroy() */
363
364 /**
365 * @ingroup globus_i_notification_topic_set
366 */
367 globus_result_t
368 globus_i_notification_topic_set_add(
369 globus_i_notification_topic_set_t topic_set,
370 const wsnt_TopicExpressionType * topic_expression)
371 1860 {
372 wstop_TopicNamespaceType * topic_space;
373 wstop_TopicNamespaceType_Topic_array *
374 1860 topics = NULL;
375 1860 wstop_TopicType_array * nonroottopics = NULL;
376 wstop_TopicNamespaceType_Topic * topic;
377 globus_i_notification_producer_topic_t *
378 topic_info;
379 globus_result_t result;
380 1860 globus_bool_t new_topic_space = GLOBUS_FALSE;
381 int i;
382 int j;
383 xsd_any * any;
384 globus_wsnt_topic_value_t topic_value;
385 size_t save_num_tokens;
386
387 1860 if (topic_set == NULL ||
388 topic_expression == NULL)
389 {
390 0 result = GLOBUS_NOTIFICATION_PRODUCER_NULL_PARAMETER();
391
392 0 goto out;
393 }
394
395 1860 result = globus_wsnt_convert_topic_to_value(
396 topic_expression->any,
397 &topic_value);
398
399 5610 for (i = 0; i < topic_value.num_tokens; i++)
400 {
401 3750 switch (topic_value.tokens[i])
402 {
403 case GLOBUS_WSNT_TOPIC_NAMESPACE:
404 1860 topic_space = globus_l_topic_space_lookup(
405 topic_set,
406 topic_value.token_values[i]);
407 1860 if (topic_space == NULL)
408 {
409 /* Create a new TopicSpace for this namespace */
410 925 topic_space = wstop_TopicNamespaceType_array_push(topic_set);
411 925 if (topic_space == NULL)
412 {
413 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
414
415 0 goto free_topic_value_out;
416 }
417 925 new_topic_space = GLOBUS_TRUE;
418 925 result = xsd_anyURI_copy_contents(
419 &topic_space->_targetNamespace,
420 &topic_value.token_values[0]);
421 925 if (result != GLOBUS_SUCCESS)
422 {
423 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
424
425 0 goto remove_topic_space_out;
426 }
427 }
428 1860 break;
429 case GLOBUS_WSNT_TOPIC_PATH_NAME:
430 1890 globus_assert(i > 0);
431 1890 if (topic_value.tokens[i-1] == GLOBUS_WSNT_TOPIC_NAMESPACE)
432 {
433 /* Root topic */
434 1860 topics = &topic_space->Topic;
435 1860 topic = NULL;
436
437 /* Check for existence of the topic already */
438 3117 for (j = 0; j < topics->length; j++)
439 {
440 1281 if (!strcmp(topics->elements[j]._name,
441 topic_value.token_values[i]))
442 {
443 24 topic = &topics->elements[j];
444 24 break;
445 }
446 }
447 1860 if (topic != NULL)
448 {
449 /* Topic path element already exists */
450 24 if (i == (topic_value.num_tokens-1))
451 {
452 /* Leaf we are adding already exists, fail */
453 0 result = GLOBUS_NOTIFICATION_PRODUCER_ALREADY_EXISTS();
454
455 0 goto remove_topic_space_out;
456 }
457 24 nonroottopics = &topic->Topic;
458 24 break;
459 }
460 else
461 {
462 /* Allocate a new topic path element (populate it the
463 * same was as the nonroot ones below
464 */
465 1836 topic = wstop_TopicNamespaceType_Topic_array_push(topics);
466 1836 if (topic == NULL)
467 {
468 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
469
470 0 goto remove_topic_space_out;
471 }
472 }
473 }
474 else
475 {
476 /* Non-root topic */
477 30 topic = NULL;
478
479 /* Check for existence of the topic already */
480 42 for (j = 0; j < nonroottopics->length; j++)
481 {
482 18 if (!strcmp(nonroottopics->elements[j]._name,
483 topic_value.token_values[i]))
484 {
485 6 topic = &nonroottopics->elements[j];
486 6 break;
487 }
488 }
489
490 30 if (topic != NULL)
491 {
492 /* Topic path element already exists */
493 6 if (i == (topic_value.num_tokens-1))
494 {
495 /* Leaf we are adding already exists, fail */
496 0 result = GLOBUS_NOTIFICATION_PRODUCER_ALREADY_EXISTS();
497
498 0 goto remove_topic_space_out;
499 }
500 6 nonroottopics = &topic->Topic;
501 6 break;
502 }
503 else
504 {
505 /* Allocate a new topic path element (populate it below
506 */
507 24 topic = (wstop_TopicNamespaceType_Topic *)
508 wstop_TopicType_array_push(nonroottopics);
509 24 if (topic == NULL)
510 {
511 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
512
513 0 goto remove_topic_space_out;
514 }
515 }
516
517 24 nonroottopics = &topic->Topic;
518 }
519
520 1860 result = xsd_NCName_copy_contents(
521 &topic->_name,
522 &topic_value.token_values[i]);
523 1860 if (result != GLOBUS_SUCCESS)
524 {
525 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
526
527 0 goto free_topic;
528 }
529 1860 topic_info =
530 malloc(sizeof(globus_i_notification_producer_topic_t));
531 1860 result = wsnt_TopicExpressionType_init_contents(
532 &topic_info->topic);
533 1860 if (result != GLOBUS_SUCCESS)
534 {
535 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
536
537 0 goto free_topic;
538 }
539 /* Convert the tokens up to this point in the processing
540 * of the expression to the name of this topic by setting
541 * the length of the token array to be the # of the current
542 * token.
543 */
544 1860 save_num_tokens = topic_value.num_tokens;
545 1860 topic_value.num_tokens = i+1;
546 1860 result = globus_wsnt_convert_value_to_topic(
547 &topic_value,
548 &topic_info->topic);
549 1860 if (result != GLOBUS_SUCCESS)
550 {
551 0 goto free_topic_info;
552 }
553 1860 topic_value.num_tokens = save_num_tokens;
554
555 1860 topic_info->current_message = NULL;
556 1860 result = wsa_EndpointReferenceType_array_init_contents(
557 &topic_info->subscriptions);
558
559 1860 if (result != GLOBUS_SUCCESS)
560 {
561 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
562 0 goto free_topic_info;
563 }
564 1860 any = xsd_any_array_push(&topic->any);
565 1860 if (any == NULL)
566 {
567 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
568 0 goto free_topic_info;
569 }
570 1860 any->value = topic_info;
571 1860 break;
572 default:
573 0 globus_assert(topic_value.tokens[i] == GLOBUS_WSNT_TOPIC_NAMESPACE
574 || topic_value.tokens[i] == GLOBUS_WSNT_TOPIC_PATH_NAME);
575 0 return GLOBUS_FAILURE;
576 }
577 }
578
579 1860 if (result != GLOBUS_SUCCESS)
580 {
581 0 free_topic_info:
582 0 wsnt_TopicExpressionType_destroy_contents(&topic_info->topic);
583 0 free(topic_info);
584 0 free_topic:
585 0 if (nonroottopics)
586 {
587 0 wstop_TopicType_destroy_contents((wstop_TopicType *) topic);
588 }
589 else
590 {
591 0 wstop_TopicNamespaceType_Topic_destroy_contents(topic);
592 }
593 0 topics->length--;
594 0 remove_topic_space_out:
595 0 if (new_topic_space)
596 {
597 0 wstop_TopicNamespaceType_destroy_contents(topic_space);
598 0 topic_set->length--;
599 }
600 }
601
602 1860 free_topic_value_out:
603 1860 globus_wsnt_topic_value_destroy(&topic_value);
604 1860 out:
605 1860 return result;
606 }
607 /* globus_i_notification_topic_set_add() */
608
609 /**
610 * @ingroup globus_i_notification_topic_set
611 */
612 globus_result_t
613 globus_i_notification_topic_set_lookup(
614 globus_i_notification_topic_set_t topic_set,
615 const wsnt_TopicExpressionType * topic_expression,
616 globus_list_t ** topic_list)
617 492 {
618 globus_result_t result;
619 globus_i_notification_producer_topic_t *
620 topic;
621
622 492 *topic_list = NULL;
623
624 981 if (strcmp(topic_expression->_Dialect, SIMPLE_TOPIC_EXPRESSION) == 0 ||
625 strcmp(topic_expression->_Dialect, CONCRETE_TOPIC_EXPRESSION) == 0)
626 {
627 489 result = globus_l_notification_topic_set_concrete_lookup(
628 topic_set,
629 topic_expression,
630 &topic);
631
632 489 if (result == GLOBUS_SUCCESS)
633 {
634 483 globus_list_insert(topic_list, topic);
635 }
636 }
637 3 else if (strcmp(topic_expression->_Dialect, FULL_TOPIC_EXPRESSION) == 0)
638 {
639 3 result = globus_l_notification_topic_set_full_lookup(
640 topic_set,
641 topic_expression,
642 topic_list);
643 }
644 else
645 {
646 0 result = GLOBUS_NOTIFICATION_PRODUCER_DIALECT_UNKNOWN();
647 }
648 492 return result;
649 }
650
651 /**
652 * @ingroup globus_i_notification_topic_set
653 */
654 globus_result_t
655 globus_i_notification_topic_set_remove(
656 globus_i_notification_topic_set_t topic_set,
657 const wsnt_TopicExpressionType * topic_expression)
658 3 {
659 wstop_TopicNamespaceType * topic_space;
660 wstop_TopicNamespaceType_Topic_array *
661 3 topics = NULL;
662 3 wstop_TopicType_array * nonroottopics = NULL;
663 3 wstop_TopicType * parent_topic = NULL;
664 wstop_TopicNamespaceType_Topic * topic;
665 globus_i_notification_producer_topic_t *
666 topic_info;
667 globus_result_t result;
668 3 globus_bool_t new_topic_space = GLOBUS_FALSE;
669 int i;
670 int j;
671 xsd_any * any;
672 globus_wsnt_topic_value_t topic_value;
673 size_t save_num_tokens;
674
675 3 if (topic_set == NULL ||
676 topic_expression == NULL)
677 {
678 0 result = GLOBUS_NOTIFICATION_PRODUCER_NULL_PARAMETER();
679
680 0 goto out;
681 }
682
683 3 result = globus_wsnt_convert_topic_to_value(
684 topic_expression->any,
685 &topic_value);
686
687 9 for (i = 0; i < topic_value.num_tokens; i++)
688 {
689 6 switch (topic_value.tokens[i])
690 {
691 case GLOBUS_WSNT_TOPIC_NAMESPACE:
692 3 topic_space = globus_l_topic_space_lookup(
693 topic_set,
694 topic_value.token_values[i]);
695 3 if (topic_space == NULL)
696 {
697 0 result = GLOBUS_NOTIFICATION_PRODUCER_TOPIC_NOT_SUPPORTED();
698
699 0 goto free_topic_value_out;
700 }
701 3 break;
702 case GLOBUS_WSNT_TOPIC_PATH_NAME:
703 3 globus_assert(i > 0);
704 3 if (topic_value.tokens[i-1] == GLOBUS_WSNT_TOPIC_NAMESPACE)
705 {
706 /* Root topic */
707 3 topics = &topic_space->Topic;
708 3 topic = NULL;
709
710 /* Check for existence of the topic already */
711 3 for (j = 0; j < topics->length; j++)
712 {
713 3 if (!strcmp(topics->elements[j]._name,
714 topic_value.token_values[i]))
715 {
716 3 topic = &topics->elements[j];
717 3 break;
718 }
719 }
720 }
721 else
722 {
723 /* Non-root topic */
724 0 parent_topic = (wstop_TopicType *) topic;
725 0 topic = NULL;
726
727 /* Check for existence of the topic already */
728 0 for (j = 0; j < nonroottopics->length; j++)
729 {
730 0 if (!strcmp(nonroottopics->elements[j]._name,
731 topic_value.token_values[i]))
732 {
733 0 topic = &nonroottopics->elements[j];
734 0 break;
735 }
736 }
737 }
738 3 if (topic == NULL)
739 {
740 0 result = GLOBUS_NOTIFICATION_PRODUCER_TOPIC_NOT_SUPPORTED();
741
742 0 goto free_topic_value_out;
743 }
744 3 nonroottopics = &topic->Topic;
745 3 break;
746 default:
747 0 globus_assert(topic_value.tokens[i] == GLOBUS_WSNT_TOPIC_NAMESPACE
748 || topic_value.tokens[i] == GLOBUS_WSNT_TOPIC_PATH_NAME);
749 0 return GLOBUS_FAILURE;
750 }
751 }
752
753 3 if (topic == NULL)
754 {
755 0 result = GLOBUS_NOTIFICATION_PRODUCER_TOPIC_NOT_SUPPORTED();
756
757 0 goto free_topic_value_out;
758 }
759
760 /* Free subtopics */
761
762 3 if (parent_topic)
763 {
764 0 globus_l_notification_topic_destroy_contents((wstop_TopicType *) topic);
765 0 memmove(&parent_topic->Topic.elements[j],
766 &parent_topic->Topic.elements[j+1],
767 --(parent_topic->Topic.length) - j);
768 }
769 else
770 {
771 /* Free root topic */
772 3 globus_l_notification_root_topic_destroy_contents(
773 topic);
774 3 memmove(&topics->elements[j],
775 &topics->elements[j+1],
776 --(topics->length) - j);
777 }
778
779 3 free_topic_value_out:
780 3 globus_wsnt_topic_value_destroy(&topic_value);
781 3 out:
782 3 return result;
783 }
784 /* globus_i_notification_topic_set_remove() */
785
786 static
787 void
788 globus_l_notification_root_topic_destroy_contents(
789 wstop_TopicNamespaceType_Topic * topic)
790 3 {
791 int i;
792 3 for (i = topic->Topic.length - 1; i >= 0; i--)
793 {
794 0 globus_l_notification_topic_destroy_contents(&topic->Topic.elements[i]);
795 0 topic->Topic.length--;
796 }
797 3 globus_l_notification_topic_info_destroy(topic->any.elements[0].value);
798 3 wstop_TopicNamespaceType_Topic_destroy_contents(topic);
799 3 }
800 /* globus_l_notification_topic_destroy_contents() */
801
802 static
803 void
804 globus_l_notification_topic_destroy_contents(
805 wstop_TopicType * topic)
806 0 {
807 int i;
808 0 for (i = topic->Topic.length - 1; i >= 0; i--)
809 {
810 0 globus_l_notification_topic_destroy_contents(&topic->Topic.elements[i]);
811 0 topic->Topic.length--;
812 }
813 0 globus_l_notification_topic_info_destroy(topic->any.elements[0].value);
814 0 wstop_TopicType_destroy_contents(topic);
815 0 }
816 /* globus_l_notification_topic_destroy_contents() */
817
818 static
819 void
820 globus_l_notification_topic_info_destroy(
821 globus_i_notification_producer_topic_t *
822 topic_info)
823 3 {
824 int i;
825 wsa_EndpointReferenceType * epr;
826 globus_i_notification_subscription_entry_t *
827 subscription_entry;
828 globus_resource_t subscription_resource;
829 globus_result_t result;
830
831 3 wsnt_TopicExpressionType_destroy_contents(&topic_info->topic);
832
833 3 if (topic_info->current_message)
834 {
835 0 xsd_any_destroy(
836 topic_info->current_message);
837 0 topic_info->current_message = NULL;
838 }
839
840 3 for (i = 0; i < topic_info->subscriptions.length; i++)
841 {
842 0 epr = &topic_info->subscriptions.elements[i];
843
844 0 subscription_entry = globus_hashtable_remove(
845 &globus_i_notification_subscriptions,
846 (void *) epr);
847
848 0 if (subscription_entry)
849 {
850 0 wsa_EndpointReferenceType_destroy(subscription_entry->epr);
851 0 free(subscription_entry);
852 }
853
854 0 result = globus_wsrf_core_get_resource_from_epr(
855 epr,
856 &subscription_resource);
857
858 0 if (result == GLOBUS_SUCCESS)
859 {
860 0 globus_resource_destroy(subscription_resource);
861 }
862 }
863 3 wsa_EndpointReferenceType_array_destroy_contents(&topic_info->subscriptions);
864 3 }
865 /* globus_l_notification_topic_info_destroy() */
866
867 static
868 globus_result_t
869 globus_l_notification_topic_set_concrete_lookup(
870 globus_i_notification_topic_set_t topic_set,
871 const wsnt_TopicExpressionType * topic_expression,
872 globus_i_notification_producer_topic_t **
873 topic)
874 489 {
875 globus_result_t result;
876 wstop_TopicNamespaceType * topic_space;
877 wstop_TopicNamespaceType_Topic_array *
878 topics;
879 wstop_TopicType_array * nonroottopics;
880 wstop_TopicType * topic_reference;
881 int i, j;
882 globus_wsnt_topic_value_t topic_value;
883
884 489 *topic = NULL;
885
886 489 result = globus_wsnt_convert_topic_to_value(
887 topic_expression->any,
888 &topic_value);
889 489 if (result != GLOBUS_SUCCESS)
890 {
891 0 goto out;
892 }
893
894 1479 for (i = 0; i < topic_value.num_tokens; i++)
895 {
896 996 switch (topic_value.tokens[i])
897 {
898 case GLOBUS_WSNT_TOPIC_NAMESPACE:
899 489 topic_space = globus_l_topic_space_lookup(
900 topic_set,
901 topic_value.token_values[i]);
902 489 if (topic_space == NULL)
903 {
904 6 result = GLOBUS_NOTIFICATION_PRODUCER_TOPIC_NOT_SUPPORTED();
905 6 goto free_topic_value_out;
906 }
907 483 break;
908 case GLOBUS_WSNT_TOPIC_PATH_NAME:
909 507 if (i == 0)
910 {
911 0 result = GLOBUS_NOTIFICATION_PRODUCER_TOPIC_NOT_SUPPORTED();
912 0 goto free_topic_value_out;
913 }
914 507 if (topic_value.tokens[i-1] == GLOBUS_WSNT_TOPIC_NAMESPACE)
915 {
916 /* Root topic */
917 483 topics = &topic_space->Topic;
918 483 topic_reference = NULL;
919
920 /* Find this topic element */
921 937 for (j = 0; j < topics->length; j++)
922 {
923 937 if (!strcmp(topics->elements[j]._name,
924 topic_value.token_values[i]))
925 {
926 483 topic_reference = (wstop_TopicType *)
927 &topics->elements[j];
928 483 break;
929 }
930 }
931 483 if (topic_reference == NULL)
932 {
933 0 result = GLOBUS_NOTIFICATION_PRODUCER_TOPIC_NOT_SUPPORTED();
934 0 goto free_topic_value_out;
935 }
936 483 nonroottopics = &topic_reference->Topic;
937 }
938 else
939 {
940 /* Non-root topic */
941 24 topic_reference = NULL;
942
943 /* Check for existence of the topic already */
944 33 for (j = 0; j < nonroottopics->length; j++)
945 {
946 33 if (!strcmp(nonroottopics->elements[j]._name,
947 topic_value.token_values[i]))
948 {
949 24 topic_reference = &nonroottopics->elements[j];
950 24 break;
951 }
952 }
953
954 24 if (topic_reference == NULL)
955 {
956 0 result = GLOBUS_NOTIFICATION_PRODUCER_TOPIC_NOT_SUPPORTED();
957 0 goto free_topic_value_out;
958 }
959 24 nonroottopics = &topic_reference->Topic;
960 }
961 507 break;
962 default:
963 0 globus_assert(topic_value.tokens[i] == GLOBUS_WSNT_TOPIC_NAMESPACE
964 || topic_value.tokens[i] == GLOBUS_WSNT_TOPIC_PATH_NAME);
965 0 return GLOBUS_FAILURE;
966 }
967 }
968
969
970 483 if (topic_reference == NULL)
971 {
972 0 result = GLOBUS_NOTIFICATION_PRODUCER_TOPIC_NOT_SUPPORTED();
973 }
974 483 *topic = topic_reference->any.elements[0].value;
975
976 489 free_topic_value_out:
977 489 globus_wsnt_topic_value_destroy(&topic_value);
978 489 out:
979 489 return result;
980 }
981 /* globus_l_notification_topic_set_concrete_lookup() */
982
983 static
984 globus_result_t
985 globus_l_notification_topic_set_full_lookup(
986 globus_i_notification_topic_set_t topic_set,
987 const wsnt_TopicExpressionType * topic_expression,
988 globus_list_t ** topic_list)
989 3 {
990 3 globus_result_t result = GLOBUS_SUCCESS;
991 globus_wsnt_topic_value_t topic_value;
992 xpath_TargetedXPathQueryType query;
993
994 3 result = globus_wsnt_convert_topic_to_value(
995 topic_expression->any,
996 &topic_value);
997 3 if (result != GLOBUS_SUCCESS)
998 {
999 0 goto out;
1000 }
1001 3 result = globus_l_topic_expression_to_xpath(
1002 &topic_value,
1003 &query);
1004 3 if (result != GLOBUS_SUCCESS)
1005 {
1006 0 goto destroy_topic_value_out;
1007 }
1008 3 result = globus_l_notification_topic_set_xpath_lookup(
1009 topic_set,
1010 &query,
1011 topic_list);
1012
1013 3 xpath_TargetedXPathQueryType_destroy_contents(&query);
1014 3 destroy_topic_value_out:
1015 3 globus_wsnt_topic_value_destroy(&topic_value);
1016 3 out:
1017 3 return result;
1018 }
1019 /* globus_l_notification_topic_set_full_lookup() */
1020
1021 static
1022 globus_result_t
1023 globus_l_notification_topic_set_xpath_lookup(
1024 globus_i_notification_topic_set_t topic_set,
1025 xpath_TargetedXPathQueryType * query,
1026 globus_list_t ** topic_list)
1027 3 {
1028 int i;
1029 xmlDocPtr doc;
1030 xmlNsPtr ns;
1031 xmlNodePtr root;
1032 xmlXPathContextPtr xpath_context;
1033 xmlXPathCompExprPtr xpath_expression;
1034 xmlXPathObjectPtr xpath_result;
1035 xmlNodePtr node;
1036 3 globus_result_t result = GLOBUS_SUCCESS;
1037 xpath_TargetedXPathQueryType * serialized_xpath_expression;
1038 globus_i_notification_producer_topic_t *
1039 topic;
1040 3 serialized_xpath_expression = query;
1041
1042 3 xpath_expression = xmlXPathCompile(
1043 BAD_CAST serialized_xpath_expression->queryString);
1044
1045 3 if (xpath_expression == NULL)
1046 {
1047 0 result = GLOBUS_NOTIFICATION_PRODUCER_INVALID_TOPIC_EXPRESSION();
1048
1049 0 goto out;
1050 }
1051
1052 3 result = globus_l_notification_topic_set_to_dom(&doc, topic_set);
1053 3 if (result != GLOBUS_SUCCESS)
1054 {
1055 0 goto out;
1056 }
1057
1058 3 xpath_context = xmlXPathNewContext(doc);
1059 3 if (xpath_context == NULL)
1060 {
1061 0 goto free_doc_out;
1062 }
1063 3 xpath_context->node = xmlDocGetRootElement(doc);
1064
1065 3 for (i = 0; i < serialized_xpath_expression->namespaceMappings.length; i++)
1066 {
1067 0 xmlXPathRegisterNs(
1068 xpath_context,
1069 BAD_CAST serialized_xpath_expression->namespaceMappings.elements[i].mappedName,
1070 BAD_CAST serialized_xpath_expression->namespaceMappings.elements[i].Namespace);
1071 }
1072 3 xpath_result = xmlXPathCompiledEval(xpath_expression, xpath_context);
1073
1074 3 if (xpath_result == NULL || xpath_result->type != XPATH_NODESET ||
1075 xpath_result->nodesetval == NULL)
1076 {
1077 goto destroy_context_out;
1078
1079 }
1080
1081 3 if (xpath_result->type != XPATH_NODESET ||
1082 xpath_result->nodesetval == NULL ||
1083 xpath_result->nodesetval->nodeNr == 0)
1084 {
1085 goto destroy_xpath_result_out;
1086 }
1087
1088 3 if ((xpath_result->type == XPATH_NODESET &&
1089 (xpath_result->nodesetval == NULL ||
1090 xpath_result->nodesetval->nodeNr == 0)))
1091 {
1092 0 result = GLOBUS_FAILURE;
1093 }
1094 6 for (i = 0; i < xpath_result->nodesetval->nodeNr; i++)
1095 {
1096 /* For each node, we find, look up topic pointer and add to the list */
1097 3 node = xpath_result->nodesetval->nodeTab[i];
1098 3 topic = node->_private;
1099
1100 3 globus_list_insert(topic_list, topic);
1101 }
1102
1103 3 destroy_xpath_result_out:
1104 3 if (xpath_result != NULL)
1105 {
1106 3 xmlXPathFreeObject(xpath_result);
1107 }
1108 3 destroy_context_out:
1109 3 xmlXPathFreeContext(xpath_context);
1110 3 free_doc_out:
1111 3 xmlFreeDoc(doc);
1112 3 free_xpath_expression_out:
1113 3 xmlXPathFreeCompExpr(xpath_expression);
1114 3 out:
1115 3 return result;
1116 }
1117 /* globus_l_notification_topic_set_full_lookup() */
1118 globus_result_t
1119 globus_l_notification_topic_set_to_dom(
1120 xmlDocPtr * doc_out,
1121 globus_i_notification_topic_set_t topic_set)
1122 10 {
1123 xmlDocPtr doc;
1124 xmlNsPtr wstop_ns;
1125 xmlNsPtr ns;
1126 xmlNodePtr root;
1127 xmlNodePtr parent;
1128 xmlNodePtr root_topic_node;
1129 xmlNodePtr child_topic_node;
1130 xmlAttrPtr topicattr;
1131 10 int nsnum=0;
1132 wstop_TopicNamespaceType * topic_namespace;
1133 wstop_TopicNamespaceType_Topic * root_topic;
1134 wstop_TopicType * child_topic;
1135 10 xmlChar nsbuf[6] = "ns";
1136 globus_result_t result;
1137 int i,j,k;
1138
1139 10 doc = xmlNewDoc((xmlChar *) "1.0");
1140 10 if (doc == NULL)
1141 {
1142 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
1143
1144 0 goto out;
1145 }
1146 10 root = xmlNewDocNode(doc, NULL, BAD_CAST wstop_TopicSet_qname.local, NULL);
1147 10 if (root == NULL)
1148 {
1149 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
1150
1151 0 goto free_doc_out;
1152 }
1153 10 xmlDocSetRootElement(doc, root);
1154 10 wstop_ns = xmlNewNs(
1155 root, BAD_CAST wstop_TopicSet_qname.Namespace, BAD_CAST "wstop");
1156 10 if (wstop_ns == NULL)
1157 {
1158 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
1159
1160 0 goto free_doc_out;
1161 }
1162 10 xmlSetNs(root, wstop_ns);
1163
1164 /* Create nodes in the tree for each Topic. Outer loop processes a
1165 * wstop_TopicNamespaceType_array.
1166 */
1167 47 for (i = 0; i < topic_set->length; i++)
1168 {
1169 37 topic_namespace = &topic_set->elements[i];
1170
1171 /* Create prefix for this Topic Namespace */
1172 37 sprintf((char *) nsbuf+2, "%03d", nsnum++);
1173 37 globus_assert(nsnum < 1000);
1174
1175 104 for (j = 0; j < topic_namespace->Topic.length; j++)
1176 {
1177 /* Create a new node for each root topic. The private data in the
1178 * node is the globus_i_notification_producer_topic_t associated
1179 * with that topic.
1180 */
1181 67 root_topic = &topic_namespace->Topic.elements[j];
1182
1183 67 root_topic_node = xmlNewChild(root, NULL, BAD_CAST root_topic->_name, NULL);
1184 67 if (root_topic_node == NULL)
1185 {
1186 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
1187
1188 0 goto free_doc_out;
1189 }
1190 67 ns = xmlNewNs(root_topic_node,
1191 BAD_CAST topic_namespace->_targetNamespace,
1192 BAD_CAST nsbuf);
1193 67 if (ns == NULL)
1194 {
1195 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
1196
1197 0 goto free_doc_out;
1198 }
1199 67 xmlSetNs(root_topic_node, ns);
1200
1201 67 root_topic_node->_private = root_topic->any.elements[0].value;
1202 67 wstop_ns = xmlNewNs(root_topic_node,
1203 BAD_CAST wstop_TopicSet_qname.Namespace,
1204 BAD_CAST "wstop");
1205 67 if (wstop_ns == NULL)
1206 {
1207 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
1208
1209 0 goto free_doc_out;
1210 }
1211
1212 67 topicattr = xmlNewNsProp(root_topic_node,
1213 wstop_ns,
1214 BAD_CAST "topic",
1215 BAD_CAST "true");
1216 67 if (topicattr == NULL)
1217 {
1218 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
1219
1220 0 goto free_doc_out;
1221 }
1222
1223 67 parent = root_topic_node;
1224 73 for (k = 0; k < root_topic->Topic.length; k++)
1225 {
1226 /* Recurse through the subtopics of the topic tree and create
1227 * nodes
1228 */
1229 6 result = globus_l_notification_topic_to_dom(
1230 doc,
1231 parent,
1232 &root_topic->Topic.elements[k]);
1233 6 if (result != GLOBUS_SUCCESS)
1234 {
1235 0 goto free_doc_out;
1236 }
1237 }
1238 }
1239 }
1240 10 result = GLOBUS_SUCCESS;
1241 10 free_doc_out:
1242 10 if (result != GLOBUS_SUCCESS)
1243 {
1244 0 xmlFreeDoc(doc);
1245 0 doc = NULL;
1246 }
1247 10 out:
1248 10 *doc_out = doc;
1249 10 return result;
1250 }
1251 /* globus_l_notification_topic_set_to_dom() */
1252
1253 static
1254 globus_result_t
1255 globus_l_notification_topic_to_dom(
1256 xmlDocPtr doc,
1257 xmlNodePtr parent,
1258 wstop_TopicType * child_topic)
1259 9 {
1260 9 globus_result_t result = GLOBUS_SUCCESS;
1261 int i;
1262 xmlNodePtr child_topic_node;
1263 xmlNsPtr ns;
1264 xmlNsPtr wstop_ns;
1265 xmlAttrPtr topicattr;
1266
1267 /* Recurse through the subtopics of the topic tree and create
1268 * nodes
1269 */
1270 9 child_topic_node = xmlNewChild(
1271 parent,
1272 NULL,
1273 BAD_CAST child_topic->_name,
1274 NULL);
1275 9 if (child_topic_node == NULL)
1276 {
1277 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
1278
1279 0 goto free_doc_out;
1280 }
1281 9 ns = xmlNewNs(child_topic_node, NULL, NULL);
1282 9 if (ns == NULL)
1283 {
1284 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
1285
1286 0 goto free_doc_out;
1287 }
1288 9 xmlSetNs(child_topic_node, ns);
1289
1290 9 child_topic_node->_private = child_topic->any.elements[0].value;
1291
1292 9 wstop_ns = xmlNewNs(child_topic_node,
1293 BAD_CAST wstop_TopicSet_qname.Namespace,
1294 BAD_CAST "wstop");
1295 9 if (wstop_ns == NULL)
1296 {
1297 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
1298
1299 0 goto free_doc_out;
1300 }
1301 9 topicattr = xmlNewNsProp(child_topic_node,
1302 wstop_ns,
1303 BAD_CAST "topic",
1304 BAD_CAST "true");
1305 9 if (topicattr == NULL)
1306 {
1307 0 result = GLOBUS_NOTIFICATION_PRODUCER_OUT_OF_MEMORY();
1308
1309 0 goto free_doc_out;
1310 }
1311
1312 12 for (i = 0; i < child_topic->Topic.length; i++)
1313 {
1314 3 result = globus_l_notification_topic_to_dom(
1315 doc,
1316 child_topic_node,
1317 &child_topic->Topic.elements[i]);
1318
1319 3 if (result != GLOBUS_SUCCESS)
1320 {
1321 0 goto free_doc_out;
1322 }
1323 }
1324 9 free_doc_out:
1325 9 return result;
1326 }
1327 /* globus_l_notification_topic_to_dom() */
1328
1329 static
1330 wstop_TopicNamespaceType *
1331 globus_l_topic_space_lookup(
1332 globus_i_notification_topic_set_t topic_set,
1333 xsd_anyURI Namespace)
1334 2352 {
1335 int i;
1336
1337 5526 for (i = 0; i < topic_set->length; i++)
1338 {
1339 4595 if (strcmp(topic_set->elements[i]._targetNamespace, Namespace) == 0)
1340 {
1341 1421 return &topic_set->elements[i];
1342 }
1343 }
1344 931 return NULL;
1345 }
1346 /* globus_l_topic_space_lookup() */
1347
1348 static
1349 globus_result_t
1350 globus_l_topic_expression_to_xpath(
1351 globus_wsnt_topic_value_t * topic_value,
1352 xpath_TargetedXPathQueryType * query)
1353 3 {
1354 globus_result_t result;
1355 int i;
1356 3 size_t query_len = 0;
1357 char * query_string;
1358 3 char * save_ns = NULL;
1359
1360 3 result = xpath_TargetedXPathQueryType_init_contents(query);
1361
1362 3 if (result != GLOBUS_SUCCESS)
1363 {
1364 0 goto out;
1365 }
1366 3 query_len += 2; /* * */
1367 12 for (i = 0; i < topic_value->num_tokens; i++)
1368 {
1369 9 int next_token = -1;
1370 9 if ((i+1) < topic_value->num_tokens)
1371 {
1372 6 next_token = topic_value->tokens[i+1];
1373 }
1374 9 switch (topic_value->tokens[i])
1375 {
1376 case GLOBUS_WSNT_TOPIC_NAMESPACE:
1377 3 save_ns = topic_value->token_values[i];
1378 3 break;
1379 case GLOBUS_WSNT_TOPIC_PATH_NAME:
1380 3 query_len += strlen(topic_value->token_values[i]);
1381 3 if (save_ns)
1382 {
1383 3 query_len += 45; /* [local-name()='%s' and namespace-uri()= '%s'] */
1384 3 query_len += strlen(save_ns);
1385 }
1386 else
1387 {
1388 0 query_len += 19; /* [local-name()='%s'] */
1389 }
1390 3 query_len += 2;
1391 3 break;
1392 case GLOBUS_WSNT_TOPIC_PATH_WILDCARD:
1393 3 query_len+=4; /* '*' '/' '*' */
1394 3 if (save_ns)
1395 {
1396 3 query_len += 20; /* [namespace-uri()=''] */
1397 3 query_len += strlen(save_ns);
1398 }
1399 3 break;
1400 case GLOBUS_WSNT_TOPIC_SUBTREE:
1401 0 if (next_token == GLOBUS_WSNT_TOPIC_DOT)
1402 {
1403 0 query_len += 27; /* /descendant-or-self::node() */
1404 0 if (save_ns)
1405 {
1406 0 query_len += 20; /* [namespace-uri()=''] */
1407 0 query_len += strlen(save_ns);
1408 }
1409 0 i++;
1410 }
1411 0 else if (next_token == GLOBUS_WSNT_TOPIC_PATH_NAME)
1412 {
1413 0 query_len += 27; /* /descendant-or-self::node() */
1414 0 if (save_ns)
1415 {
1416 0 query_len += 20; /* [namespace-uri()=''] */
1417 0 query_len += strlen(save_ns);
1418 }
1419 }
1420 0 else if (next_token == GLOBUS_WSNT_TOPIC_PATH_WILDCARD)
1421 {
1422 0 query_len += 19; /* /descendant::node() */
1423 0 if (save_ns)
1424 {
1425 0 query_len += 20; /* [namespace-uri()=''] */
1426 0 query_len += strlen(save_ns);
1427 }
1428 }
1429 0 break;
1430 case GLOBUS_WSNT_TOPIC_DOT:
1431 0 globus_assert(topic_value->tokens[i] !=
1432 GLOBUS_WSNT_TOPIC_DOT);
1433 0 break;
1434 case GLOBUS_WSNT_TOPIC_CONJUNCTION:
1435 0 query_len+=2; /* |* */
1436 break;
1437 }
1438 9 if (next_token != -1 && next_token != GLOBUS_WSNT_TOPIC_CONJUNCTION)
1439 {
1440 6 query_len++;
1441 }
1442 }
1443 3 query_string = malloc(query_len+1);
1444 3 if (query_string == NULL)
1445 {
1446 0 result = GlobusSoapMessageErrorOutOfMemory;
1447
1448 0 goto out;
1449 }
1450 3 query_len = 0;
1451 3 save_ns = NULL;
1452 3 query_string[query_len++] = '*';
1453 12 for (i = 0; i < topic_value->num_tokens; i++)
1454 {
1455 9 int next_token = -1;
1456 9 if ((i+1) < topic_value->num_tokens)
1457 {
1458 6 next_token = topic_value->tokens[i+1];
1459 }
1460 9 switch (topic_value->tokens[i])
1461 {
1462 case GLOBUS_WSNT_TOPIC_NAMESPACE:
1463 3 save_ns = topic_value->token_values[i];
1464 3 break;
1465 case GLOBUS_WSNT_TOPIC_PATH_NAME:
1466 3 if (save_ns)
1467 {
1468 0 query_len += sprintf(
1469 query_string + query_len,
1470 "[local-name()='%s' and namespace-uri()='%s']",
1471 topic_value->token_values[i],
1472 save_ns);
1473 0 save_ns = NULL;
1474 }
1475 else
1476 {
1477 3 query_len += sprintf(
1478 query_string + query_len,
1479 "[local-name()='%s']",
1480 topic_value->token_values[i]);
1481 }
1482 3 if (next_token != -1 &&
1483 next_token != GLOBUS_WSNT_TOPIC_CONJUNCTION)
1484 {
1485 0 query_len += sprintf(
1486 query_string + query_len,
1487 "/*");
1488 }
1489 3 break;
1490 case GLOBUS_WSNT_TOPIC_PATH_WILDCARD:
1491 3 if (save_ns)
1492 {
1493 3 query_len += sprintf(query_string + query_len,
1494 "[namespace-uri()='%s']",
1495 save_ns);
1496 3 save_ns = NULL;
1497 }
1498 3 if (next_token != -1 &&
1499 next_token != GLOBUS_WSNT_TOPIC_CONJUNCTION)
1500 {
1501 3 query_len += sprintf(query_string + query_len,
1502 "/*");
1503 }
1504 3 break;
1505 case GLOBUS_WSNT_TOPIC_SUBTREE:
1506 0 if (next_token == GLOBUS_WSNT_TOPIC_DOT)
1507 {
1508 0 if (save_ns)
1509 {
1510 0 query_len += sprintf(query_string + query_len,
1511 "[namespace-uri()='%s']/descendant-or-self::node()",
1512 save_ns);
1513 0 save_ns = NULL;
1514 }
1515 else
1516 {
1517 0 if (query_string[query_len-1] == '*')
1518 {
1519 0 query_len--;
1520 }
1521 0 query_len += sprintf(query_string + query_len,
1522 "descendant-or-self::node()");
1523 }
1524 0 i++;
1525 }
1526 0 else if (next_token == GLOBUS_WSNT_TOPIC_PATH_NAME)
1527 {
1528 0 if (save_ns)
1529 {
1530 0 query_len += sprintf(query_string + query_len,
1531 "[namespace-uri()='%s']"
1532 "/descendant-or-self::node()",
1533 save_ns);
1534 0 save_ns = NULL;
1535 }
1536 else
1537 {
1538 0 if (query_string[query_len-1] == '*')
1539 {
1540 0 query_len--;
1541 }
1542 0 query_len += sprintf(query_string + query_len,
1543 "descendant-or-self::node()");
1544 }
1545 }
1546 else
1547 {
1548 0 if (save_ns)
1549 {
1550 0 query_len += sprintf(query_string + query_len,
1551 "[namespace-uri()='%s']"
1552 "/descendant::node()",
1553 save_ns);
1554 0 save_ns = NULL;
1555 }
1556 else
1557 {
1558 0 if (query_string[query_len-1] == '*')
1559 {
1560 0 query_len--;
1561 }
1562 0 query_len += sprintf(query_string + query_len,
1563 "descendant::node()");
1564 }
1565 }
1566 0 break;
1567 case GLOBUS_WSNT_TOPIC_DOT:
1568 0 globus_assert(topic_value->tokens[i] !=
1569 GLOBUS_WSNT_TOPIC_DOT);
1570 0 break;
1571 case GLOBUS_WSNT_TOPIC_CONJUNCTION:
1572 0 query_len += sprintf(query_string+query_len, "|*");
1573 break;
1574 }
1575 }
1576 3 query_string[query_len++] = '\0';
1577 3 query->queryString = query_string;
1578 3 out:
1579 3 return result;
1580 }
1581 /* globus_l_topic_expression_to_xpath() */
1582