summaryrefslogtreecommitdiffstats
path: root/src/core/util/core_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/util/core_utils.c')
-rw-r--r--src/core/util/core_utils.c1635
1 files changed, 1635 insertions, 0 deletions
diff --git a/src/core/util/core_utils.c b/src/core/util/core_utils.c
new file mode 100644
index 0000000..5ae9f31
--- /dev/null
+++ b/src/core/util/core_utils.c
@@ -0,0 +1,1635 @@
+/*
+ * 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_core_utils.h>
+#include <axutil_string.h>
+#include <axis2_conf.h>
+#include <axis2_relates_to.h>
+#include <axis2_addr.h>
+#include <axis2_http_transport.h>
+#include <axutil_uuid_gen.h>
+#include <axutil_property.h>
+#include <axis2_conf_ctx.h>
+
+
+/* internal structure to keep the rest map in a multi level hash */
+typedef struct
+{
+ /* the structure will keep as many as following fields */
+
+ /* if the mapped value is directly the operation */
+ axis2_op_t *op_desc;
+
+ /* if the mapped value is a constant, this keeps a hash map of
+ possible constants => corrosponding map_internal structure */
+ axutil_hash_t *consts_map;
+
+ /* if the mapped value is a param, this keeps a hash map of
+ possible param_values => corrosponding_map_internal structre */
+ axutil_hash_t *params_map;
+
+} axutil_core_utils_map_internal_t;
+
+/* some functions to use internally in handling rest map */
+/* infer op from the live url */
+axis2_op_t *
+axis2_core_utils_infer_op_from_parent_rest_map(
+ const axutil_env_t *env,
+ axutil_hash_t *rest_map,
+ axis2_char_t *live_url,
+ axutil_array_list_t *param_keys,
+ axutil_array_list_t *param_values);
+
+/* build the restmap recursively - internal function*/
+axis2_status_t AXIS2_CALL
+axis2_core_utils_internal_build_rest_map_recursively(
+ const axutil_env_t * env,
+ axis2_char_t * url,
+ axutil_core_utils_map_internal_t *mapping_struct,
+ axis2_op_t *op_desc);
+
+/* infer op from the live url recursively */
+axis2_op_t *AXIS2_CALL
+axis2_core_utils_internal_infer_op_from_rest_map_recursively(
+ const axutil_env_t *env,
+ const axutil_core_utils_map_internal_t *parent_mapping_struct,
+ axis2_char_t *live_url,
+ axutil_array_list_t *param_keys,
+ axutil_array_list_t *param_values);
+
+/* match a pattern with a url component */
+axis2_status_t
+axis2_core_utils_match_url_component_with_pattern(
+ const axutil_env_t *env,
+ axis2_char_t *pattern,
+ axis2_char_t *url_component,
+ axutil_array_list_t *param_keys,
+ axutil_array_list_t *param_values);
+
+AXIS2_EXTERN axis2_msg_ctx_t *AXIS2_CALL
+axis2_core_utils_create_out_msg_ctx(
+ const axutil_env_t * env,
+ axis2_msg_ctx_t * in_msg_ctx)
+{
+ axis2_ctx_t *ctx = NULL;
+ axis2_msg_ctx_t *new_msg_ctx = NULL;
+ axis2_conf_ctx_t *conf_ctx = NULL;
+ axis2_transport_in_desc_t *transport_in = NULL;
+ axis2_transport_out_desc_t *transport_out = NULL;
+ axis2_msg_info_headers_t *old_msg_info_headers = NULL;
+ axis2_msg_info_headers_t *msg_info_headers = NULL;
+ axis2_endpoint_ref_t *reply_to = NULL;
+ axis2_endpoint_ref_t *fault_to = NULL;
+ axis2_endpoint_ref_t *to = NULL;
+ const axis2_char_t *msg_id = NULL;
+ axis2_relates_to_t *relates_to = NULL;
+ const axis2_char_t *action = NULL;
+ axis2_op_ctx_t *op_ctx = NULL;
+ axis2_svc_ctx_t *svc_ctx = NULL;
+ axis2_bool_t doing_rest = AXIS2_FALSE;
+ axis2_bool_t doing_mtom = AXIS2_FALSE;
+ axis2_bool_t server_side = AXIS2_FALSE;
+ axis2_svc_grp_ctx_t *svc_grp_ctx = NULL;
+ axis2_char_t *msg_uuid = NULL;
+ axutil_stream_t *out_stream = NULL;
+ axutil_param_t *expose_headers_param = NULL;
+ axis2_bool_t expose_headers = AXIS2_FALSE;
+
+ AXIS2_PARAM_CHECK(env->error, in_msg_ctx, NULL);
+
+ conf_ctx = axis2_msg_ctx_get_conf_ctx(in_msg_ctx, env);
+ transport_in = axis2_msg_ctx_get_transport_in_desc(in_msg_ctx, env);
+ transport_out = axis2_msg_ctx_get_transport_out_desc(in_msg_ctx, env);
+
+ new_msg_ctx = axis2_msg_ctx_create(env, conf_ctx, transport_in, transport_out);
+ if(!new_msg_ctx)
+ {
+ return NULL;
+ }
+
+ 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)
+ {
+ axis2_msg_ctx_set_transport_headers(new_msg_ctx, env,
+ axis2_msg_ctx_extract_transport_headers(in_msg_ctx, env));
+ }
+ axis2_msg_ctx_set_http_accept_record_list(new_msg_ctx, env,
+ axis2_msg_ctx_extract_http_accept_record_list(in_msg_ctx, env));
+ axis2_msg_ctx_set_http_accept_charset_record_list(new_msg_ctx, env,
+ axis2_msg_ctx_extract_http_accept_charset_record_list(in_msg_ctx, env));
+ axis2_msg_ctx_set_http_accept_language_record_list(new_msg_ctx, env,
+ axis2_msg_ctx_extract_http_accept_language_record_list(in_msg_ctx, env));
+
+ old_msg_info_headers = axis2_msg_ctx_get_msg_info_headers(in_msg_ctx, env);
+ if(!old_msg_info_headers)
+ {
+ return NULL;
+ }
+ msg_info_headers = axis2_msg_ctx_get_msg_info_headers(new_msg_ctx, env);
+ if(!msg_info_headers)
+ {
+ /* if there is no msg info header in ew msg ctx, then create one */
+ msg_info_headers = axis2_msg_info_headers_create(env, NULL, NULL);
+ if(!msg_info_headers)
+ return NULL;
+ axis2_msg_ctx_set_msg_info_headers(new_msg_ctx, env, msg_info_headers);
+ }
+
+ msg_uuid = axutil_uuid_gen(env);
+ axis2_msg_info_headers_set_message_id(msg_info_headers, env, msg_uuid);
+ if(msg_uuid)
+ {
+ AXIS2_FREE(env->allocator, msg_uuid);
+ msg_uuid = NULL;
+ }
+ reply_to = axis2_msg_info_headers_get_reply_to(old_msg_info_headers, env);
+ axis2_msg_info_headers_set_to(msg_info_headers, env, reply_to);
+
+ fault_to = axis2_msg_info_headers_get_fault_to(old_msg_info_headers, env);
+ axis2_msg_info_headers_set_fault_to(msg_info_headers, env, fault_to);
+
+ to = axis2_msg_info_headers_get_to(old_msg_info_headers, env);
+ axis2_msg_info_headers_set_from(msg_info_headers, env, to);
+
+ msg_id = axis2_msg_info_headers_get_message_id(old_msg_info_headers, env);
+
+ /* we can create with default Relates to namespace.
+ Actual namespace based on addressing version will be created in addressing out handler */
+ relates_to = axis2_relates_to_create(env, msg_id,
+ AXIS2_WSA_RELATES_TO_RELATIONSHIP_TYPE_DEFAULT_VALUE);
+ axis2_msg_info_headers_set_relates_to(msg_info_headers, env, relates_to);
+
+ action = axis2_msg_info_headers_get_action(old_msg_info_headers, env);
+ axis2_msg_info_headers_set_action(msg_info_headers, env, action);
+
+ op_ctx = axis2_msg_ctx_get_op_ctx(in_msg_ctx, env);
+ axis2_msg_ctx_set_op_ctx(new_msg_ctx, env, op_ctx);
+
+ svc_ctx = axis2_msg_ctx_get_svc_ctx(in_msg_ctx, env);
+ axis2_msg_ctx_set_svc_ctx(new_msg_ctx, env, svc_ctx);
+
+ ctx = axis2_msg_ctx_get_base(in_msg_ctx, env);
+ if(ctx)
+ {
+ axis2_ctx_t *new_ctx = axis2_msg_ctx_get_base(new_msg_ctx, env);
+ if(new_ctx)
+ {
+ axis2_ctx_set_property_map(new_ctx, env, axis2_ctx_get_property_map(ctx, env));
+ }
+ }
+
+ out_stream = axis2_msg_ctx_get_transport_out_stream(in_msg_ctx, env);
+ axis2_msg_ctx_set_transport_out_stream(new_msg_ctx, env, out_stream);
+ axis2_msg_ctx_set_out_transport_info(new_msg_ctx, env, axis2_msg_ctx_get_out_transport_info(
+ in_msg_ctx, env));
+
+ /* Setting the character set encoding */
+ doing_rest = axis2_msg_ctx_get_doing_rest(in_msg_ctx, env);
+ axis2_msg_ctx_set_doing_rest(new_msg_ctx, env, doing_rest);
+
+ doing_mtom = axis2_msg_ctx_get_doing_mtom(in_msg_ctx, env);
+ axis2_msg_ctx_set_doing_mtom(new_msg_ctx, env, doing_mtom);
+
+ server_side = axis2_msg_ctx_get_server_side(in_msg_ctx, env);
+ axis2_msg_ctx_set_server_side(new_msg_ctx, env, server_side);
+
+ svc_grp_ctx = axis2_msg_ctx_get_svc_grp_ctx(in_msg_ctx, env);
+ axis2_msg_ctx_set_svc_grp_ctx(new_msg_ctx, env, svc_grp_ctx);
+
+ axis2_msg_ctx_set_is_soap_11(new_msg_ctx, env, axis2_msg_ctx_get_is_soap_11(in_msg_ctx, env));
+ axis2_msg_ctx_set_keep_alive(new_msg_ctx, env, axis2_msg_ctx_is_keep_alive(in_msg_ctx, env));
+
+ axis2_msg_ctx_set_charset_encoding(new_msg_ctx, env, axis2_msg_ctx_get_charset_encoding(
+ in_msg_ctx, env));
+
+ return new_msg_ctx;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axis2_core_utils_reset_out_msg_ctx(
+ const axutil_env_t * env,
+ axis2_msg_ctx_t * out_msg_ctx)
+{
+ axis2_msg_info_headers_t *msg_info_headers = NULL;
+ if(!out_msg_ctx)
+ return;
+
+ msg_info_headers = axis2_msg_ctx_get_msg_info_headers(out_msg_ctx, env);
+ if(msg_info_headers)
+ {
+ axis2_msg_info_headers_set_to(msg_info_headers, env, NULL);
+ axis2_msg_info_headers_set_fault_to(msg_info_headers, env, NULL);
+ axis2_msg_info_headers_set_from(msg_info_headers, env, NULL);
+ axis2_msg_info_headers_set_reply_to(msg_info_headers, env, NULL);
+ }
+
+ axis2_msg_ctx_set_op_ctx(out_msg_ctx, env, NULL);
+ axis2_msg_ctx_set_svc_ctx(out_msg_ctx, env, NULL);
+ axis2_msg_ctx_reset_transport_out_stream(out_msg_ctx, env);
+ axis2_msg_ctx_reset_out_transport_info(out_msg_ctx, env);
+ axis2_msg_ctx_set_svc_grp_ctx(out_msg_ctx, env, NULL);
+
+ return;
+}
+
+AXIS2_EXTERN axutil_qname_t *AXIS2_CALL
+axis2_core_utils_get_module_qname(
+ const axutil_env_t * env,
+ const axis2_char_t * name,
+ const axis2_char_t * version)
+{
+ axutil_qname_t *ret_qname = NULL;
+ AXIS2_PARAM_CHECK(env->error, name, NULL);
+
+ if(version && 0 != axutil_strlen(version))
+ {
+ axis2_char_t *mod_name1 = NULL;
+ axis2_char_t *mod_name = NULL;
+ mod_name1 = axutil_stracat(env, name, "-");
+ if(!mod_name1)
+ {
+ return NULL;
+ }
+ mod_name = axutil_stracat(env, mod_name1, version);
+ if(!mod_name)
+ {
+ AXIS2_FREE(env->allocator, mod_name1);
+ mod_name1 = NULL;
+ return NULL;
+ }
+ ret_qname = axutil_qname_create(env, mod_name, NULL, NULL);
+ AXIS2_FREE(env->allocator, mod_name);
+ AXIS2_FREE(env->allocator, mod_name1);
+ return ret_qname;
+ }
+ ret_qname = axutil_qname_create(env, name, NULL, NULL);
+ return ret_qname;
+}
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axis2_core_utils_calculate_default_module_version(
+ const axutil_env_t * env,
+ axutil_hash_t * modules_map,
+ axis2_conf_t * axis_conf)
+{
+ axutil_hash_t *default_modules = NULL;
+ axutil_hash_index_t *hi = NULL;
+ void *val = NULL;
+
+ AXIS2_PARAM_CHECK(env->error, modules_map, AXIS2_FAILURE);
+ AXIS2_PARAM_CHECK(env->error, axis_conf, AXIS2_FAILURE);
+
+ default_modules = axutil_hash_make(env);
+ if(!default_modules)
+ {
+ return AXIS2_FAILURE;
+ }
+ for(hi = axutil_hash_first(modules_map, env); hi; hi = axutil_hash_next(env, hi))
+ {
+ axis2_module_desc_t *mod_desc = NULL;
+
+ axutil_hash_this(hi, NULL, NULL, &val);
+ mod_desc = (axis2_module_desc_t *)val;
+ if(mod_desc)
+ {
+ const axutil_qname_t *module_qname = NULL;
+ module_qname = axis2_module_desc_get_qname(mod_desc, env);
+ if(module_qname)
+ {
+ axis2_char_t *mod_name_with_ver = NULL;
+ mod_name_with_ver = axutil_qname_get_localpart(module_qname, env);
+ if(mod_name_with_ver)
+ {
+ axis2_char_t *module_name_str = NULL;
+ axis2_char_t *module_ver_str = NULL;
+ axis2_char_t *current_def_ver = NULL;
+
+ module_name_str = axis2_core_utils_get_module_name(env, mod_name_with_ver);
+ if(!module_name_str)
+ {
+ return AXIS2_FAILURE;
+ }
+ module_ver_str = axis2_core_utils_get_module_version(env, mod_name_with_ver);
+ current_def_ver = axutil_hash_get(default_modules, module_name_str,
+ AXIS2_HASH_KEY_STRING);
+ if(current_def_ver)
+ {
+ if(module_ver_str && AXIS2_TRUE == axis2_core_utils_is_latest_mod_ver(env,
+ module_ver_str, current_def_ver))
+ {
+ axutil_hash_set(default_modules, module_name_str,
+ AXIS2_HASH_KEY_STRING, module_ver_str);
+ }
+ else
+ {
+ if(module_name_str)
+ {
+ AXIS2_FREE(env->allocator, module_name_str);
+ }
+ if(module_ver_str)
+ {
+ AXIS2_FREE(env->allocator, module_ver_str);
+ }
+ }
+ }
+ else
+ {
+ axutil_hash_set(default_modules, module_name_str, AXIS2_HASH_KEY_STRING,
+ module_ver_str);
+ }
+
+ if(module_name_str)
+ {
+ AXIS2_FREE(env->allocator, module_name_str);
+ }
+ }
+ }
+ }
+ val = NULL;
+ }
+
+ hi = NULL;
+ val = NULL;
+ for(hi = axutil_hash_first(default_modules, env); hi; hi = axutil_hash_next(env, hi))
+ {
+ void *key_string = NULL;
+ axutil_hash_this(hi, (const void **)&key_string, NULL, &val);
+ if(key_string && NULL != val)
+ {
+ axis2_conf_add_default_module_version(axis_conf, env, (axis2_char_t *)key_string,
+ (axis2_char_t *)val);
+ AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Added default module"
+ " version : %s for module : %s", (axis2_char_t *)val, (axis2_char_t *)key_string);
+ }
+ }
+
+ if(default_modules)
+ {
+ axutil_hash_free(default_modules, env);
+ default_modules = NULL;
+ }
+
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axis2_char_t *AXIS2_CALL
+axis2_core_utils_get_module_name(
+ const axutil_env_t * env,
+ axis2_char_t * module_name)
+{
+ axis2_char_t version_seperator = '-';
+ axis2_char_t *name = NULL;
+ axis2_char_t *version_sep_loc = NULL;
+
+ AXIS2_PARAM_CHECK(env->error, module_name, NULL);
+
+ name = axutil_strdup(env, module_name);
+ if(!name)
+ {
+ return NULL;
+ }
+ version_sep_loc = axutil_rindex(name, version_seperator);
+ if(version_sep_loc)
+ {
+ *version_sep_loc = '\0';
+ }
+ return name;
+}
+
+AXIS2_EXTERN axis2_char_t *AXIS2_CALL
+axis2_core_utils_get_module_version(
+ const axutil_env_t * env,
+ axis2_char_t * module_name)
+{
+ axis2_char_t version_seperator = '-';
+ axis2_char_t *version_sep_loc = NULL;
+
+ AXIS2_PARAM_CHECK(env->error, module_name, NULL);
+
+ version_sep_loc = axutil_rindex(module_name, version_seperator);
+ if(version_sep_loc)
+ {
+ return axutil_strdup(env, version_sep_loc + sizeof(axis2_char_t));
+ }
+ return NULL;
+}
+
+AXIS2_EXTERN axis2_bool_t AXIS2_CALL
+axis2_core_utils_is_latest_mod_ver(
+ const axutil_env_t * env,
+ axis2_char_t * module_ver,
+ axis2_char_t * current_def_ver)
+{
+ double cur_ver = 0.0;
+ double mod_ver = 0.0;
+ AXIS2_PARAM_CHECK(env->error, module_ver, AXIS2_FALSE);
+ AXIS2_PARAM_CHECK(env->error, current_def_ver, AXIS2_FALSE);
+ cur_ver = atof(current_def_ver);
+ mod_ver = atof(module_ver);
+ if(mod_ver > cur_ver)
+ {
+ return AXIS2_TRUE;
+ }
+ return AXIS2_FAILURE;
+}
+
+/* build the rest map - external function */
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axis2_core_utils_prepare_rest_mapping(
+ const axutil_env_t * env,
+ axis2_char_t * url,
+ axutil_hash_t *rest_map,
+ axis2_op_t *op_desc)
+{
+
+ axis2_char_t *first_delimitter = NULL;
+ axis2_char_t *next_level_url = NULL;
+ axis2_char_t *mapping_key = NULL;
+ axutil_core_utils_map_internal_t *mapping_struct = NULL;
+ axis2_status_t status = AXIS2_SUCCESS;
+ axis2_char_t *bracket_start = NULL;
+
+ first_delimitter = axutil_strchr(url, '/');
+
+ if(first_delimitter)
+ {
+ /* if there is another recursive level,
+ this will get the url of that level */
+ next_level_url = first_delimitter + 1;
+ *first_delimitter = '\0';
+ }
+
+ if((bracket_start = axutil_strchr(url, '{')))
+ {
+ /* we support multiple param per url component,
+ but we validate only one param */
+ if(axutil_strchr(bracket_start, '}'))
+ {
+ /* this is validated */
+ }
+
+ else
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_URL_FORMAT, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "Invalid URL Format, no closing bracket in declaring parameters");
+ return AXIS2_FAILURE;
+ }
+ }
+
+ /* only constants are allowed in this level, so here url become the mapping_key */
+ mapping_key = url;
+
+ if(*mapping_key == '\0') /* empty mapping key */
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_URL_FORMAT, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Invalid URL Format: empty mapping key");
+ return AXIS2_FAILURE;
+ }
+
+ /* retrieve or create the mapping structure for the key*/
+ mapping_struct = axutil_hash_get(rest_map, mapping_key, AXIS2_HASH_KEY_STRING);
+ if(!mapping_struct)
+ {
+ mapping_struct = (axutil_core_utils_map_internal_t*)AXIS2_MALLOC(env->allocator,
+ sizeof(axutil_core_utils_map_internal_t));
+ if(!mapping_struct)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ return AXIS2_FAILURE;
+
+ }
+ memset(mapping_struct, 0, sizeof(axutil_core_utils_map_internal_t));
+
+ mapping_key = axutil_strdup(env, mapping_key);
+ axutil_hash_set(rest_map, mapping_key, AXIS2_HASH_KEY_STRING, mapping_struct);
+ }
+
+ if(!next_level_url)
+ {
+ /* if no next level url, put the op_desc in right this level */
+ if(mapping_struct->op_desc)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_DUPLICATE_URL_REST_MAPPING, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Duplicate URL Mapping found");
+ return AXIS2_FAILURE;
+ }
+ mapping_struct->op_desc = op_desc;
+ }
+ else
+ {
+ /* we have to build the map_internal structure recursively */
+ status = axis2_core_utils_internal_build_rest_map_recursively(env, next_level_url,
+ mapping_struct, op_desc);
+ }
+
+ return status;
+
+}
+
+/* build the restmap recursively - internal function*/
+axis2_status_t AXIS2_CALL
+axis2_core_utils_internal_build_rest_map_recursively(
+ const axutil_env_t * env,
+ axis2_char_t * url,
+ axutil_core_utils_map_internal_t *parent_mapping_struct,
+ axis2_op_t *op_desc)
+{
+
+ /* Here url is expected to be in the form
+ {student}/marks/{subject} or
+ marks/{subject}
+ */
+
+ axis2_char_t *first_delimitter = NULL;
+ axis2_char_t *next_level_url = NULL;
+ axis2_char_t *mapping_key = NULL;
+ axutil_core_utils_map_internal_t *mapping_struct = NULL;
+ axutil_hash_t *cur_level_rest_map = NULL;
+ axis2_status_t status = AXIS2_SUCCESS;
+ axis2_char_t *bracket_start = NULL;
+
+ axis2_bool_t is_key_a_param = AXIS2_FALSE;
+
+ first_delimitter = axutil_strchr(url, '/');
+
+ if(first_delimitter)
+ {
+ /* if there is another recurisive level,
+ this will get the url of that level */
+ next_level_url = first_delimitter + 1;
+ *first_delimitter = '\0';
+ }
+
+ if((bracket_start = axutil_strchr(url, '{')))
+ {
+ /* we support multiple param per url component,
+ but we validate only one param */
+ if(axutil_strchr(bracket_start, '}'))
+ {
+ is_key_a_param = AXIS2_TRUE;
+ }
+
+ else
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_URL_FORMAT, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "Invalid URL Format, no closing bracket in declaring parameters");
+ return AXIS2_FAILURE;
+ }
+ }
+
+ /* here the url become the mapping_key */
+ mapping_key = url;
+
+ if(*mapping_key == '\0') /* empty mappng key */
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_URL_FORMAT, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Invalid URL Format: empty mapping key");
+ return AXIS2_FAILURE;
+ }
+
+ if(is_key_a_param)
+ {
+ /* set the rest map as the params_map */
+ if(parent_mapping_struct->params_map == NULL)
+ {
+ parent_mapping_struct->params_map = axutil_hash_make(env);
+ if(!parent_mapping_struct->params_map)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ return AXIS2_FAILURE;
+ }
+ }
+ cur_level_rest_map = parent_mapping_struct->params_map;
+ }
+ else
+ {
+ /* set the rest map as the consts_map */
+ if(parent_mapping_struct->consts_map == NULL)
+ {
+ parent_mapping_struct->consts_map = axutil_hash_make(env);
+ if(!parent_mapping_struct->consts_map)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ return AXIS2_FAILURE;
+ }
+ }
+ cur_level_rest_map = parent_mapping_struct->consts_map;
+ }
+
+ /* retrieve or create the maping structure for the key*/
+ mapping_struct = axutil_hash_get(cur_level_rest_map, mapping_key, AXIS2_HASH_KEY_STRING);
+ if(!mapping_struct)
+ {
+ mapping_struct = (axutil_core_utils_map_internal_t*)AXIS2_MALLOC(env->allocator,
+ sizeof(axutil_core_utils_map_internal_t));
+ if(!mapping_struct)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ return AXIS2_FAILURE;
+
+ }
+ memset(mapping_struct, 0, sizeof(axutil_core_utils_map_internal_t));
+
+ mapping_key = axutil_strdup(env, mapping_key);
+ axutil_hash_set(cur_level_rest_map, mapping_key, AXIS2_HASH_KEY_STRING, mapping_struct);
+ }
+
+ if(!next_level_url)
+ {
+ /* if no next level url, put the op_desc in right this level */
+ if(mapping_struct->op_desc)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_DUPLICATE_URL_REST_MAPPING, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Duplicate URL Mapping found");
+ return AXIS2_FAILURE;
+ }
+ mapping_struct->op_desc = op_desc;
+ }
+ else
+ {
+ /* we have to build the map_internal structure recursively */
+ status = axis2_core_utils_internal_build_rest_map_recursively(env, next_level_url,
+ mapping_struct, op_desc);
+ }
+
+ return status;
+}
+
+/* free the rest map recursively */
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axis2_core_utils_free_rest_map(
+ const axutil_env_t *env,
+ axutil_hash_t *rest_map)
+{
+
+ axutil_hash_index_t *hi = NULL;
+ const void *key = NULL;
+ void *val = NULL;
+ axis2_status_t status = AXIS2_SUCCESS;
+
+ for(hi = axutil_hash_first(rest_map, env); hi; hi = axutil_hash_next(env, hi))
+ {
+ axutil_hash_this(hi, &key, NULL, &val);
+
+ if(val)
+ {
+ axutil_core_utils_map_internal_t *mapping_struct = NULL;
+ mapping_struct = (axutil_core_utils_map_internal_t*)val;
+
+ /* freeing the consts_map and params_map */
+ if(mapping_struct->consts_map)
+ {
+ axis2_core_utils_free_rest_map(env, mapping_struct->consts_map);
+ }
+
+ if(mapping_struct->params_map)
+ {
+ axis2_core_utils_free_rest_map(env, mapping_struct->params_map);
+ }
+ AXIS2_FREE(env->allocator, mapping_struct);
+ }
+
+ if(key)
+ {
+ AXIS2_FREE(env->allocator, (axis2_char_t *)key);
+ key = NULL;
+ }
+ }
+ axutil_hash_free(rest_map, env);
+ return status;
+}
+
+AXIS2_EXTERN axis2_op_t *AXIS2_CALL
+axis2_core_utils_get_rest_op_with_method_and_location(
+ axis2_svc_t *svc,
+ const axutil_env_t *env,
+ const axis2_char_t *method,
+ const axis2_char_t *location,
+ axutil_array_list_t *param_keys,
+ axutil_array_list_t *param_values)
+{
+ axis2_char_t *addition_params_str = NULL;
+ axis2_char_t *adjusted_local_url = NULL;
+
+ axis2_char_t *live_mapping_url = NULL;
+ axis2_char_t *local_url = NULL;
+
+ axis2_op_t *op = NULL;
+
+ int key_len = 0;
+
+ AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Checking for operation using "
+ "REST HTTP Location fragment : %s", location);
+
+ /* we are creating a dup of the location */
+ local_url = (axis2_char_t*)axutil_strdup(env, location);
+ if(!local_url)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create the live rest mapping url");
+ return NULL;
+ }
+
+ /* checking the existence of the addition parameters
+ after the question mark '?' */
+ addition_params_str = strchr(local_url, '?');
+ if(addition_params_str)
+ {
+ *addition_params_str = '\0';
+ addition_params_str++;
+ }
+
+ /* if the first character is '/' ignore that */
+ if(*local_url == '/')
+ {
+ adjusted_local_url = local_url + 1;
+ }
+ else
+ {
+ adjusted_local_url = local_url;
+ }
+
+ /* now create the mapping url */
+ key_len = axutil_strlen(method) + axutil_strlen(adjusted_local_url) + 2;
+
+ live_mapping_url
+ = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * key_len));
+
+ if(!live_mapping_url)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create the live rest mapping url");
+ AXIS2_FREE(env->allocator, local_url);
+ return NULL;
+ }
+
+ sprintf(live_mapping_url, "%s:%s", method, adjusted_local_url);
+
+ op = axis2_core_utils_infer_op_from_parent_rest_map(env, axis2_svc_get_rest_map(svc, env),
+ live_mapping_url, param_keys, param_values);
+
+ if(op)
+ {
+ axis2_char_t *params_str;
+
+ AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI,
+ "Operation found using target endpoint uri fragment");
+
+ /* here we are going to extract out the additional parameters
+ * put after '?' mark */
+ params_str = addition_params_str;
+ while(params_str && *params_str != '\0')
+ {
+ axis2_char_t *next_params_str = NULL;
+ axis2_char_t *key_value_seperator = NULL;
+
+ axis2_char_t *key = NULL;
+ axis2_char_t *value = NULL;
+
+ /* we take one parameter pair to the params_str */
+ next_params_str = strchr(params_str, '&');
+ if(next_params_str)
+ {
+ *next_params_str = '\0';
+ }
+
+ key_value_seperator = strchr(params_str, '=');
+ if(key_value_seperator)
+ {
+ /* devide the key value pair */
+ *key_value_seperator = '\0';
+ key = params_str;
+ value = key_value_seperator + 1;
+ }
+ else
+ {
+ /* there is no '=' symbol, that mean only the key exist */
+ key = params_str;
+ }
+ if(key)
+ {
+ key = axutil_strdup(env, key);
+ axutil_array_list_add(param_keys, env, key);
+ }
+ if(value)
+ {
+ value = axutil_strdup(env, value);
+ axutil_array_list_add(param_values, env, value);
+ }
+
+ if(next_params_str)
+ {
+ /* if there was an '&' character then */
+ params_str = next_params_str + 1;
+ }
+ else
+ {
+ params_str = NULL; /* just to end the loop */
+ }
+ }
+ }
+
+ if(live_mapping_url)
+ {
+ AXIS2_FREE(env->allocator, live_mapping_url);
+ }
+ if(local_url)
+ {
+ AXIS2_FREE(env->allocator, local_url);
+ }
+ return op;
+}
+
+/* infer op from the live url */
+axis2_op_t *
+axis2_core_utils_infer_op_from_parent_rest_map(
+ const axutil_env_t *env,
+ axutil_hash_t *rest_map,
+ axis2_char_t *live_url,
+ axutil_array_list_t *param_keys,
+ axutil_array_list_t *param_values)
+{
+ axis2_char_t *first_delimitter = NULL;
+ axis2_char_t *next_level_url = NULL;
+ axis2_char_t *url_component = NULL;
+
+ axis2_op_t *op_desc = NULL;
+ axutil_core_utils_map_internal_t *mapping_struct = NULL;
+
+ first_delimitter = axutil_strchr(live_url, '/');
+
+ if(first_delimitter)
+ {
+ /* if there is another recursive level,
+ this will get the url of that level */
+ next_level_url = first_delimitter + 1;
+ *first_delimitter = '\0';
+ }
+
+ /* so live url is the url_component */
+ url_component = live_url;
+
+ /* check it in the hash map */
+ mapping_struct = (axutil_core_utils_map_internal_t*)axutil_hash_get(rest_map, url_component,
+ AXIS2_HASH_KEY_STRING);
+
+ if(mapping_struct)
+ {
+ if(!next_level_url)
+ {
+ /* if no level exists, find it here */
+ op_desc = mapping_struct->op_desc;
+ }
+ else
+ {
+
+ op_desc = axis2_core_utils_internal_infer_op_from_rest_map_recursively(env,
+ mapping_struct, next_level_url, param_keys, param_values);
+ }
+ }
+ if(!op_desc)
+ {
+ /* if the url is not mapped to the given constant url
+ * we have to match it with the url pattern */
+
+ axutil_hash_index_t *hi = NULL;
+ const void *key = NULL;
+ void *val = NULL;
+ axis2_status_t matched_status = AXIS2_FAILURE;
+
+ for(hi = axutil_hash_first(rest_map, env); hi; hi = axutil_hash_next(env, hi))
+ {
+ axutil_hash_this(hi, &key, NULL, &val);
+
+ if(key == url_component)
+ {
+ continue; /* skip the already checked key */
+ }
+ if(key && val)
+ {
+ axis2_char_t *hash_key = (axis2_char_t*)key;
+ axis2_char_t *dup_url_component = NULL;
+ axis2_char_t *dup_pattern = NULL;
+
+ /* temporary param keys and values for each entry */
+ axutil_array_list_t *tmp_param_keys = NULL;
+ axutil_array_list_t *tmp_param_values = NULL;
+
+ tmp_param_keys = axutil_array_list_create(env, 10);
+ if(!tmp_param_keys)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+
+ return NULL;
+ }
+ tmp_param_values = axutil_array_list_create(env, 10);
+ if(!tmp_param_values)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ axutil_array_list_free(tmp_param_keys, env);
+ return NULL;
+ }
+
+ dup_url_component = axutil_strdup(env, url_component);
+ if(!dup_url_component)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ axutil_array_list_free(tmp_param_keys, env);
+ axutil_array_list_free(tmp_param_values, env);
+ return NULL;
+ }
+ dup_pattern = axutil_strdup(env, hash_key);
+ if(!dup_pattern)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ axutil_array_list_free(tmp_param_keys, env);
+ axutil_array_list_free(tmp_param_values, env);
+ AXIS2_FREE(env->allocator, dup_url_component);
+ return NULL;
+ }
+
+ matched_status = axis2_core_utils_match_url_component_with_pattern(env,
+ dup_pattern, dup_url_component, tmp_param_keys, tmp_param_values);
+
+ AXIS2_FREE(env->allocator, dup_url_component);
+ AXIS2_FREE(env->allocator, dup_pattern);
+
+ if(matched_status == AXIS2_SUCCESS && val)
+ {
+ mapping_struct = (axutil_core_utils_map_internal_t*)val;
+
+ if(!next_level_url)
+ {
+ op_desc = mapping_struct->op_desc;
+ }
+ else
+ {
+
+ op_desc = axis2_core_utils_internal_infer_op_from_rest_map_recursively(env,
+ mapping_struct, next_level_url, tmp_param_keys, tmp_param_values);
+ }
+ if(op_desc)
+ {
+ /* we are done, the url is matched with a pattern */
+ /* but before leaving should merge the param arrays */
+
+ int i = 0;
+ void *param_key = NULL;
+ void *param_value = NULL;
+
+ for(i = 0; i < axutil_array_list_size(tmp_param_keys, env); i++)
+ {
+ /* size(tmp_param_keys) == size(tmp_param_values) */
+ param_key = axutil_array_list_get(tmp_param_keys, env, i);
+ param_value = axutil_array_list_get(tmp_param_values, env, i);
+
+ /* add it to original array */
+ axutil_array_list_add(param_keys, env, param_key);
+ axutil_array_list_add(param_values, env, param_value);
+
+ }
+ /* since of is found, no more searches needed */
+ break;
+ }
+ }
+ /* freeing the temporary arrays */
+ axutil_array_list_free(tmp_param_keys, env);
+ axutil_array_list_free(tmp_param_values, env);
+ }
+ }
+ }
+
+ if(!op_desc)
+ {
+ /* no more to look up */
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_URL_FORMAT, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "REST maping structure is NULL for the accessed URL");
+ return NULL;
+ }
+
+ return op_desc;
+}
+
+/* infer op from the live url recursively */
+axis2_op_t *AXIS2_CALL
+axis2_core_utils_internal_infer_op_from_rest_map_recursively(
+ const axutil_env_t *env,
+ const axutil_core_utils_map_internal_t *parent_mapping_struct,
+ axis2_char_t *live_url,
+ axutil_array_list_t *param_keys,
+ axutil_array_list_t *param_values)
+{
+
+ axis2_char_t *first_delimitter = NULL;
+ axis2_char_t *next_level_url = NULL;
+ axis2_char_t *url_component = NULL;
+
+ axis2_op_t *op_desc = NULL;
+ axutil_core_utils_map_internal_t *child_mapping_struct = NULL;
+
+ axutil_hash_index_t *hi = NULL;
+ const void *key = NULL;
+ void *val = NULL;
+
+ first_delimitter = axutil_strchr(live_url, '/');
+
+ if(first_delimitter)
+ {
+ /* if there is another recurisive level,
+ this will get the url of that level */
+ next_level_url = first_delimitter + 1;
+ *first_delimitter = '\0';
+ }
+
+ /* so live url is the url_component */
+ url_component = live_url;
+
+ /* first check the url component in the constants array list */
+ if(parent_mapping_struct->consts_map)
+ {
+ child_mapping_struct = axutil_hash_get(parent_mapping_struct->consts_map, url_component,
+ AXIS2_HASH_KEY_STRING);
+ }
+
+ /* if the url component exists in the consts_map, go through it inside */
+
+ if(child_mapping_struct)
+ {
+ if(!next_level_url)
+ {
+ /* there is no another level, so the op should be here */
+
+ op_desc = child_mapping_struct->op_desc;
+
+ if(!op_desc)
+ {
+ AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI,
+ "The operation descriptor not found constant given in the url");
+ }
+ /* rather than returning NULL we continue to search params_map */
+
+ }
+ else
+ {
+
+ op_desc = axis2_core_utils_internal_infer_op_from_rest_map_recursively(env,
+ child_mapping_struct, next_level_url, param_keys, param_values);
+ }
+ }
+
+ if(op_desc)
+ {
+ /* if the op for the accessed url found, no further searching is needed */
+ return op_desc;
+ }
+
+ /* if it is not found in the consts_map we have to assume it is in a params_map */
+
+ if(!parent_mapping_struct->params_map)
+ {
+ /* wrong operation, abort to continue to let calling function to check other operations */
+ if(first_delimitter)
+ {
+ /* restore the delimmiters */
+ *first_delimitter = '/';
+ }
+ return NULL;
+ }
+
+ for(hi = axutil_hash_first(parent_mapping_struct->params_map, env); hi; hi = axutil_hash_next(
+ env, hi))
+ {
+ axutil_hash_this(hi, &key, NULL, &val);
+
+ if(key && val)
+ {
+ int i = 0;
+ axis2_char_t *hash_key = (axis2_char_t*)key;
+ axis2_status_t matched_status = AXIS2_SUCCESS;
+ axis2_char_t *dup_url_component = NULL;
+ axis2_char_t *dup_pattern = NULL;
+
+ /* temporary param keys and values for each entry */
+ axutil_array_list_t *tmp_param_keys;
+ axutil_array_list_t *tmp_param_values;
+
+ tmp_param_keys = axutil_array_list_create(env, 10);
+ if(!tmp_param_keys)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+
+ return NULL;
+ }
+ tmp_param_values = axutil_array_list_create(env, 10);
+ if(!tmp_param_values)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ axutil_array_list_free(tmp_param_keys, env);
+ return NULL;
+ }
+
+ dup_url_component = axutil_strdup(env, url_component);
+ if(!dup_url_component)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ axutil_array_list_free(tmp_param_keys, env);
+ axutil_array_list_free(tmp_param_values, env);
+ return NULL;
+ }
+ dup_pattern = axutil_strdup(env, hash_key);
+ if(!dup_pattern)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ axutil_array_list_free(tmp_param_keys, env);
+ axutil_array_list_free(tmp_param_values, env);
+ AXIS2_FREE(env->allocator, dup_url_component);
+ return NULL;
+ }
+
+ matched_status = axis2_core_utils_match_url_component_with_pattern(env, dup_pattern,
+ dup_url_component, tmp_param_keys, tmp_param_values);
+
+ AXIS2_FREE(env->allocator, dup_url_component);
+ AXIS2_FREE(env->allocator, dup_pattern);
+
+ if(matched_status == AXIS2_SUCCESS)
+ {
+ child_mapping_struct = (axutil_core_utils_map_internal_t*)val;
+
+ if(!next_level_url)
+ {
+ /* there is no another level, so the op should be here */
+ op_desc = child_mapping_struct->op_desc;
+
+ }
+ else
+ {
+
+ /* if there is next level, we should check that level too */
+ op_desc = axis2_core_utils_internal_infer_op_from_rest_map_recursively(env,
+ child_mapping_struct, next_level_url, tmp_param_keys, tmp_param_values);
+ }
+
+ if(op_desc)
+ {
+ /* the operation is found */
+ /* but before leaving should merge the param arrays */
+
+ int i = 0;
+ void *param_key = NULL;
+ void *param_value = NULL;
+ for(i = 0; i < axutil_array_list_size(tmp_param_keys, env); i++)
+ {
+ /* size(tmp_param_keys) == size(tmp_param_values) */
+ param_key = axutil_array_list_get(tmp_param_keys, env, i);
+ param_value = axutil_array_list_get(tmp_param_values, env, i);
+
+ /* add it to original array */
+ axutil_array_list_add(param_keys, env, param_key);
+ axutil_array_list_add(param_values, env, param_value);
+
+ }
+
+ /* freeing the temporary arrays */
+ axutil_array_list_free(tmp_param_keys, env);
+ axutil_array_list_free(tmp_param_values, env);
+ /* since of is found, no more searches needed */
+ break;
+ }
+ }
+
+ /* if we come here => op is not yet found */
+ /* just freeing the temp key and value arrays */
+ for(i = 0; i < axutil_array_list_size(tmp_param_keys, env); i++)
+ {
+ void *value = axutil_array_list_get(tmp_param_keys, env, i);
+ if(value)
+ {
+ AXIS2_FREE(env->allocator, value);
+ }
+ }
+ for(i = 0; i < axutil_array_list_size(tmp_param_values, env); i++)
+ {
+ void *value = axutil_array_list_get(tmp_param_values, env, i);
+ if(value)
+ {
+ AXIS2_FREE(env->allocator, value);
+ }
+ }
+ axutil_array_list_free(tmp_param_keys, env);
+ axutil_array_list_free(tmp_param_values, env);
+ }
+ }
+
+ if(!op_desc)
+ {
+ /* this is not an error, since the calling function
+ may find another opertion match with the url */
+ AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI,
+ "The operation descriptor not found for the accessed URL");
+
+ if(first_delimitter)
+ {
+ /* restore the delimmiters */
+ *first_delimitter = '/';
+ }
+ }
+ return op_desc;
+}
+
+/* match a pattern with a url component */
+axis2_status_t
+axis2_core_utils_match_url_component_with_pattern(
+ const axutil_env_t *env,
+ axis2_char_t *pattern,
+ axis2_char_t *url_component,
+ axutil_array_list_t *param_keys,
+ axutil_array_list_t *param_values)
+{
+ axutil_array_list_t *const_components = NULL;
+ axis2_char_t *c = NULL;
+ axis2_char_t *url_c = NULL;
+ axis2_char_t *pattern_c = NULL;
+ axis2_char_t *const_part = NULL;
+ axis2_char_t *param_part = NULL;
+ axis2_char_t *param_value = NULL;
+ axis2_status_t status = AXIS2_SUCCESS;
+ /* here the state can have following values
+ 0 - inside a constant
+ 1 - inside a param
+ */
+ int loop_state = 0;
+ int i = 0;
+ int pattern_ending_with_param = 0;
+
+ /* the constant that undergoing matching */
+ int matching_constant_index = 0;
+ axis2_char_t *matching_constant = NULL;
+
+ /* dividing the pattern to consts */
+ const_components = axutil_array_list_create(env, 10);
+ if(!const_components)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ }
+ /* check whether the pattern ending with a param */
+ if(*(pattern + axutil_strlen(pattern) - 1) == '}')
+ {
+ pattern_ending_with_param = 1;
+ }
+
+ const_part = pattern;
+ /* a parse to fil the const array and key array */
+ for(c = pattern; c && *c != '\0'; c++)
+ {
+ if(loop_state == 0)
+ {
+ /* inside a constant */
+ if(*c == '{')
+ {
+ if(const_part == c)
+ {
+ /* no const part */
+ }
+ else
+ {
+ /* add the constant */
+ *c = '\0';
+ const_part = axutil_strdup(env, const_part);
+ if(!const_part)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+
+ status = AXIS2_FAILURE;
+ break;
+
+ }
+ axutil_array_list_add(const_components, env, const_part);
+
+ }
+ param_part = c + 1; /* start the param */
+ loop_state = 1; /* moving to the param from next iteration */
+ }
+ else if(*c == '}')
+ {
+ /* invalid state */
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_URL_FORMAT, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in parsing the url for %s",
+ url_component);
+
+ status = AXIS2_FAILURE;
+ break;
+ }
+ }
+ else
+ {
+ /* inside a param */
+ if(*c == '}')
+ {
+ if(*(c + 1) == '{') /* you can not have two params without a constant in between */
+ {
+ /* invalid state */
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_URL_FORMAT, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(
+ env->log,
+ AXIS2_LOG_SI,
+ "Error in parsing the url for %s, Please put constant between 2 parameters",
+ url_component);
+
+ status = AXIS2_FAILURE;
+ break;
+ }
+ if(param_part == c)
+ {
+ /* no param part */
+ }
+ else
+ {
+ /* add the param */
+ *c = '\0';
+ param_part = axutil_strdup(env, param_part);
+
+ if(param_part == NULL)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ status = AXIS2_FAILURE;
+ break;
+ }
+ axutil_array_list_add(param_keys, env, param_part);
+
+ const_part = c + 1; /* start the const */
+ }
+ loop_state = 0; /* moving to the const from next iteration */
+ }
+ else if(*c == '{')
+ {
+ /* invalid state */
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_URL_FORMAT, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in parsing the url for %s",
+ url_component);
+
+ status = AXIS2_FAILURE;
+ break;
+
+ }
+ }
+ }
+ /* loop should stop in state 0 */
+ if(loop_state != 0)
+ {
+ status = AXIS2_FAILURE;
+ }
+
+ if(const_part != c)
+ {
+ /* add the tailing const */
+ const_part = axutil_strdup(env, const_part);
+ if(!const_part)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ status = AXIS2_FAILURE;
+ }
+ axutil_array_list_add(const_components, env, const_part);
+ }
+
+ if(axutil_array_list_size(const_components, env) == 0 && status == AXIS2_SUCCESS)
+ {
+ /* no constants mean, the url componenent itself is the value */
+ url_component = axutil_strdup(env, url_component);
+ if(url_component)
+ {
+ axutil_array_list_add(param_values, env, url_component);
+
+ /* free the empty const array */
+
+ axutil_array_list_free(const_components, env);
+ return AXIS2_SUCCESS;
+ }
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ status = AXIS2_FAILURE;
+
+ }
+
+ if(status == AXIS2_FAILURE)
+ {
+ /* invalid state */
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_URL_FORMAT, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in parsing the url for %s", url_component);
+
+ /* free the const array */
+ for(i = 0; i < axutil_array_list_size(const_components, env); i++)
+ {
+ void *value;
+ value = axutil_array_list_get(const_components, env, i);
+
+ AXIS2_FREE(env->allocator, value);
+ }
+
+ axutil_array_list_free(const_components, env);
+
+ return status;
+ }
+
+ /* we are tracking the loop_state here too - this is useful only to track start*/
+ /* we are using the param_value part to track the matching param value */
+ if(*pattern != '{')
+ {
+ /* starting_with_constant */
+ loop_state = 0;
+ param_value = NULL;
+ }
+ else
+ {
+ /* starting_with_param */
+ loop_state = 1;
+ param_value = url_component;
+
+ }
+
+ matching_constant_index = 0;
+ matching_constant = axutil_array_list_get(const_components, env, 0);
+
+ /* now parse the url component */
+ for(url_c = url_component; *url_c != '\0' && status == AXIS2_SUCCESS && matching_constant
+ != NULL; url_c++)
+ {
+ axis2_char_t *tmp_url_c = url_c;
+ pattern_c = matching_constant;
+
+ while(*tmp_url_c == *pattern_c && *tmp_url_c != '\0' && *pattern_c != '\0')
+ {
+ tmp_url_c++;
+ pattern_c++;
+ }
+
+ if(*pattern_c == '\0')
+ {
+ /* we finised matching the constant pattern successfuly*/
+ if(loop_state == 0)
+ {
+ /* loop_state => we expected there is a constant */
+ }
+ else
+ {
+ /* we expected a param, but the constant is found =>
+ url_c should mark the end of the param */
+ if(param_value == NULL)
+ {
+ /* unexpected invalid state */
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_URL_FORMAT, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in parsing the url for %s",
+ url_component);
+ status = AXIS2_FAILURE;
+ }
+ *url_c = '\0';
+ param_value = axutil_strdup(env, param_value);
+
+ if(param_value == NULL)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ status = AXIS2_FAILURE;
+ break;
+ }
+ axutil_array_list_add(param_values, env, param_value);
+
+ }
+ /* next the param part is starting */
+ param_value = tmp_url_c;
+
+ loop_state = 1; /* the end of the constant expects, start of a variable */
+
+ /* so we found one constant, go for the other */
+ matching_constant_index++;
+ matching_constant = axutil_array_list_get(const_components, env,
+ matching_constant_index);
+
+ tmp_url_c--;
+ /* increment the url_c to tmp_url_c */
+ url_c = tmp_url_c;
+ }
+ else
+ {
+ /* pattern not matched */
+ if(loop_state == 0)
+ {
+ /* we are expected this to be a constant, but it has not happend
+ * mean: the pattern match failed
+ */
+ status = AXIS2_FAILURE;
+ break;
+ }
+ }
+
+ }
+
+ if(matching_constant_index != axutil_array_list_size(const_components, env))
+ {
+ status = AXIS2_FAILURE;
+ }
+
+ if(pattern_ending_with_param)
+ {
+ if(param_value)
+ {
+ param_value = axutil_strdup(env, param_value);
+
+ if(param_value == NULL)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create internal rest mapping structure");
+ status = AXIS2_FAILURE;
+ }
+ else
+ {
+ axutil_array_list_add(param_values, env, param_value);
+ }
+ }
+ }
+ else if(*url_c != '\0')
+ {
+ /* here the pattern ending is a constant (not a param), and matches all are already made
+ * but some url part left => this is a not mach */
+ status = AXIS2_FAILURE;
+ }
+
+ /* finally freeing the const array */
+ for(i = 0; i < axutil_array_list_size(const_components, env); i++)
+ {
+ void *value;
+ value = axutil_array_list_get(const_components, env, i);
+
+ AXIS2_FREE(env->allocator, value);
+ }
+ axutil_array_list_free(const_components, env);
+
+ return status;
+}