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_common.h"
18 #include "globus_i_handler_chain.h"
19 #include "globus_extension.h"
20 #include "globus_soap_message.h"
21
22 globus_extension_registry_t             globus_handler_registry =
23 {
24     NULL,
25     GLOBUS_FALSE,
26     GLOBUS_FALSE
27 };
28
29 0 GlobusDebugDefine(GLOBUS_HANDLER);
30
31 static globus_list_t *                  globus_l_handler_extensions = NULL;
32 static globus_mutex_t                   globus_l_handler_extensions_mutex;
33
34 enum globus_l_handler_debug_levels
35 {
36     GLOBUS_L_HANDLER_DEBUG_TRACE      = 1,
37     GLOBUS_L_HANDLER_DEBUG_ERROR      = 2
38 };
39
40 #define GlobusHandlerDebugPrintf(level, message)                            \
41     GlobusDebugPrintf(GLOBUS_HANDLER, level, message)
42
43 #define GlobusHandlerDebugEnter()                                           \
44     GlobusHandlerDebugPrintf(                                               \
45         GLOBUS_L_HANDLER_DEBUG_TRACE,                                       \
46         ("[%s] Entering\n", _globus_func_name))
47
48 #define GlobusHandlerDebugExit()                                            \
49     GlobusHandlerDebugPrintf(                                               \
50         GLOBUS_L_HANDLER_DEBUG_TRACE,                                       \
51         ("[%s] Exiting\n", _globus_func_name))
52
53 #define GlobusHandlerErrorHeaderElementNotFound() \
54     globus_error_put( \
55         globus_error_construct_error( \
56             GLOBUS_HANDLER_MODULE, \
57             NULL, \
58             GLOBUS_HANDLER_ERROR_HEADER_ELEMENT_NOT_FOUND, \
59             __FILE__, \
60             _globus_func_name, \
61             __LINE__, \
62             "No Header element found"))
63
64 #define GlobusHandlerErrorRegistryLookupFailed(CAUSE, ENDPOINT) \
65     globus_error_put( \
66                 globus_error_construct_error( \
67                     GLOBUS_HANDLER_MODULE, \
68                     (CAUSE ? globus_error_get(CAUSE) : NULL), \
69                     GLOBUS_HANDLER_ERROR_REGISTRY_LOOKUP_FAILED, \
70                     __FILE__, \
71                     _globus_func_name, \
72                     __LINE__, \
73                     "No handler found at endpoint: %s", ENDPOINT))
74
75 #define GlobusHandlerErrorDefaultTriggerAlreadyDefined()                  \
76     globus_error_put(                                                     \
77                 globus_error_construct_error(                             \
78                     GLOBUS_HANDLER_MODULE,                                \
79                     NULL,                                                 \
80                     GLOBUS_HANDLER_ERROR_DEFAULT_TRIGGER_ALREADY_DEFINED, \
81                     __FILE__,                                             \
82                     _globus_func_name,                                    \
83                     __LINE__,                                             \
84                     "A default trigger handler has already been defined"))
85
86 #define GlobusHandlerErrorNoTriggersDefined()                   \
87     globus_error_put(                                           \
88                 globus_error_construct_error(                   \
89                     GLOBUS_HANDLER_MODULE,                      \
90                     NULL,                                       \
91                     GLOBUS_HANDLER_ERROR_NO_TRIGGERS_DEFINED,   \
92                     __FILE__,                                   \
93                     _globus_func_name,                          \
94                     __LINE__,                                   \
95                     "No triggers defined"))
96
97 static int
98 globus_l_handler_activate(void);
99
100 static int
101 globus_l_handler_deactivate(void);
102
103 #include "version.h"
104
105 globus_module_descriptor_t              globus_i_handler_module =
106 {
107     "globus_handler",
108     globus_l_handler_activate,
109     globus_l_handler_deactivate,
110     GLOBUS_NULL,
111     GLOBUS_NULL,
112     &local_version
113 };
114
115 static int
116 globus_l_handler_activate(void)
117 {
118 0     int rc;
119
120 0     rc = globus_module_activate(GLOBUS_COMMON_MODULE);
121 0     if(rc != GLOBUS_SUCCESS)
122     {
123 0         return rc;
124     }
125
126 0     GlobusHandlerDebugEnter();
127
128 0     rc = globus_module_activate(GLOBUS_SOAP_MESSAGE_MODULE);
129 0     if(rc != GLOBUS_SUCCESS)
130     {
131 0         globus_module_deactivate(GLOBUS_COMMON_MODULE);
132 0         return rc;
133     }
134
135 0     globus_mutex_init(&globus_l_handler_extensions_mutex, NULL);
136
137 0     GlobusHandlerDebugExit();
138 0     return GLOBUS_SUCCESS;
139 }
140
141 static
142 void
143 globus_l_handler_extension_destroy(
144     void *                              ep)
145 0 {
146 0     char *                              symbol = (char *) ep;
147
148 0     globus_extension_deactivate(symbol);
149 0     globus_free(symbol);
150 }
151
152 static int
153 globus_l_handler_deactivate(void)
154 0 {
155 0     GlobusFuncName(globus_l_handler_deactivate);
156 0     GlobusHandlerDebugEnter();
157
158 0     globus_mutex_lock(&globus_l_handler_extensions_mutex); 
159 0     if(globus_l_handler_extensions) 
160     { 
161 0         globus_list_destroy_all(globus_l_handler_extensions, 
162                                 globus_l_handler_extension_destroy); 
163 0         globus_l_handler_extensions = NULL; 
164     } 
165 0     globus_mutex_unlock(&globus_l_handler_extensions_mutex); 
166 0     globus_mutex_destroy(&globus_l_handler_extensions_mutex); 
167     
168 0     globus_module_deactivate(GLOBUS_SOAP_MESSAGE_MODULE);
169
170 0     GlobusHandlerDebugExit();
171 0     GlobusDebugDestroy(GLOBUS_HANDLER);
172
173 0     globus_module_deactivate(GLOBUS_COMMON_MODULE);
174
175 0     return GLOBUS_SUCCESS;
176 }
177
178 typedef struct globus_l_handler_s
179 {
180     globus_extension_handle_t           extension_handle;
181     globus_handler_invoke_func_t        invoke;
182     globus_handler_trigger_t *          trigger;
183 } globus_l_handler_t;
184
185 globus_result_t
186 globus_handler_chain_init(
187     globus_handler_chain_t *            chain)
188 7642 {
189 7642     globus_handler_chain_t              new_chain;
190 7642     globus_result_t                     result = GLOBUS_SUCCESS;
191
192 7642     GlobusFuncName(globus_handler_chain_init);
193 7642     GlobusHandlerDebugEnter();
194
195 7642     new_chain = globus_malloc(sizeof(globus_i_handler_chain_t));
196 7642     if(!new_chain)
197     {
198 0         result = GlobusSoapMessageErrorOutOfMemory;
199 0         GlobusHandlerDebugExit();
200 0         return result;
201     }
202 7642     memset(new_chain, 0, sizeof(globus_i_handler_chain_t));
203     
204 7642     *chain = new_chain;
205
206 7642     GlobusHandlerDebugExit();
207 7642     return result;
208 }
209
210 void
211 globus_l_handler_destroy(
212     void *                              h)
213 27671 {
214 27671     globus_l_handler_t *                entry;
215
216 27671     entry = (globus_l_handler_t *) h;
217
218 27671     if(entry)
219     {
220 27671         free(entry);
221     }
222 }
223
224 void
225 globus_handler_chain_destroy(
226     globus_handler_chain_t              chain)
227 11336 {
228 11336     globus_extension_handle_t           ext;
229 11336     globus_list_t *                     extensions;
230 11336     GlobusFuncName(globus_handler_chain_init);
231 11336     GlobusHandlerDebugEnter();
232
233 11336     globus_list_destroy_all(chain->request_handlers, 
234                             globus_l_handler_destroy);
235 11336     globus_list_destroy_all(chain->response_handlers, 
236                             globus_l_handler_destroy);
237 11336     globus_list_destroy_all(chain->request_init_handlers,
238                             globus_l_handler_destroy);
239 11336     globus_list_destroy_all(chain->request_destroy_handlers,
240                             globus_l_handler_destroy);
241 11336     globus_list_destroy_all(chain->response_init_handlers,
242                             globus_l_handler_destroy);
243 11336     globus_list_destroy_all(chain->response_destroy_handlers,
244                             globus_l_handler_destroy);
245 11336     if(chain->triggers)
246     {
247 3974         globus_hashtable_destroy_all(
248     &chain->triggers,
249     globus_l_handler_destroy);
250     }
251
252 11336     extensions = chain->extensions;
253 19284     while(extensions)
254     {
255 7948 ext = globus_list_first(extensions);
256 7948 globus_extension_release(ext);
257 7948 extensions = globus_list_rest(extensions);
258     }
259
260 11336     globus_list_free(chain->extensions);
261
262 11336     globus_free(chain);
263
264 11336     GlobusHandlerDebugExit();
265 }
266
267 static
268 void
269 globus_l_handler_hash_entry_copy(
270     void **                             dest_key,
271     void **                             dest_datum,
272     void *                              src_key,
273     void *                              src_datum)
274 19215 {
275 19215     globus_l_handler_t *                dest_handler;
276 19215     globus_l_handler_t *                src_handler;
277
278 19215     src_handler = (globus_l_handler_t *)src_datum;
279 19215     dest_handler = globus_malloc(sizeof(globus_l_handler_t));
280 19215     if(!dest_handler)
281     {
282 0         *dest_key = NULL;
283 0         *dest_datum = NULL;
284     }
285     
286 19215     memset(dest_handler, 0, sizeof(globus_l_handler_t));
287     
288 19215     dest_handler->invoke = src_handler->invoke;
289 19215     dest_handler->trigger = src_handler->trigger;
290
291 19215     *dest_datum = (void *)dest_handler;
292 19215     *dest_key = (void *)dest_handler->trigger->element;
293 }
294
295 static
296 globus_result_t
297 globus_l_handle_chain_copy(
298     globus_list_t **                    dest,
299     globus_list_t *                     src)
300 23058 {
301 23058     globus_result_t                     result = GLOBUS_SUCCESS;
302 23058     globus_l_handler_t *                src_handler;
303 23058     globus_l_handler_t *                new_handler;
304 23058     GlobusFuncName(globus_l_handler_chain_copy);
305 23058     GlobusHandlerDebugEnter();
306     
307 38430     for(; !globus_list_empty(src); src = globus_list_rest(src))
308     {
309 7686         src_handler = globus_list_first(src);
310         
311 7686         new_handler = globus_malloc(sizeof(globus_l_handler_t));
312 7686         if(!new_handler)
313         {
314 0             result = GlobusSoapMessageErrorOutOfMemory;
315 0             GlobusHandlerDebugExit();
316 0             return result;
317         }
318
319 7686         memset(new_handler, 0, sizeof(globus_l_handler_t));
320         
321 7686         new_handler->invoke = src_handler->invoke;
322 7686         globus_list_insert(dest, new_handler);
323 7686         dest = globus_list_rest_ref(*dest);
324     }
325
326 23058     GlobusHandlerDebugExit();
327 23058     return result;
328 }
329
330 globus_result_t
331 globus_handler_chain_copy(
332     globus_handler_chain_t *            dest,
333     globus_handler_chain_t              src)
334 3843 {
335 3843     globus_extension_handle_t           ext;
336 3843     globus_list_t *                     extensions;
337 3843     globus_handler_chain_t              new_chain;
338 3843     globus_result_t                     result = GLOBUS_SUCCESS;
339     
340 3843     GlobusFuncName(globus_handler_chain_copy);
341 3843     GlobusHandlerDebugEnter();
342
343 3843     new_chain = globus_malloc(sizeof(globus_i_handler_chain_t));
344 3843     if(!new_chain)
345     {
346 0         result = GlobusSoapMessageErrorOutOfMemory;
347 0         goto exit;
348     }
349
350 3843     memset(new_chain, 0, sizeof(globus_i_handler_chain_t));
351     
352 3843     result = globus_l_handle_chain_copy(
353         &new_chain->request_handlers, src->request_handlers);
354 3843     if(result != GLOBUS_SUCCESS)
355     {
356 0         goto error;
357     }
358     
359 3843     result = globus_l_handle_chain_copy(
360         &new_chain->response_handlers, src->response_handlers);
361 3843     if(result != GLOBUS_SUCCESS)
362     {
363 0         goto destroy_request_handlers;
364     }
365
366 3843     result = globus_l_handle_chain_copy(
367         &new_chain->request_init_handlers, src->request_init_handlers);
368 3843     if(result != GLOBUS_SUCCESS)
369     {
370 0         goto destroy_response_handlers;
371     }
372
373 3843     result = globus_l_handle_chain_copy(
374         &new_chain->request_destroy_handlers, src->request_destroy_handlers);
375 3843     if(result != GLOBUS_SUCCESS)
376     {
377 0         goto destroy_request_init_handlers;
378     }
379
380 3843     result = globus_l_handle_chain_copy(
381         &new_chain->response_init_handlers, src->response_init_handlers);
382 3843     if(result != GLOBUS_SUCCESS)
383     {
384 0         goto destroy_request_destroy_handlers;
385     }
386
387 3843     result = globus_l_handle_chain_copy(
388         &new_chain->response_destroy_handlers, src->response_destroy_handlers);
389 3843     if(result != GLOBUS_SUCCESS)
390     {
391 0         goto destroy_response_init_handlers;
392     }
393
394 3843     if(src->triggers)
395     {
396 3843         globus_hashtable_copy(
397             &new_chain->triggers,
398             &src->triggers,
399             globus_l_handler_hash_entry_copy);
400     }
401
402 3843     new_chain->default_trigger = src->default_trigger;
403
404 3843     extensions = src->extensions;
405 11529     while(extensions)
406     {
407 7686 ext = globus_list_first(extensions);
408 7686 globus_extension_reference(ext);
409 7686 globus_list_insert(&new_chain->extensions, (void *)ext);
410 7686 extensions = globus_list_rest(extensions);
411     }
412     
413 3843     *dest = new_chain;
414
415 3843     GlobusHandlerDebugExit();
416 3843     return result;
417  
418  destroy_response_init_handlers:
419 0     globus_list_destroy_all(
420 new_chain->response_init_handlers, globus_l_handler_destroy);
421
422  destroy_request_destroy_handlers:
423 0     globus_list_destroy_all(
424 new_chain->request_destroy_handlers, globus_l_handler_destroy);
425  
426  destroy_request_init_handlers:
427 0     globus_list_destroy_all(
428         new_chain->request_init_handlers, globus_l_handler_destroy);
429
430  destroy_response_handlers:
431 0     globus_list_destroy_all(
432         new_chain->response_handlers, globus_l_handler_destroy);
433     
434  destroy_request_handlers:
435 0     globus_list_destroy_all(
436         new_chain->request_handlers, globus_l_handler_destroy);
437     
438  error:
439 0     globus_free(new_chain);
440
441  exit:
442 0     GlobusHandlerDebugExit();
443 0     return result;
444 }
445
446 static
447 int
448 globus_l_handler_chain_list_insert_last(
449      globus_list_t * volatile *         headp,
450      void *                             datum)
451 276 {
452 276     globus_list_t *                     entry = NULL;
453 276     globus_list_t *                     tmp_list;
454     
455 276     if(!*headp)
456     {   
457 276         globus_list_insert(headp, datum);   
458     }   
459     else   
460     {   
461 0         tmp_list = *headp;   
462     
463 0         while(tmp_list->next)
464         {
465 0             tmp_list = globus_list_rest(tmp_list);
466         }
467 0         globus_list_insert(&entry, datum);
468 0         tmp_list->next = entry;   
469     }
470     
471 276     return 0;
472 }
473
474 static
475 globus_result_t
476 globus_l_handler_chain_push(
477     globus_list_t **                    chain,
478     globus_extension_handle_t           extension_handle,
479     globus_handler_invoke_func_t        invoke,
480     globus_bool_t                       last)
481 552 {
482 552     globus_result_t                     result = GLOBUS_SUCCESS;
483 552     globus_l_handler_t *                handler;
484 552     GlobusFuncName(globus_handler_chain_push);
485 552     GlobusHandlerDebugEnter();
486     
487 552     handler = globus_malloc(sizeof(globus_l_handler_t));
488 552     if(!handler)
489     {
490 0         result = GlobusSoapMessageErrorOutOfMemory;
491 0         goto exit;
492     }
493
494 552     memset(handler, 0, sizeof(globus_l_handler_t));
495 552     handler->invoke = invoke;
496     
497 552     if(last)
498     {
499 276         globus_l_handler_chain_list_insert_last(chain, handler);
500     }
501     else
502     {
503 276         globus_list_insert(chain, handler);
504     }
505
506  exit:
507 552     GlobusHandlerDebugExit();
508 552     return result;
509 }
510
511 globus_result_t
512 globus_l_handler_triggers_insert(
513     globus_hashtable_t *                triggers,
514     globus_extension_handle_t           ext,
515     globus_list_t *                     trigger_list)
516 552 {
517 552     globus_result_t                     result = GLOBUS_SUCCESS;
518 552     globus_list_t *                     trigger_iter;
519 552     globus_handler_trigger_t *          trigger;
520 552     globus_l_handler_t *                handler;
521 552     GlobusFuncName(globus_handler_chain_push);
522 552     GlobusHandlerDebugEnter();
523     
524 552     if(!*triggers)
525     {
526 276         globus_hashtable_init(
527             triggers, 20, xsd_QName_hash, xsd_QName_keyeq);
528     }
529     
530 552     trigger_iter = trigger_list;
531 3006     while(trigger_iter)
532     {
533 2454         trigger = globus_list_first(trigger_iter);
534
535 2454         handler = globus_malloc(sizeof(globus_l_handler_t));
536 2454         if(!handler)
537         {
538 0             result = GlobusSoapMessageErrorOutOfMemory;
539 0             goto exit;
540         }
541
542 2454         memset(handler, 0, sizeof(globus_l_handler_t));
543 2454         handler->trigger = trigger;
544
545 2454         globus_hashtable_insert(
546             triggers, 
547             handler->trigger->element,
548             handler);
549 2454         trigger_iter = globus_list_rest(trigger_iter);
550     }
551
552  exit:
553 552     GlobusHandlerDebugExit();
554 552     return result;
555 }
556
557 globus_result_t
558 globus_handler_chain_push(
559     globus_handler_chain_t              chain,
560     globus_handler_type_t               type,
561     const char *                        endpoint)
562 552 {
563 552     globus_handler_descriptor_t *       handler_desc;
564 552     globus_result_t                     result = GLOBUS_SUCCESS;
565 552     globus_extension_handle_t           extension_handle;
566 552     GlobusFuncName(globus_handler_chain_push);
567 552     GlobusHandlerDebugEnter();
568
569 552     handler_desc = globus_extension_lookup(
570         &extension_handle, GLOBUS_HANDLER_REGISTRY, (void *)endpoint);
571 552     if(!handler_desc)
572     {
573 0         globus_result_t                 tmp_result;
574
575 0         tmp_result = globus_extension_activate(endpoint);
576 0         if(tmp_result != GLOBUS_SUCCESS)
577         {
578 0             result = GlobusHandlerErrorRegistryLookupFailed(
579                 tmp_result, endpoint);            
580 0             goto exit;
581         }
582
583 0         globus_mutex_lock(&globus_l_handler_extensions_mutex);
584 0         globus_list_insert(
585             &globus_l_handler_extensions, strdup(endpoint));
586 0         globus_mutex_unlock(&globus_l_handler_extensions_mutex);
587
588 0         handler_desc = globus_extension_lookup(
589             &extension_handle, GLOBUS_HANDLER_REGISTRY, (void *)endpoint);
590 0         if(!handler_desc)
591         {
592 0             result = GlobusHandlerErrorRegistryLookupFailed(
593                 GLOBUS_FAILURE, endpoint);
594 0             goto exit;
595         }
596     }
597
598 552     globus_list_insert(&chain->extensions, (void *)extension_handle);
599
600 552     if((type & GLOBUS_HANDLER_TYPE_REQUEST) && handler_desc->request)
601     {
602 276         globus_l_handler_chain_push(&chain->request_handlers,
603             extension_handle, handler_desc->request, GLOBUS_FALSE);
604     }
605     
606 552     if((type & GLOBUS_HANDLER_TYPE_RESPONSE) && handler_desc->response)
607     {
608 276         globus_l_handler_chain_push(&chain->response_handlers,
609             extension_handle, handler_desc->response, GLOBUS_TRUE);
610     }
611
612 552     if((type & GLOBUS_HANDLER_TYPE_REQUEST_INIT) && handler_desc->request_init)
613     {
614 0         globus_l_handler_chain_push(
615             &chain->request_init_handlers,
616             extension_handle, handler_desc->request_init, GLOBUS_FALSE);
617     }
618
619 552     if((type & GLOBUS_HANDLER_TYPE_RESPONSE_INIT) && handler_desc->response_init)
620     {
621 0         globus_l_handler_chain_push(
622             &chain->response_init_handlers,
623             extension_handle, handler_desc->response_init, GLOBUS_FALSE);
624     }
625
626 552     if((type & GLOBUS_HANDLER_TYPE_REQUEST_DESTROY) && handler_desc->request_destroy)
627     {
628 0         globus_l_handler_chain_push(
629             &chain->request_destroy_handlers,
630             extension_handle, handler_desc->request_destroy, GLOBUS_FALSE);
631     }
632
633 552     if((type & GLOBUS_HANDLER_TYPE_RESPONSE_DESTROY) && 
634        handler_desc->response_destroy)
635     {
636 0         globus_l_handler_chain_push(
637             &chain->response_destroy_handlers,
638             extension_handle, handler_desc->response_destroy, GLOBUS_FALSE);
639     }
640
641
642 552     if(handler_desc->default_trigger)
643     {
644 306         if(chain->default_trigger && 
645            (chain->default_trigger != handler_desc->default_trigger))
646         {
647 0             result = GlobusHandlerErrorDefaultTriggerAlreadyDefined();
648 0             goto exit;
649         }
650
651 306         chain->default_trigger = handler_desc->default_trigger;
652     }
653
654 552     if(handler_desc->trigger_list)
655     {
656 552         globus_l_handler_triggers_insert(
657             &chain->triggers, extension_handle,
658             handler_desc->trigger_list);
659     }
660
661 exit:
662     
663 552     GlobusHandlerDebugExit();
664 552     return result;
665 }
666
667 static
668 void
669 globus_l_handler_callback_call_next(
670     void *                              args)
671 89261 {
672 89261     globus_l_handler_t *                next_handler;
673 89261     globus_handler_session_descriptor_t session;
674 89261     globus_handler_invoke_func_t        trigger;
675 89261     globus_assert(args);
676 89261     session = (globus_handler_session_descriptor_t) args;
677
678 89261     if(session->trigger)
679     {
680 25508         trigger = session->trigger;
681 25508         session->trigger = NULL;
682 25508         trigger(session, session->message, session->result);
683 25508         return;
684     }
685
686 63753     if(globus_list_empty(session->remaining_handlers))
687     {
688 52593         session->callback_func(session->result, session->callback_args);
689 52593         globus_free(session);
690 52593         return;
691     }
692
693 11160     next_handler = globus_list_first(session->remaining_handlers);
694 11160     session->remaining_handlers = globus_list_rest(
695         session->remaining_handlers);
696 11160     next_handler->invoke(session, session->message, session->result);
697 }
698
699 void
700 globus_handler_finished(
701     globus_handler_session_descriptor_t session,
702     globus_result_t                     result)
703 89261 {
704 89261     globus_result_t                     local_result = GLOBUS_SUCCESS;
705 89261     GlobusFuncName(globus_handler_finished);
706 89261     GlobusHandlerDebugEnter();
707
708 89261     session->result = result;
709
710 89261     local_result = globus_callback_register_oneshot(
711         NULL, NULL,
712         globus_l_handler_callback_call_next,
713         session);
714 89261     if(local_result != GLOBUS_SUCCESS)
715     {
716 0         globus_panic(GLOBUS_HANDLER_MODULE,
717                      local_result,
718                      "[%s:%d] Couldn't register callback",
719                      _globus_func_name,
720                      __LINE__);
721     }
722
723 89261     GlobusHandlerDebugExit();
724 }
725
726 globus_bool_t
727 globus_handler_chain_has_trigger(
728     globus_handler_chain_t              chain,
729     const xsd_QName *                   element)
730 0 {
731 0     if(chain->triggers && globus_hashtable_lookup(
732     &chain->triggers, 
733     (void *)element))
734     {
735 0 return GLOBUS_TRUE;
736     }
737 0     return GLOBUS_FALSE;
738 }
739
740 globus_result_t
741 globus_handler_chain_register_trigger(
742     globus_handler_chain_t              chain,
743     globus_soap_message_handle_t        message,
744     const xsd_QName *                   element,
745     globus_handler_callback_func_t      callback,
746     void *                              user_args)
747 25508 {
748 25508     globus_handler_session_descriptor_t desc;
749 25508     globus_l_handler_t *                handler;
750 25508     globus_result_t                     result = GLOBUS_SUCCESS;
751 25508     GlobusFuncName(globus_handler_chain_register_trigger);
752 25508     GlobusHandlerDebugEnter();
753     
754 25508     if(!chain->triggers)
755     {
756 0         result = GlobusHandlerErrorNoTriggersDefined();
757 0         goto exit;
758     }
759
760 25508     desc = (globus_handler_session_descriptor_t) globus_malloc(
761         sizeof(globus_i_handler_session_descriptor_t));
762 25508     if(!desc)
763     {
764 0         result = GlobusSoapMessageErrorOutOfMemory;
765 0         goto exit;
766     }
767 25508     memset(desc, 0, sizeof(globus_i_handler_session_descriptor_t));
768     
769 25508     desc->message = message;
770 25508     desc->callback_func = callback;
771 25508     desc->callback_args = user_args;
772     
773 25508     handler = globus_hashtable_lookup(
774         &chain->triggers, 
775         (void *)element);
776 25508     if(handler)
777     {
778 23256         desc->trigger = handler->trigger->invoke;
779     }
780 2252     else if(chain->default_trigger)
781     {
782 2252         desc->trigger = chain->default_trigger;
783     }
784     else
785     {
786 0         result = GLOBUS_HANDLER_STATUS_NOT_TRIGGERED;
787 0         goto exit;
788     }
789     
790 25508     globus_handler_finished(desc, GLOBUS_SUCCESS);
791         
792  exit:
793
794 25508     GlobusHandlerDebugExit();
795 25508     return result;
796 }
797
798 void
799 globus_handler_chain_register_invoke(
800     globus_handler_chain_t              chain,
801     globus_handler_type_t               type,
802     globus_soap_message_handle_t        message,
803     globus_handler_callback_func_t      callback,
804     void *                              user_args)
805 27085 {
806 27085     globus_handler_session_descriptor_t desc;
807 27085     GlobusFuncName(globus_handler_chain_register_invoke);
808 27085     GlobusHandlerDebugEnter();
809     
810 27085     desc = (globus_handler_session_descriptor_t) globus_malloc(
811         sizeof(globus_i_handler_session_descriptor_t));
812 27085     if(!desc)
813     {
814 0         globus_handler_finished(NULL, GlobusSoapMessageErrorOutOfMemory);
815     }
816
817 27085     memset(desc, 0, sizeof(globus_i_handler_session_descriptor_t));
818
819 27085     desc->message = message;
820 27085     desc->callback_func = callback;
821 27085     desc->callback_args = user_args;
822
823 27085     switch(type)
824     {
825     case GLOBUS_HANDLER_TYPE_REQUEST_INIT:
826 5600         desc->remaining_handlers = chain->request_init_handlers;
827 5600         break;
828     case GLOBUS_HANDLER_TYPE_REQUEST_DESTROY:
829 5599         desc->remaining_handlers = chain->request_destroy_handlers;
830 5599         break;
831     case GLOBUS_HANDLER_TYPE_REQUEST:
832 5599         desc->remaining_handlers = chain->request_handlers;
833 5599         break;
834     case GLOBUS_HANDLER_TYPE_RESPONSE_INIT:
835 2332         desc->remaining_handlers = chain->response_init_handlers;
836 2332         break;
837     case GLOBUS_HANDLER_TYPE_RESPONSE_DESTROY:
838 2394         desc->remaining_handlers = chain->response_destroy_handlers;
839 2394         break;
840     case GLOBUS_HANDLER_TYPE_RESPONSE:
841 5561         desc->remaining_handlers = chain->response_handlers;
842 5561         break;
843     default:
844 0         desc->remaining_handlers = NULL;
845     }
846
847 27085     globus_handler_finished(desc, GLOBUS_SUCCESS);
848
849 27085     GlobusHandlerDebugExit();