From 0425aadc78680e53000fd0108b540d6eca048516 Mon Sep 17 00:00:00 2001 From: gmcdonald Date: Sat, 13 Feb 2010 01:32:03 +0000 Subject: Moving axis svn, part of TLP move INFRA-2441 git-svn-id: http://svn.apache.org/repos/asf/axis/axis2/c/core/trunk@909681 13f79535-47bb-0310-9956-ffa450edef68 --- src/core/clientapi/op_client.c | 1439 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1439 insertions(+) create mode 100644 src/core/clientapi/op_client.c (limited to 'src/core/clientapi/op_client.c') diff --git a/src/core/clientapi/op_client.c b/src/core/clientapi/op_client.c new file mode 100644 index 0000000..3ccb776 --- /dev/null +++ b/src/core/clientapi/op_client.c @@ -0,0 +1,1439 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include "axis2_callback_recv.h" +#include +#include +#include +#include +#include +#include +#include + +struct axis2_op_client +{ + axis2_svc_ctx_t *svc_ctx; + + axis2_options_t *options; + + axis2_op_ctx_t *op_ctx; + + axis2_callback_t *callback; + + axis2_bool_t completed; + + /* to hold the locally created async result */ + axis2_async_result_t *async_result; + + axis2_callback_recv_t *callback_recv; + + /** message exchange pattern */ + axis2_char_t *mep; + + axis2_char_t *soap_version_uri; + axutil_string_t *soap_action; + axis2_char_t *wsa_action; + axis2_bool_t reuse; + +}; + +typedef struct axis2_op_client_worker_func_args +{ + const axutil_env_t *env; + axis2_op_client_t *op_client; + axis2_callback_t *callback; + axis2_op_t *op; + axis2_msg_ctx_t *msg_ctx; +} axis2_op_client_worker_func_args_t; + +void *AXIS2_THREAD_FUNC axis2_op_client_worker_func( + axutil_thread_t * thd, + void *data); + +static axis2_char_t *AXIS2_CALL axis2_op_client_get_transport_from_url( + const axis2_char_t * url, + const axutil_env_t * env); + +AXIS2_EXTERN axis2_op_client_t *AXIS2_CALL +axis2_op_client_create( + const axutil_env_t * env, + axis2_op_t * op, + axis2_svc_ctx_t * svc_ctx, + axis2_options_t * options) +{ + axis2_op_client_t *op_client = NULL; + const axis2_char_t *mep_uri = NULL; + + AXIS2_ENV_CHECK(env, NULL); + AXIS2_PARAM_CHECK(env->error, op, NULL); + AXIS2_PARAM_CHECK(env->error, svc_ctx, NULL); + AXIS2_PARAM_CHECK(env->error, options, NULL); + + op_client = AXIS2_MALLOC(env->allocator, sizeof(axis2_op_client_t)); + if(!op_client) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create op client."); + return NULL; + } + + /** initialize data */ + op_client->callback = NULL; + op_client->completed = AXIS2_FALSE; + op_client->reuse = AXIS2_FALSE; + op_client->async_result = NULL; + op_client->callback_recv = NULL; + + op_client->options = options; + op_client->svc_ctx = svc_ctx; + + op_client->mep = NULL; + op_client->soap_version_uri = NULL; + op_client->soap_action = NULL; + op_client->wsa_action = NULL; + + op_client->op_ctx = axis2_op_ctx_create(env, op, op_client->svc_ctx); + if(!(op_client->op_ctx)) + { + axis2_op_client_free(op_client, env); + return NULL; + } + + mep_uri = axis2_op_get_msg_exchange_pattern(op, env); + + if(!mep_uri) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_MEP_CANNOT_DETERMINE_MEP, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot find message exchange pattern uri."); + axis2_op_client_free(op_client, env); + return NULL; + } + + op_client->mep = axutil_strdup(env, mep_uri); + + op_client->soap_version_uri = axutil_strdup(env, AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI); + if(!(op_client->soap_version_uri)) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create soap version uri."); + axis2_op_client_free(op_client, env); + return NULL; + } + + /** initialize parser for thread safety */ + axiom_xml_reader_init(); + return op_client; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_set_options( + axis2_op_client_t * op_client, + const axutil_env_t * env, + const axis2_options_t * options) +{ + if(op_client->options) + { + axis2_options_free(op_client->options, env); + } + op_client->options = (axis2_options_t *)options; + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN const axis2_options_t *AXIS2_CALL +axis2_op_client_get_options( + const axis2_op_client_t * op_client, + const axutil_env_t * env) +{ + return op_client->options; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_add_msg_ctx( + axis2_op_client_t * op_client, + const axutil_env_t * env, + axis2_msg_ctx_t * mc) +{ + axis2_msg_ctx_t *out_msg_ctx = NULL, *in_msg_ctx = NULL; + axis2_msg_ctx_t **msg_ctx_map = NULL; + + /* Don't use AXIS2_PARAM_CHECK to verify op_client, as it clobbers + env->error->status_code on no error destroying the information + therein that an error has already occurred. */ + if(!op_client) + { + if(axutil_error_get_status_code(env->error) == AXIS2_SUCCESS) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_NULL_PARAM, AXIS2_FAILURE); + } + return AXIS2_FAILURE; + } + /* mc message context pointer may be NULL, e.g., when no response message + is received */ + + if(op_client->op_ctx) + { + msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_client->op_ctx, env); + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "op_ctx is NULL, unable to continue"); + return AXIS2_FAILURE; + } + + if(msg_ctx_map) + { + out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT]; + in_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN]; + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "msg_ctx_map is NULL, unable to continue"); + return AXIS2_FAILURE; + } + + if(op_client->reuse) + { + /* This is the second invocation using the same service client, + so reset */ + if(out_msg_ctx) + { + axis2_msg_ctx_free(out_msg_ctx, env); + out_msg_ctx = NULL; + msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT] = NULL; + } + + if(in_msg_ctx) + { + axis2_msg_ctx_free(in_msg_ctx, env); + in_msg_ctx = NULL; + msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN] = NULL; + } + + axis2_op_ctx_set_complete(op_client->op_ctx, env, AXIS2_FALSE); + op_client->reuse = AXIS2_FALSE; + } + + if(out_msg_ctx && in_msg_ctx) + { + /* may be this is the second invocation using the same service clinet, + so reset */ + axis2_msg_ctx_free(out_msg_ctx, env); + out_msg_ctx = NULL; + msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT] = NULL; + axis2_msg_ctx_free(in_msg_ctx, env); + in_msg_ctx = NULL; + msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN] = NULL; + axis2_op_ctx_set_complete(op_client->op_ctx, env, AXIS2_FALSE); + } + + if(!out_msg_ctx) + { + msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT] = mc; + } + else + { + msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN] = mc; + axis2_op_ctx_set_complete(op_client->op_ctx, env, AXIS2_TRUE); + } + + if(out_msg_ctx && !mc) + { + axutil_property_t *dump_property; + axis2_char_t *dump_value = NULL; + if(!axis2_msg_ctx_get_doing_rest(out_msg_ctx, env)) + { + dump_property = axis2_msg_ctx_get_property(out_msg_ctx, env, AXIS2_DUMP_INPUT_MSG_TRUE); + if(dump_property) + { + dump_value = (axis2_char_t *)axutil_property_get_value(dump_property, env); + } + } + + if(axutil_strcmp(dump_value, AXIS2_VALUE_TRUE)) + { + axis2_msg_ctx_free(out_msg_ctx, env); + out_msg_ctx = NULL; + msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT] = NULL; + } + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_add_out_msg_ctx( + axis2_op_client_t * op_client, + const axutil_env_t * env, + axis2_msg_ctx_t * mc) +{ + axis2_msg_ctx_t **msg_ctx_map = NULL; + + msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_client->op_ctx, env); + + if(msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT]) + { + axis2_msg_ctx_free(msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT], env); + } + msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT] = mc; + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_add_in_msg_ctx( + axis2_op_client_t * op_client, + const axutil_env_t * env, + axis2_msg_ctx_t * mc) +{ + axis2_msg_ctx_t **msg_ctx_map = NULL; + + msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_client->op_ctx, env); + + if(msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN]) + { + axis2_msg_ctx_free(msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN], env); + } + msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN] = mc; + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN const axis2_msg_ctx_t *AXIS2_CALL +axis2_op_client_get_msg_ctx( + const axis2_op_client_t * op_client, + const axutil_env_t * env, + const axis2_wsdl_msg_labels_t message_label) +{ + return axis2_op_ctx_get_msg_ctx(op_client->op_ctx, env, message_label); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_set_callback( + axis2_op_client_t * op_client, + const axutil_env_t * env, + axis2_callback_t * callback) +{ + if(op_client->callback) + { + axis2_callback_free(op_client->callback, env); + } + + op_client->callback = callback; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_callback_t *AXIS2_CALL +axis2_op_client_get_callback( + axis2_op_client_t * op_client, + const axutil_env_t * env) +{ + return op_client->callback; +} + +/* This function is called from service client irrespective of the message exchange pattern + * and whether one/two way channel used. + */ +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_execute( + axis2_op_client_t * op_client, + const axutil_env_t * env, + const axis2_bool_t block) +{ + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_msg_ctx_t *msg_ctx = NULL; + + axis2_transport_out_desc_t *transport_out = NULL; + axis2_transport_in_desc_t *transport_in = NULL; + + axis2_status_t status = AXIS2_FAILURE; + axis2_op_t *op = NULL; + axis2_char_t *msg_id = NULL; + + if(op_client->completed) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Op client execute failed. Already completed."); + return AXIS2_FAILURE; + } + + conf_ctx = axis2_svc_ctx_get_conf_ctx(op_client->svc_ctx, env); + + msg_ctx = (axis2_msg_ctx_t *)axis2_op_client_get_msg_ctx(op_client, env, + AXIS2_WSDL_MESSAGE_LABEL_OUT); + + if(!msg_ctx) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Op client execute failed. Message context is not valid."); + return AXIS2_FAILURE; + } + + axis2_msg_ctx_set_options(msg_ctx, env, op_client->options); + + /** + if the transport to use for sending is not specified, try to find it + from the URL or the client option. + */ + transport_out = axis2_options_get_transport_out(op_client->options, env); + if(!transport_out) + { + axis2_endpoint_ref_t *to_epr = NULL; + axutil_property_t *property = NULL; + property = axis2_options_get_property(op_client->options, env, AXIS2_TARGET_EPR); + if(property) + { + to_epr = axutil_property_get_value(property, env); + } + + if(!to_epr) + { + to_epr = axis2_options_get_to(op_client->options, env); + } + + if(!to_epr) + { + to_epr = axis2_msg_ctx_get_to(msg_ctx, env); + } + + transport_out = axis2_op_client_infer_transport(op_client, env, to_epr); + } + + if(!transport_out) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Op client execute failed. Cannot find transport out."); + return AXIS2_FAILURE; + } + + if(!(axis2_msg_ctx_get_transport_out_desc(msg_ctx, env))) + { + axis2_msg_ctx_set_transport_out_desc(msg_ctx, env, transport_out); + } + + transport_in = axis2_options_get_transport_in(op_client->options, env); + if(!transport_in) + { + axis2_conf_ctx_t *conf_ctx = axis2_svc_ctx_get_conf_ctx(op_client->svc_ctx, env); + + if(conf_ctx) + { + axis2_conf_t *conf = axis2_conf_ctx_get_conf(conf_ctx, env); + if(conf) + { + transport_in = axis2_conf_get_transport_in(conf, env, + axis2_transport_out_desc_get_enum(transport_out, env)); + } + } + } + if(!transport_in) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Op client execute failed. Cannot find transport in."); + return AXIS2_FAILURE; + } + + if(!(axis2_msg_ctx_get_transport_in_desc(msg_ctx, env))) + { + axis2_msg_ctx_set_transport_in_desc(msg_ctx, env, transport_in); + } + + op = axis2_op_ctx_get_op(op_client->op_ctx, env); + + if(!op) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Op client execute failed. Cannot find operation."); + return AXIS2_FAILURE; + } + status = axis2_op_client_prepare_invocation(op_client, env, op, msg_ctx); + if(status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Op client execute failed. Preparing for invocation failed."); + return AXIS2_FAILURE; + } + msg_id = (axis2_char_t *)axutil_uuid_gen(env); + axis2_msg_ctx_set_message_id(msg_ctx, env, msg_id); + if(msg_id) + { + AXIS2_FREE(env->allocator, msg_id); + msg_id = NULL; + } + + /* If dual channel. */ + if(axis2_options_get_use_separate_listener(op_client->options, env)) + { + axis2_engine_t *engine = NULL; + + if(op_client->callback) + { + AXIS2_CALLBACK_RECV_ADD_CALLBACK(op_client->callback_recv, env, + axis2_msg_ctx_get_msg_id(msg_ctx, env), op_client->callback); + } + + axis2_msg_ctx_set_op_ctx(msg_ctx, env, axis2_op_find_op_ctx(op, env, msg_ctx, + op_client-> svc_ctx)); + axis2_msg_ctx_set_svc_ctx(msg_ctx, env, op_client->svc_ctx); + + /* send the message */ + engine = axis2_engine_create(env, conf_ctx); + if(!engine) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Op client execute failed due to engine creation failure."); + return AXIS2_FAILURE; + } + axis2_engine_send(engine, env, msg_ctx); + axis2_engine_free(engine, env); + } + else /* Same channel will be used irrespective of message exchange pattern. */ + { + if(block) + { + axis2_msg_ctx_t *response_mc = NULL; + + axis2_msg_ctx_set_svc_ctx(msg_ctx, env, op_client->svc_ctx); + axis2_msg_ctx_set_conf_ctx(msg_ctx, env, axis2_svc_ctx_get_conf_ctx( + op_client-> svc_ctx, env)); + axis2_msg_ctx_set_op_ctx(msg_ctx, env, op_client->op_ctx); + + /*Send the SOAP Message and receive a response */ + response_mc = axis2_op_client_two_way_send(env, msg_ctx); + if(!response_mc) + { + const axis2_char_t *mep = axis2_op_get_msg_exchange_pattern(op, env); + if(!(axutil_strcmp(mep, AXIS2_MEP_URI_OUT_ONLY)) || !(axutil_strcmp(mep, + AXIS2_MEP_URI_ROBUST_OUT_ONLY))) + { + if(env->error) + { + return env->error->status_code; + } + else + { + return AXIS2_FAILURE; + } + } + else + { + return AXIS2_FAILURE; + } + } + axis2_op_client_add_msg_ctx(op_client, env, response_mc); + } + else + { + axis2_op_client_worker_func_args_t *arg_list = NULL; + arg_list = AXIS2_MALLOC(env->allocator, sizeof(axis2_op_client_worker_func_args_t)); + if(!arg_list) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "No memory. Cannot create op client worker function argument list."); + return AXIS2_FAILURE; + } + arg_list->env = env; + arg_list->op_client = op_client; + arg_list->callback = op_client->callback; + arg_list->op = op; + arg_list->msg_ctx = msg_ctx; +#ifdef AXIS2_SVR_MULTI_THREADED + if (env->thread_pool) + { + axutil_thread_t *worker_thread = NULL; + worker_thread = axutil_thread_pool_get_thread(env->thread_pool, + axis2_op_client_worker_func, + (void *) + arg_list); + if (!worker_thread) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Thread creation failed call invoke non blocking"); + } + else + { + axutil_thread_pool_thread_detach(env->thread_pool, + worker_thread); + } + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Thread pool not set in environment" + "Cannot invoke call non blocking"); + } +#else + axis2_op_client_worker_func(NULL, (void *)arg_list); +#endif + + } + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_reset( + axis2_op_client_t * op_client, + const axutil_env_t * env) +{ + if(!op_client->completed) + return AXIS2_FAILURE; + + op_client->completed = AXIS2_FALSE; + + op_client->op_ctx = NULL; + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_complete( + axis2_op_client_t * op_client, + const axutil_env_t * env, + axis2_msg_ctx_t * mc) +{ + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_listener_manager_t *listener_manager = NULL; + AXIS2_TRANSPORT_ENUMS transport = AXIS2_TRANSPORT_ENUM_HTTP; + + conf_ctx = axis2_msg_ctx_get_conf_ctx(mc, env); + + if(!conf_ctx) + return AXIS2_FAILURE; + + if(!listener_manager) + return AXIS2_FAILURE; + + return axis2_listener_manager_stop(listener_manager, env, transport); +} + +AXIS2_EXTERN axis2_op_ctx_t *AXIS2_CALL +axis2_op_client_get_operation_context( + const axis2_op_client_t * op_client, + const axutil_env_t * env) +{ + return op_client->op_ctx; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_op_client_free( + axis2_op_client_t * op_client, + const axutil_env_t * env) +{ + if(!op_client) + return; + + /*if(op_client->callback) + { + axis2_callback_free(op_client->callback, env); + }*/ + + if(op_client->op_ctx) + { + axis2_op_ctx_free(op_client->op_ctx, env); + op_client->op_ctx = NULL; + } + + if(op_client->soap_version_uri) + { + AXIS2_FREE(env->allocator, op_client->soap_version_uri); + } + + if(op_client->mep) + { + AXIS2_FREE(env->allocator, op_client->mep); + } + + if(axis2_options_get_xml_parser_reset(op_client->options, env)) + { + axiom_xml_reader_cleanup(); + } + + AXIS2_FREE(env->allocator, op_client); +} + +/* This function is the thread worker function for the single channel non blocking case. Here + * being non-blocking implies that message is two way. */ +void *AXIS2_THREAD_FUNC +axis2_op_client_worker_func( + axutil_thread_t * thd, + void *data) +{ + axis2_op_client_worker_func_args_t *args_list = NULL; + axis2_op_ctx_t *op_ctx = NULL; + axis2_msg_ctx_t *response = NULL; + axutil_env_t *th_env = NULL; + axutil_thread_pool_t *th_pool = NULL; + + args_list = (axis2_op_client_worker_func_args_t *)data; + if(!args_list) + { + return NULL; + } + + th_env = axutil_init_thread_env(args_list->env); + + op_ctx = axis2_op_ctx_create(th_env, args_list->op, args_list->op_client->svc_ctx); + if(!op_ctx) + { + return NULL; + } + axis2_msg_ctx_set_op_ctx(args_list->msg_ctx, th_env, op_ctx); + axis2_msg_ctx_set_svc_ctx(args_list->msg_ctx, th_env, args_list->op_client->svc_ctx); + + /* send the request and wait for response */ + response = axis2_op_client_two_way_send(th_env, args_list->msg_ctx); + + /* We do not need to handle the NULL response here because this thread function is called only + * in the single channel non blocking case which, imply this is two way message by design. + */ + + /* Here after the code is a subset of what callback receiver do in dual channel case.*/ + axis2_op_client_add_msg_ctx(args_list->op_client, th_env, response); + args_list->op_client->async_result = axis2_async_result_create(th_env, response); + + if(args_list->callback) + { + axis2_callback_invoke_on_complete(args_list->callback, th_env, + args_list->op_client->async_result); + + axis2_callback_set_complete(args_list->callback, th_env, AXIS2_TRUE); + } + + /* Clean up memory */ + axis2_async_result_free(args_list->op_client->async_result, th_env); + + axis2_op_ctx_free(op_ctx, th_env); + + th_pool = th_env->thread_pool; + + AXIS2_FREE(th_env->allocator, args_list); + + if(th_env) + { + axutil_free_thread_env(th_env); + th_env = NULL; + } + axutil_thread_pool_exit_thread(th_pool, thd); + return NULL; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_set_callback_recv( + axis2_op_client_t * op_client, + const axutil_env_t * env, + axis2_callback_recv_t * callback_recv) +{ + op_client->callback_recv = callback_recv; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axutil_string_t *AXIS2_CALL +axis2_op_client_get_soap_action( + const axis2_op_client_t * op_client, + const axutil_env_t * env) +{ + return op_client->soap_action; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_prepare_invocation( + axis2_op_client_t * op_client, + const axutil_env_t * env, + axis2_op_t * op, + axis2_msg_ctx_t * msg_ctx) +{ + axis2_svc_t *svc = NULL; + + AXIS2_PARAM_CHECK(env->error, op, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + + /* make sure operation's MEP is the same as given MEP */ + if(op_client->mep) + { + if(axutil_strcmp(op_client->mep, axis2_op_get_msg_exchange_pattern(op, env))) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_MEP_MISMATCH_IN_MEP_CLIENT, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Message exchange pattern of op client and operation are different."); + return AXIS2_FAILURE; + } + } + else + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_MEP_CANNOT_BE_NULL_IN_MEP_CLIENT, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Message exchange pattern of op client is not valid."); + return AXIS2_FAILURE; + } + /* If operation has a parent service get it */ + svc = axis2_op_get_parent(op, env); + if(svc) + { + axis2_svc_ctx_set_svc(op_client->svc_ctx, env, svc); + } + else + { + svc = axis2_svc_ctx_get_svc(op_client->svc_ctx, env); + if(svc) + { + axis2_op_t *temp_op = NULL; + const axutil_qname_t *op_qname = axis2_op_get_qname(op, env); + temp_op = axis2_svc_get_op_with_qname(svc, env, op_qname); + if(!temp_op) + { + axis2_svc_add_op(svc, env, op); + } + } + } + + if(op_client->wsa_action) + { + axis2_msg_ctx_set_wsa_action(msg_ctx, env, op_client->wsa_action); + } + + if(op_client->soap_action) + { + axis2_msg_ctx_set_soap_action(msg_ctx, env, op_client->soap_action); + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_msg_ctx_t *AXIS2_CALL +axis2_op_client_prepare_soap_envelope( + axis2_op_client_t * op_client, + const axutil_env_t * env, + axiom_node_t * to_send) +{ + axis2_msg_ctx_t *msg_ctx = NULL; + axiom_soap_envelope_t *envelope = NULL; + int soap_version = AXIOM_SOAP12; + + if(op_client->svc_ctx) + { + msg_ctx = axis2_msg_ctx_create(env, axis2_svc_ctx_get_conf_ctx(op_client-> svc_ctx, env), + NULL, NULL); + } + + if(!msg_ctx) + { + return NULL; + } + + if(op_client->soap_version_uri) + { + if(!(axutil_strcmp(op_client->soap_version_uri, AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI))) + soap_version = AXIOM_SOAP11; + else + soap_version = AXIOM_SOAP12; + } + + envelope = axiom_soap_envelope_create_default_soap_envelope(env, soap_version); + if(!envelope) + { + return NULL; + } + + if(to_send) + { + axiom_soap_body_t *soap_body = NULL; + soap_body = axiom_soap_envelope_get_body(envelope, env); + if(soap_body) + { + axiom_node_t *node = NULL; + node = axiom_soap_body_get_base_node(soap_body, env); + if(node) + { + axiom_node_add_child(node, env, to_send); + } + } + } + + axis2_msg_ctx_set_soap_envelope(msg_ctx, env, envelope); + + return msg_ctx; +} + +AXIS2_EXTERN axis2_transport_out_desc_t *AXIS2_CALL +axis2_op_client_infer_transport( + axis2_op_client_t * op_client, + const axutil_env_t * env, + axis2_endpoint_ref_t * epr) +{ + axis2_char_t *transport = NULL; + axis2_transport_out_desc_t *transport_out_desc = NULL; + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_conf_t *conf = NULL; + AXIS2_TRANSPORT_ENUMS transport_enum = AXIS2_TRANSPORT_ENUM_MAX; + + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Start:axis2_op_client_infer_transport"); + + /* We first try the client option */ + transport_enum = axis2_options_get_sender_transport_protocol(op_client->options, env); + if(transport_enum == AXIS2_TRANSPORT_ENUM_MAX) + { + /* If we couldn't find the transport we default to HTTP */ + transport_enum = AXIS2_TRANSPORT_ENUM_HTTP; + /* We try to infer transport from the url */ + if(epr) + { + const axis2_char_t *to_url = axis2_endpoint_ref_get_address(epr, env); + + transport = axis2_op_client_get_transport_from_url(to_url, env); + } + + if(transport) + { + if(!axutil_strcmp(transport, AXIS2_TRANSPORT_HTTP)) + { + transport_enum = AXIS2_TRANSPORT_ENUM_HTTP; + } + else if(!axutil_strcmp(transport, AXIS2_TRANSPORT_HTTPS)) + { + transport_enum = AXIS2_TRANSPORT_ENUM_HTTPS; + } + else if(!axutil_strcmp(transport, AXIS2_TRANSPORT_XMPP)) + { + transport_enum = AXIS2_TRANSPORT_ENUM_XMPP; + } + else if(!axutil_strcmp(transport, AXIS2_TRANSPORT_TCP)) + { + transport_enum = AXIS2_TRANSPORT_ENUM_TCP; + } + else if(!axutil_strcmp(transport, AXIS2_TRANSPORT_AMQP)) + { + transport_enum = AXIS2_TRANSPORT_ENUM_AMQP; + } + else if(!axutil_strcmp(transport, AXIS2_TRANSPORT_UDP)) + { + transport_enum = AXIS2_TRANSPORT_ENUM_UDP; + } + + AXIS2_FREE(env->allocator, transport); + transport = NULL; + } + } + conf_ctx = axis2_svc_ctx_get_conf_ctx(op_client->svc_ctx, env); + if(conf_ctx) + { + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + if(conf) + { + transport_out_desc = axis2_conf_get_transport_out(conf, env, transport_enum); + } + } + if(!transport_out_desc) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot infer transport"); + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_CANNOT_INFER_TRANSPORT, AXIS2_FAILURE); + } + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "End:axis2_op_client_infer_transport"); + return transport_out_desc; +} + +AXIS2_EXTERN axiom_soap_envelope_t *AXIS2_CALL +axis2_op_client_create_default_soap_envelope( + axis2_op_client_t * op_client, + const axutil_env_t * env) +{ + axiom_soap_envelope_t *envelope = NULL; + + if(!(axutil_strcmp(AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI, op_client->soap_version_uri))) + { + envelope = axiom_soap_envelope_create_with_soap_version_prefix(env, AXIOM_SOAP12, NULL); + } + + if(!(axutil_strcmp(AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI, op_client->soap_version_uri))) + { + envelope = axiom_soap_envelope_create_with_soap_version_prefix(env, AXIOM_SOAP11, NULL); + } + return envelope; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_engage_module( + axis2_op_client_t * op_client, + const axutil_env_t * env, + const axutil_qname_t * qname) +{ + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_conf_t *conf = NULL; + + if(op_client->svc_ctx) + { + conf_ctx = axis2_svc_ctx_get_conf_ctx(op_client->svc_ctx, env); + if(conf_ctx) + { + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + if(conf) + { + /*if it is already engaged do not engage it again */ + if(!(axis2_conf_is_engaged(conf, env, qname))) + { + return axis2_conf_engage_module(conf, env, qname); + } + } + } + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_set_soap_version_uri( + axis2_op_client_t * op_client, + const axutil_env_t * env, + const axis2_char_t * soap_version_uri) +{ + if(op_client->soap_version_uri) + { + AXIS2_FREE(env->allocator, op_client->soap_version_uri); + op_client->soap_version_uri = NULL; + } + + if(soap_version_uri) + { + op_client->soap_version_uri = axutil_strdup(env, soap_version_uri); + if(!(op_client->soap_version_uri)) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create soap version uri."); + return AXIS2_FAILURE; + } + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_set_soap_action( + axis2_op_client_t * op_client, + const axutil_env_t * env, + axutil_string_t * soap_action) +{ + if(op_client->soap_action) + { + axutil_string_free(op_client->soap_action, env); + op_client->soap_action = NULL; + } + + if(soap_action) + { + op_client->soap_action = axutil_string_clone(soap_action, env); + if(!(op_client->soap_action)) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create soap action."); + return AXIS2_FAILURE; + } + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_op_client_set_wsa_action( + axis2_op_client_t * op_client, + const axutil_env_t * env, + const axis2_char_t * wsa_action) +{ + if(op_client->wsa_action) + { + AXIS2_FREE(env->allocator, op_client->wsa_action); + op_client->wsa_action = NULL; + } + + if(wsa_action) + { + op_client->wsa_action = axutil_strdup(env, wsa_action); + if(!(op_client->wsa_action)) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create wsa action."); + return AXIS2_FAILURE; + } + } + + return AXIS2_SUCCESS; +} + +static axis2_char_t *AXIS2_CALL +axis2_op_client_get_transport_from_url( + const axis2_char_t * url, + const axutil_env_t * env) +{ + axis2_char_t *transport = NULL; + const axis2_char_t *start = NULL; + const axis2_char_t *end = NULL; + AXIS2_PARAM_CHECK(env->error, url, NULL); + start = url; + end = url; + while((*end) && (*end) != ':') + end++; + + if((*end) == ':') + { + const axis2_char_t *c = NULL; + transport = AXIS2_MALLOC(env->allocator, (end - start + 1) * sizeof(char)); + if(!transport) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "No memory. Cannot create transport protocol identifier."); + return NULL; + } + + for(c = start; c < end; c++) + transport[c - start] = *c; + transport[c - start] = '\0'; + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "URL is malformed or does not contain a transport protocol"); + } + return transport; +} + +AXIS2_EXTERN axis2_svc_ctx_t *AXIS2_CALL +axis2_op_client_get_svc_ctx( + const axis2_op_client_t * op_client, + const axutil_env_t * env) +{ + return op_client->svc_ctx; +} + +/* This function is called only for single channel invocations */ +AXIS2_EXTERN axis2_msg_ctx_t *AXIS2_CALL +axis2_op_client_two_way_send( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axis2_engine_t *engine = NULL; + axis2_status_t status = AXIS2_SUCCESS; + axis2_msg_ctx_t *response = NULL; + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_op_t *op = NULL; + axiom_soap_envelope_t *response_envelope = NULL; + axutil_property_t *property = NULL; + long index = -1; + axis2_bool_t wait_indefinitely = AXIS2_FALSE; + axis2_char_t *mep = NULL; + + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + engine = axis2_engine_create(env, conf_ctx); + if(!engine) + return NULL; + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_TIMEOUT_IN_SECONDS); + if(property) + { + axis2_char_t *value = axutil_property_get_value(property, env); + if(value) + index = AXIS2_ATOI(value); + if(index == -1) + { + wait_indefinitely = AXIS2_TRUE; + index = 1; + } + } + + status = axis2_engine_send(engine, env, msg_ctx); + + axis2_engine_free(engine, env); + engine = NULL; + + if(status != AXIS2_SUCCESS) + { + if(AXIS2_ERROR_GET_STATUS_CODE(env->error) == AXIS2_SUCCESS) + { + AXIS2_ERROR_SET_STATUS_CODE(env->error, AXIS2_FAILURE); + } + return NULL; + } + + op = axis2_msg_ctx_get_op(msg_ctx, env); + if(op) + { + mep = (axis2_char_t *)axis2_op_get_msg_exchange_pattern(op, env); + } + + if(!mep) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_MEP_CANNOT_DETERMINE_MEP, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot determine message exchange pattern."); + return NULL; + } + + /* handle one way non robust case */ + if(!(axutil_strcmp(mep, AXIS2_MEP_URI_OUT_ONLY))) + { + return NULL; + } + + /* create the response */ + response = axis2_msg_ctx_create(env, conf_ctx, + axis2_msg_ctx_get_transport_in_desc(msg_ctx, env), axis2_msg_ctx_get_transport_out_desc( + msg_ctx, env)); + if(!response) + return NULL; + + axis2_msg_ctx_set_server_side(response, env, AXIS2_FALSE); + axis2_msg_ctx_set_conf_ctx(response, env, axis2_msg_ctx_get_conf_ctx(msg_ctx, env)); + axis2_msg_ctx_set_svc_grp_ctx(response, env, axis2_msg_ctx_get_svc_grp_ctx(msg_ctx, env)); + + /* If request is REST we assume the response is REST, so set the variable */ + axis2_msg_ctx_set_doing_rest(response, env, axis2_msg_ctx_get_doing_rest(msg_ctx, env)); + axis2_msg_ctx_set_status_code(response, env, axis2_msg_ctx_get_status_code(msg_ctx, env)); + + if(op) + { + axis2_op_register_op_ctx(op, env, response, axis2_msg_ctx_get_op_ctx(msg_ctx, env)); + } + + /* set response envelope */ + if(engine) + { + axis2_engine_free(engine, env); + engine = NULL; + } + response_envelope = axis2_msg_ctx_get_response_soap_envelope(msg_ctx, env); + if(response_envelope) + { + axis2_msg_ctx_set_soap_envelope(response, env, response_envelope); + engine = axis2_engine_create(env, conf_ctx); + if(engine) + { + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HANDLER_ALREADY_VISITED); + if(property) + { + axis2_char_t *value = axutil_property_get_value(property, env); + if(!axutil_strcmp(AXIS2_VALUE_TRUE, value)) + { + if(engine) + { + axis2_engine_free(engine, env); + } + return response; + } + } + status = axis2_engine_receive(engine, env, response); + } + } + else + { + while(!response_envelope && index > 0) + { + /*wait till the response arrives */ + AXIS2_SLEEP(1); + if(!wait_indefinitely) + index--; + response_envelope = axis2_msg_ctx_get_response_soap_envelope(msg_ctx, env); + } + /* if it is a two way message, then the status should be in error, + else it is a one way message */ + if(response_envelope) + { + axis2_msg_ctx_set_soap_envelope(response, env, response_envelope); + /* There could be a scenariao where the message has already passed + * through the incoming phases. eg. Reliable Messaging 1.0 two + * way single channel + */ + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HANDLER_ALREADY_VISITED); + if(property) + { + axis2_char_t *value = axutil_property_get_value(property, env); + if(!axutil_strcmp(AXIS2_VALUE_TRUE, value)) + { + return response; + } + } + engine = axis2_engine_create(env, conf_ctx); + if(engine) + { + status = axis2_engine_receive(engine, env, response); + if(status != AXIS2_SUCCESS) + return NULL; + } + } + else + { + if(AXIS2_ERROR_GET_STATUS_CODE(env->error) != AXIS2_SUCCESS) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_BLOCKING_INVOCATION_EXPECTS_RESPONSE, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Response is not valid. Blocking invocation expects response."); + if(engine) + { + axis2_engine_free(engine, env); + engine = NULL; + } + axis2_msg_ctx_free(response, env); + return NULL; + } + } + } + + /*following is no longer valid. Just keeping for others view*/ + + /* property is NULL, and we set null for AXIS2_TRANSPORT_IN in msg_ctx to + avoid double free of this property */ + /*axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_TRANSPORT_IN, property);*/ + + if(engine) + { + axis2_engine_free(engine, env); + engine = NULL; + } + if(!(axutil_strcmp(mep, AXIS2_MEP_URI_ROBUST_OUT_ONLY)) && response) + { + if(axis2_msg_ctx_get_doing_rest(response, env) && axis2_msg_ctx_get_status_code(response, + env) >= 400) + { + /* All HTTP 4xx and 5xx status codes are treated as errors */ + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "HTTP client transport error."); + return NULL; + } + switch(axis2_msg_ctx_get_status_code(response, env)) + { + /* In a SOAP request HTTP status code 500 is used for errors */ + case 500: + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "HTTP client transport error."); + break; + case 0: + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_BLOCKING_INVOCATION_EXPECTS_RESPONSE, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Response is not valid. Blocking invocation expects response."); + break; + case -1: + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_BLOCKING_INVOCATION_EXPECTS_RESPONSE, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Response is not valid. Blocking invocation expects response."); + break; + } + + if(response) + { + axis2_msg_ctx_free(response, env); + } + + return NULL; + } + return response; +} + +AXIS2_EXTERN axis2_msg_ctx_t *AXIS2_CALL +axis2_op_client_receive( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axis2_engine_t *engine = NULL; + axis2_status_t status = AXIS2_SUCCESS; + axis2_msg_ctx_t *response = NULL; + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_op_t *op = NULL; + axiom_soap_envelope_t *response_envelope = NULL; + axutil_property_t *property = NULL; + + /* create the response */ + response = axis2_msg_ctx_create(env, conf_ctx, + axis2_msg_ctx_get_transport_in_desc(msg_ctx, env), axis2_msg_ctx_get_transport_out_desc( + msg_ctx, env)); + if(!response) + return NULL; + + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_TRANSPORT_IN); + if(property) + { + axis2_msg_ctx_set_property(response, env, AXIS2_TRANSPORT_IN, property); + property = NULL; + } + + op = axis2_msg_ctx_get_op(msg_ctx, env); + if(op) + { + axis2_op_register_op_ctx(op, env, response, axis2_msg_ctx_get_op_ctx(msg_ctx, env)); + } + axis2_msg_ctx_set_server_side(response, env, AXIS2_FALSE); + axis2_msg_ctx_set_conf_ctx(response, env, axis2_msg_ctx_get_conf_ctx(msg_ctx, env)); + axis2_msg_ctx_set_svc_grp_ctx(response, env, axis2_msg_ctx_get_svc_grp_ctx(msg_ctx, env)); + + /* If request is REST we assume the response is REST, so set the variable */ + axis2_msg_ctx_set_doing_rest(response, env, axis2_msg_ctx_get_doing_rest(msg_ctx, env)); + + response_envelope = axis2_msg_ctx_get_response_soap_envelope(msg_ctx, env); + if(response_envelope) + { + axis2_msg_ctx_set_soap_envelope(response, env, response_envelope); + if(engine) + { + axis2_engine_free(engine, env); + engine = NULL; + } + + engine = axis2_engine_create(env, conf_ctx); + if(engine) + { + status = axis2_engine_receive(engine, env, response); + if(status != AXIS2_SUCCESS) + { + return NULL; + } + } + + } + else + { + /* if it is a two way message, then the status should be in error, + else it is a one way message */ + if(AXIS2_ERROR_GET_STATUS_CODE(env->error) != AXIS2_SUCCESS) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_BLOCKING_INVOCATION_EXPECTS_RESPONSE, + AXIS2_FAILURE); + return NULL; + } + } + + /* property is NULL, and we set null for AXIS2_TRANSPORT_IN in msg_ctx to + avoid double free of this property */ + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_TRANSPORT_IN, property); + + if(engine) + { + axis2_engine_free(engine, env); + engine = NULL; + } + return response; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_op_client_set_reuse( + axis2_op_client_t * op_client, + const axutil_env_t * env, + axis2_bool_t reuse) +{ + op_client->reuse = reuse; +} -- cgit v1.1-32-gdbae