diff options
author | gmcdonald | 2010-02-13 01:32:03 +0000 |
---|---|---|
committer | gmcdonald | 2010-02-13 01:32:03 +0000 |
commit | 0425aadc78680e53000fd0108b540d6eca048516 (patch) | |
tree | 8ec7ab8e015d454c5ec586dfc91e05a2dce1cfc0 /src/core/clientapi | |
download | axis2c-0425aadc78680e53000fd0108b540d6eca048516.tar.gz axis2c-0425aadc78680e53000fd0108b540d6eca048516.tar.bz2 |
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
Diffstat (limited to 'src/core/clientapi')
-rw-r--r-- | src/core/clientapi/Makefile.am | 17 | ||||
-rw-r--r-- | src/core/clientapi/async_result.c | 83 | ||||
-rw-r--r-- | src/core/clientapi/callback.c | 272 | ||||
-rw-r--r-- | src/core/clientapi/callback_recv.c | 199 | ||||
-rw-r--r-- | src/core/clientapi/listener_manager.c | 302 | ||||
-rw-r--r-- | src/core/clientapi/op_client.c | 1439 | ||||
-rw-r--r-- | src/core/clientapi/options.c | 1068 | ||||
-rw-r--r-- | src/core/clientapi/stub.c | 228 | ||||
-rw-r--r-- | src/core/clientapi/svc_client.c | 1624 |
9 files changed, 5232 insertions, 0 deletions
diff --git a/src/core/clientapi/Makefile.am b/src/core/clientapi/Makefile.am new file mode 100644 index 0000000..8dead6f --- /dev/null +++ b/src/core/clientapi/Makefile.am @@ -0,0 +1,17 @@ +noinst_LTLIBRARIES = libaxis2_clientapi.la
+libaxis2_clientapi_la_SOURCES = async_result.c \
+ callback.c \
+ listener_manager.c \
+ callback_recv.c \
+ stub.c \
+ options.c \
+ op_client.c \
+ svc_client.c
+
+INCLUDES = -I$(top_builddir)/include \
+ -I$(top_builddir)/src/core/engine \
+ -I$(top_builddir)/src/core/deployment \
+ -I$(top_builddir)/util/include \
+ -I$(top_builddir)/util/include/platforms \
+ -I$(top_builddir)/axiom/include \
+ -I$(top_builddir)/neethi/include
diff --git a/src/core/clientapi/async_result.c b/src/core/clientapi/async_result.c new file mode 100644 index 0000000..693e283 --- /dev/null +++ b/src/core/clientapi/async_result.c @@ -0,0 +1,83 @@ +/* + * 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_async_result.h> +#include <axis2_const.h> +#include <axutil_hash.h> + +struct axis2_async_result +{ + + /** result message context */ + axis2_msg_ctx_t *result; +}; + +AXIS2_EXTERN axis2_async_result_t *AXIS2_CALL +axis2_async_result_create( + const axutil_env_t * env, + axis2_msg_ctx_t * result) +{ + axis2_async_result_t *async_result = NULL; + + AXIS2_ENV_CHECK(env, NULL); + + async_result = AXIS2_MALLOC(env->allocator, sizeof(axis2_async_result_t)); + if(!async_result) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create asynchronous result."); + return NULL; + } + + async_result->result = NULL; + + if(result) + { + async_result->result = result; /* shallow copy */ + } + + return async_result; +} + +AXIS2_EXTERN axiom_soap_envelope_t *AXIS2_CALL +axis2_async_result_get_envelope( + axis2_async_result_t * async_result, + const axutil_env_t * env) +{ + if(async_result->result) + { + return axis2_msg_ctx_get_soap_envelope(async_result->result, env); + } + + return NULL; +} + +AXIS2_EXTERN axis2_msg_ctx_t *AXIS2_CALL +axis2_async_result_get_result( + axis2_async_result_t * async_result, + const axutil_env_t * env) +{ + return async_result->result; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_async_result_free( + axis2_async_result_t * async_result, + const axutil_env_t * env) +{ + AXIS2_FREE(env->allocator, async_result); +} diff --git a/src/core/clientapi/callback.c b/src/core/clientapi/callback.c new file mode 100644 index 0000000..6f875df --- /dev/null +++ b/src/core/clientapi/callback.c @@ -0,0 +1,272 @@ +/* + * 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_callback.h> +#include <axis2_const.h> +#include <axutil_hash.h> + +struct axis2_callback +{ + + /** callback complete? */ + axis2_bool_t complete; + + /** envelope corresponding to the result */ + axiom_soap_envelope_t *envelope; + + /** message context corresponding to the result */ + axis2_msg_ctx_t *msg_ctx; + + /** error code */ + int error; + + /** to store callback specific data */ + void *data; + axutil_thread_mutex_t *mutex; + + /** + * This function is called by invoke_on_complete. + * Users could provide this method so that they can define what to be + * done when the callback returns on completion. + * @param callback pointer to callback struct + * @param env pointer to environment struct + * @return AXIS2_SUCCESS on success, else AXIS2_FAILURE + */ + axis2_status_t + ( + AXIS2_CALL * on_complete) + ( + axis2_callback_t * callback, + const axutil_env_t * env); + + /** + * This function is called by report_error. + * Users could provide this method so that they can define what to be done + * when the callback returns an error. + * @param callback pointer to callback struct + * @param env pointer to environment struct + * @param exception error code representing the error + * @return AXIS2_SUCCESS on success, else AXIS2_FAILURE + */ + axis2_status_t + ( + AXIS2_CALL * on_error) +( axis2_callback_t * callback, +const axutil_env_t * env, +const int exception); +}; + +static axis2_status_t AXIS2_CALL axis2_callback_on_complete( + axis2_callback_t * callback, + const axutil_env_t * env); + +static axis2_status_t AXIS2_CALL axis2_callback_on_error( + axis2_callback_t * callback, + const axutil_env_t * env, + int exception); + +AXIS2_EXTERN axis2_callback_t *AXIS2_CALL +axis2_callback_create( + const axutil_env_t * env) +{ + axis2_callback_t *callback = NULL; + + AXIS2_ENV_CHECK(env, NULL); + + callback = AXIS2_MALLOC(env->allocator, sizeof(axis2_callback_t)); + if(!callback) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create callback."); + return NULL; + } + + callback->complete = AXIS2_FALSE; + callback->envelope = NULL; + callback->msg_ctx = NULL; + callback->error = AXIS2_ERROR_NONE; + callback->data = NULL; + callback->mutex = NULL; + callback->on_complete = axis2_callback_on_complete; + callback->on_error = axis2_callback_on_error; + + callback->mutex = axutil_thread_mutex_create(env->allocator, AXIS2_THREAD_MUTEX_DEFAULT); + return callback; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_callback_invoke_on_complete( + axis2_callback_t * callback, + const axutil_env_t * env, + axis2_async_result_t * result) +{ + axis2_status_t status = AXIS2_FAILURE; + + callback->envelope = axis2_async_result_get_envelope(result, env); + callback->msg_ctx = axis2_async_result_get_result(result, env); + axis2_msg_ctx_increment_ref(callback->msg_ctx, env); /* this will be set in opclient's msgctx + map and will be deleted from there */ + + status = callback->on_complete(callback, env); + + return status; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_callback_report_error( + axis2_callback_t * callback, + const axutil_env_t * env, + const int exception) +{ + axis2_callback_set_error(callback, env, exception); + return callback->on_error(callback, env, exception); +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_callback_get_complete( + const axis2_callback_t * callback, + const axutil_env_t * env) +{ + return callback->complete; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_callback_set_complete( + axis2_callback_t * callback, + const axutil_env_t * env, + const axis2_bool_t complete) +{ + callback->complete = complete; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axiom_soap_envelope_t *AXIS2_CALL +axis2_callback_get_envelope( + const axis2_callback_t * callback, + const axutil_env_t * env) +{ + return callback->envelope; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_callback_set_envelope( + axis2_callback_t * callback, + const axutil_env_t * env, + axiom_soap_envelope_t * envelope) +{ + callback->envelope = envelope; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_msg_ctx_t *AXIS2_CALL +axis2_callback_get_msg_ctx( + const axis2_callback_t * callback, + const axutil_env_t * env) +{ + return callback->msg_ctx; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_callback_set_msg_ctx( + axis2_callback_t * callback, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + callback->msg_ctx = msg_ctx; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_callback_get_error( + const axis2_callback_t * callback, + const axutil_env_t * env) +{ + return callback->error; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_callback_set_error( + axis2_callback_t * callback, + const axutil_env_t * env, + const int error) +{ + callback->error = error; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_callback_free( + axis2_callback_t * callback, + const axutil_env_t * env) +{ + if(callback->mutex) + { + axutil_thread_mutex_destroy(callback->mutex); + } + + AXIS2_FREE(env->allocator, callback); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_callback_set_data( + axis2_callback_t * callback, + void *data) +{ + callback->data = (void *)data; + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN void *AXIS2_CALL +axis2_callback_get_data( + const axis2_callback_t * callback) +{ + return callback->data; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_callback_set_on_complete( + axis2_callback_t * callback, + axis2_on_complete_func_ptr func) +{ + callback->on_complete = func; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_callback_set_on_error( + axis2_callback_t * callback, + axis2_on_error_func_ptr func) +{ + callback->on_error = func; +} + +static axis2_status_t AXIS2_CALL +axis2_callback_on_complete( + axis2_callback_t * callback, + const axutil_env_t * env) +{ + return AXIS2_SUCCESS; +} + +static axis2_status_t AXIS2_CALL +axis2_callback_on_error( + axis2_callback_t * callback, + const axutil_env_t * env, + int exception) +{ + return AXIS2_SUCCESS; +} diff --git a/src/core/clientapi/callback_recv.c b/src/core/clientapi/callback_recv.c new file mode 100644 index 0000000..f45ed87 --- /dev/null +++ b/src/core/clientapi/callback_recv.c @@ -0,0 +1,199 @@ +/* + * 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_callback_recv.h" +#include <axis2_const.h> +#include <axutil_hash.h> + +struct axis2_callback_recv +{ + /** base context struct */ + axis2_msg_recv_t *base; + axis2_bool_t base_deep_copy; + + /** callback map */ + axutil_hash_t *callback_map; + axutil_thread_mutex_t *mutex; +}; + +static axis2_status_t AXIS2_CALL axis2_callback_recv_receive( + axis2_msg_recv_t * msg_recv, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + void *callback_recv_param); + +AXIS2_EXTERN axis2_callback_recv_t *AXIS2_CALL +axis2_callback_recv_create( + const axutil_env_t * env) +{ + axis2_callback_recv_t *callback_recv = NULL; + + AXIS2_ENV_CHECK(env, NULL); + + callback_recv = AXIS2_MALLOC(env->allocator, sizeof(axis2_callback_recv_t)); + + if(!callback_recv) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create callback receive."); + return NULL; + } + + callback_recv->base = NULL; + callback_recv->base_deep_copy = AXIS2_TRUE; + callback_recv->callback_map = NULL; + callback_recv->mutex = NULL; + + callback_recv->base = axis2_msg_recv_create(env); + if(!callback_recv->base) + { + axis2_callback_recv_free(callback_recv, env); + return NULL; + } + axis2_msg_recv_set_derived(callback_recv->base, env, callback_recv); + axis2_msg_recv_set_receive(callback_recv->base, env, axis2_callback_recv_receive); + + callback_recv->callback_map = axutil_hash_make(env); + if(!callback_recv->callback_map) + { + axis2_callback_recv_free(callback_recv, env); + return NULL; + } + + callback_recv->mutex = axutil_thread_mutex_create(env->allocator, AXIS2_THREAD_MUTEX_DEFAULT); + return callback_recv; +} + +AXIS2_EXTERN axis2_msg_recv_t *AXIS2_CALL +axis2_callback_recv_get_base( + axis2_callback_recv_t * callback_recv, + const axutil_env_t * env) +{ + callback_recv->base_deep_copy = AXIS2_FALSE; + return callback_recv->base; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_callback_recv_free( + axis2_callback_recv_t * callback_recv, + const axutil_env_t * env) +{ + if(callback_recv->mutex) + { + axutil_thread_mutex_destroy(callback_recv->mutex); + } + + if(callback_recv->callback_map) + { + axutil_hash_index_t *hi = NULL; + const void *key = NULL; + void *val = NULL; + for(hi = axutil_hash_first(callback_recv->callback_map, env); hi; hi = axutil_hash_next( + env, hi)) + { + axutil_hash_this(hi, &key, NULL, &val); + if(key) + { + AXIS2_FREE(env->allocator, (char *)key); + } + if(val) + { + axis2_callback_t *callback = (axis2_callback_t *) val; + axis2_callback_free(callback, env); + } + + } + + axutil_hash_free(callback_recv->callback_map, env); + } + + if(callback_recv->base && callback_recv->base_deep_copy) + { + axis2_msg_recv_free(callback_recv->base, env); + } + + if(callback_recv) + { + AXIS2_FREE(env->allocator, callback_recv); + } +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_callback_recv_add_callback( + axis2_callback_recv_t * callback_recv, + const axutil_env_t * env, + const axis2_char_t * msg_id, + axis2_callback_t * callback) +{ + if(msg_id) + { + axis2_char_t *mid = axutil_strdup(env, msg_id); + axutil_hash_set(callback_recv->callback_map, mid, AXIS2_HASH_KEY_STRING, callback); + } + return AXIS2_SUCCESS; +} + +/* In the dual channel invocations client set a callback function to be invoked when a resonse + * is received from the server. When the response is received by the listening port of the + * listener manager, in the engine receive call the message is finally hit by callback receiver + * which is an implementation of the axis2 message receiver. This is the function that is called + * at that stage. The client set callback function is called from within here. + */ +static axis2_status_t AXIS2_CALL +axis2_callback_recv_receive( + axis2_msg_recv_t * msg_recv, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + void *callback_recv_param) +{ + axis2_callback_recv_t *callback_recv = NULL; + axis2_relates_to_t *relates_to = NULL; + axis2_msg_info_headers_t *msg_info_headers = NULL; + + callback_recv = axis2_msg_recv_get_derived(msg_recv, env); + + msg_info_headers = axis2_msg_ctx_get_msg_info_headers(msg_ctx, env); + if(msg_info_headers) + { + relates_to = axis2_msg_info_headers_get_relates_to(msg_info_headers, env); + if(relates_to) + { + const axis2_char_t *msg_id = axis2_relates_to_get_value(relates_to, env); + if(msg_id) + { + axis2_async_result_t *result = NULL; + axis2_callback_t *callback = (axis2_callback_t *)axutil_hash_get( + callback_recv->callback_map, msg_id, AXIS2_HASH_KEY_STRING); + + result = axis2_async_result_create(env, msg_ctx); + if(callback && result) + { + axis2_callback_invoke_on_complete(callback, env, result); + axis2_callback_set_complete(callback, env, AXIS2_TRUE); + axis2_msg_ctx_set_soap_envelope(msg_ctx, env, NULL); + } + + axis2_async_result_free(result, env); + if(callback && result) + return AXIS2_SUCCESS; + } + } + } + + return AXIS2_FAILURE; +} + diff --git a/src/core/clientapi/listener_manager.c b/src/core/clientapi/listener_manager.c new file mode 100644 index 0000000..1e3e3f2 --- /dev/null +++ b/src/core/clientapi/listener_manager.c @@ -0,0 +1,302 @@ +/* + * 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_listener_manager.h> +#include <axis2_const.h> +#include <axutil_hash.h> +#include <axis2_transport_receiver.h> + +/** + * keep information about the listener for a given transport + */ +typedef struct axis2_transport_listener_state +{ + int waiting_calls; + + axis2_transport_receiver_t *listener; + +} axis2_transport_listener_state_t; + +struct axis2_listener_manager +{ + + /** hash map of listeners */ + axis2_transport_listener_state_t *listener_map[AXIS2_TRANSPORT_ENUM_MAX]; + axutil_thread_t *listener_thread[AXIS2_TRANSPORT_ENUM_MAX]; + + /** configuration context */ + axis2_conf_ctx_t *conf_ctx; +}; + +typedef struct axis2_listener_manager_worker_func_args +{ + const axutil_env_t *env; + axis2_listener_manager_t *listner_manager; + axis2_transport_receiver_t *listener; +} axis2_listener_manager_worker_func_args_t; + +void *AXIS2_THREAD_FUNC axis2_listener_manager_worker_func( + axutil_thread_t * thd, + void *data); + +AXIS2_EXTERN axis2_listener_manager_t *AXIS2_CALL +axis2_listener_manager_create( + const axutil_env_t * env) +{ + axis2_listener_manager_t *listener_manager = NULL; + int i = 0; + + AXIS2_ENV_CHECK(env, NULL); + + listener_manager = AXIS2_MALLOC(env->allocator, sizeof(axis2_listener_manager_t)); + + if(!listener_manager) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create listener manager."); + return NULL; + } + + listener_manager->conf_ctx = NULL; + + for(i = 0; i < AXIS2_TRANSPORT_ENUM_MAX; i++) + { + listener_manager->listener_map[i] = NULL; + listener_manager->listener_thread[i] = NULL; + } + + return listener_manager; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_listener_manager_make_sure_started( + axis2_listener_manager_t * listener_manager, + const axutil_env_t * env, + const AXIS2_TRANSPORT_ENUMS transport, + axis2_conf_ctx_t * conf_ctx) +{ + axis2_transport_listener_state_t *tl_state = NULL; + + AXIS2_PARAM_CHECK(env->error, conf_ctx, AXIS2_FAILURE); + + if(listener_manager->conf_ctx) + { + if(conf_ctx != listener_manager->conf_ctx) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_CLIENT_SIDE_SUPPORT_ONLY_ONE_CONF_CTX, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Only one configuration context is supported at client side."); + return AXIS2_FAILURE; + } + } + else + { + listener_manager->conf_ctx = conf_ctx; + } + + tl_state = listener_manager->listener_map[transport]; + + if(!tl_state) + { + /*means this transport not yet started, start the transport */ + axis2_transport_in_desc_t *transport_in = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_receiver_t *listener = NULL; + + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + if(conf) + { + transport_in = axis2_conf_get_transport_in(conf, env, transport); + if(transport_in) + { + listener = axis2_transport_in_desc_get_recv(transport_in, env); + if(listener) + { + axutil_thread_t *worker_thread = NULL; + axis2_listener_manager_worker_func_args_t *arg_list = NULL; + arg_list = AXIS2_MALLOC(env->allocator, + sizeof(axis2_listener_manager_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 listener manager worker function arguments."); + return AXIS2_FAILURE; + } + arg_list->env = env; + arg_list->listner_manager = listener_manager; + arg_list->listener = listener; +#ifdef AXIS2_SVR_MULTI_THREADED + if (env->thread_pool) + { + worker_thread = + axutil_thread_pool_get_thread(env->thread_pool, + axis2_listener_manager_worker_func, + (void *) arg_list); + if (!worker_thread) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Thread creation failed" + "Invoke non blocking failed"); + } + else + { + /*axutil_thread_pool_thread_detach(env->thread_pool, + worker_thread);*/ + /* we should not detach this, because, in the dual channel case + we should be able to terminate the thread before deleting the listener */ + } + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Thread pool not set in environment." + " Cannot invoke call non blocking"); + } +#else + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Threading not enabled." + " Cannot start separate listener"); + return AXIS2_FAILURE; +#endif + + tl_state = AXIS2_MALLOC(env->allocator, + sizeof(axis2_transport_listener_state_t)); + + if(!tl_state) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "No memory. Cannot create transport listener state."); + } + else + { + tl_state->listener = listener; + tl_state->waiting_calls = 0; + listener_manager->listener_map[transport] = tl_state; + listener_manager->listener_thread[transport] = worker_thread; + } + } + } + } + } + + if(tl_state) + { + tl_state->waiting_calls++; + return AXIS2_SUCCESS; + } + else + return AXIS2_FAILURE; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_listener_manager_stop( + axis2_listener_manager_t * listener_manager, + const axutil_env_t * env, + const AXIS2_TRANSPORT_ENUMS transport) +{ + axis2_transport_listener_state_t *tl_state = NULL; + axis2_status_t status = AXIS2_FAILURE; + axutil_thread_t *listener_thread = NULL; + + tl_state = listener_manager->listener_map[transport]; + listener_thread = listener_manager->listener_thread[transport]; + + if(tl_state) + { + tl_state->waiting_calls--; + if(tl_state->waiting_calls == 0) + { + status = axis2_transport_receiver_stop(tl_state->listener, env); + if(status == AXIS2_SUCCESS) + listener_manager->listener_map[transport] = NULL; + } + } + + if(listener_thread) + { + axutil_thread_pool_exit_thread(env->thread_pool, listener_thread); + listener_manager->listener_thread[transport] = NULL; + } + + return status; +} + +AXIS2_EXTERN axis2_endpoint_ref_t *AXIS2_CALL +axis2_listener_manager_get_reply_to_epr( + const axis2_listener_manager_t * listener_manager, + const axutil_env_t * env, + const axis2_char_t * svc_name, + const AXIS2_TRANSPORT_ENUMS transport) +{ + axis2_transport_listener_state_t *tl_state = NULL; + + tl_state = listener_manager->listener_map[transport]; + if(tl_state) + { + return axis2_transport_receiver_get_reply_to_epr(tl_state->listener, env, svc_name); + } + return NULL; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_listener_manager_free( + axis2_listener_manager_t * listener_manager, + const axutil_env_t * env) +{ + int i = 0; + + for(i = 0; i < AXIS2_TRANSPORT_ENUM_MAX; i++) + { + if(listener_manager->listener_map[i]) + AXIS2_FREE(env->allocator, listener_manager->listener_map[i]); + } + + AXIS2_FREE(env->allocator, listener_manager); +} + +AXIS2_EXTERN axis2_conf_ctx_t *AXIS2_CALL +axis2_listener_manager_get_conf_ctx( + const axis2_listener_manager_t * listener_manager, + const axutil_env_t * env) +{ + return listener_manager->conf_ctx; +} + +void *AXIS2_THREAD_FUNC +axis2_listener_manager_worker_func( + axutil_thread_t * thd, + void *data) +{ + axis2_listener_manager_worker_func_args_t *args_list = NULL; + const axutil_env_t *th_env = NULL; + + args_list = (axis2_listener_manager_worker_func_args_t *)data; + if(!args_list) + return NULL; + + th_env = axutil_init_thread_env(args_list->env); + /* Start the protocol server. For examlle if protocol is http axis2_http_server_start function + * of the axis2_http_receiver is called. + */ + if(args_list->listener) + { + axis2_transport_receiver_start(args_list->listener, th_env); + } + return NULL; +} 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 <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; + + 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; +} diff --git a/src/core/clientapi/options.c b/src/core/clientapi/options.c new file mode 100644 index 0000000..26c5d33 --- /dev/null +++ b/src/core/clientapi/options.c @@ -0,0 +1,1068 @@ +/* + * 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_options.h> +#include <axis2_const.h> +#include <axutil_hash.h> +#include <axiom_soap_const.h> +#include <axis2_msg_info_headers.h> +#include <axutil_array_list.h> +#include <axis2_http_transport.h> + +struct axis2_options +{ + + /** parent options */ + axis2_options_t *parent; + + axutil_hash_t *properties; + + axis2_char_t *soap_version_uri; + + int soap_version; + + long timeout_in_milli_seconds; + + axis2_bool_t use_separate_listener; + + /** addressing specific properties */ + axis2_msg_info_headers_t *msg_info_headers; + + axis2_transport_receiver_t *receiver; + + axis2_transport_in_desc_t *transport_in; + + AXIS2_TRANSPORT_ENUMS transport_in_protocol; + + /** for sending and receiving messages */ + axis2_transport_out_desc_t *transport_out; + AXIS2_TRANSPORT_ENUMS sender_transport_protocol; + + axis2_bool_t manage_session; + axis2_bool_t enable_mtom; + axutil_string_t *soap_action; + axis2_bool_t xml_parser_reset; +}; + +AXIS2_EXTERN axis2_options_t *AXIS2_CALL +axis2_options_create( + const axutil_env_t * env) +{ + axis2_options_t *options = NULL; + + AXIS2_ENV_CHECK(env, NULL); + + options = AXIS2_MALLOC(env->allocator, sizeof(axis2_options_t)); + if(!options) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create options."); + return NULL; + } + + options->parent = NULL; + options->properties = NULL; + options->soap_version_uri = NULL; + options->timeout_in_milli_seconds = -1; + options->use_separate_listener = -1; + options->receiver = NULL; + options->transport_in = NULL; + options->transport_in_protocol = AXIS2_TRANSPORT_ENUM_MAX; + options->transport_out = NULL; + options->sender_transport_protocol = AXIS2_TRANSPORT_ENUM_MAX; + options->manage_session = -1; + options->soap_version = AXIOM_SOAP12; + options->enable_mtom = AXIS2_FALSE; + options->soap_action = NULL; + options->xml_parser_reset = AXIS2_TRUE; + + options->msg_info_headers = axis2_msg_info_headers_create(env, NULL, NULL); + if(!options->msg_info_headers) + { + axis2_options_free(options, env); + return NULL; + } + + options->properties = axutil_hash_make(env); + if(!options->properties) + { + axis2_options_free(options, env); + return NULL; + } + + return options; +} + +AXIS2_EXTERN axis2_options_t *AXIS2_CALL +axis2_options_create_with_parent( + const axutil_env_t * env, + axis2_options_t * parent) +{ + + axis2_options_t *options = NULL; + + options = axis2_options_create(env); + + if(options) + { + options->parent = parent; + } + return options; +} + +AXIS2_EXTERN const axis2_char_t *AXIS2_CALL +axis2_options_get_action( + const axis2_options_t * options, + const axutil_env_t * env) +{ + const axis2_char_t *action = NULL; + action = axis2_msg_info_headers_get_action(options->msg_info_headers, env); + + if(!action && options->parent) + { + return axis2_options_get_action(options->parent, env); + } + + return action; +} + +AXIS2_EXTERN axis2_endpoint_ref_t *AXIS2_CALL +axis2_options_get_fault_to( + const axis2_options_t * options, + const axutil_env_t * env) +{ + axis2_endpoint_ref_t *fault_to = NULL; + + fault_to = axis2_msg_info_headers_get_fault_to(options->msg_info_headers, env); + + if(!fault_to && options->parent) + { + return axis2_options_get_fault_to(options->parent, env); + } + + return fault_to; +} + +AXIS2_EXTERN axis2_endpoint_ref_t *AXIS2_CALL +axis2_options_get_from( + const axis2_options_t * options, + const axutil_env_t * env) +{ + axis2_endpoint_ref_t *from = NULL; + + from = axis2_msg_info_headers_get_from(options->msg_info_headers, env); + + if(!from && options->parent) + { + return axis2_options_get_from(options->parent, env); + } + + return from; +} + +AXIS2_EXTERN axis2_transport_receiver_t *AXIS2_CALL +axis2_options_get_transport_receiver( + const axis2_options_t * options, + const axutil_env_t * env) +{ + if(!options->receiver && options->parent) + { + return axis2_options_get_transport_receiver(options->parent, env); + } + + return options->receiver; +} + +AXIS2_EXTERN axis2_transport_in_desc_t *AXIS2_CALL +axis2_options_get_transport_in( + const axis2_options_t * options, + const axutil_env_t * env) +{ + if(!options->transport_in && options->parent) + { + return axis2_options_get_transport_in(options->parent, env); + } + + return options->transport_in; +} + +AXIS2_EXTERN AXIS2_TRANSPORT_ENUMS AXIS2_CALL +axis2_options_get_transport_in_protocol( + const axis2_options_t * options, + const axutil_env_t * env) +{ + if(options->parent) + { + return axis2_options_get_transport_in_protocol(options->parent, env); + } + + return options->transport_in_protocol; +} + +AXIS2_EXTERN const axis2_char_t *AXIS2_CALL +axis2_options_get_message_id( + const axis2_options_t * options, + const axutil_env_t * env) +{ + const axis2_char_t *message_id = NULL; + + message_id = axis2_msg_info_headers_get_message_id(options->msg_info_headers, env); + + if(!message_id && options->parent) + { + return axis2_options_get_message_id(options->parent, env); + } + + return message_id; +} + +AXIS2_EXTERN axutil_hash_t *AXIS2_CALL +axis2_options_get_properties( + const axis2_options_t * options, + const axutil_env_t * env) +{ + if(!axutil_hash_count(options->properties) && options->parent) + { + return axis2_options_get_properties(options->parent, env); + } + + return options->properties; +} + +AXIS2_EXTERN void *AXIS2_CALL +axis2_options_get_property( + const axis2_options_t * options, + const axutil_env_t * env, + const axis2_char_t * key) +{ + void *property = NULL; + + property = axutil_hash_get(options->properties, key, AXIS2_HASH_KEY_STRING); + + if(!property && options->parent) + { + return axis2_options_get_property(options->parent, env, key); + } + + return property; +} + +AXIS2_EXTERN axis2_relates_to_t *AXIS2_CALL +axis2_options_get_relates_to( + const axis2_options_t * options, + const axutil_env_t * env) +{ + axis2_relates_to_t *relates_to = NULL; + + relates_to = axis2_msg_info_headers_get_relates_to(options->msg_info_headers, env); + + if(!relates_to && options->parent) + { + return axis2_options_get_relates_to(options->parent, env); + } + + return relates_to; +} + +AXIS2_EXTERN axis2_endpoint_ref_t *AXIS2_CALL +axis2_options_get_reply_to( + const axis2_options_t * options, + const axutil_env_t * env) +{ + axis2_endpoint_ref_t *reply_to = NULL; + + reply_to = axis2_msg_info_headers_get_reply_to(options->msg_info_headers, env); + + if(!reply_to && options->parent) + { + return axis2_options_get_reply_to(options->parent, env); + } + + return reply_to; +} + +AXIS2_EXTERN axis2_transport_out_desc_t *AXIS2_CALL +axis2_options_get_transport_out( + const axis2_options_t * options, + const axutil_env_t * env) +{ + if(!options->transport_out && options->parent) + { + return axis2_options_get_transport_out(options->parent, env); + } + + return options->transport_out; +} + +AXIS2_EXTERN AXIS2_TRANSPORT_ENUMS AXIS2_CALL +axis2_options_get_sender_transport_protocol( + const axis2_options_t * options, + const axutil_env_t * env) +{ + if(options->parent) + { + return axis2_options_get_sender_transport_protocol(options->parent, env); + } + + return options->sender_transport_protocol; +} + +AXIS2_EXTERN const axis2_char_t *AXIS2_CALL +axis2_options_get_soap_version_uri( + const axis2_options_t * options, + const axutil_env_t * env) +{ + if(!options->soap_version_uri && options->parent) + { + return axis2_options_get_soap_version_uri(options->parent, env); + } + + if(options->soap_version_uri) + { + return options->soap_version_uri; + } + return AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI; + +} + +AXIS2_EXTERN long AXIS2_CALL +axis2_options_get_timeout_in_milli_seconds( + const axis2_options_t * options, + const axutil_env_t * env) +{ + if(options->timeout_in_milli_seconds == -1) + { + if(options->parent) + { + return axis2_options_get_timeout_in_milli_seconds(options->parent, env); + } + else + { + return AXIS2_DEFAULT_TIMEOUT_MILLISECONDS; + } + } + + return options->timeout_in_milli_seconds; +} + +AXIS2_EXTERN axis2_endpoint_ref_t *AXIS2_CALL +axis2_options_get_to( + const axis2_options_t * options, + const axutil_env_t * env) +{ + axis2_endpoint_ref_t *to = NULL; + + to = axis2_msg_info_headers_get_to(options->msg_info_headers, env); + + if(!to && options->parent) + { + return axis2_options_get_to(options->parent, env); + } + + return to; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_options_get_use_separate_listener( + const axis2_options_t * options, + const axutil_env_t * env) +{ + if(options->use_separate_listener == -1) + { + if(options->parent) + { + return axis2_options_get_use_separate_listener(options->parent, env); + } + else + { + return AXIS2_FALSE; + } + } + + return options->use_separate_listener; +} + +AXIS2_EXTERN axis2_options_t *AXIS2_CALL +axis2_options_get_parent( + const axis2_options_t * options, + const axutil_env_t * env) +{ + return options->parent; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_parent( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_options_t * parent) +{ + options->parent = (axis2_options_t *)parent; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_action( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_char_t * action) +{ + axis2_msg_info_headers_set_action(options->msg_info_headers, env, action); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_fault_to( + axis2_options_t * options, + const axutil_env_t * env, + axis2_endpoint_ref_t * fault_to) +{ + axis2_msg_info_headers_set_fault_to(options->msg_info_headers, env, fault_to); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_from( + axis2_options_t * options, + const axutil_env_t * env, + axis2_endpoint_ref_t * from) +{ + axis2_msg_info_headers_set_from(options->msg_info_headers, env, from); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_to( + axis2_options_t * options, + const axutil_env_t * env, + axis2_endpoint_ref_t * to) +{ + axis2_msg_info_headers_set_to(options->msg_info_headers, env, to); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_transport_receiver( + axis2_options_t * options, + const axutil_env_t * env, + axis2_transport_receiver_t * receiver) +{ + options->receiver = receiver; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_transport_in( + axis2_options_t * options, + const axutil_env_t * env, + axis2_transport_in_desc_t * transport_in) +{ + options->transport_in = transport_in; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_transport_in_protocol( + axis2_options_t * options, + const axutil_env_t * env, + const AXIS2_TRANSPORT_ENUMS transport_in_protocol) +{ + options->transport_in_protocol = transport_in_protocol; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_message_id( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_char_t * message_id) +{ + axis2_msg_info_headers_set_message_id(options->msg_info_headers, env, message_id); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_properties( + axis2_options_t * options, + const axutil_env_t * env, + axutil_hash_t * properties) +{ + if(options->properties) + { + axutil_hash_free(options->properties, env); + } + options->properties = properties; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_property( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_char_t * property_key, + const void *property) +{ + axutil_hash_set(options->properties, property_key, AXIS2_HASH_KEY_STRING, property); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_relates_to( + axis2_options_t * options, + const axutil_env_t * env, + axis2_relates_to_t * relates_to) +{ + axis2_msg_info_headers_set_relates_to(options->msg_info_headers, env, relates_to); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_reply_to( + axis2_options_t * options, + const axutil_env_t * env, + axis2_endpoint_ref_t * reply_to) +{ + axis2_msg_info_headers_set_reply_to(options->msg_info_headers, env, reply_to); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_transport_out( + axis2_options_t * options, + const axutil_env_t * env, + axis2_transport_out_desc_t * transport_out) +{ + options->transport_out = transport_out; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_sender_transport( + axis2_options_t * options, + const axutil_env_t * env, + const AXIS2_TRANSPORT_ENUMS sender_transport, + axis2_conf_t * conf) +{ + options->transport_out = axis2_conf_get_transport_out(conf, env, sender_transport); + + if(!options->transport_out) + { + return AXIS2_FAILURE; + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_soap_version_uri( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_char_t * soap_version_uri) +{ + if(options->soap_version_uri) + { + AXIS2_FREE(env->allocator, options->soap_version_uri); + options->soap_version_uri = NULL; + } + + if(soap_version_uri) + { + options->soap_version_uri = axutil_strdup(env, soap_version_uri); + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_timeout_in_milli_seconds( + axis2_options_t * options, + const axutil_env_t * env, + const long timeout_in_milli_seconds) +{ + options->timeout_in_milli_seconds = timeout_in_milli_seconds; + /* set the property AXIS2_HTTP_CONNECTION_TIMEOUT, + * to be picked up by http_sender + */ + if(options->timeout_in_milli_seconds > 0) + { + axis2_char_t time_str[19]; /* supports 18 digit timeout */ + axutil_property_t *property = axutil_property_create(env); + sprintf(time_str, "%ld", options->timeout_in_milli_seconds); + if(property) + { + axutil_property_set_scope(property, env, AXIS2_SCOPE_REQUEST); + axutil_property_set_value(property, env, axutil_strdup(env, time_str)); + axis2_options_set_property(options, env, AXIS2_HTTP_CONNECTION_TIMEOUT, property); + } + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_transport_info( + axis2_options_t * options, + const axutil_env_t * env, + const AXIS2_TRANSPORT_ENUMS sender_transport, + const AXIS2_TRANSPORT_ENUMS receiver_transport, + const axis2_bool_t use_separate_listener) +{ + /* + here we check for the legal combination + */ + if(!use_separate_listener) + { + if(sender_transport != receiver_transport) + { + return AXIS2_FAILURE; + } + } + else + { + axis2_options_set_use_separate_listener(options, env, use_separate_listener); + } + axis2_options_set_transport_in_protocol(options, env, receiver_transport); + options->sender_transport_protocol = sender_transport; + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_use_separate_listener( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_bool_t use_separate_listener) +{ + axutil_property_t *property = NULL; + + options->use_separate_listener = use_separate_listener; + + if(use_separate_listener) + { + property = axutil_property_create(env); + axutil_property_set_value(property, env, axutil_strdup(env, AXIS2_VALUE_TRUE)); + axis2_options_set_property(options, env, AXIS2_USE_SEPARATE_LISTENER, property); + } + else + { + property = axutil_property_create(env); + axutil_property_set_value(property, env, axutil_strdup(env, AXIS2_VALUE_FALSE)); + axis2_options_set_property(options, env, AXIS2_USE_SEPARATE_LISTENER, property); + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_add_reference_parameter( + axis2_options_t * options, + const axutil_env_t * env, + axiom_node_t * reference_parameter) +{ + axis2_msg_info_headers_add_ref_param(options->msg_info_headers, env, reference_parameter); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_manage_session( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_bool_t manage_session) +{ + options->manage_session = manage_session; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_options_get_manage_session( + const axis2_options_t * options, + const axutil_env_t * env) +{ + if(options->manage_session == -1) + { + if(options->parent) + { + return axis2_options_get_manage_session(options->parent, env); + } + else + { + return AXIS2_FALSE; + } + } + + return options->manage_session; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_msg_info_headers( + axis2_options_t * options, + const axutil_env_t * env, + axis2_msg_info_headers_t * msg_info_headers) +{ + if(options->msg_info_headers) + { + axis2_msg_info_headers_free(options->msg_info_headers, env); + } + + options->msg_info_headers = msg_info_headers; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_msg_info_headers_t *AXIS2_CALL +axis2_options_get_msg_info_headers( + const axis2_options_t * options, + const axutil_env_t * env) +{ + return options->msg_info_headers; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_options_free( + axis2_options_t * options, + const axutil_env_t * env) +{ + if(options->properties) + { + axutil_hash_index_t *hi = NULL; + void *val = NULL; + const void *key = NULL; + for(hi = axutil_hash_first(options->properties, env); hi; hi = axutil_hash_next(env, hi)) + { + axutil_property_t *property = NULL; + + axutil_hash_this(hi, &key, NULL, &val); + property = (axutil_property_t *)val; + + if(property) + { + axutil_property_free(property, env); + } + } + axutil_hash_free(options->properties, env); + } + + if(options->soap_version_uri) + { + AXIS2_FREE(env->allocator, options->soap_version_uri); + } + + if(options->msg_info_headers) + { + axis2_msg_info_headers_free(options->msg_info_headers, env); + } + + if(options->soap_action) + { + axutil_string_free(options->soap_action, env); + } + + AXIS2_FREE(env->allocator, options); +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_options_get_soap_version( + const axis2_options_t * options, + const axutil_env_t * env) +{ + return options->soap_version; + +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_soap_version( + axis2_options_t * options, + const axutil_env_t * env, + const int soap_version) +{ + if(soap_version == AXIOM_SOAP11) + { + options->soap_version = soap_version; + axis2_options_set_soap_version_uri(options, env, AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI); + } + else + { + options->soap_version = AXIOM_SOAP12; + axis2_options_set_soap_version_uri(options, env, AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI); + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_enable_mtom( + axis2_options_t * options, + const axutil_env_t * env, + axis2_bool_t enable_mtom) +{ + options->enable_mtom = enable_mtom; + + if(enable_mtom) + { + axutil_property_t *property = axutil_property_create(env); + if(property) + { + axutil_property_set_scope(property, env, AXIS2_SCOPE_REQUEST); + axutil_property_set_value(property, env, axutil_strdup(env, AXIS2_VALUE_TRUE)); + axis2_options_set_property(options, env, AXIS2_ENABLE_MTOM, property); + } + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_options_get_enable_mtom( + const axis2_options_t * options, + const axutil_env_t * env) +{ + return options->enable_mtom; +} + +AXIS2_EXTERN axutil_string_t *AXIS2_CALL +axis2_options_get_soap_action( + const axis2_options_t * options, + const axutil_env_t * env) +{ + return options->soap_action; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_soap_action( + axis2_options_t * options, + const axutil_env_t * env, + axutil_string_t * soap_action) +{ + if(options->soap_action) + { + axutil_string_free(options->soap_action, env); + options->soap_action = NULL; + } + + if(soap_action) + { + options->soap_action = axutil_string_clone(soap_action, env); + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_options_get_xml_parser_reset( + const axis2_options_t * options, + const axutil_env_t * env) +{ + return options->xml_parser_reset; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_xml_parser_reset( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_bool_t xml_parser_reset) +{ + options->xml_parser_reset = xml_parser_reset; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_enable_rest( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_bool_t enable_rest) +{ + axutil_property_t *rest_property = NULL; + + if(enable_rest) + { + rest_property = axutil_property_create(env); + axutil_property_set_value(rest_property, env, axutil_strdup(env, AXIS2_VALUE_TRUE)); + axis2_options_set_property(options, env, AXIS2_ENABLE_REST, rest_property); + } + else + { + rest_property = axutil_property_create(env); + axutil_property_set_value(rest_property, env, axutil_strdup(env, AXIS2_VALUE_FALSE)); + axis2_options_set_property(options, env, AXIS2_ENABLE_REST, rest_property); + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_test_http_auth( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_bool_t test_http_auth) +{ + axutil_property_t *test_auth_property = NULL; + + if(test_http_auth) + { + test_auth_property = axutil_property_create(env); + axutil_property_set_value(test_auth_property, env, axutil_strdup(env, AXIS2_VALUE_TRUE)); + axis2_options_set_property(options, env, AXIS2_TEST_HTTP_AUTH, test_auth_property); + } + else + { + test_auth_property = axutil_property_create(env); + axutil_property_set_value(test_auth_property, env, axutil_strdup(env, AXIS2_VALUE_FALSE)); + axis2_options_set_property(options, env, AXIS2_TEST_HTTP_AUTH, test_auth_property); + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_test_proxy_auth( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_bool_t test_proxy_auth) +{ + axutil_property_t *test_auth_property = NULL; + + if(test_proxy_auth) + { + test_auth_property = axutil_property_create(env); + axutil_property_set_value(test_auth_property, env, axutil_strdup(env, AXIS2_VALUE_TRUE)); + axis2_options_set_property(options, env, AXIS2_TEST_PROXY_AUTH, test_auth_property); + } + else + { + test_auth_property = axutil_property_create(env); + axutil_property_set_value(test_auth_property, env, axutil_strdup(env, AXIS2_VALUE_FALSE)); + axis2_options_set_property(options, env, AXIS2_TEST_PROXY_AUTH, test_auth_property); + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_http_method( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_char_t * http_method) +{ + axutil_property_t *method_property = NULL; + + method_property = axutil_property_create(env); + axutil_property_set_value(method_property, env, axutil_strdup(env, http_method)); + axis2_options_set_property(options, env, AXIS2_HTTP_METHOD, method_property); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_http_headers( + axis2_options_t * options, + const axutil_env_t * env, + axutil_array_list_t * http_header_list) +{ + axutil_property_t *headers_property = NULL; + + headers_property = axutil_property_create(env); + axutil_property_set_value(headers_property, env, http_header_list); + axis2_options_set_property(options, env, AXIS2_TRANSPORT_HEADER_PROPERTY, headers_property); + axutil_property_set_free_func(headers_property, env, axutil_array_list_free_void_arg); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_proxy_auth_info( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_char_t * username, + const axis2_char_t * password, + const axis2_char_t * auth_type) +{ + axis2_bool_t force_proxy_auth = AXIS2_FALSE; + axutil_property_t *prop_pw = NULL; + axutil_property_t *prop_un = NULL; + + prop_un = axutil_property_create(env); + axutil_property_set_value(prop_un, env, axutil_strdup(env, username)); + axis2_options_set_property(options, env, AXIS2_PROXY_AUTH_UNAME, prop_un); + + prop_pw = axutil_property_create(env); + axutil_property_set_value(prop_pw, env, axutil_strdup(env, password)); + axis2_options_set_property(options, env, AXIS2_PROXY_AUTH_PASSWD, prop_pw); + + if(auth_type) + { + if((axutil_strcasecmp(auth_type, AXIS2_PROXY_AUTH_TYPE_BASIC) == 0) || (axutil_strcasecmp( + auth_type, AXIS2_PROXY_AUTH_TYPE_DIGEST) == 0)) + { + force_proxy_auth = AXIS2_TRUE; + } + } + if(force_proxy_auth) + { + axutil_property_t *proxy_auth_property = axutil_property_create(env); + axutil_property_t *proxy_auth_type_property = axutil_property_create(env); + + axutil_property_set_value(proxy_auth_property, env, axutil_strdup(env, AXIS2_VALUE_TRUE)); + axis2_options_set_property(options, env, AXIS2_FORCE_PROXY_AUTH, proxy_auth_property); + + axutil_property_set_value(proxy_auth_type_property, env, axutil_strdup(env, auth_type)); + axis2_options_set_property(options, env, AXIS2_PROXY_AUTH_TYPE, proxy_auth_type_property); + } + else + { + axutil_property_t *proxy_auth_property = axutil_property_create(env); + axutil_property_set_value(proxy_auth_property, env, axutil_strdup(env, AXIS2_VALUE_FALSE)); + axis2_options_set_property(options, env, AXIS2_FORCE_PROXY_AUTH, proxy_auth_property); + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_options_set_http_auth_info( + axis2_options_t * options, + const axutil_env_t * env, + const axis2_char_t * username, + const axis2_char_t * password, + const axis2_char_t * auth_type) +{ + axis2_bool_t force_http_auth = AXIS2_FALSE; + axutil_property_t *prop_un = NULL; + axutil_property_t *prop_pw = NULL; + + prop_un = axutil_property_create(env); + axutil_property_set_value(prop_un, env, axutil_strdup(env, username)); + axis2_options_set_property(options, env, AXIS2_HTTP_AUTH_UNAME, prop_un); + + prop_pw = axutil_property_create(env); + axutil_property_set_value(prop_pw, env, axutil_strdup(env, password)); + axis2_options_set_property(options, env, AXIS2_HTTP_AUTH_PASSWD, prop_pw); + + if(auth_type) + { + if((axutil_strcasecmp(auth_type, AXIS2_HTTP_AUTH_TYPE_BASIC) == 0) || (axutil_strcasecmp( + auth_type, AXIS2_HTTP_AUTH_TYPE_DIGEST) == 0)) + { + force_http_auth = AXIS2_TRUE; + } + } + if(force_http_auth) + { + axutil_property_t *http_auth_property = axutil_property_create(env); + axutil_property_t *http_auth_type_property = axutil_property_create(env); + + axutil_property_set_value(http_auth_property, env, axutil_strdup(env, AXIS2_VALUE_TRUE)); + axis2_options_set_property(options, env, AXIS2_FORCE_HTTP_AUTH, http_auth_property); + + axutil_property_set_value(http_auth_type_property, env, axutil_strdup(env, auth_type)); + axis2_options_set_property(options, env, AXIS2_HTTP_AUTH_TYPE, http_auth_type_property); + } + else + { + axutil_property_t *http_auth_property = axutil_property_create(env); + axutil_property_set_value(http_auth_property, env, axutil_strdup(env, AXIS2_VALUE_FALSE)); + axis2_options_set_property(options, env, AXIS2_FORCE_HTTP_AUTH, http_auth_property); + } + return AXIS2_SUCCESS; +} + diff --git a/src/core/clientapi/stub.c b/src/core/clientapi/stub.c new file mode 100644 index 0000000..2b27274 --- /dev/null +++ b/src/core/clientapi/stub.c @@ -0,0 +1,228 @@ +/* + * 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_stub.h> + +struct axis2_stub +{ + axis2_svc_client_t *svc_client; + axis2_options_t *options; +}; + +AXIS2_EXTERN axis2_stub_t *AXIS2_CALL +axis2_stub_create( + const axutil_env_t * env) +{ + axis2_stub_t *stub = NULL; + + AXIS2_ENV_CHECK(env, NULL); + + stub = (axis2_stub_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_stub_t)); + + if(!stub) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create stub."); + return NULL; + } + stub->svc_client = NULL; + stub->options = NULL; + + return stub; +} + +AXIS2_EXTERN axis2_stub_t *AXIS2_CALL +axis2_stub_create_with_endpoint_ref_and_client_home( + const axutil_env_t * env, + axis2_endpoint_ref_t * endpoint_ref, + const axis2_char_t * client_home) +{ + axis2_stub_t *stub = NULL; + + AXIS2_ENV_CHECK(env, NULL); + AXIS2_PARAM_CHECK(env->error, endpoint_ref, NULL); + + stub = (axis2_stub_t *)axis2_stub_create(env); + + if(!stub) + { + return NULL; + } + + stub->svc_client = axis2_svc_client_create(env, client_home); + + if(!stub->svc_client) + { + axis2_stub_free(stub, env); + return NULL; + } + + stub->options = axis2_options_create(env); + if(!stub->options) + { + axis2_stub_free(stub, env); + return NULL; + } + + axis2_svc_client_set_options(stub->svc_client, env, stub->options); + + axis2_options_set_to(stub->options, env, endpoint_ref); + + return stub; +} + +AXIS2_EXTERN axis2_stub_t *AXIS2_CALL +axis2_stub_create_with_endpoint_uri_and_client_home( + const axutil_env_t * env, + const axis2_char_t * endpoint_uri, + const axis2_char_t * client_home) +{ + axis2_stub_t *stub = NULL; + axis2_endpoint_ref_t *endpoint_ref = NULL; + + AXIS2_ENV_CHECK(env, NULL); + AXIS2_PARAM_CHECK(env->error, endpoint_uri, NULL); + + endpoint_ref = axis2_endpoint_ref_create(env, endpoint_uri); + if(!endpoint_ref) + { + return NULL; + } + stub = (axis2_stub_t *)axis2_stub_create_with_endpoint_ref_and_client_home(env, endpoint_ref, + client_home); + + if(!stub) + { + return NULL; + } + + return stub; +} + +void AXIS2_CALL +axis2_stub_free( + axis2_stub_t * stub, + const axutil_env_t * env) +{ + if(stub) + { + if(stub->svc_client) + { + axis2_svc_client_free(stub->svc_client, env); + } + + AXIS2_FREE(env->allocator, stub); + } +} + +axis2_status_t AXIS2_CALL +axis2_stub_set_endpoint_ref( + axis2_stub_t * stub, + const axutil_env_t * env, + axis2_endpoint_ref_t * endpoint_ref) +{ + AXIS2_PARAM_CHECK(env->error, endpoint_ref, AXIS2_FAILURE); + axis2_options_set_to(stub->options, env, endpoint_ref); + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_stub_set_endpoint_uri( + axis2_stub_t * stub, + const axutil_env_t * env, + const axis2_char_t * endpoint_uri) +{ + axis2_endpoint_ref_t *endpoint_ref = NULL; + + AXIS2_PARAM_CHECK(env->error, endpoint_uri, AXIS2_FAILURE); + + endpoint_ref = axis2_endpoint_ref_create(env, endpoint_uri); + if(!endpoint_ref) + { + return AXIS2_FAILURE; + } + axis2_options_set_to(stub->options, env, endpoint_ref); + + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_stub_set_use_separate_listener( + axis2_stub_t * stub, + const axutil_env_t * env, + const axis2_bool_t use_separate_listener) +{ + return axis2_options_set_use_separate_listener(stub->options, env, use_separate_listener); +} + +axis2_status_t AXIS2_CALL +axis2_stub_engage_module( + axis2_stub_t * stub, + const axutil_env_t * env, + const axis2_char_t * module_name) +{ + AXIS2_PARAM_CHECK(env->error, module_name, AXIS2_FAILURE); + + return axis2_svc_client_engage_module(stub->svc_client, env, module_name); +} + +axis2_status_t AXIS2_CALL +axis2_stub_set_soap_version( + axis2_stub_t * stub, + const axutil_env_t * env, + const int soap_version) +{ + if(!stub->options) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Cannot set soap version. Stub option is not valid."); + return AXIS2_FAILURE; + } + return axis2_options_set_soap_version(stub->options, env, soap_version); +} + +const axis2_char_t *AXIS2_CALL +axis2_stub_get_svc_ctx_id( + const axis2_stub_t * stub, + const axutil_env_t * env) +{ + const axis2_svc_ctx_t *svc_ctx = NULL; + const axis2_char_t *svc_ctx_id = NULL; + + AXIS2_PARAM_CHECK(env->error, stub, NULL); + + svc_ctx = axis2_svc_client_get_svc_ctx(stub->svc_client, env); + svc_ctx_id = axis2_svc_ctx_get_svc_id(svc_ctx, env); + return svc_ctx_id; +} + +axis2_svc_client_t *AXIS2_CALL +axis2_stub_get_svc_client( + const axis2_stub_t * stub, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, stub, NULL); + return stub->svc_client; +} + +axis2_options_t *AXIS2_CALL +axis2_stub_get_options( + const axis2_stub_t * stub, + const axutil_env_t * env) +{ + return stub->options; +} diff --git a/src/core/clientapi/svc_client.c b/src/core/clientapi/svc_client.c new file mode 100644 index 0000000..d25f340 --- /dev/null +++ b/src/core/clientapi/svc_client.c @@ -0,0 +1,1624 @@ +/* + * 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_svc_client.h> +#include <axis2_phases_info.h> +#include <axis2_const.h> +#include <axutil_hash.h> +#include <axutil_uri.h> +#include "axis2_callback_recv.h" +#include <axiom_soap_const.h> +#include <axiom_soap_body.h> +#include <axiom_soap_header.h> +#include <axiom_util.h> +#include <axis2_listener_manager.h> +#include <axis2_module_desc.h> +#include <axutil_array_list.h> +#include <axis2_options.h> +#include <axis2_conf_init.h> +#include <platforms/axutil_platform_auto_sense.h> +#include <stdio.h> +#include <axutil_generic_obj.h> +#include <axis2_http_transport.h> +#include <axis2_http_header.h> +#include <neethi_util.h> +#include <axis2_policy_include.h> + +struct axis2_svc_client +{ + axis2_svc_t *svc; + + axis2_conf_t *conf; + + axis2_conf_ctx_t *conf_ctx; + + axis2_svc_ctx_t *svc_ctx; + + axis2_options_t *options; + + axis2_options_t *override_options; + + /* SOAP Headers */ + axutil_array_list_t *headers; + + /* for receiving the async messages */ + axis2_callback_recv_t *callback_recv; + + axis2_listener_manager_t *listener_manager; + + axis2_op_client_t *op_client; + + axiom_soap_envelope_t *last_response_soap_envelope; + + axis2_bool_t last_response_has_fault; + + axis2_bool_t reuse; + + axis2_bool_t auth_failed; + + axis2_bool_t required_auth_is_http; + + axis2_char_t *auth_type; + + axutil_array_list_t *http_headers; + + int http_status_code; + + axis2_bool_t keep_externally_passed_ctx_and_svc; + +}; + +static void +axis2_svc_client_set_http_info( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +static axis2_svc_t * +axis2_svc_client_create_annonymous_svc( + axis2_svc_client_t * svc_client, + const axutil_env_t * env); + +static axis2_bool_t +axis2_svc_client_init_transports_from_conf_ctx( + const axutil_env_t * env, + axis2_svc_client_t * svc_client, + axis2_conf_ctx_t * conf_ctx, + const axis2_char_t * client_home); + +static axis2_bool_t +axis2_svc_client_init_data( + const axutil_env_t * env, + axis2_svc_client_t * svc_client); + +static axis2_bool_t +axis2_svc_client_fill_soap_envelope( + const axutil_env_t * env, + axis2_svc_client_t * svc_client, + axis2_msg_ctx_t * msg_ctx, + const axiom_node_t * payload); + +AXIS2_EXTERN axis2_svc_client_t *AXIS2_CALL +axis2_svc_client_create( + const axutil_env_t * env, + const axis2_char_t * client_home) +{ + axis2_svc_client_t *svc_client = NULL; + + AXIS2_ENV_CHECK(env, NULL); + svc_client = axis2_svc_client_create_with_conf_ctx_and_svc(env, client_home, NULL, NULL); + + return svc_client; +} + +AXIS2_EXTERN axis2_svc_client_t *AXIS2_CALL +axis2_svc_client_create_with_conf_ctx_and_svc( + const axutil_env_t * env, + const axis2_char_t * client_home, + axis2_conf_ctx_t * conf_ctx, + axis2_svc_t * svc) +{ + axis2_svc_client_t *svc_client = NULL; + axis2_svc_grp_t *svc_grp = NULL; + axis2_svc_grp_ctx_t *svc_grp_ctx = NULL; + const axis2_char_t *svc_grp_name = NULL; + + svc_client = AXIS2_MALLOC(env->allocator, sizeof(axis2_svc_client_t)); + if(!svc_client) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create service client."); + return NULL; + } + + svc_client->svc = NULL; + svc_client->conf = NULL; + svc_client->conf_ctx = NULL; + svc_client->svc_ctx = NULL; + svc_client->options = NULL; + svc_client->override_options = NULL; + svc_client->headers = NULL; + svc_client->callback_recv = NULL; + svc_client->listener_manager = NULL; + svc_client->op_client = NULL; + svc_client->last_response_soap_envelope = NULL; + svc_client->last_response_has_fault = AXIS2_FALSE; + svc_client->reuse = AXIS2_FALSE; + svc_client->auth_failed = AXIS2_FALSE; + svc_client->required_auth_is_http = AXIS2_FALSE; + svc_client->auth_type = NULL; + svc_client->http_headers = NULL; + svc_client->keep_externally_passed_ctx_and_svc = AXIS2_FALSE; + + if(!axis2_svc_client_init_data(env, svc_client)) + { + axis2_svc_client_free(svc_client, env); + return NULL; + } + + /*create the default conf_ctx if it is NULL */ + if(!axis2_svc_client_init_transports_from_conf_ctx(env, svc_client, conf_ctx, client_home)) + { + axis2_svc_client_free(svc_client, env); + return NULL; + } + + svc_client->conf = axis2_conf_ctx_get_conf(svc_client->conf_ctx, env); + + if(svc) + { + svc_client->keep_externally_passed_ctx_and_svc = AXIS2_TRUE; + svc_client->svc = svc; + } + else + { + svc_client->svc = axis2_svc_client_create_annonymous_svc(svc_client, env); + if(!svc_client->svc) + { + axis2_svc_client_free(svc_client, env); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot create annonymous service."); + return NULL; + } + } + + /** add the service to the config context if it isn't in there already */ + if(!axis2_conf_get_svc(svc_client->conf, env, axis2_svc_get_name(svc_client->svc, env))) + { + axis2_conf_add_svc(svc_client->conf, env, svc_client->svc); + } + + /** create a service context for myself: create a new service group + context and then get the service context for myself as I'll need that + later for stuff that I gotta do */ + svc_grp = axis2_svc_get_parent(svc_client->svc, env); + if(!svc_grp) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot access service group of service client."); + return NULL; + } + + svc_grp_ctx = axis2_svc_grp_get_svc_grp_ctx(svc_grp, env, svc_client->conf_ctx); + if(!svc_grp_ctx) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Cannot access service group context of service client."); + return NULL; + } + + svc_grp_name = axis2_svc_grp_get_name(svc_grp, env); + if(!svc_grp_name) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Cannot access service group name of service client."); + return NULL; /* service group name is mandatory */ + } + + axis2_conf_ctx_register_svc_grp_ctx(svc_client->conf_ctx, env, svc_grp_name, svc_grp_ctx); + + svc_client->svc_ctx = axis2_svc_grp_ctx_get_svc_ctx(svc_grp_ctx, env, axis2_svc_get_name( + svc_client->svc, env)); + + return svc_client; +} + +AXIS2_EXTERN axis2_svc_t *AXIS2_CALL +axis2_svc_client_get_svc( + const axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, svc_client, NULL); + return svc_client->svc; +} + +AXIS2_EXTERN axis2_conf_ctx_t *AXIS2_CALL +axis2_svc_client_get_conf_ctx( + const axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, svc_client, NULL); + return svc_client->conf_ctx; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_set_options( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axis2_options_t * options) +{ + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FAILURE); + if(svc_client->options) + { + axis2_options_free(svc_client->options, env); + } + svc_client->options = (axis2_options_t *)options; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN const axis2_options_t *AXIS2_CALL +axis2_svc_client_get_options( + const axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, svc_client, NULL); + return svc_client->options; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_set_override_options( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axis2_options_t * override_options) +{ + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FAILURE); + if(svc_client->override_options) + { + axis2_options_free(svc_client->override_options, env); + } + + svc_client->override_options = (axis2_options_t *)override_options; + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN const axis2_options_t *AXIS2_CALL +axis2_svc_client_get_override_options( + const axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, svc_client, NULL); + return svc_client->override_options; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_engage_module( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axis2_char_t * module_name) +{ + axis2_module_desc_t *module = NULL; + axutil_qname_t *mod_qname = NULL; + + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, module_name, AXIS2_FAILURE); + + mod_qname = axutil_qname_create(env, module_name, NULL, NULL); + + if(!mod_qname) + { + return AXIS2_FAILURE; + } + + module = axis2_conf_get_module(svc_client->conf, env, mod_qname); + + axutil_qname_free(mod_qname, env); + mod_qname = NULL; + + if(module) + { + return axis2_svc_engage_module(svc_client->svc, env, module, svc_client->conf); + } + return AXIS2_FAILURE; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_disengage_module( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axis2_char_t * module_name) +{ + axis2_module_desc_t *module = NULL; + axutil_qname_t *mod_qname = NULL; + + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, module_name, AXIS2_FAILURE); + + mod_qname = axutil_qname_create(env, module_name, NULL, NULL); + if(!mod_qname) + { + return AXIS2_FAILURE; + } + + module = axis2_conf_get_module(svc_client->conf, env, mod_qname); + axutil_qname_free(mod_qname, env); + mod_qname = NULL; + + if(module) + { + return axis2_svc_disengage_module(svc_client->svc, env, module, svc_client->conf); + } + return AXIS2_FAILURE; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_add_header( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + axiom_node_t * header) +{ + + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FAILURE); + if(!svc_client->headers) + { + svc_client->headers = axutil_array_list_create(env, 0); + if(!svc_client->headers) + { + return AXIS2_FAILURE; + } + } + axutil_array_list_add(svc_client->headers, env, header); + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_remove_all_headers( + axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + int i = 0; + int size = 0; + + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FAILURE); + + if(!svc_client->headers) + { + return AXIS2_SUCCESS; + } + + size = axutil_array_list_size(svc_client->headers, env); + + for(i = size - 1; i > -1; i--) + { + axutil_array_list_remove(svc_client->headers, env, i); + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_send_robust_with_op_qname( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axutil_qname_t * op_qname, + const axiom_node_t * payload) +{ + axis2_msg_ctx_t *msg_ctx = NULL; + axis2_status_t status = AXIS2_FAILURE; + axis2_bool_t qname_free_flag = AXIS2_FALSE; + + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FAILURE); + + if(!op_qname) + { + op_qname = axutil_qname_create(env, AXIS2_ANON_ROBUST_OUT_ONLY_OP, NULL, NULL); + if(!op_qname) + { + return AXIS2_FAILURE; + } + qname_free_flag = AXIS2_TRUE; + } + else + { + axis2_op_t *op = NULL; + axis2_char_t *mep = NULL; + axis2_svc_t *svc = NULL; + svc = axis2_svc_client_get_svc(svc_client, env); + if(!svc) + { + return AXIS2_FAILURE; + } + op = axis2_svc_get_op_with_qname(svc, env, op_qname); + if(!op) + { + return AXIS2_FAILURE; + } + mep = (axis2_char_t *)axis2_op_get_msg_exchange_pattern(op, env); + if(!mep || axutil_strcmp(AXIS2_MEP_URI_OUT_ONLY, mep) != 0) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "%s%s", + "To use this method opeation uri should be", AXIS2_MEP_URI_OUT_ONLY); + return AXIS2_FAILURE; + } + } + + svc_client->auth_failed = AXIS2_FALSE; + svc_client->required_auth_is_http = AXIS2_FALSE; + if(svc_client->auth_type) + { + AXIS2_FREE(env->allocator, svc_client->auth_type); + } + svc_client->auth_type = NULL; + + msg_ctx = axis2_msg_ctx_create(env, axis2_svc_ctx_get_conf_ctx(svc_client->svc_ctx, env), NULL, + NULL); + if(!axis2_svc_client_fill_soap_envelope(env, svc_client, msg_ctx, payload)) + { + return AXIS2_FAILURE; + } + + if(!axis2_svc_client_create_op_client(svc_client, env, op_qname)) + { + return AXIS2_FAILURE; + } + + axis2_op_client_add_out_msg_ctx(svc_client->op_client, env, msg_ctx); + status = axis2_op_client_execute(svc_client->op_client, env, AXIS2_TRUE); + axis2_svc_client_set_http_info(svc_client, env, msg_ctx); + svc_client->auth_failed = axis2_msg_ctx_get_auth_failed(msg_ctx, env); + svc_client->required_auth_is_http = axis2_msg_ctx_get_required_auth_is_http(msg_ctx, env); + if(axis2_msg_ctx_get_auth_type(msg_ctx, env)) + { + svc_client->auth_type = axutil_strdup(env, axis2_msg_ctx_get_auth_type(msg_ctx, env)); + } + + if(qname_free_flag) + { + axutil_qname_free((axutil_qname_t *)op_qname, env); + } + + return status; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_send_robust( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axiom_node_t * payload) +{ + return axis2_svc_client_send_robust_with_op_qname(svc_client, env, NULL, payload); +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_svc_client_fire_and_forget_with_op_qname( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axutil_qname_t * op_qname, + const axiom_node_t * payload) +{ + axis2_msg_ctx_t *msg_ctx = NULL; + axis2_bool_t qname_free_flag = AXIS2_FALSE; + + AXIS2_PARAM_CHECK_VOID(env->error, svc_client); + + if(!op_qname) + { + op_qname = axutil_qname_create(env, AXIS2_ANON_OUT_ONLY_OP, NULL, NULL); + if(!op_qname) + { + return; + } + qname_free_flag = AXIS2_TRUE; + } + + svc_client->auth_failed = AXIS2_FALSE; + svc_client->required_auth_is_http = AXIS2_FALSE; + if(svc_client->auth_type) + { + AXIS2_FREE(env->allocator, svc_client->auth_type); + } + svc_client->auth_type = NULL; + + msg_ctx = axis2_msg_ctx_create(env, axis2_svc_ctx_get_conf_ctx(svc_client->svc_ctx, env), NULL, + NULL); + if(!axis2_svc_client_fill_soap_envelope(env, svc_client, msg_ctx, payload)) + { + return; + } + + if(!axis2_svc_client_create_op_client(svc_client, env, op_qname)) + { + return; + } + + axis2_op_client_add_out_msg_ctx(svc_client->op_client, env, msg_ctx); + axis2_op_client_execute(svc_client->op_client, env, AXIS2_TRUE); + axis2_svc_client_set_http_info(svc_client, env, msg_ctx); + svc_client->auth_failed = axis2_msg_ctx_get_auth_failed(msg_ctx, env); + svc_client->required_auth_is_http = axis2_msg_ctx_get_required_auth_is_http(msg_ctx, env); + if(axis2_msg_ctx_get_auth_type(msg_ctx, env)) + { + svc_client->auth_type = axutil_strdup(env, axis2_msg_ctx_get_auth_type(msg_ctx, env)); + } + + if(qname_free_flag) + { + axutil_qname_free((axutil_qname_t *)op_qname, env); + } +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_svc_client_fire_and_forget( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axiom_node_t * payload) +{ + axis2_svc_client_fire_and_forget_with_op_qname(svc_client, env, NULL, payload); +} + +AXIS2_EXTERN axiom_node_t *AXIS2_CALL +axis2_svc_client_send_receive_with_op_qname( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axutil_qname_t * op_qname, + const axiom_node_t * payload) +{ + axiom_soap_envelope_t *soap_envelope = NULL; + axiom_soap_body_t *soap_body = NULL; + axiom_node_t *soap_node = NULL; + axis2_op_t *op = NULL; + axutil_param_t *param = NULL; + axutil_uri_t *action_uri = NULL; + axis2_char_t *action_str = NULL; + axis2_bool_t qname_free_flag = AXIS2_FALSE; + + axis2_msg_ctx_t *res_msg_ctx = NULL; + axis2_msg_ctx_t *msg_ctx = NULL; + + AXIS2_PARAM_CHECK(env->error, svc_client, NULL); + + svc_client->last_response_soap_envelope = NULL; + svc_client->last_response_has_fault = AXIS2_FALSE; + svc_client->auth_failed = AXIS2_FALSE; + svc_client->required_auth_is_http = AXIS2_FALSE; + if(svc_client->auth_type) + { + AXIS2_FREE(env->allocator, svc_client->auth_type); + } + svc_client->auth_type = NULL; + + op = axis2_svc_get_op_with_qname(svc_client->svc, env, op_qname); + if(op) + { + param = axis2_op_get_param(op, env, AXIS2_SOAP_ACTION); + if(param) + { + action_uri = (axutil_uri_t *)axutil_param_get_value(param, env); + action_str = axutil_uri_to_string(action_uri, env, AXIS2_URI_UNP_OMITUSERINFO); + axis2_options_set_action(svc_client->options, env, action_str); + } + } + + if(!op_qname) + { + op_qname = axutil_qname_create(env, AXIS2_ANON_OUT_IN_OP, NULL, NULL); + if(!op_qname) + return NULL; + + qname_free_flag = AXIS2_TRUE; + } + + /* If dual channel blocking. We come to this block if the client indicate to use + * a separate listener but don't provide a callback function to acted upon when + * response is received in the listener thread. What we do here is we create a callback + * and call axis2_svc_client_send_receive_non_blocking_with_op_qname with it. */ + if(axis2_options_get_use_separate_listener(svc_client->options, env)) + { + axis2_callback_t *callback = NULL; + axis2_msg_ctx_t *msg_ctx = NULL; + long index = 0; + + /* This means doing a Request-Response invocation using two channels. + If the transport is a two way transport (e.g. http), only one channel is used + (e.g. in http cases 202 OK is sent to say no response available). + Axis2 gets blocked and return when the response is available. */ + + callback = axis2_callback_create(env); + if(!callback) + { + return NULL; + } + + /* Call two channel non blocking invoke to do the work and wait on the callback. We don't + * set a callback function for the callback. That functionality is handled here. + */ + axis2_svc_client_send_receive_non_blocking_with_op_qname(svc_client, env, op_qname, + payload, callback); + + index = axis2_options_get_timeout_in_milli_seconds(svc_client->options, env) / 10; + + while(!axis2_callback_get_complete(callback, env)) + { + if(index-- >= 0) + { + AXIS2_USLEEP(10000); + } + else + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_RESPONSE_TIMED_OUT, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Response time out."); + return NULL; + } + } + + soap_envelope = axis2_callback_get_envelope(callback, env); + msg_ctx = axis2_callback_get_msg_ctx(callback, env); + axis2_op_client_add_in_msg_ctx(svc_client->op_client, env, msg_ctx); + + /* start of hack to get rid of memory leak */ + /*msg_ctx = axis2_msg_ctx_create(env, axis2_svc_ctx_get_conf_ctx(svc_client-> svc_ctx, env), + NULL, NULL); + if(!msg_ctx) + return NULL; + + axis2_op_client_add_in_msg_ctx(svc_client->op_client, env, msg_ctx); + + axis2_msg_ctx_set_soap_envelope(msg_ctx, env, soap_envelope);*/ + /* end of hack to get rid of memory leak */ + + /* process the result of the invocation */ + if(!soap_envelope) + { + if(axis2_callback_get_error(callback, env) != AXIS2_ERROR_NONE) + { + AXIS2_ERROR_SET(env->error, axis2_callback_get_error(callback, env), AXIS2_FAILURE); + return NULL; + } + } + } + else + { + msg_ctx = axis2_msg_ctx_create(env, axis2_svc_ctx_get_conf_ctx(svc_client->svc_ctx, env), + NULL, NULL); + if(!msg_ctx) + return NULL; + + if(!axis2_svc_client_fill_soap_envelope(env, svc_client, msg_ctx, payload)) + { + return NULL; + } + + if(!axis2_svc_client_create_op_client(svc_client, env, op_qname)) + { + return NULL; + } + + axis2_op_client_add_msg_ctx(svc_client->op_client, env, msg_ctx); + axis2_op_client_execute(svc_client->op_client, env, AXIS2_TRUE); + axis2_svc_client_set_http_info(svc_client, env, msg_ctx); + svc_client->auth_failed = axis2_msg_ctx_get_auth_failed(msg_ctx, env); + svc_client->required_auth_is_http = axis2_msg_ctx_get_required_auth_is_http(msg_ctx, env); + if(axis2_msg_ctx_get_auth_type(msg_ctx, env)) + { + svc_client->auth_type = axutil_strdup(env, axis2_msg_ctx_get_auth_type(msg_ctx, env)); + } + res_msg_ctx = (axis2_msg_ctx_t *)axis2_op_client_get_msg_ctx(svc_client-> op_client, env, + AXIS2_WSDL_MESSAGE_LABEL_IN); + + if(res_msg_ctx) + { + soap_envelope = axis2_msg_ctx_get_soap_envelope(res_msg_ctx, env); + } + else + { + axis2_op_client_add_msg_ctx(svc_client->op_client, env, res_msg_ctx); + /* set in msg_ctx to be NULL to reset */ + } + } + + if(qname_free_flag) + { + axutil_qname_free((axutil_qname_t *)op_qname, env); + } + + if(!soap_envelope) + { + return NULL; + } + svc_client->last_response_soap_envelope = soap_envelope; + + soap_body = axiom_soap_envelope_get_body(soap_envelope, env); + + if(!soap_body) + { + axiom_node_t *node = axiom_soap_envelope_get_base_node(soap_envelope, env); + if(node) + { + axiom_element_t *envelope_element = (axiom_element_t *)axiom_node_get_data_element( + node, env); + axiom_util_get_first_child_element_with_localname(envelope_element, env, node, + AXIOM_SOAP_BODY_LOCAL_NAME, &soap_node); + if(soap_node) + { + return axiom_node_get_first_element(soap_node, env); + } + } + return NULL; + } + + if(axis2_msg_ctx_get_doing_rest(res_msg_ctx, env)) + { + /* All HTTP 4xx and 5xx status codes are treated as errors */ + if(axis2_msg_ctx_get_status_code(res_msg_ctx, env) >= 400) + { + svc_client->last_response_has_fault = AXIS2_TRUE; + } + else + { + svc_client->last_response_has_fault = AXIS2_FALSE; + } + } + else + { + svc_client->last_response_has_fault = axiom_soap_body_has_fault(soap_body, env); + } + + if(AXIOM_SOAP11 == axiom_soap_envelope_get_soap_version(soap_envelope, env)) + { + axiom_soap_body_convert_fault_to_soap11(soap_body, env); + } + + soap_node = axiom_soap_body_get_base_node(soap_body, env); + if(!soap_node) + { + return NULL; + } + return axiom_node_get_first_element(soap_node, env); +} + +AXIS2_EXTERN axiom_node_t *AXIS2_CALL +axis2_svc_client_send_receive( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axiom_node_t * payload) +{ + return axis2_svc_client_send_receive_with_op_qname(svc_client, env, NULL, payload); +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_svc_client_send_receive_non_blocking_with_op_qname( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axutil_qname_t * op_qname, + const axiom_node_t * payload, + axis2_callback_t * callback) +{ + axis2_msg_ctx_t *msg_ctx = NULL; + AXIS2_TRANSPORT_ENUMS transport_in_protocol; + axis2_bool_t qname_free_flag = AXIS2_FALSE; + + AXIS2_PARAM_CHECK_VOID(env->error, svc_client); + + if(!op_qname) + { + op_qname = axutil_qname_create(env, AXIS2_ANON_OUT_IN_OP, NULL, NULL); + if(!op_qname) + return; + qname_free_flag = AXIS2_TRUE; + } + + svc_client->auth_failed = AXIS2_FALSE; + svc_client->required_auth_is_http = AXIS2_FALSE; + if(svc_client->auth_type) + { + AXIS2_FREE(env->allocator, svc_client->auth_type); + } + svc_client->auth_type = NULL; + + msg_ctx = axis2_msg_ctx_create(env, axis2_svc_ctx_get_conf_ctx(svc_client-> svc_ctx, env), + NULL, NULL); + if(!msg_ctx) + return; + + if(!axis2_svc_client_fill_soap_envelope(env, svc_client, msg_ctx, payload)) + { + return; + } + + if(!axis2_svc_client_create_op_client(svc_client, env, op_qname)) + { + return; + } + + axis2_op_client_set_callback(svc_client->op_client, env, callback); + axis2_op_client_add_out_msg_ctx(svc_client->op_client, env, msg_ctx); + + /* If dual channel */ + if(axis2_options_get_use_separate_listener(svc_client->options, env)) + { + axis2_op_t *op = NULL; + + transport_in_protocol = axis2_options_get_transport_in_protocol(svc_client->options, env); + if(transport_in_protocol == AXIS2_TRANSPORT_ENUM_MAX) + { + axis2_options_set_transport_in_protocol(svc_client->options, env, + AXIS2_TRANSPORT_ENUM_HTTP); + transport_in_protocol = AXIS2_TRANSPORT_ENUM_HTTP; + } + axis2_listener_manager_make_sure_started(svc_client->listener_manager, env, + transport_in_protocol, svc_client->conf_ctx); + /* Following sleep is required to ensure the listener is ready to receive response. + If it is missing, the response gets lost. - Samisa */ + AXIS2_USLEEP(1); + + op = axis2_svc_get_op_with_qname(svc_client->svc, env, op_qname); + /* At the end of the incoming flow this message receiver will be hit */ + axis2_op_set_msg_recv(op, env, + AXIS2_CALLBACK_RECV_GET_BASE(svc_client-> callback_recv, env)); + axis2_op_client_set_callback_recv(svc_client->op_client, env, svc_client->callback_recv); + } + + axis2_op_client_execute(svc_client->op_client, env, AXIS2_FALSE); + axis2_svc_client_set_http_info(svc_client, env, msg_ctx); + svc_client->auth_failed = axis2_msg_ctx_get_auth_failed(msg_ctx, env); + svc_client->required_auth_is_http = axis2_msg_ctx_get_required_auth_is_http(msg_ctx, env); + if(axis2_msg_ctx_get_auth_type(msg_ctx, env)) + { + svc_client->auth_type = axutil_strdup(env, axis2_msg_ctx_get_auth_type(msg_ctx, env)); + } + + if(qname_free_flag) + { + axutil_qname_free((axutil_qname_t *)op_qname, env); + op_qname = NULL; + } +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_svc_client_send_receive_non_blocking( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axiom_node_t * payload, + axis2_callback_t * callback) +{ + axis2_svc_client_send_receive_non_blocking_with_op_qname(svc_client, env, NULL, payload, + callback); +} + +AXIS2_EXTERN axis2_op_client_t *AXIS2_CALL +axis2_svc_client_create_op_client( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axutil_qname_t * op_qname) +{ + axis2_op_t *op = NULL; + + AXIS2_PARAM_CHECK(env->error, svc_client, NULL); + + op = axis2_svc_get_op_with_qname(svc_client->svc, env, op_qname); + + if(!op) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot find operation to create op client."); + return NULL; + } + + if(!(svc_client->op_client) || svc_client->reuse) + { + if((svc_client->reuse) && (svc_client->op_client)) + axis2_op_client_free(svc_client->op_client, env); + svc_client->op_client = axis2_op_client_create(env, op, svc_client->svc_ctx, + svc_client->options); + } + + /** + If override options have been set, that means we need to make sure + those options override the options of even the operation client. So, + what we do is switch the parents around to make that work. + */ + if(svc_client->override_options) + { + axis2_options_set_parent(svc_client->override_options, env, axis2_op_client_get_options( + svc_client-> op_client, env)); + axis2_op_client_set_options(svc_client->op_client, env, svc_client->override_options); + } + svc_client->reuse = AXIS2_TRUE; + axis2_op_client_set_reuse(svc_client->op_client, env, svc_client->reuse); + return svc_client->op_client; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_finalize_invoke( + axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + AXIS2_TRANSPORT_ENUMS transport_in_protocol; + + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FAILURE); + + transport_in_protocol = axis2_options_get_transport_in_protocol(svc_client->options, env); + + if(svc_client->listener_manager) + { + return axis2_listener_manager_stop(svc_client->listener_manager, env, transport_in_protocol); + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN const axis2_endpoint_ref_t *AXIS2_CALL +axis2_svc_client_get_own_endpoint_ref( + const axis2_svc_client_t * svc_client, + const axutil_env_t * env, + const axis2_char_t * transport) +{ + return NULL; +} + +AXIS2_EXTERN const axis2_endpoint_ref_t *AXIS2_CALL +axis2_svc_client_get_target_endpoint_ref( + const axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + return NULL; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_set_target_endpoint_ref( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + axis2_endpoint_ref_t * target_endpoint_ref) +{ + return AXIS2_FAILURE; +} + +AXIS2_EXTERN axis2_svc_ctx_t *AXIS2_CALL +axis2_svc_client_get_svc_ctx( + const axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, svc_client, NULL); + return svc_client->svc_ctx; +} + +static axis2_bool_t +axis2_svc_client_init_transports_from_conf_ctx( + const axutil_env_t * env, + axis2_svc_client_t * svc_client, + axis2_conf_ctx_t * conf_ctx, + const axis2_char_t * client_home) +{ + svc_client->conf_ctx = conf_ctx; + if(!svc_client->conf_ctx) + { + svc_client->conf_ctx = axis2_build_client_conf_ctx(env, client_home); + if(!svc_client->conf_ctx) + { + return AXIS2_FALSE; + } + } + else + { + svc_client->keep_externally_passed_ctx_and_svc = AXIS2_TRUE; + } + + if(!svc_client->listener_manager) + { + svc_client->listener_manager = axis2_listener_manager_create(env); + if(!svc_client->listener_manager) + { + return AXIS2_FALSE; + } + } + + return AXIS2_TRUE; +} + +static axis2_bool_t +axis2_svc_client_init_data( + const axutil_env_t * env, + axis2_svc_client_t * svc_client) +{ + svc_client->svc = NULL; + svc_client->conf_ctx = NULL; + svc_client->svc_ctx = NULL; + + svc_client->options = axis2_options_create(env); + if(!svc_client->options) + { + return AXIS2_FALSE; + } + + svc_client->override_options = NULL; + svc_client->headers = NULL; + + if(svc_client->callback_recv) + { + AXIS2_CALLBACK_RECV_FREE(svc_client->callback_recv, env); + svc_client->callback_recv = NULL; + } + + svc_client->callback_recv = axis2_callback_recv_create(env); + if(!svc_client->callback_recv) + { + return AXIS2_FALSE; + } + + return AXIS2_TRUE; +} + +static axis2_svc_t * +axis2_svc_client_create_annonymous_svc( + axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + + /** + now add anonymous operations to the axis2 service for use with the + shortcut client API. NOTE: We only add the ones we know we'll use + later in the convenience API; if you use + this constructor then you can't expect any magic! + */ + axutil_qname_t *tmp_qname; + axis2_svc_t *svc; + axis2_op_t *op_out_in, *op_out_only, *op_robust_out_only; + axis2_phases_info_t *info = NULL; + + tmp_qname = axutil_qname_create(env, AXIS2_ANON_SERVICE, NULL, NULL); + if(!tmp_qname) + { + return NULL; + } + + svc = axis2_svc_create_with_qname(env, tmp_qname); + axutil_qname_free(tmp_qname, env); + if(!svc) + { + return NULL; + } + + tmp_qname = axutil_qname_create(env, AXIS2_ANON_OUT_IN_OP, NULL, NULL); + if(!tmp_qname) + { + return NULL; + } + op_out_in = axis2_op_create_with_qname(env, tmp_qname); + axutil_qname_free(tmp_qname, env); + + tmp_qname = axutil_qname_create(env, AXIS2_ANON_OUT_ONLY_OP, NULL, NULL); + if(!tmp_qname) + { + return NULL; + } + op_out_only = axis2_op_create_with_qname(env, tmp_qname); + axutil_qname_free(tmp_qname, env); + + tmp_qname = axutil_qname_create(env, AXIS2_ANON_ROBUST_OUT_ONLY_OP, NULL, NULL); + if(!tmp_qname) + { + return NULL; + } + op_robust_out_only = axis2_op_create_with_qname(env, tmp_qname); + axutil_qname_free(tmp_qname, env); + + if(!op_out_in || !op_out_only || !op_robust_out_only) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + if(op_out_in) + { + axis2_op_free(op_out_in, env); + } + if(op_out_only) + { + axis2_op_free(op_out_only, env); + } + if(op_robust_out_only) + { + axis2_op_free(op_robust_out_only, env); + } + + return NULL; + } + + axis2_op_set_msg_exchange_pattern(op_out_in, env, AXIS2_MEP_URI_OUT_IN); + axis2_op_set_msg_exchange_pattern(op_out_only, env, AXIS2_MEP_URI_OUT_ONLY); + axis2_op_set_msg_exchange_pattern(op_robust_out_only, env, AXIS2_MEP_URI_ROBUST_OUT_ONLY); + + /* Setting operation phase */ + info = axis2_conf_get_phases_info(svc_client->conf, env); + axis2_phases_info_set_op_phases(info, env, op_out_in); + axis2_phases_info_set_op_phases(info, env, op_out_only); + axis2_phases_info_set_op_phases(info, env, op_robust_out_only); + axis2_svc_add_op(svc, env, op_out_in); + axis2_svc_add_op(svc, env, op_out_only); + axis2_svc_add_op(svc, env, op_robust_out_only); + return svc; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_svc_client_free( + axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + if(!svc_client) + { + return; + } + + if(svc_client->headers) + { + axis2_svc_client_remove_all_headers(svc_client, env); + axutil_array_list_free(svc_client->headers, env); + svc_client->headers = NULL; + } + + if(svc_client->svc && !svc_client->keep_externally_passed_ctx_and_svc) + { + axis2_svc_free(svc_client->svc, env); + } + + if(svc_client->callback_recv) + { + AXIS2_CALLBACK_RECV_FREE(svc_client->callback_recv, env); + } + + if(svc_client->op_client) + { + axis2_op_client_free(svc_client->op_client, env); + svc_client->op_client = NULL; + } + + if(svc_client->options) + { + axis2_options_free(svc_client->options, env); + } + + if(svc_client->listener_manager) + { + axis2_listener_manager_free(svc_client->listener_manager, env); + } + + if(svc_client->conf_ctx && !svc_client->keep_externally_passed_ctx_and_svc) + { + axis2_conf_ctx_free(svc_client->conf_ctx, env); + } + + if(svc_client->auth_type) + { + AXIS2_FREE(env->allocator, svc_client->auth_type); + } + + if(svc_client->http_headers) + { + axis2_svc_client_set_http_info(svc_client, env, NULL); + } + + AXIS2_FREE(env->allocator, svc_client); + + return; +} + +static axis2_bool_t +axis2_svc_client_fill_soap_envelope( + const axutil_env_t * env, + axis2_svc_client_t * svc_client, + axis2_msg_ctx_t * msg_ctx, + const axiom_node_t * payload) +{ + const axis2_char_t *soap_version_uri; + int soap_version; + axiom_soap_envelope_t *envelope = NULL; + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FAILURE); + + soap_version_uri = axis2_options_get_soap_version_uri(svc_client->options, env); + + if(!soap_version_uri) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot find soap version uri."); + return AXIS2_FALSE; + } + + if(axutil_strcmp(soap_version_uri, AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI) == 0) + { + soap_version = AXIOM_SOAP11; + } + else + { + soap_version = AXIOM_SOAP12; + } + + envelope = axiom_soap_envelope_create_default_soap_envelope(env, soap_version); + if(!envelope) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot create default soap envelope."); + return AXIS2_FALSE; + } + + if(svc_client->headers) + { + axiom_soap_header_t *soap_header = NULL; + soap_header = axiom_soap_envelope_get_header(envelope, env); + + if(soap_header) + { + axiom_node_t *header_node = NULL; + header_node = axiom_soap_header_get_base_node(soap_header, env); + + if(header_node) + { + int size = 0; + int i = 0; + size = axutil_array_list_size(svc_client->headers, env); + while(i < size) + { + axiom_node_t *node = NULL; + node = axutil_array_list_remove(svc_client->headers, env, 0); + /* This removes and retrieves data. The order of the + * removal is chosen such that the headers are appended + * in the order they were added. + */ + size--; + if(node) + { + axiom_node_add_child(header_node, env, node); + } + } + } + } + } + + if(payload) + { + 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, (axiom_node_t *)payload); + } + } + } + + axis2_msg_ctx_set_soap_envelope(msg_ctx, env, envelope); + + return AXIS2_TRUE; +} + +AXIS2_EXTERN axis2_op_client_t *AXIS2_CALL +axis2_svc_client_get_op_client( + const axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, svc_client, NULL); + return svc_client->op_client; +} + +AXIS2_EXTERN axiom_soap_envelope_t *AXIS2_CALL +axis2_svc_client_get_last_response_soap_envelope( + const axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, svc_client, NULL); + return svc_client->last_response_soap_envelope; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_svc_client_get_last_response_has_fault( + const axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FALSE); + return svc_client->last_response_has_fault; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_svc_client_get_http_auth_required( + const axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FALSE); + if(svc_client->auth_failed && svc_client->required_auth_is_http) + { + return AXIS2_TRUE; + } + return AXIS2_FALSE; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_svc_client_get_proxy_auth_required( + const axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FALSE); + if(svc_client->auth_failed && !svc_client->required_auth_is_http) + { + return AXIS2_TRUE; + } + return AXIS2_FALSE; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_svc_client_get_auth_type( + const axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + return svc_client->auth_type; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_set_proxy_with_auth( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + axis2_char_t * proxy_host, + axis2_char_t * proxy_port, + axis2_char_t * username, + axis2_char_t * password) +{ + axis2_transport_out_desc_t *trans_desc = NULL; + axis2_conf_t *conf = NULL; + axutil_param_container_t *param_container; + axutil_param_t *param; + axis2_char_t *proxy = AXIS2_HTTP_PROXY_API; + axutil_hash_t *attribute; + axutil_generic_obj_t *host_obj = NULL; + axutil_generic_obj_t *port_obj = NULL; + axutil_generic_obj_t *username_obj = NULL; + axutil_generic_obj_t *password_obj = NULL; + axiom_attribute_t *host_attr = NULL; + axiom_attribute_t *port_attr = NULL; + axiom_attribute_t *username_attr = NULL; + axiom_attribute_t *password_attr = NULL; + + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, proxy_host, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, proxy_port, AXIS2_FAILURE); + + if(svc_client->conf) + { + conf = svc_client->conf; + trans_desc = axis2_conf_get_transport_out(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + if(!trans_desc) + { + return AXIS2_FAILURE; + } + param_container = axis2_transport_out_desc_param_container(trans_desc, env); + param = axutil_param_create(env, proxy, (void *)NULL); + + if(!param) + { + return AXIS2_FAILURE; + } + + attribute = axutil_hash_make(env); + host_obj = axutil_generic_obj_create(env); + port_obj = axutil_generic_obj_create(env); + host_attr = axiom_attribute_create(env, AXIS2_HTTP_PROXY_HOST, proxy_host, NULL); + port_attr = axiom_attribute_create(env, AXIS2_HTTP_PROXY_PORT, proxy_port, NULL); + axutil_generic_obj_set_value(host_obj, env, host_attr); + axutil_generic_obj_set_free_func(host_obj, env, axiom_attribute_free_void_arg); + axutil_generic_obj_set_value(port_obj, env, port_attr); + axutil_generic_obj_set_free_func(port_obj, env, axiom_attribute_free_void_arg); + + axutil_hash_set(attribute, AXIS2_HTTP_PROXY_HOST, AXIS2_HASH_KEY_STRING, host_obj); + axutil_hash_set(attribute, AXIS2_HTTP_PROXY_PORT, AXIS2_HASH_KEY_STRING, port_obj); + if(username && password) + { + username_obj = axutil_generic_obj_create(env); + password_obj = axutil_generic_obj_create(env); + username_attr = axiom_attribute_create(env, AXIS2_HTTP_PROXY_USERNAME, username, NULL); + password_attr = axiom_attribute_create(env, AXIS2_HTTP_PROXY_PASSWORD, password, NULL); + axutil_generic_obj_set_value(username_obj, env, username_attr); + axutil_generic_obj_set_value(password_obj, env, password_attr); + axutil_generic_obj_set_free_func(username_obj, env, axiom_attribute_free_void_arg); + axutil_generic_obj_set_free_func(password_obj, env, axiom_attribute_free_void_arg); + axutil_hash_set(attribute, AXIS2_HTTP_PROXY_USERNAME, AXIS2_HASH_KEY_STRING, + username_obj); + axutil_hash_set(attribute, AXIS2_HTTP_PROXY_PASSWORD, AXIS2_HASH_KEY_STRING, + password_obj); + } + axutil_param_set_attributes(param, env, attribute); + axutil_param_container_add_param(param_container, env, param); + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_set_proxy( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + axis2_char_t * proxy_host, + axis2_char_t * proxy_port) +{ + return axis2_svc_client_set_proxy_with_auth(svc_client, env, proxy_host, proxy_port, NULL, NULL); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_set_policy_from_om( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + axiom_node_t * root_node) +{ + neethi_policy_t *neethi_policy = NULL; + + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FAILURE); + neethi_policy = neethi_util_create_policy_from_om(env, root_node); + + if(neethi_policy) + { + return axis2_svc_client_set_policy(svc_client, env, neethi_policy); + } + else + { + return AXIS2_FAILURE; + } +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_set_policy( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + neethi_policy_t * policy) +{ + + axis2_svc_t *svc = NULL; + axis2_desc_t *desc = NULL; + axis2_policy_include_t *policy_include = NULL; + + AXIS2_PARAM_CHECK(env->error, svc_client, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, policy, AXIS2_FAILURE); + + svc = axis2_svc_client_get_svc(svc_client, env); + + if(!svc) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Cannot find service of service client. Cannot set policy."); + return AXIS2_FAILURE; + } + + desc = axis2_svc_get_base(svc, env); + if(!desc) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Cannot find service description of service client. Cannot set policy."); + return AXIS2_FAILURE; + } + + policy_include = axis2_desc_get_policy_include(desc, env); + if(!policy_include) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot find policy include. Cannot set policy."); + return AXIS2_FAILURE; + } + + axis2_policy_include_add_policy_element(policy_include, env, AXIS2_SERVICE_POLICY, policy); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL +axis2_svc_client_get_http_headers( + axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + return svc_client->http_headers; +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_svc_client_get_http_status_code( + axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + return svc_client->http_status_code; +} + +void +axis2_svc_client_set_http_info( + axis2_svc_client_t * svc_client, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axis2_transport_in_desc_t *transport_in = NULL; + axutil_param_t *expose_headers_param = NULL; + axis2_bool_t expose_headers = AXIS2_FALSE; + + if(msg_ctx) + { + transport_in = axis2_msg_ctx_get_transport_in_desc(msg_ctx, env); + if(transport_in) + { + expose_headers_param = axutil_param_container_get_param( + axis2_transport_in_desc_param_container(transport_in, env), env, + AXIS2_EXPOSE_HEADERS); + } + if(expose_headers_param) + { + axis2_char_t *expose_headers_value = NULL; + expose_headers_value = axutil_param_get_value(expose_headers_param, env); + if(expose_headers_value && 0 == axutil_strcasecmp(expose_headers_value, + AXIS2_VALUE_TRUE)) + { + expose_headers = AXIS2_TRUE; + } + } + } + if(expose_headers) + { + if(svc_client->http_headers == axis2_msg_ctx_get_http_output_headers(msg_ctx, env)) + { + svc_client->http_status_code = axis2_msg_ctx_get_status_code(msg_ctx, env); + return; + } + } + + if(svc_client->http_headers) + { + axis2_http_header_t *header = NULL; + while(axutil_array_list_size(svc_client->http_headers, env)) + { + header = (axis2_http_header_t *)axutil_array_list_remove(svc_client->http_headers, env, + 0); + if(header) + { + axis2_http_header_free(header, env); + } + } + axutil_array_list_free(svc_client->http_headers, env); + svc_client->http_headers = NULL; + } + svc_client->http_status_code = 0; + + if(msg_ctx) + { + if(expose_headers) + { + svc_client->http_headers = axis2_msg_ctx_extract_http_output_headers(msg_ctx, env); + } + svc_client->http_status_code = axis2_msg_ctx_get_status_code(msg_ctx, env); + } +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_svc_client_close( + axis2_svc_client_t * svc_client, + const axutil_env_t * env) +{ + axis2_status_t status = AXIS2_FAILURE; + axutil_property_t *property = NULL; + axis2_endpoint_ref_t *replyto = NULL; + + property = axutil_property_create_with_args(env, 0, 0, 0, AXIS2_VALUE_TRUE); + axis2_options_set_property(svc_client->options, env, AXIS2_SVC_CLIENT_CLOSED, property); + replyto = axis2_options_get_reply_to(svc_client->options, env); + if(replyto) + { + axiom_node_t *reply = NULL; + + reply = axis2_svc_client_send_receive(svc_client, env, NULL); + if(reply) + { + status = AXIS2_SUCCESS; + } + } + else + { + status = axis2_svc_client_send_robust(svc_client, env, NULL); + } + + return status; +} + |