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_i_operation_provider.h"
19 #include "globus_soap_message.h"
20 #include "globus_soap_message_utils.h"
21 #include "version.h"
22 #include "xsd_QName.h"
23
24 #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
25 globus_extension_registry_t globus_operation_provider_registry =
26 {
27 NULL,
28 GLOBUS_FALSE,
29 GLOBUS_FALSE
30 };
31
32 0 GlobusDebugDefine(GLOBUS_OPERATION_PROVIDER);
33
34 static
35 int
36 globus_l_operation_provider_activate(void);
37
38 static
39 int
40 globus_l_operation_provider_deactivate(void);
41
42 static
43 void
44 globus_l_operation_entry_destroy(
45 void * value);
46
47 static
48 globus_result_t
49 globus_l_operation_table_add_provider(
50 globus_operation_table_t table,
51 xsd_QName * operation_name,
52 globus_operation_provider_descriptor_t * op_desc,
53 globus_extension_handle_t ext_handle);
54
55 globus_module_descriptor_t globus_l_operation_provider_module =
56 {
57 "globus_operation_provider",
58 globus_l_operation_provider_activate,
59 globus_l_operation_provider_deactivate,
60 GLOBUS_NULL,
61 GLOBUS_NULL,
62 &local_version
63 };
64
65 typedef struct globus_l_operation_entry_s
66 {
67 globus_operation_provider_descriptor_t * descriptor;
68 globus_extension_handle_t extension_handle;
69 } globus_l_operation_entry_t;
70
71 #endif /* GLOBUS_DONT_DOCUMENT_INTERNAL */
72
73 /**
74 * Initialize a new operation provider table
75 * @ingroup globus_operation_provider
76 *
77 * Creates a new operation provider table. The caller is responsible for
78 * destroying the table after it is no longer needed by calling
79 * globus_operation_table_destroy().
80 *
81 * @param table
82 * New table to initialize.
83 * @param Namespace
84 * Ignored
85 *
86 * @retval GLOBUS_SUCCESS
87 * Operation provider table successfully initialized.
88 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
89 * The @a table parameter is NULL.
90 * @retval GLOBUS_OPERATION_PROVIDER_ERROR_TyPE_OUT_OF_MEMORY
91 * Insufficient memory to create a new operation provider table.
92 * @retval GLOBUS_OPERATION_PROVIDER_ERROR_TYPE_FAILED_INIT
93 * Error initializing some internal part of the operation provider
94 * table.
95 */
96 globus_result_t
97 globus_operation_table_init(
98 globus_operation_table_t * table,
99 const char * Namespace)
100 400 {
101 400 int rc = 0;
102 400 globus_result_t result = GLOBUS_SUCCESS;
103 400 globus_operation_table_t newtable = NULL;
104 GlobusFuncName(globus_operation_table_init);
105 400 GlobusOperationProviderDebugEnter();
106
107 400 if (table == NULL)
108 {
109 0 result = GlobusSoapMessageErrorNullParam;
110
111 0 goto exit;
112 }
113 400 newtable = calloc(1, sizeof(globus_l_operation_table_t));
114 400 if(!newtable)
115 {
116 0 result = GlobusOperationProviderErrorOutOfMemory;
117 0 goto error_exit;
118 }
119
120 400 if (Namespace)
121 {
122 /* Why? */
123 400 newtable->Namespace = globus_libc_strdup(Namespace);
124 }
125 400 rc = globus_hashtable_init(&newtable->table,
126 11,
127 globus_hashtable_string_hash,
128 globus_hashtable_string_keyeq);
129 400 if(rc != GLOBUS_SUCCESS)
130 {
131 0 result = GlobusOperationProviderErrorFailedInit(
132 (globus_result_t)rc);
133 }
134
135 400 if (result != GLOBUS_SUCCESS)
136 {
137 0 if (newtable->Namespace)
138 {
139 0 free(newtable->Namespace);
140 }
141 0 free(newtable);
142 0 newtable = NULL;
143 }
144 400 error_exit:
145 400 *table = newtable;
146
147 400 exit:
148 400 GlobusOperationProviderDebugExit();
149 400 return result;
150 }
151 /* globus_operation_table_init() */
152
153 /**
154 * Look up an operation in an operation provider table
155 * @ingroup globus_operation_provider
156 * Look up an operation name in an operation table and return the provider
157 * function for that operation.
158 *
159 * @param table
160 * Operation provider table to query.
161 * @param operation_id
162 * Name of the operation to look up.
163 * @param operation
164 * Pointer to be set to the value of the operation provider which will
165 * process this operation.
166 *
167 * @retval GLOBUS_SUCCESS
168 * Operation lookup successful.
169 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
170 * One of @a table, @a operation_id or @a operation is NULL.
171 * @retval GLOBUS_OPERATION_PROVIDER_ERROR_TYPE_OP_NOT_FOUND
172 * The operation table does not contain a provider to handle the
173 * operation named by @a operation_id.
174 */
175 globus_result_t
176 globus_operation_table_get_operation(
177 globus_operation_table_t table,
178 const char * operation_id,
179 void ** operation)
180 21954 {
181 globus_l_operation_entry_t * op_entry;
182 21954 globus_result_t result = GLOBUS_SUCCESS;
183 GlobusFuncName(globus_operation_table_call);
184 21954 GlobusOperationProviderDebugEnter();
185
186 21954 if (operation == NULL || table == NULL || operation_id == NULL)
187 {
188 0 result = GlobusSoapMessageErrorNullParam;
189
190 0 goto exit;
191 }
192 21954 op_entry = globus_hashtable_lookup(
193 &table->table, (void *)operation_id);
194 21954 if(!op_entry)
195 {
196 0 result = GlobusOperationProviderErrorOpNotFound(operation_id);
197 0 goto exit;
198 }
199
200 21954 *operation = op_entry->descriptor->operation_func;
201
202 21954 exit:
203 21954 if (result != GLOBUS_SUCCESS)
204 {
205 0 if (operation != NULL)
206 {
207 0 *operation = NULL;
208 }
209 }
210
211 21954 GlobusOperationProviderDebugExit();
212 21954 return result;
213 }
214 /* globus_operation_table_get_operation() */
215
216 /**
217 * Add an operation to the operation provider table and set the provider which
218 * will handle it
219 * @ingroup globus_operation_provider
220 *
221 * Defines an entry for a new operation in the provider table. The @a op_desc
222 * parameter contains information about how the operation is implemented so
223 * that the service engine can dispatch this operation.
224 *
225 * @param table
226 * Operation provider table to query.
227 * @param operation_name
228 * Name of the operation to add the provider for. The @a id field in the
229 * @a op_desc structure will be used as the operation name in the
230 * operation_table.
231 * @param op_desc
232 * Description of the operation implementation.
233 *
234 * @retval GLOBUS_SUCCESS
235 * Operation added successfully.
236 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
237 * One of @a table, @a operation_id or @a operation is NULL.
238 * @retval GLOBUS_OPERATION_PROVIDER_ERROR_TYPE_FAILED_TABLE_INSERT
239 * The operation could not be added to the operation table.
240 */
241 globus_result_t
242 globus_operation_table_add_default_provider(
243 globus_operation_table_t table,
244 xsd_QName * operation_name,
245 globus_operation_provider_descriptor_t *
246 op_desc)
247 2371 {
248 2371 globus_result_t result = GLOBUS_SUCCESS;
249 GlobusFuncName(globus_operation_table_add_default_provider);
250 2371 GlobusOperationProviderDebugEnter();
251
252 2371 if (table == NULL || operation_name == NULL || op_desc == NULL)
253 {
254 0 result = GlobusSoapMessageErrorNullParam;
255
256 0 goto exit;
257 }
258
259 2371 result = globus_l_operation_table_add_provider(
260 table, operation_name, op_desc, NULL);
261 2371 if(result != GLOBUS_SUCCESS)
262 {
263 0 result = GlobusOperationProviderErrorFailedTableInsert(operation_name);
264 0 goto exit;
265 }
266
267 2371 exit:
268 2371 GlobusOperationProviderDebugExit();
269 2371 return result;
270 }
271 /* globus_operation_table_add_default_provider() */
272
273 /**
274 * Add an operation to the operation provider table and set the provider which
275 * will handle it
276 * @ingroup globus_operation_provider
277 *
278 * Looks up the @a operation_name in the operation provider registry and add
279 * its to an operation provider table.
280 *
281 * This function is equivalent to looking up the @a operation_name in the
282 * operation provider table and then calling
283 * globus_operation_table_add_default_provider().
284 *
285 * @param table
286 * Operation provider table to query.
287 * @param operation_name
288 * Name of the operation to add the provider for. The @a operation_name
289 * is looked up in the global operation provider registry and then
290 * added to the @a table.
291 *
292 * @retval GLOBUS_SUCCESS
293 * Operation added successfully.
294 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
295 * One of @a table, @a operation_id or @a operation is NULL.
296 * @retval GLOBUS_OPERATION_PROVIDER_ERROR_TYPE_FAILED_TABLE_INSERT
297 * The operation could not be added to the operation table.
298 */
299 globus_result_t
300 globus_operation_table_add_provider(
301 globus_operation_table_t table,
302 xsd_QName * operation_name)
303 3434 {
304 3434 globus_result_t result = GLOBUS_SUCCESS;
305 globus_extension_handle_t ext_handle;
306 globus_operation_provider_descriptor_t * op_desc;
307 GlobusFuncName(globus_operation_table_add_provider);
308 3434 GlobusOperationProviderDebugEnter();
309
310 3434 op_desc = globus_extension_lookup(&ext_handle,
311 GLOBUS_OPERATION_PROVIDER_REGISTRY,
312 operation_name);
313 3434 if(!op_desc)
314 {
315 0 result = GlobusOperationProviderErrorRegistryLookupFailed(
316 operation_name);
317 0 goto exit;
318 }
319
320 3434 result = globus_l_operation_table_add_provider(
321 table, operation_name, op_desc, ext_handle);
322 3434 if(result != GLOBUS_SUCCESS)
323 {
324 0 result = GlobusOperationProviderErrorFailedTableInsert(operation_name);
325 0 goto release_extension;
326 }
327
328 3434 goto exit;
329
330 0 release_extension:
331
332 0 globus_extension_release(ext_handle);
333
334 3434 exit:
335
336 3434 GlobusOperationProviderDebugExit();
337 3434 return result;
338 }
339 /* globus_operation_table_add_provider() */
340
341 /**
342 * Destroy an operation table
343 * @ingroup globus_operation_provider
344 *
345 * Destroy an operation able and free all memory associated with it.
346 *
347 * @param table
348 * Operation provider table to destroy.
349 */
350 void
351 globus_operation_table_destroy(
352 globus_operation_table_t table)
353 96 {
354 GlobusFuncName(globus_operation_table_destroy);
355 96 GlobusOperationProviderDebugEnter();
356
357 96 if(table)
358 {
359 96 if(table->table)
360 {
361 96 globus_hashtable_destroy_all(&table->table,
362 globus_l_operation_entry_destroy);
363 }
364
365 96 if(table->Namespace)
366 {
367 96 free(table->Namespace);
368 }
369
370 96 free(table);
371 }
372
373 96 GlobusOperationProviderDebugExit();
374 96 }
375 /* globus_operation_table_destroy() */
376
377 /**
378 * Call all operation provider resource initialization functions for a new
379 * resource
380 * @ingroup globus_operation_provider
381 *
382 * Calls the init_resource function for each operation provider associated
383 * with a service.
384 *
385 * @param table
386 * Operation provider table associated with the service which is creating
387 * the resouce.
388 * @param epr
389 * Endpoint reference of the resource which is be constructed.
390 *
391 * @retval GLOBUS_SUCCESS
392 * All operation providers successfully initialized.
393 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
394 * One of @a table or @a epr is NULL.
395 * @retval GLOBUS_OPERATION_PROVIDER_ERROR_TYPE_FAILED_RESOURCE_INIT
396 * One of the operation providers failed to initialize the resource.
397 */
398 globus_result_t
399 globus_operation_table_init_resource(
400 globus_operation_table_t table,
401 const struct wsa_EndpointReferenceType_s *
402 epr)
403 292 {
404 globus_l_operation_entry_t * entry;
405 globus_operation_provider_descriptor_t * op;
406 292 globus_result_t result = GLOBUS_SUCCESS;
407 GlobusFuncName(globus_operation_table_init_resource);
408
409 292 GlobusOperationProviderDebugEnter();
410
411 292 if (table == NULL || epr == NULL)
412 {
413 0 result = GlobusSoapMessageErrorNullParam;
414
415 0 goto exit;
416 }
417
418 292 entry = globus_hashtable_first(&table->table);
419 3434 while(entry)
420 {
421 2850 op = entry->descriptor;
422 2850 if(op && op->init_resource)
423 {
424 596 result = op->init_resource(epr);
425 596 if(result != GLOBUS_SUCCESS)
426 {
427 0 GlobusOperationProviderErrorFailedResourceInit(
428 result, op->name);
429 0 goto exit;
430 }
431 }
432
433 2850 entry = globus_hashtable_next(&table->table);
434 }
435
436 292 exit:
437 292 GlobusOperationProviderDebugExit();
438 292 return result;
439 }
440 /* globus_operation_table_init_resource() */
441
442 #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
443 static
444 int
445 globus_l_operation_provider_activate(void)
446 718 {
447 int rc;
448
449 718 rc = globus_module_activate(GLOBUS_COMMON_MODULE);
450 718 if(rc != GLOBUS_SUCCESS)
451 {
452 0 return rc;
453 }
454
455 718 GlobusDebugInit(GLOBUS_OPERATION_PROVIDER, TRACE ERROR);
456
457 718 rc = globus_module_activate(GLOBUS_SOAP_MESSAGE_MODULE);
458 718 if(rc != GLOBUS_SUCCESS)
459 {
460 0 globus_module_deactivate(GLOBUS_COMMON_MODULE);
461 0 return rc;
462 }
463
464 718 rc = globus_extension_registry_set_hashing(
465 GLOBUS_OPERATION_PROVIDER_REGISTRY,
466 xsd_QName_hash,
467 xsd_QName_keyeq);
468 718 if(rc != GLOBUS_SUCCESS)
469 {
470 0 globus_module_deactivate(GLOBUS_COMMON_MODULE);
471 0 return rc;
472 }
473
474 718 return 0;
475 }
476 /* globus_l_operation_provider_activate() */
477
478 static
479 int
480 globus_l_operation_provider_deactivate(void)
481 150 {
482 GlobusFuncName(globus_l_operation_provider_deactivate);
483 150 GlobusOperationProviderDebugEnter();
484
485 150 globus_module_deactivate(GLOBUS_SOAP_MESSAGE_MODULE);
486
487 150 GlobusOperationProviderDebugExit();
488
489 150 GlobusDebugDestroy(GLOBUS_OPERATION_PROVIDER);
490 150 globus_module_deactivate(GLOBUS_COMMON_MODULE);
491
492 150 return GLOBUS_SUCCESS;
493 }
494 /* globus_l_operation_provider_deactivate() */
495
496 static
497 void
498 globus_l_operation_entry_destroy(
499 void * value)
500 990 {
501 globus_l_operation_entry_t * entry;
502 GlobusFuncName(globus_l_operation_entry_destroy);
503 990 GlobusOperationProviderDebugEnter();
504
505 990 entry = (globus_l_operation_entry_t *) value;
506
507 990 globus_extension_registry_remove(
508 GLOBUS_OPERATION_PROVIDER_REGISTRY,
509 entry->descriptor->name);
510
511 990 if(entry->extension_handle)
512 {
513 894 globus_extension_release(entry->extension_handle);
514 }
515
516 990 free(entry);
517
518 990 GlobusOperationProviderDebugExit();
519 990 }
520 /* globus_l_operation_entry_destroy() */
521
522 static
523 globus_result_t
524 globus_l_operation_table_add_provider(
525 globus_operation_table_t table,
526 xsd_QName * operation_name,
527 globus_operation_provider_descriptor_t * op_desc,
528 globus_extension_handle_t ext_handle)
529 5805 {
530 5805 int rc = 0;
531 5805 globus_result_t result = GLOBUS_SUCCESS;
532 5805 globus_l_operation_entry_t * op_entry = NULL;
533 GlobusFuncName(globus_l_operation_table_add_default_provider);
534 5805 GlobusOperationProviderDebugEnter();
535
536 /* lookup operation name to see if we already have one of those */
537 5805 op_entry = globus_hashtable_lookup(&table->table, (void *)op_desc->id);
538 5805 if(op_entry)
539 {
540 /* remove it so that we can store the new value */
541 1875 op_entry = globus_hashtable_remove(&table->table, (void *)op_desc->id);
542 1875 if(op_entry->extension_handle)
543 {
544 0 globus_extension_release(op_entry->extension_handle);
545 }
546
547 1875 free(op_entry);
548 }
549
550 5805 op_entry = globus_malloc(sizeof(globus_l_operation_entry_t));
551 5805 if(!op_entry)
552 {
553 0 result = GlobusOperationProviderErrorOutOfMemory;
554 0 goto exit;
555 }
556 5805 memset(op_entry, 0, sizeof(globus_l_operation_entry_t));
557
558 5805 op_entry->descriptor = op_desc;
559 5805 op_entry->extension_handle = ext_handle;
560
561 5805 rc = globus_hashtable_insert(&table->table,
562 (void *)op_desc->id, op_entry);
563 5805 if(rc != GLOBUS_SUCCESS)
564 {
565 0 result = GlobusOperationProviderErrorFailedTableInsert(operation_name);
566 0 goto exit;
567 }
568
569 5805 exit:
570
571 5805 GlobusOperationProviderDebugExit();
572 5805 return result;
573 }
574 /* globus_l_operation_table_add_provider() */