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
13 #include "globus_i_operation_provider.h"
14 #include "globus_soap_message.h"
15
16 globus_extension_registry_t             globus_operation_provider_registry =
17 {
18     NULL,
19     GLOBUS_FALSE,
20     GLOBUS_FALSE
21 };
22
23 0 GlobusDebugDefine(GLOBUS_OPERATION_PROVIDER);
24
25 static int
26 globus_l_operation_provider_activate(void);
27
28 static int
29 globus_l_operation_provider_deactivate(void);
30
31 static
32 void
33 globus_l_operation_entry_destroy(
34     void *                              value);
35
36 #include "version.h"
37
38 globus_module_descriptor_t              globus_l_operation_provider_module =
39 {
40     "globus_operation_provider",
41     globus_l_operation_provider_activate,
42     globus_l_operation_provider_deactivate,
43     GLOBUS_NULL,
44     GLOBUS_NULL,
45     &local_version
46 };
47
48 typedef struct globus_l_operation_entry_s
49 {
50     globus_operation_provider_descriptor_t * descriptor;
51     globus_extension_handle_t                extension_handle;
52 } globus_l_operation_entry_t;
53
54 static int
55 globus_l_operation_provider_activate(void)
56 {
57 33     int rc;
58
59 33     rc = globus_module_activate(GLOBUS_COMMON_MODULE);
60 33     if(rc != GLOBUS_SUCCESS)
61     {
62 0         return rc;
63     }
64     
65 33     GlobusDebugInit(GLOBUS_OPERATION_PROVIDER, TRACE ERROR);
66
67 33     rc = globus_module_activate(GLOBUS_SOAP_MESSAGE_MODULE);
68 33     if(rc != GLOBUS_SUCCESS)
69     {
70 0         globus_module_deactivate(GLOBUS_COMMON_MODULE);
71 0         return rc;
72     }
73     
74 33     rc = globus_extension_registry_set_hashing(
75         GLOBUS_OPERATION_PROVIDER_REGISTRY,
76         xsd_QName_hash,
77         xsd_QName_keyeq);
78 33     if(rc != GLOBUS_SUCCESS)
79     {
80 0         globus_module_deactivate(GLOBUS_COMMON_MODULE);
81 0         return rc;
82     }
83
84 33     return 0;
85 }
86
87 static int
88 globus_l_operation_provider_deactivate(void)
89 33 {
90 33     GlobusFuncName(globus_l_operation_provider_deactivate);
91 33     GlobusOperationProviderDebugEnter();
92
93 33     globus_module_deactivate(GLOBUS_SOAP_MESSAGE_MODULE);
94
95 33     GlobusOperationProviderDebugExit();
96
97 33     GlobusDebugDestroy(GLOBUS_OPERATION_PROVIDER);
98 33     globus_module_deactivate(GLOBUS_COMMON_MODULE);
99
100 33     return GLOBUS_SUCCESS;
101 }
102
103 globus_result_t
104 globus_operation_table_init(
105     globus_operation_table_t *          table,
106     const char *                        Namespace)
107 29 {
108 29     int                                 rc = 0;
109 29     globus_result_t                     result = GLOBUS_SUCCESS;
110 29     globus_operation_table_t            newtable;
111 29     GlobusFuncName(globus_operation_table_init);
112 29     GlobusOperationProviderDebugEnter();
113     
114 29     newtable = globus_malloc(sizeof(globus_l_operation_table_t));
115 29     if(!newtable)
116     {
117 0         result = GlobusOperationProviderErrorOutOfMemory;
118 0         goto exit;
119     }
120 29     memset(newtable, 0, sizeof(globus_l_operation_table_t));
121     
122 29     newtable->Namespace = globus_libc_strdup(Namespace);
123 29     rc = globus_hashtable_init(&newtable->table,
124                             10,
125                             globus_hashtable_string_hash,
126                             globus_hashtable_string_keyeq);
127 29     if(rc != GLOBUS_SUCCESS)
128     {
129 0         result = GlobusOperationProviderErrorFailedInit((globus_result_t)rc);
130 0         goto exit;
131     }
132
133 29     *table = newtable;
134
135  exit:
136
137 29     GlobusOperationProviderDebugExit();
138 29     return result;
139 }
140
141 globus_result_t
142 globus_operation_table_get_operation(
143     globus_operation_table_t            table,
144     const char *                        operation_id,
145     void **                             init_operation,
146     void **                             operation)
147 4244 {
148 4244     globus_l_operation_entry_t *        op_entry;
149 4244     globus_result_t                     result = GLOBUS_SUCCESS;
150 4244     GlobusFuncName(globus_operation_table_call);
151 4244     GlobusOperationProviderDebugEnter();
152
153 4244     op_entry = (globus_l_operation_entry_t *) globus_hashtable_lookup(
154         &table->table, (void *)operation_id);
155 4244     if(!op_entry)
156     {
157 0         result = GlobusOperationProviderErrorOpNotFound(operation_id);
158 0         goto exit;
159     }
160
161 4244     *init_operation = op_entry->descriptor->init_operation_func;
162 4244     *operation = op_entry->descriptor->operation_func;
163
164  exit:
165
166 4244     GlobusOperationProviderDebugExit();
167 4244     return result;
168 }
169
170 globus_result_t
171 globus_l_operation_table_add_provider(
172     globus_operation_table_t                 table,
173     xsd_QName *                              operation_name,
174     globus_operation_provider_descriptor_t * op_desc,
175     globus_extension_handle_t                ext_handle)
176 385 {
177 385     int                                 rc = 0;
178 385     globus_result_t                     result = GLOBUS_SUCCESS;
179 385     globus_l_operation_entry_t *        op_entry = NULL;
180 385     GlobusFuncName(globus_l_operation_table_add_default_provider);
181 385     GlobusOperationProviderDebugEnter();
182
183     /* lookup operation name to see if we already have one of those */
184 385     op_entry = globus_hashtable_lookup(&table->table, (void *)op_desc->id);
185 385     if(op_entry)
186     {
187         /* remove it so that we can store the new value */
188 170         op_entry = globus_hashtable_remove(&table->table, (void *)op_desc->id);
189 170         if(op_entry->extension_handle)
190         {
191 0             globus_extension_release(op_entry->extension_handle);
192         }
193
194 170         free(op_entry);
195     }
196
197 385     op_entry = globus_malloc(sizeof(globus_l_operation_entry_t));
198 385     if(!op_entry)
199     {
200 0         result = GlobusOperationProviderErrorOutOfMemory;
201 0         goto exit;
202     }
203 385     memset(op_entry, 0, sizeof(globus_l_operation_entry_t));
204     
205 385     op_entry->descriptor = op_desc;
206 385     op_entry->extension_handle = ext_handle;
207
208 385     rc = globus_hashtable_insert(&table->table, 
209                                  (void *)op_desc->id, op_entry);
210 385     if(rc != GLOBUS_SUCCESS)
211     {
212 0         result = GlobusOperationProviderErrorFailedTableInsert(operation_name);
213         goto exit;
214     }
215     
216  exit:
217
218 385     GlobusOperationProviderDebugExit();
219 385     return result;
220 }
221
222 globus_result_t
223 globus_operation_table_add_default_provider(
224     globus_operation_table_t            table,
225     xsd_QName *                         operation_name,
226     globus_operation_provider_descriptor_t * op_desc)
227 211 {
228 211     globus_result_t                     result = GLOBUS_SUCCESS;
229 211     GlobusFuncName(globus_operation_table_add_default_provider);
230 211     GlobusOperationProviderDebugEnter();
231
232 211     globus_assert(op_desc);
233
234 211     result = globus_l_operation_table_add_provider(
235         table, operation_name, op_desc, NULL);
236 211     if(result != GLOBUS_SUCCESS)
237     {
238 0         result = GlobusOperationProviderErrorFailedTableInsert(operation_name);
239         goto exit;
240     }
241
242  exit:
243         
244 211     GlobusOperationProviderDebugExit();
245 211     return result;
246 }
247
248 globus_result_t
249 globus_operation_table_add_provider(
250     globus_operation_table_t            table,
251     xsd_QName *                         operation_name)
252 174 {
253 174     globus_result_t                     result = GLOBUS_SUCCESS;
254 174     globus_extension_handle_t           ext_handle;
255 174     globus_operation_provider_descriptor_t * op_desc;
256 174     GlobusFuncName(globus_operation_table_add_provider);
257 174     GlobusOperationProviderDebugEnter();
258
259 174     op_desc = globus_extension_lookup(&ext_handle, 
260                                       GLOBUS_OPERATION_PROVIDER_REGISTRY,
261                                       operation_name);
262 174     if(!op_desc)
263     {
264 0         result = GlobusOperationProviderErrorRegistryLookupFailed(
265             operation_name);
266 0         goto exit;
267     }
268
269 174     result = globus_l_operation_table_add_provider(
270         table, operation_name, op_desc, ext_handle);
271 174     if(result != GLOBUS_SUCCESS)
272     {
273 0         result = GlobusOperationProviderErrorFailedTableInsert(operation_name);
274         goto release_extension;
275     }
276
277 0     goto exit;
278
279  release_extension:
280
281 0     globus_extension_release(ext_handle);
282
283  exit:
284
285 174     GlobusOperationProviderDebugExit();
286 174     return result;
287 }
288
289 static
290 void
291 globus_l_operation_entry_destroy(
292     void *                              value)
293 0 {
294 0     globus_l_operation_entry_t *  entry;
295 0     GlobusFuncName(globus_l_operation_entry_destroy);
296 0     GlobusOperationProviderDebugEnter();
297
298 0     entry = (globus_l_operation_entry_t *) value;
299
300 0     globus_extension_registry_remove(
301         GLOBUS_OPERATION_PROVIDER_REGISTRY,
302         entry->descriptor->name);
303
304 0     if(entry->extension_handle)
305     {
306 0         globus_extension_release(entry->extension_handle);
307     }
308
309 0     free(entry);
310
311 0     GlobusOperationProviderDebugExit();
312 }
313
314 void
315 globus_operation_table_destroy(
316     globus_operation_table_t            table)
317 0 {
318 0     GlobusFuncName(globus_operation_table_destroy);
319 0     GlobusOperationProviderDebugEnter();
320
321 0     if(table)
322     {
323 0         if(table->table)
324         {
325 0             globus_hashtable_destroy_all(&table->table, 
326                                          globus_l_operation_entry_destroy);
327         }
328         
329 0         if(table->Namespace)
330         {
331 0             free(table->Namespace);
332         }
333
334 0         free(table);
335     }
336     
337 0     GlobusOperationProviderDebugExit();
338 }
339
340 globus_result_t
341 globus_operation_table_init_resource(
342     globus_operation_table_t            table,
343     const char *                        id)
344 25 {
345 25     globus_l_operation_entry_t *             entry;
346 25     globus_operation_provider_descriptor_t * op;
347 25     globus_result_t                          result = GLOBUS_SUCCESS;
348
349 25     GlobusFuncName(globus_operation_table_init_resource);
350 25     GlobusOperationProviderDebugEnter();
351
352 25     entry = globus_hashtable_first(&table->table);
353 212     while(entry)
354     {
355 187         op = entry->descriptor;
356 187         if(op && op->init_resource)
357         {
358 25             result = op->init_resource(id);
359 25             if(result != GLOBUS_SUCCESS)
360             {
361 0                 GlobusOperationProviderErrorFailedResourceInit(
362                     result, op->name);
363 0                 goto exit;
364             }
365         }
366
367 187         entry = globus_hashtable_next(&table->table);
368     }
369
370  exit:
371 25     GlobusOperationProviderDebugExit();
372 25     return result;