blob: cc34fcf66bb4c57972b5cfa4c3260b0191443964 [file] [log] [blame]
/*
* 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;
#ifdef AXIS2_JSON_ENABLED
axis2_bool_t doing_json = AXIS2_FALSE;
#endif
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);
#ifdef AXIS2_JSON_ENABLED
doing_json = axis2_msg_ctx_get_doing_json(in_msg_ctx, env);
axis2_msg_ctx_set_doing_json(new_msg_ctx, env, doing_json);
#endif
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;
}