| /* |
| * 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 <axis2_op_client.h> |
| #include <axis2_const.h> |
| #include <axutil_hash.h> |
| #include <axutil_uuid_gen.h> |
| #include <axis2_listener_manager.h> |
| #include <axis2_engine.h> |
| #include "axis2_callback_recv.h" |
| #include <axiom_xml_reader.h> |
| #include <axis2_core_utils.h> |
| #include <axiom_soap_envelope.h> |
| #include <axiom_soap_const.h> |
| #include <axiom_soap_body.h> |
| #include <axutil_types.h> |
| #include <platforms/axutil_platform_auto_sense.h> |
| |
| 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; |
| axis2_char_t *msg_id = 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)); |
| |
| msg_id = (axis2_char_t *)axutil_uuid_gen(env); |
| axis2_msg_ctx_set_message_id(response, env, msg_id); |
| if(msg_id) |
| { |
| AXIS2_FREE(env->allocator, msg_id); |
| msg_id = NULL; |
| } |
| |
| /* 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) |
| { |
| axiom_soap_body_t * soap_body = NULL; |
| axis2_bool_t has_fault = AXIS2_FALSE; |
| axis2_msg_ctx_set_soap_envelope(response, env, response_envelope); |
| soap_body = axiom_soap_envelope_get_body(response_envelope, env); |
| has_fault = axiom_soap_body_has_fault(soap_body, env); |
| |
| 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; |
| } |
| } |
| if(has_fault) |
| { |
| status = axis2_engine_receive_fault(engine, env, msg_ctx); |
| } |
| else |
| { |
| status = axis2_engine_receive(engine, env, response); |
| } |
| if(status != AXIS2_SUCCESS ) |
| return NULL; |
| } |
| } |
| 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; |
| } |
| |