You are viewing a plain text version of this content. The canonical link for it is here.
Posted to axis-cvs@ws.apache.org by di...@apache.org on 2008/11/15 15:05:56 UTC
svn commit: r714264 - in /webservices/axis2/trunk/c:
include/axis2_core_utils.h include/axis2_svc.h src/core/description/svc.c
src/core/engine/rest_disp.c src/core/util/core_utils.c
util/include/axutil_error.h
Author: dimuthu
Date: Sat Nov 15 06:05:56 2008
New Revision: 714264
URL: http://svn.apache.org/viewvc?rev=714264&view=rev
Log:
fix for https://issues.apache.org/jira/browse/AXIS2C-1290
Modified:
webservices/axis2/trunk/c/include/axis2_core_utils.h
webservices/axis2/trunk/c/include/axis2_svc.h
webservices/axis2/trunk/c/src/core/description/svc.c
webservices/axis2/trunk/c/src/core/engine/rest_disp.c
webservices/axis2/trunk/c/src/core/util/core_utils.c
webservices/axis2/trunk/c/util/include/axutil_error.h
Modified: webservices/axis2/trunk/c/include/axis2_core_utils.h
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/c/include/axis2_core_utils.h?rev=714264&r1=714263&r2=714264&view=diff
==============================================================================
--- webservices/axis2/trunk/c/include/axis2_core_utils.h (original)
+++ webservices/axis2/trunk/c/include/axis2_core_utils.h Sat Nov 15 06:05:56 2008
@@ -91,6 +91,27 @@
int * param_count,
axis2_char_t **** params);
+ 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_EXTERN axis2_status_t AXIS2_CALL
+ axis2_core_utils_free_rest_map (
+ const axutil_env_t * env,
+ axutil_hash_t *rest_map);
+
+ AXIS2_EXTERN axis2_op_t *AXIS2_CALL
+ 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);
+
+
/** @} */
#ifdef __cplusplus
Modified: webservices/axis2/trunk/c/include/axis2_svc.h
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/c/include/axis2_svc.h?rev=714264&r1=714263&r2=714264&view=diff
==============================================================================
--- webservices/axis2/trunk/c/include/axis2_svc.h (original)
+++ webservices/axis2/trunk/c/include/axis2_svc.h Sat Nov 15 06:05:56 2008
@@ -127,6 +127,19 @@
const axis2_char_t * http_method,
const axis2_char_t * http_location);
+
+ /**
+ * Gets the RESTful operation map for a given service
+ * @param svc pointer to service struct
+ * @param env pointer to environment struct
+ * @return pointer to hash with the information
+ * (method, url)=> processing structure for each ops
+ */
+ AXIS2_EXTERN axutil_hash_t *AXIS2_CALL
+ axis2_svc_get_rest_map(
+ const axis2_svc_t * svc,
+ const axutil_env_t * env);
+
/**
* Gets operation corresponding to the name.
* @param svc pointer to service struct
Modified: webservices/axis2/trunk/c/src/core/description/svc.c
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/c/src/core/description/svc.c?rev=714264&r1=714263&r2=714264&view=diff
==============================================================================
--- webservices/axis2/trunk/c/src/core/description/svc.c (original)
+++ webservices/axis2/trunk/c/src/core/description/svc.c Sat Nov 15 06:05:56 2008
@@ -23,6 +23,7 @@
#include "../deployment/axis2_desc_builder.h"
#include <axis2_svc_skeleton.h>
#include <axutil_thread.h>
+#include <axis2_core_utils.h>
struct axis2_svc
{
@@ -433,27 +434,7 @@
if (svc->op_rest_map)
{
- axutil_hash_index_t *hi = NULL;
- const void *key = NULL;
- void *val = NULL;
-
- for (hi = axutil_hash_first(svc->op_rest_map, env); hi;
- hi = axutil_hash_next(env, hi))
- {
- axutil_hash_this(hi, &key, NULL, &val);
-
- if (val)
- {
- axutil_array_list_free_void_arg(val, env);
- }
-
- if (key)
- {
- AXIS2_FREE(env->allocator, (axis2_char_t *) key);
- key = NULL;
- }
- }
- axutil_hash_free(svc->op_rest_map, env);
+ axis2_core_utils_free_rest_map(env, svc->op_rest_map);
}
if (svc->schema_target_ns_prefix)
@@ -1301,77 +1282,54 @@
const axis2_char_t * location,
axis2_op_t * op_desc)
{
- axutil_array_list_t *op_list = NULL;
- axis2_char_t *key = NULL;
- axis2_char_t *loc_str = NULL;
- axis2_char_t *loc_str_tmp = NULL;
- axis2_char_t *rindex = NULL;
- const axis2_char_t *svcname = NULL;
- int plen;
- AXIS2_PARAM_CHECK(env->error, op_desc, AXIS2_FAILURE);
- svcname = axis2_svc_get_name(svc, env);
- op_list = axis2_svc_get_rest_op_list_with_method_and_location(svc, env,
- method, location);
- if (!op_list)
+
+ axis2_char_t *mapping_url = NULL;
+ int key_len = 0;
+ axis2_char_t* question_char = NULL;
+ axis2_char_t* local_location_str = NULL;
+ axis2_status_t status = AXIS2_SUCCESS;
+
+ local_location_str = (axis2_char_t *) location; /* Casted to facilitate loop */
+
+ /* skip the biginning '/' */
+ if(*local_location_str == '/')
{
- op_list = axutil_array_list_create(env, 0);
- if (!op_list)
- {
- AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
- AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
- "Creating rest operation list failed for service", svcname);
- return AXIS2_FAILURE;
- }
- loc_str_tmp = (axis2_char_t *) location; /* Casted to facilitate loop */
- if (loc_str_tmp[1] == '/')
- {
- loc_str_tmp++;
- } /* ignore any '/' at the beginning */
- if (strchr(loc_str_tmp, '?'))
- {
- axis2_char_t *temp = NULL;
+ local_location_str ++;
+ }
+ question_char = axutil_strchr(local_location_str, '?');
+ if(question_char)
+ {
+ *question_char = '\0';
+ }
- temp = strchr(loc_str_tmp, '?');
- temp[0] = '\0';
- } /* ignore block after '?' */
- do
- {
- axis2_char_t *temp = NULL;
- temp = strchr(loc_str_tmp, '{');
- if (temp)
- {
- loc_str_tmp = temp;
- }
- else
- {
- loc_str_tmp += strlen(loc_str_tmp);
- break;
- }
- } while (loc_str_tmp[1] &&
- loc_str_tmp[1] == '{');
+ key_len = axutil_strlen(method) + axutil_strlen(local_location_str) + 2;
- loc_str = (axis2_char_t *) axutil_strmemdup(location, (loc_str_tmp - location), env);
+ mapping_url = (axis2_char_t *) (AXIS2_MALLOC (env->allocator,
+ sizeof (axis2_char_t) * key_len));
+ if(!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 rest mapping url");
+ return AXIS2_FAILURE;
+ }
- rindex = axutil_rindex(loc_str, '/');
- if (rindex && *rindex)
- {
- loc_str_tmp = axutil_string_substring_ending_at(loc_str, (int)(rindex - loc_str));
- /* We are sure that the difference lies within the int range */
- }
- else
- {
- loc_str_tmp = loc_str;
- }
+ sprintf(mapping_url, "%s:%s", method, local_location_str);
+
+ status = axis2_core_utils_prepare_rest_mapping(env,
+ mapping_url,
+ svc->op_rest_map,
+ op_desc);
+
+ if(mapping_url) {
+ AXIS2_FREE(env->allocator, mapping_url);
+ }
- plen = axutil_strlen (method) + axutil_strlen (loc_str_tmp) + 2;
- key = (axis2_char_t *) (AXIS2_MALLOC (env->allocator,
- sizeof (axis2_char_t) * plen));
- sprintf (key, "%s:%s", method, loc_str_tmp);
- AXIS2_FREE (env->allocator, loc_str);
- axutil_hash_set(svc->op_rest_map, key, AXIS2_HASH_KEY_STRING, op_list);
+ /* restore the question character */
+ if(question_char) {
+ *question_char = '?';
}
- return axutil_array_list_add(op_list, env, op_desc);
+ return status;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
@@ -1602,3 +1560,11 @@
return svc->mutex;
}
+AXIS2_EXTERN axutil_hash_t *AXIS2_CALL
+axis2_svc_get_rest_map(
+ const axis2_svc_t * svc,
+ const axutil_env_t * env)
+{
+ return svc->op_rest_map;
+}
+
Modified: webservices/axis2/trunk/c/src/core/engine/rest_disp.c
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/c/src/core/engine/rest_disp.c?rev=714264&r1=714263&r2=714264&view=diff
==============================================================================
--- webservices/axis2/trunk/c/src/core/engine/rest_disp.c (original)
+++ webservices/axis2/trunk/c/src/core/engine/rest_disp.c Sat Nov 15 06:05:56 2008
@@ -167,10 +167,17 @@
axiom_node_t *body_child_node = NULL;
axiom_node_t *body_element_node = NULL;
axis2_bool_t soap_env_exists = AXIS2_TRUE;
- int param_count = 0;
- axis2_char_t ***params = NULL;
int i = 0;
+ axutil_array_list_t *param_keys = NULL;
+ axutil_array_list_t *param_values = NULL;
+
+ /* param_values keeps pointer to
+ the live_mapping_url and local_url
+ so should not free until param_values are freed */
+ axis2_char_t *live_mapping_url = NULL;
+ axis2_char_t *local_url = NULL;
+
AXIS2_PARAM_CHECK(env->error, svc, NULL);
if (!axis2_msg_ctx_get_doing_rest(msg_ctx, env))
@@ -198,60 +205,149 @@
location = strstr(address, url_tokens[0]);
if (location)
{
+ axis2_char_t *addition_params_str = NULL;
+ axis2_char_t *adjusted_local_url = NULL;
+ const axis2_char_t *method = NULL;
+
+ int key_len = 0;
+
location += strlen(url_tokens[0]);
+ method = axis2_msg_ctx_get_rest_http_method(msg_ctx, env);
+
+
AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI,
- "Checking for operation using \
-REST HTTP Location fragment : %s", location);
- op = axis2_core_utils_get_rest_op_with_method_and_location(svc, env,
- axis2_msg_ctx_get_rest_http_method(msg_ctx, env), location,
- ¶m_count, ¶ms);
- if (op)
+ "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 existance of the addition parameters
+ after the question mark '?' */
+ addition_params_str = strchr(local_url, '?');
+ if(addition_params_str)
{
- AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI,
- "Operation found using target endpoint uri fragment");
+ *addition_params_str = '\0';
+ addition_params_str ++;
+ }
+
+ /* if the first character is '/' ignore that */
+ if(*local_url == '/')
+ {
+ adjusted_local_url = local_url + 1;
}
else
{
- int i = 0;
- int j = 0;
- axutil_array_list_t *supported_rest_methods = NULL;
- const axis2_char_t *http_method = NULL;
- axis2_char_t *rest_methods[] = {AXIS2_HTTP_GET, AXIS2_HTTP_POST,
- AXIS2_HTTP_PUT, AXIS2_HTTP_DELETE, AXIS2_HTTP_HEAD};
- supported_rest_methods = axutil_array_list_create(env, 0);
- http_method = axis2_msg_ctx_get_rest_http_method(msg_ctx, env);
- if (!http_method)
+ 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);
+
+ param_keys = axutil_array_list_create(env, 10);
+ param_values = axutil_array_list_create(env, 10);
+
+ if(!param_keys || !param_values)
+ {
+ AXIS2_FREE(env->allocator, local_url);
+ AXIS2_FREE(env->allocator, live_mapping_url);
+ if(param_keys)
+ {
+ axutil_array_list_free(param_keys, env);
+ }
+ if(param_values)
{
- AXIS2_LOG_WARNING (env->log, AXIS2_LOG_SI,
- "unable to find http method \
-for location: %s", location);
- return NULL;
+ axutil_array_list_free(param_values, env);
}
+ 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 parameter maps");
+ AXIS2_FREE(env->allocator, local_url);
+ return NULL;
+ }
+
+ 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;
- for (i = 0; i < 5; i++)
+ 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')
{
- if (axutil_strcasecmp(rest_methods[i],
- http_method))
+ 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)
{
- if (axis2_core_utils_get_rest_op_with_method_and_location(svc, env,
- rest_methods[i], location, ¶m_count, ¶ms))
- {
- for (j = 0; j < param_count; j++)
- {
- AXIS2_FREE (env->allocator, params[j][0]);
- AXIS2_FREE (env->allocator, params[j][1]);
- AXIS2_FREE (env->allocator, params[j]);
- }
- if (params)
- {
- AXIS2_FREE (env->allocator, params);
- }
- axutil_array_list_add(supported_rest_methods, env,
- axutil_strdup(env, rest_methods[i]));
- }
+ *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) {
+ axutil_array_list_add(param_keys, env, key);
+ }
+ if(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 */
}
}
- axis2_msg_ctx_set_supported_rest_http_methods(msg_ctx, env, supported_rest_methods);
}
}
}
@@ -266,6 +362,23 @@
if (!op)
{
+ if(param_keys)
+ {
+ axutil_array_list_free(param_keys, env);
+ }
+ if(param_values)
+ {
+ axutil_array_list_free(param_values, env);
+ }
+ /* after freeing param_values, it is safe to free live_mapping_url and local_url*/
+ if (live_mapping_url)
+ {
+ AXIS2_FREE (env->allocator, live_mapping_url);
+ }
+ if(local_url)
+ {
+ AXIS2_FREE(env->allocator, local_url);
+ }
return NULL;
}
@@ -285,6 +398,24 @@
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOAP_ENVELOPE_OR_SOAP_BODY_NULL,
AXIS2_FAILURE);
+
+ if(param_keys)
+ {
+ axutil_array_list_free(param_keys, env);
+ }
+ if(param_values)
+ {
+ axutil_array_list_free(param_values, env);
+ }
+ /* after freeing param_values, it is safe to free live_mapping_url and local_url*/
+ if (live_mapping_url)
+ {
+ AXIS2_FREE (env->allocator, live_mapping_url);
+ }
+ if(local_url)
+ {
+ AXIS2_FREE(env->allocator, local_url);
+ }
return NULL;
}
@@ -303,22 +434,36 @@
&body_child_node);
axiom_soap_body_add_child(soap_body, env, body_child_node);
}
- for (i = 0; i < param_count; i++)
- {
- axiom_node_t *node = NULL;
- axiom_element_t *element = NULL;
+
+ if(param_keys && param_values) {
+ for (i = 0; i < axutil_array_list_size(param_keys, env); i++)
+ {
+ axis2_char_t *param_key = NULL;
+ axis2_char_t *param_value = NULL;
+
+ axiom_node_t *node = NULL;
+ axiom_element_t *element = NULL;
+
+ param_key = axutil_array_list_get(param_keys, env, i);
+ param_value = axutil_array_list_get(param_values, env, i);
- element = axiom_element_create(env, NULL, params[i][0],
- NULL, &node);
- axiom_element_set_text(element, env, params[i][1], node);
- axiom_node_add_child(body_child_node, env, node);
- AXIS2_FREE (env->allocator, params[i][0]);
- AXIS2_FREE (env->allocator, params[i][1]);
- AXIS2_FREE (env->allocator, params[i]);
+ element = axiom_element_create(env, NULL, param_key,
+ NULL, &node);
+ axiom_element_set_text(element, env, param_value, node);
+ axiom_node_add_child(body_child_node, env, node);
+ }
+
+ axutil_array_list_free(param_keys, env);
+ axutil_array_list_free(param_values, env);
+ }
+ /* after freeing param_values, it is safe to free live_mapping_url */
+ if (live_mapping_url)
+ {
+ AXIS2_FREE (env->allocator, live_mapping_url);
}
- if (params)
+ if(local_url)
{
- AXIS2_FREE (env->allocator, params);
+ AXIS2_FREE(env->allocator, local_url);
}
if (!soap_env_exists)
@@ -340,114 +485,3 @@
return axis2_disp_find_svc_and_op(handler, env, msg_ctx);
}
-/*
-axis2_op_t *AXIS2_CALL
-axis2_rest_disp_get_rest_op_with_method_and_location(
- const axis2_svc_t * svc,
- const axutil_env_t * env,
- const axis2_char_t * method,
- const axis2_char_t * location,
- int * param_count,
- axis2_char_t **** params)
-{
- axutil_array_list_t *op_list = NULL;
- axis2_char_t *loc_str = NULL;
- axis2_char_t *loc_str_tmp = NULL;
- axis2_char_t *rindex = NULL;
- axis2_bool_t pass_one = AXIS2_TRUE;
- axis2_bool_t loop_state = AXIS2_TRUE;
- AXIS2_PARAM_CHECK(env->error, location, NULL);
- AXIS2_PARAM_CHECK(env->error, method, NULL);
-
- loc_str = axutil_strtrim(env, location, NULL);
- if (!loc_str)
- {
- return NULL;
- }
- loc_str_tmp = loc_str;
- if (loc_str_tmp[0] == '/')
- {
- loc_str_tmp++;
- }
- if (strchr(loc_str_tmp, '?'))
- {
- axis2_char_t *temp = NULL;
-
- temp = strchr(loc_str_tmp, '?');
- temp[0] = '\0';
- }
- while(loop_state)
- {
- rindex = axutil_rindex(loc_str_tmp, '/');
-
- if (rindex && *rindex)
- {
- loc_str_tmp = axutil_string_substring_ending_at(loc_str_tmp, (int)(rindex - loc_str_tmp));
- }
- else if (pass_one)
- {
- pass_one = AXIS2_FALSE;
- }
- else
- {
- int i = 0;
- i = (int)strlen(loc_str_tmp);
- if (i == 0)
- {
- break;
- }
- loc_str_tmp[i - 1] = '\0';
- }
-
- if (!loc_str_tmp || !*loc_str_tmp)
- {
- break;
- }
- op_list = axis2_svc_get_rest_op_list_with_method_and_location(svc, env,
- method, loc_str_tmp);
- if (op_list && axutil_array_list_size(op_list, env) != 0)
- {
- int i = 0;
- int size = 0;
-
- size = axutil_array_list_size(op_list, env);
- for (i = 0; i < size; i++)
- {
- axis2_op_t *op_temp = NULL;
- axis2_char_t *op_location = NULL;
- int match_count = 0;
- axis2_char_t ***matches = NULL;
- axis2_status_t status = AXIS2_FAILURE;
-
- op_temp = axutil_array_list_get(op_list, env, i);
- op_location = axis2_op_get_rest_http_location(op_temp, env);
- if (!op_location)
- {
- continue;
- }
- status = axutil_parse_rest_url_for_params(env, op_location, location,
- &match_count, &matches);
- if (status == AXIS2_SUCCESS)
- {
- *params = matches;
- *param_count = match_count;
- AXIS2_FREE (env->allocator, loc_str);
- return op_temp;
- }
- else if (matches)
- {
- for (i = 0; i < match_count; i++)
- {
- AXIS2_FREE (env->allocator, matches[i]);
- }
- AXIS2_FREE (env->allocator, matches);
- }
- }
- }
- }
- AXIS2_FREE (env->allocator, loc_str);
- return NULL;
-}
-
-*/
-
Modified: webservices/axis2/trunk/c/src/core/util/core_utils.c
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/c/src/core/util/core_utils.c?rev=714264&r1=714263&r2=714264&view=diff
==============================================================================
--- webservices/axis2/trunk/c/src/core/util/core_utils.c (original)
+++ webservices/axis2/trunk/c/src/core/util/core_utils.c Sat Nov 15 06:05:56 2008
@@ -427,114 +427,556 @@
}
-AXIS2_EXTERN axis2_op_t *AXIS2_CALL
-axis2_core_utils_get_rest_op_with_method_and_location(
- const axis2_svc_t * svc,
+
+/* 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;
+
+
+/* build the restmap recursively - internal function*/
+axis2_status_t AXIS2_CALL
+axis2_core_utils_internal_build_rest_map_recursively(
const axutil_env_t * env,
- const axis2_char_t * method,
- const axis2_char_t * location,
- int * param_count,
- axis2_char_t **** params)
- {
- axutil_array_list_t *op_list = NULL;
- axis2_char_t *loc_str = NULL;
- axis2_char_t *loc_str_tmp = NULL;
- axis2_char_t *rindex = NULL;
- axis2_bool_t pass_one = AXIS2_TRUE;
- axis2_bool_t loop_state = AXIS2_TRUE;
- AXIS2_PARAM_CHECK(env->error, location, NULL);
- AXIS2_PARAM_CHECK(env->error, method, NULL);
-
- loc_str = axutil_strtrim(env, location, NULL);
- if (!loc_str)
- {
- return NULL;
- }
- loc_str_tmp = loc_str;
- if (loc_str_tmp[0] == '/')
- {
- loc_str_tmp++;
- }
- if (strchr(loc_str_tmp, '?'))
- {
- axis2_char_t *temp = NULL;
-
- temp = strchr(loc_str_tmp, '?');
- temp[0] = '\0';
- }
- while(loop_state)
- {
- rindex = axutil_rindex(loc_str_tmp, '/');
-
- if (rindex && *rindex)
- {
- loc_str_tmp = axutil_string_substring_ending_at(loc_str_tmp, (int)(rindex - loc_str_tmp));
- /* We are sure that the difference lies within the int range */
- }
- else if (pass_one)
- {
- pass_one = AXIS2_FALSE;
- }
- else
- {
- int i = 0;
- i = (int)strlen(loc_str_tmp);
- /* We are sure that the difference lies within the int range */
- if (i == 0)
- {
- break;
- }
- loc_str_tmp[i - 1] = '\0';
- }
-
- if (!loc_str_tmp || !*loc_str_tmp)
- {
- break;
- }
- op_list = axis2_svc_get_rest_op_list_with_method_and_location(svc, env,
- method, loc_str_tmp);
- if (op_list && axutil_array_list_size(op_list, env) != 0)
- {
- int i = 0;
- int size = 0;
-
- size = axutil_array_list_size(op_list, env);
- for (i = 0; i < size; i++)
- {
- axis2_op_t *op_temp = NULL;
- axis2_char_t *op_location = NULL;
- int match_count = 0;
- axis2_char_t ***matches = NULL;
- axis2_status_t status = AXIS2_FAILURE;
-
- op_temp = axutil_array_list_get(op_list, env, i);
- op_location = axis2_op_get_rest_http_location(op_temp, env);
- if (!op_location)
- {
- continue;
- }
- status = axutil_parse_rest_url_for_params(env, op_location, location,
- &match_count, &matches);
- if (status == AXIS2_SUCCESS)
- {
- *params = matches;
- *param_count = match_count;
- AXIS2_FREE (env->allocator, loc_str);
- return op_temp;
- }
- else if (matches)
- {
- for (i = 0; i < match_count; i++)
- {
- AXIS2_FREE (env->allocator, matches[i]);
- }
- AXIS2_FREE (env->allocator, matches);
- }
- }
- }
- }
- AXIS2_FREE (env->allocator, loc_str);
- return NULL;
- }
+ 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);
+
+
+/* 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;
+
+ 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';
+ }
+
+
+ /* only constants are allowed in this level, so here 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;
+ }
+
+
+ /* retrieve or create the maping 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_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(*url == '{')
+ {
+ axis2_char_t *last_url_char = url + axutil_strlen(url) -1;
+ if(*last_url_char == '}')
+ {
+ *last_url_char = '\0';
+
+ /* mapipng key is url excluding { } */
+ mapping_key = url + 1;
+ 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;
+ }
+ }
+ else
+ {
+ /* 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);
+ }
+ }
+
+ if (key)
+ {
+ AXIS2_FREE(env->allocator, (axis2_char_t *) key);
+ key = NULL;
+ }
+ }
+ axutil_hash_free(rest_map, env);
+ return status;
+}
+
+
+/* infer op from the live url */
+AXIS2_EXTERN axis2_op_t *AXIS2_CALL
+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 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;
+
+ /* 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 == NULL)
+ {
+ /* the op is not here */
+ 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;
+ }
+
+ if(!next_level_url)
+ {
+ /* there is no another level, so the op should be here */
+ op_desc = mapping_struct->op_desc;
+ if(!op_desc) {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_URL_FORMAT, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "The operation descriptor not found for the accessed URL");
+ }
+ }
+ else {
+
+ op_desc = axis2_core_utils_internal_infer_op_from_rest_map_recursively(
+ env,
+ mapping_struct,
+ next_level_url,
+ param_keys,
+ param_values);
+ }
+ 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;
+ int params_map_count = 0;
+
+ 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;
+ }
+
+ params_map_count = axutil_hash_count(parent_mapping_struct->params_map);
+
+ 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)
+ {
+ axis2_char_t *hash_key = (axis2_char_t*)key;
+
+ 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;
+
+ if(op_desc) {
+ /* adding the hash key as the param key */
+ axutil_array_list_add(param_keys, env, hash_key);
+
+ /* adding the url component as the parma value */
+ axutil_array_list_add(param_values, env, url_component);
+
+ break;
+ }
+
+ }
+ else {
+
+ /* temporary param keys and values for each entry */
+ axutil_array_list_t *tmp_param_keys;
+ axutil_array_list_t *tmp_param_values;
+
+ if(params_map_count == 1) {
+ /* if it is only one param entry, just use the original one */
+ tmp_param_keys = param_keys;
+ tmp_param_values = param_values;
+ }
+ else {
+ tmp_param_keys = axutil_array_list_create(env, 10);
+ tmp_param_values = axutil_array_list_create(env, 10);
+ }
+
+ /* adding the hash key as the param key */
+ axutil_array_list_add(tmp_param_keys, env, hash_key);
+
+ /* adding the url component as the parma value */
+ axutil_array_list_add(tmp_param_values, env, url_component);
+
+ 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 */
+
+ if(params_map_count != 1) {
+ 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 the op not found, contiue, before that free the temp arrays */
+ 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;
+}
Modified: webservices/axis2/trunk/c/util/include/axutil_error.h
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/c/util/include/axutil_error.h?rev=714264&r1=714263&r2=714264&view=diff
==============================================================================
--- webservices/axis2/trunk/c/util/include/axutil_error.h (original)
+++ webservices/axis2/trunk/c/util/include/axutil_error.h Sat Nov 15 06:05:56 2008
@@ -336,6 +336,10 @@
/** URL NULL in http client */
AXIS2_ERROR_NULL_URL,
+ /** Invalid URL format */
+ AXIS2_ERROR_INVALID_URL_FORMAT,
+ /** Duplicate URL REST Mapping */
+ AXIS2_ERROR_DUPLICATE_URL_REST_MAPPING,
/* We need transport_info in msg_ctx */
AXIS2_ERROR_OUT_TRNSPORT_INFO_NULL,
/*Content-Type header missing in HTTP response" */