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 #include "globus_soap_message.h"
18 #include "globus_wsrf_resource.h"
19 #include "globus_service_engine.h"
20 #include "globus_operation_provider.h"
21 #include "globus_wsrf_core_tools.h"
22 #include "globus_wsrf_service_group.h"
23 #include "globus_notification_producer.h"
24
25 #include "wssg_Entry.h"
26 #include "wssg_Content.h"
27 #include "wssg_EntryType.h"
28
29 #include "wssg_MembershipContentRuleType.h"
30 #include "wssg_MembershipContentRule.h"
31 #include "wssg_ServiceGroupModificationNotificationType.h"
32 #include "wssg_EntryAdditionNotification.h"
33 #include "wssg_EntryRemovalNotification.h"
34 #include "wsa_EndpointReferenceType.h"
35 #include "wsnt_TopicExpressionType.h"
36
37 #include "version.h"
38
39
40 /**
41 * @defgroup wssg_ServiceGroup_provider ServiceGroup Provider
42 *
43 * <h2>Provider Usage Overview</h2>
44 * This operation provider implements the ServiceGroup portType
45 * defined in
46 * http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-02.pdf
47 *
48 * This portType consists of resource properties wssg:EntryURI and
49 * wssg:MembershipContentRule.
50 *
51 * This provider is located in the
52 * @b globus_wssg_ServiceGroup_provider extension. After this
53 * extension is activated, the provider may be associated with a service by
54 * adding the provider for
55 {http://docs.oasis-open.org/wsrf/sgw-2/providers}ServiceGroup to the service.
56 */
57
58 /* Prototypes */
59 static
60 globus_result_t
61 wssg_ServiceGroup_init_resource(
62 const struct wsa_EndpointReferenceType_s *epr);
63
64 static
65 void
66 wssg_ServiceGroup_get_property(
67 void * arg,
68 const xsd_QName * qname,
69 void ** property);
70
71 static
72 globus_bool_t
73 wssg_ServiceGroup_set_property(
74 void * arg,
75 const xsd_QName * qname,
76 void * property);
77
78 static
79 void
80 wssg_l_entry_add_callback(
81 void * arg,
82 const wssg_EntryType * entry);
83
84 static
85 void
86 wssg_l_entry_remove_callback(
87 void * arg,
88 const wssg_EntryType * entry);
89
90 static
91 int
92 wssg_l_ServiceGroup_activate(void);
93
94 static
95 int
96 wssg_l_ServiceGroup_deactivate(void);
97
98 /* Local Variables */
99 static xsd_QName wssg_ServiceGroup_provider_qname =
100 {
101 "http://docs.oasis-open.org/wsrf/sgw-2/providers",
102 "ServiceGroup"
103 };
104
105 static
106 wsnt_TopicExpressionType wssg_EntryAdditionTopic;
107
108 static
109 wsnt_TopicExpressionType wssg_EntryRemovalTopic;
110
111 static
112 globus_operation_provider_descriptor_t
113 wssg_ServiceGroup_descriptor =
114 {
115 &wssg_ServiceGroup_provider_qname,
116 "ServiceGroup",
117 NULL,
118 wssg_ServiceGroup_init_resource
119 };
120
121 GlobusExtensionDefineModule(globus_wssg_ServiceGroup_provider) =
122 {
123 "globus_wssg_ServiceGroup_provider",
124 wssg_l_ServiceGroup_activate,
125 wssg_l_ServiceGroup_deactivate,
126 NULL,
127 NULL,
128 &local_version
129 };
130
131
132 /**
133 * Initialize the ServiceGroup parts of the resource. This will use the
134 * globus_wsrf_service_group API to create state used to handle service
135 * group entry management, and then create some ResourceProperties which
136 * are expected by a service group implemtation.
137 *
138 * In order to set up the service group, we need to know 2 WSRF
139 * resource-specific pieces of information. One is the
140 * wssg:MembershipContentRule (which governs membership into the group) and
141 * another is the URI of the service which implements the
142 * wssg:ServiceGroupEntry functionality. We assume these are communicated
143 * through two resource properties: wssg:MembershipContentRule (an official
144 * part of the ServiceGroup resource definition), and wssg:ServiceGroupEntryURI
145 * (something added for this implementation--it's value is the URI of the
146 * service which will implement the ServiceGroupEntry functionality). If the
147 * latter is not defined, we will construct one using the default implementation
148 * of service group entries, but the former is required if the provider is
149 * to work.
150 */
151 static
152 globus_result_t
153 wssg_ServiceGroup_init_resource(
154 const struct wsa_EndpointReferenceType_s *
155 epr)
156 8 {
157 globus_result_t result;
158 char * resource_id;
159 globus_resource_t resource;
160 wssg_MembershipContentRuleType * membership_content_rule;
161 8 wsa_AttributedURIType * service_group_entry_uri = NULL;
162 xsd_QName wssg_ServiceGroupEntryURI =
163 {
164 "http://docs.oasis-open.org/wsrf/sgw-2/providers",
165 "ServiceGroupEntryURI"
166 8 };
167 wsa_EndpointReferenceType * epr_copy;
168
169 8 result = globus_wsrf_core_get_resource_id_from_epr(
170 epr,
171 &resource_id);
172
173 8 if (result != GLOBUS_SUCCESS)
174 {
175 0 goto out;
176 }
177 8 result = globus_resource_find(
178 resource_id,
179 &resource);
180 8 if (result != GLOBUS_SUCCESS)
181 {
182 0 goto free_resource_id_out;
183 }
184 8 result = globus_notification_producer_create(
185 resource_id,
186 NULL,
187 NULL);
188
189 8 if (result != GLOBUS_SUCCESS)
190 {
191 globus_object_t * err;
192
193 0 err = globus_error_get(result);
194
195 0 if (!globus_error_match(
196 err,
197 GLOBUS_NOTIFICATION_PRODUCER_MODULE,
198 GLOBUS_NOTIFICATION_PRODUCER_ERROR_TYPE_ALREADY_EXISTS))
199 {
200 0 result = globus_error_put(err);
201 0 goto finish_out;
202 }
203 else
204 {
205 0 globus_object_free(err);
206 0 result = GLOBUS_SUCCESS;
207 }
208 }
209
210 8 result = globus_resource_get_property(
211 resource,
212 &wssg_MembershipContentRule_qname,
213 (void **) &membership_content_rule,
214 NULL);
215
216 8 if (result != GLOBUS_SUCCESS)
217 {
218 0 goto finish_out;
219 }
220
221 8 result = globus_resource_get_property(
222 resource,
223 &wssg_ServiceGroupEntryURI,
224 (void **) &service_group_entry_uri,
225 NULL);
226
227 /* It's ok if this property isn't present---the service_group module
228 * has a reasonable default service_group_entry_uri value.
229 */
230 8 if (result != GLOBUS_SUCCESS &&
231 !globus_error_match(globus_error_peek(result),
232 GLOBUS_WSRF_RESOURCE_MODULE,
233 GLOBUS_WSRF_RESOURCE_ERROR_TYPE_UNKNOWN_PROPERTY))
234 {
235 0 goto finish_out;
236 }
237
238 8 result = wsa_EndpointReferenceType_copy(
239 &epr_copy,
240 epr);
241
242 8 if (result != GLOBUS_SUCCESS)
243 {
244 0 goto finish_out;
245 }
246
247 8 result = globus_service_group_create(
248 epr,
249 membership_content_rule,
250 service_group_entry_uri,
251 wssg_l_entry_add_callback,
252 wssg_l_entry_remove_callback,
253 epr_copy);
254
255 8 if (result != GLOBUS_SUCCESS)
256 {
257 0 goto free_epr_copy_out;
258 }
259
260 8 result = globus_notification_producer_topic_create(
261 resource_id,
262 &wssg_EntryAdditionTopic);
263
264 8 if (result != GLOBUS_SUCCESS)
265 {
266 0 goto destroy_service_group_out;
267 }
268 8 result = globus_notification_producer_topic_create(
269 resource_id,
270 &wssg_EntryRemovalTopic);
271
272 8 if (result != GLOBUS_SUCCESS)
273 {
274 0 goto destroy_service_group_out;
275 }
276
277 8 result = globus_resource_create_property_callback(
278 resource,
279 &wssg_Entry_qname,
280 &wssg_EntryType_array_info,
281 wssg_ServiceGroup_get_property,
282 wssg_ServiceGroup_set_property,
283 epr_copy);
284
285 8 if (result != GLOBUS_SUCCESS)
286 {
287 0 destroy_service_group_out:
288 0 globus_service_group_destroy(epr);
289 0 free_epr_copy_out:
290 0 wsa_EndpointReferenceType_destroy(epr_copy);
291 }
292 8 finish_out:
293 8 globus_resource_finish(resource);
294 8 free_resource_id_out:
295 8 free(resource_id);
296 8 out:
297 8 return result;
298 }
299 /* wssg_ServiceGroup_init_resource() */
300
301 static
302 void
303 wssg_ServiceGroup_get_property(
304 void * arg,
305 const xsd_QName * qname,
306 void ** property)
307 8 {
308 globus_resource_t resource;
309 globus_result_t result;
310 wssg_EntryType_array * entries;
311
312 8 *property = NULL;
313
314 8 result = globus_wsrf_core_get_resource_from_epr(
315 arg,
316 &resource);
317 8 if (result != GLOBUS_SUCCESS)
318 {
319 0 goto out;
320 }
321 8 if (!xsd_QName_keyeq((void *) qname, &wssg_Entry_qname))
322 {
323 0 goto finish_out;
324 }
325
326 8 result = wssg_EntryType_array_init(&entries);
327 8 if (result != GLOBUS_SUCCESS)
328 {
329 0 goto finish_out;
330 }
331
332 8 result = globus_service_group_get_entries(
333 arg,
334 entries);
335
336 8 if (result != GLOBUS_SUCCESS)
337 {
338 0 goto free_entries_out;
339 }
340
341 8 *property = entries;
342
343 8 free_entries_out:
344 8 if (result != GLOBUS_SUCCESS)
345 {
346 0 wssg_EntryType_array_destroy(entries);
347 }
348 8 finish_out:
349 8 globus_resource_finish(resource);
350 8 out:
351 return;
352 }
353 /* wssg_ServiceGroup_get_property() */
354
355 static
356 globus_bool_t
357 wssg_ServiceGroup_set_property(
358 void * arg,
359 const xsd_QName * qname,
360 void * property)
361 0 {
362 /* The properties defined here are not settable by other code */
363 0 return GLOBUS_FALSE;
364 }
365 /* wssg_ServiceGroup_set_property() */
366
367
368 static
369 void
370 wssg_l_entry_add_callback(
371 void * arg,
372 const wssg_EntryType * entry)
373 6 {
374 char * resource_id;
375 globus_result_t result;
376 xsd_any * message;
377 wssg_ServiceGroupModificationNotificationType
378 notification;
379 globus_resource_t entry_resource;
380
381 6 result = globus_wsrf_core_get_resource_id_from_epr(
382 arg,
383 &resource_id);
384
385 6 if (result != GLOBUS_SUCCESS)
386 {
387 0 goto out;
388 }
389
390 6 result = xsd_any_init(&message);
391 6 if (result != GLOBUS_SUCCESS)
392 {
393 0 goto free_resource_id_out;
394 }
395
396 6 result = xsd_QName_copy(&message->element,
397 &wssg_EntryAdditionNotification_qname);
398 6 if (result != GLOBUS_SUCCESS)
399 {
400 0 goto destroy_message_out;
401 }
402 6 message->any_info = &wssg_ServiceGroupModificationNotificationType_info;
403
404 6 result = wssg_ServiceGroupModificationNotificationType_init_contents(
405 &notification);
406 6 if (result != GLOBUS_SUCCESS)
407 {
408 0 goto destroy_message_out;
409 }
410
411 6 notification.ServiceGroupEntryEPR = entry->ServiceGroupEntryEPR;
412 6 notification.MemberServiceEPR = entry->MemberServiceEPR;
413
414 6 result = globus_wsrf_core_get_resource_from_epr(
415 entry->ServiceGroupEntryEPR,
416 &entry_resource);
417 6 if (result != GLOBUS_SUCCESS)
418 {
419 0 goto destroy_message_out;
420 }
421 6 result = globus_resource_get_property(
422 entry_resource,
423 &wssg_Content_qname,
424 (void **) &notification.Content,
425 NULL);
426 6 if (result != GLOBUS_SUCCESS)
427 {
428 0 goto finish_entry_resource_out;
429 }
430 6 message->value = &notification;
431
432 6 result = globus_notification_producer_topic_changed(
433 resource_id,
434 &wssg_EntryAdditionTopic,
435 message,
436 NULL,
437 NULL);
438
439 6 message->value = NULL;
440
441 6 finish_entry_resource_out:
442 6 globus_resource_finish(entry_resource);
443 6 destroy_message_out:
444 6 xsd_any_destroy(message);
445 6 free_resource_id_out:
446 6 free(resource_id);
447 6 out:
448 return;
449 }
450 /* wssg_l_entry_add_callback() */
451
452 static
453 void
454 wssg_l_entry_remove_callback(
455 void * arg,
456 const wssg_EntryType * entry)
457 0 {
458 char * resource_id;
459 globus_result_t result;
460 xsd_any * message;
461 wssg_ServiceGroupModificationNotificationType
462 notification;
463 globus_resource_t entry_resource;
464
465 0 result = globus_wsrf_core_get_resource_id_from_epr(
466 arg,
467 &resource_id);
468
469 0 if (result != GLOBUS_SUCCESS)
470 {
471 0 goto out;
472 }
473
474 0 result = xsd_any_init(&message);
475 0 if (result != GLOBUS_SUCCESS)
476 {
477 0 goto free_resource_id_out;
478 }
479
480 0 result = xsd_QName_copy(&message->element,
481 &wssg_EntryRemovalNotification_qname);
482 0 if (result != GLOBUS_SUCCESS)
483 {
484 0 goto destroy_message_out;
485 }
486 0 message->any_info = &wssg_ServiceGroupModificationNotificationType_info;
487
488 0 result = wssg_ServiceGroupModificationNotificationType_init_contents(
489 &notification);
490 0 if (result != GLOBUS_SUCCESS)
491 {
492 0 goto destroy_message_out;
493 }
494
495 0 notification.ServiceGroupEntryEPR = entry->ServiceGroupEntryEPR;
496 0 notification.MemberServiceEPR = entry->MemberServiceEPR;
497
498 0 result = globus_wsrf_core_get_resource_from_epr(
499 entry->ServiceGroupEntryEPR,
500 &entry_resource);
501 0 if (result != GLOBUS_SUCCESS)
502 {
503 0 goto destroy_message_out;
504 }
505 0 result = globus_resource_get_property(
506 entry_resource,
507 &wssg_Content_qname,
508 (void **) &notification.Content,
509 NULL);
510 0 if (result != GLOBUS_SUCCESS)
511 {
512 0 goto finish_entry_resource_out;
513 }
514 0 message->value = &notification;
515
516 0 result = globus_notification_producer_topic_changed(
517 resource_id,
518 &wssg_EntryRemovalTopic,
519 message,
520 NULL,
521 NULL);
522
523 0 message->value = NULL;
524
525 0 finish_entry_resource_out:
526 0 globus_resource_finish(entry_resource);
527 0 destroy_message_out:
528 0 xsd_any_destroy(message);
529 0 free_resource_id_out:
530 0 free(resource_id);
531 0 out:
532 return;
533 }
534
535 #define WSNT_NS "http://docs.oasis-open.org/wsrf/sg-2"
536
537 static
538 int
539 wssg_l_ServiceGroup_activate(void)
540 50 {
541 50 int res = 0;
542 GlobusFuncName(wssg_l_ServiceGroup_activate);
543
544 50 res = globus_module_activate(GLOBUS_WSRF_SERVICE_GROUP_MODULE);
545 50 if (res != GLOBUS_SUCCESS)
546 {
547 0 goto out;
548 }
549
550 50 res = globus_module_activate(GLOBUS_NOTIFICATION_PRODUCER_MODULE);
551
552 50 if (res != GLOBUS_SUCCESS)
553 {
554 0 goto deactivate_service_group_out;
555 }
556 50 res = globus_notification_producer_set_simple_topic_expression_contents(
557 &wssg_EntryAdditionTopic,
558 &wssg_EntryAdditionNotification_qname);
559 50 if (res != GLOBUS_SUCCESS)
560 {
561 0 goto deactivate_notification_producer_out;
562 }
563 50 res = globus_notification_producer_set_simple_topic_expression_contents(
564 &wssg_EntryRemovalTopic,
565 &wssg_EntryRemovalNotification_qname);
566 50 if (res != GLOBUS_SUCCESS)
567 {
568 0 goto destroy_addition_topic;
569 }
570
571 50 res = globus_extension_registry_add(
572 GLOBUS_OPERATION_PROVIDER_REGISTRY,
573 &wssg_ServiceGroup_provider_qname,
574 GlobusExtensionMyModule(globus_wssg_ServiceGroup_provider),
575 &wssg_ServiceGroup_descriptor);
576
577 50 if (res != GLOBUS_SUCCESS)
578 {
579 0 wsnt_TopicExpressionType_destroy_contents(&wssg_EntryRemovalTopic);
580 0 destroy_addition_topic:
581 0 wsnt_TopicExpressionType_destroy_contents(&wssg_EntryAdditionTopic);
582 0 deactivate_notification_producer_out:
583 0 globus_module_deactivate(GLOBUS_NOTIFICATION_PRODUCER_MODULE);
584 0 deactivate_service_group_out:
585 0 globus_module_deactivate(GLOBUS_WSRF_SERVICE_GROUP_MODULE);
586 }
587 50 out:
588 50 return res;
589 }
590 /* wssg_ServiceGroup_activate() */
591
592 static
593 int
594 wssg_l_ServiceGroup_deactivate(void)
595 42 {
596 GlobusFuncName(wssg_ServiceGroup_deactivate);
597
598 42 globus_extension_registry_remove(
599 GLOBUS_OPERATION_PROVIDER_REGISTRY,
600 &wssg_ServiceGroup_provider_qname);
601
602 42 wsnt_TopicExpressionType_destroy_contents(&wssg_EntryAdditionTopic);
603 42 wsnt_TopicExpressionType_destroy_contents(&wssg_EntryRemovalTopic);
604 42 globus_module_deactivate(GLOBUS_NOTIFICATION_PRODUCER_MODULE);
605 42 globus_module_deactivate(GLOBUS_WSRF_SERVICE_GROUP_MODULE);
606
607 42 return 0;
608 }