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