From 0425aadc78680e53000fd0108b540d6eca048516 Mon Sep 17 00:00:00 2001 From: gmcdonald Date: Sat, 13 Feb 2010 01:32:03 +0000 Subject: Moving axis svn, part of TLP move INFRA-2441 git-svn-id: http://svn.apache.org/repos/asf/axis/axis2/c/core/trunk@909681 13f79535-47bb-0310-9956-ffa450edef68 --- neethi/src/engine.c | 1390 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1390 insertions(+) create mode 100644 neethi/src/engine.c (limited to 'neethi/src/engine.c') diff --git a/neethi/src/engine.c b/neethi/src/engine.c new file mode 100644 index 0000000..b925cea --- /dev/null +++ b/neethi/src/engine.c @@ -0,0 +1,1390 @@ +/* + * 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 +#include +#include + +/*Private functions*/ + +static neethi_all_t * +neethi_engine_get_operator_all( + const axutil_env_t *env, + axiom_node_t *node, + axiom_element_t *element); + +static neethi_exactlyone_t * +neethi_engine_get_operator_exactlyone( + const axutil_env_t *env, + axiom_node_t *node, + axiom_element_t *element); + +static neethi_reference_t * +neethi_engine_get_operator_reference( + const axutil_env_t *env, + axiom_node_t *node, + axiom_element_t *element); + +static neethi_policy_t * +neethi_engine_get_operator_neethi_policy( + const axutil_env_t *env, + axiom_node_t *node, + axiom_element_t *element); + +static axis2_status_t +neethi_engine_process_operation_element( + const axutil_env_t *env, + neethi_operator_t *neethi_operator, + axiom_node_t *node, + axiom_element_t *element); + +static axis2_status_t +neethi_engine_add_policy_component( + const axutil_env_t *env, + neethi_operator_t *container_operator, + neethi_operator_t *component); + +static axis2_bool_t +neethi_engine_operator_is_empty( + neethi_operator_t *operator, + const axutil_env_t *env); + +static neethi_exactlyone_t * +neethi_engine_compute_resultant_component( + axutil_array_list_t *normalized_inner_components, + neethi_operator_type_t type, + const axutil_env_t *env); + +static axutil_array_list_t * +neethi_engine_operator_get_components( + neethi_operator_t *operator, + const axutil_env_t *env); + +static neethi_exactlyone_t * +neethi_engine_normalize_operator( + neethi_operator_t *operator, + neethi_registry_t *registry, + axis2_bool_t deep, + const axutil_env_t *env); + +static neethi_exactlyone_t * +neethi_engine_get_cross_product( + neethi_exactlyone_t *exactlyone1, + neethi_exactlyone_t *exactlyone2, + const axutil_env_t *env); + +static void +neethi_engine_clear_element_attributes( + axutil_hash_t *attr_hash, + const axutil_env_t *env); + +/*Implementations*/ + +/*This is the function which is called from outside*/ + +AXIS2_EXTERN neethi_policy_t *AXIS2_CALL +neethi_engine_get_policy( + const axutil_env_t *env, + axiom_node_t *node, + axiom_element_t *element) +{ + /* This function will be called recursively */ + + return neethi_engine_get_operator_neethi_policy(env, node, element); +} + +static neethi_all_t * +neethi_engine_get_operator_all( + const axutil_env_t *env, + axiom_node_t *node, + axiom_element_t *element) +{ + neethi_all_t *all = NULL; + neethi_operator_t *neethi_operator = NULL; + axis2_status_t status = AXIS2_SUCCESS; + all = neethi_all_create(env); + + if(!all) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + neethi_operator = neethi_operator_create(env); + if(!neethi_operator) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + neethi_operator_set_value(neethi_operator, env, all, OPERATOR_TYPE_ALL); + + status = neethi_engine_process_operation_element(env, neethi_operator, node, element); + + neethi_operator_set_value_null(neethi_operator, env); + neethi_operator_free(neethi_operator, env); + neethi_operator = NULL; + + if(status != AXIS2_SUCCESS) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NEETHI_ALL_CREATION_FAILED, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[neethi] All creation failed"); + neethi_all_free(all, env); + all = NULL; + return NULL; + } + return all; +} + +static neethi_exactlyone_t * +neethi_engine_get_operator_exactlyone( + const axutil_env_t *env, + axiom_node_t *node, + axiom_element_t *element) +{ + neethi_exactlyone_t *exactlyone = NULL; + neethi_operator_t *neethi_operator = NULL; + axis2_status_t status = AXIS2_SUCCESS; + + exactlyone = neethi_exactlyone_create(env); + + if(!exactlyone) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + + return NULL; + } + neethi_operator = neethi_operator_create(env); + if(!neethi_operator) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + + return NULL; + } + neethi_operator_set_value(neethi_operator, env, exactlyone, OPERATOR_TYPE_EXACTLYONE); + status = neethi_engine_process_operation_element(env, neethi_operator, node, element); + + neethi_operator_set_value_null(neethi_operator, env); + neethi_operator_free(neethi_operator, env); + neethi_operator = NULL; + + if(status != AXIS2_SUCCESS) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NEETHI_EXACTLYONE_CREATION_FAILED, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[neethi] Exactlyone creation failed."); + neethi_exactlyone_free(exactlyone, env); + exactlyone = NULL; + return NULL; + } + + return exactlyone; +} + +neethi_reference_t * +neethi_engine_get_operator_reference( + const axutil_env_t *env, + axiom_node_t *node, + axiom_element_t *element) +{ + neethi_reference_t *reference = NULL; + axutil_qname_t *qname = NULL; + axis2_char_t *attribute_value = NULL; + + reference = neethi_reference_create(env); + + if(!reference) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + + return NULL; + } + qname = axutil_qname_create(env, NEETHI_URI, NULL, NULL); + + if(!qname) + { + return NULL; + } + + attribute_value = axiom_element_get_attribute_value(element, env, qname); + if(attribute_value) + { + neethi_reference_set_uri(reference, env, attribute_value); + } + return reference; +} + +/* This function will be called when we encounter a wsp:Policy + * element */ + +static neethi_policy_t * +neethi_engine_get_operator_neethi_policy( + const axutil_env_t *env, + axiom_node_t *node, + axiom_element_t *element) +{ + neethi_policy_t *neethi_policy = NULL; + neethi_operator_t *neethi_operator = NULL; + axis2_status_t status = AXIS2_SUCCESS; + + /* Creates a policy struct */ + + neethi_policy = neethi_policy_create(env); + + if(!neethi_policy) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + + /* Then we wrap it in a neethi_operator */ + + neethi_operator = neethi_operator_create(env); + if(!neethi_operator) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + neethi_operator_set_value(neethi_operator, env, neethi_policy, OPERATOR_TYPE_POLICY); + + /* This function will do all the processing and build the + * policy object model */ + + status = neethi_engine_process_operation_element(env, neethi_operator, node, element); + + /* To prevent freeing the policy object from the operator + * we set it to null. This object will be freed from a parent + * or from an outsider who creates a policy object */ + + neethi_operator_set_value_null(neethi_operator, env); + neethi_operator_free(neethi_operator, env); + neethi_operator = NULL; + + if(status != AXIS2_SUCCESS) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NEETHI_POLICY_CREATION_FAILED, AXIS2_FAILURE); + + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[neethi] Policy creation failed."); + neethi_policy_free(neethi_policy, env); + neethi_policy = NULL; + return NULL; + } + return neethi_policy; +} + +/* This function will construct the policy objecy model by + * filling the component array_list inside the passing + * policy operator */ + +static axis2_status_t +neethi_engine_process_operation_element( + const axutil_env_t *env, + neethi_operator_t *neethi_operator, + axiom_node_t *node, + axiom_element_t *element) +{ + + neethi_operator_type_t type; + axiom_element_t *child_element = NULL; + axiom_node_t *child_node = NULL; + axiom_children_iterator_t *children_iter = NULL; + void *value = NULL; + + type = neethi_operator_get_type(neethi_operator, env); + value = neethi_operator_get_value(neethi_operator, env); + + if(type == OPERATOR_TYPE_POLICY) + { + /* wsp:Policy element can have any number of attributes + * we will store them in a hash from the uri and localname */ + + axutil_hash_t *attributes = axiom_element_extract_attributes(element, env, node); + + if(attributes) + { + axutil_hash_index_t *hi = NULL; + + /* When creating the policy object we created the hash */ + + axutil_hash_t *ht = neethi_policy_get_attributes((neethi_policy_t *)value, env); + + if(!ht) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[neethi] Policy hash map creation failed."); + return AXIS2_FAILURE; + } + + for(hi = axutil_hash_first(attributes, env); hi; hi = axutil_hash_next(env, hi)) + { + axis2_char_t *key = NULL; + void *val = NULL; + axutil_qname_t *qname = NULL; + axis2_char_t *attr_val = NULL; + axiom_namespace_t *ns = NULL; + axis2_char_t *ns_uri = NULL; + axiom_attribute_t *om_attr = NULL; + + axutil_hash_this(hi, NULL, NULL, &val); + if(val) + { + om_attr = (axiom_attribute_t *)val; + ns = axiom_attribute_get_namespace(om_attr, env); + if(ns) + { + ns_uri = axiom_namespace_get_uri(ns, env); + } + + qname = axutil_qname_create(env, axiom_attribute_get_localname(om_attr, env), + ns_uri, NULL); + if(qname) + { + key = axutil_qname_to_string(qname, env); + if(key) + { + attr_val = axiom_attribute_get_value(om_attr, env); + if(attr_val) + { + /* axutil_qname_free will free the returned key + * of the qname so will duplicate it when storing */ + + axutil_hash_set(ht, axutil_strdup(env, key), AXIS2_HASH_KEY_STRING, + axutil_strdup(env, attr_val)); + } + } + axutil_qname_free(qname, env); + } + } + } + /* axiom_element_extract_attributes method will always returns + * a cloned copy, so we need to free it after we have done with it */ + + neethi_engine_clear_element_attributes(attributes, env); + attributes = NULL; + } + } + + children_iter = axiom_element_get_children(element, env, node); + if(children_iter) + { + while(axiom_children_iterator_has_next(children_iter, env)) + { + /* Extract the element and check the namespace. If the namespace + * is in ws_policy then we call the relevent operator builder + * otherwise we will call the assertion_builder */ + + child_node = axiom_children_iterator_next(children_iter, env); + if(child_node) + { + if(axiom_node_get_node_type(child_node, env) == AXIOM_ELEMENT) + { + child_element = (axiom_element_t *)axiom_node_get_data_element(child_node, env); + if(child_element) + { + axiom_namespace_t *namespace = NULL; + axis2_char_t *uri = NULL; + axis2_char_t *local_name = NULL; + neethi_operator_t *operator = NULL; + local_name = axiom_element_get_localname(child_element, env); + + namespace = axiom_element_get_namespace(child_element, env, child_node); + if(!namespace) + { + AXIS2_ERROR_SET(env->error, + AXIS2_ERROR_NEETHI_ELEMENT_WITH_NO_NAMESPACE, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] Element with no namespace"); + return AXIS2_FAILURE; + } + uri = axiom_namespace_get_uri(namespace, env); + if(!uri) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_EMPTY_NAMESPACE_URI, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] Invalid Empty namespace uri."); + return AXIS2_FAILURE; + } + if((axutil_strcmp(uri, NEETHI_NAMESPACE) == 0) || (axutil_strcmp(uri, + NEETHI_POLICY_15_NAMESPACE) == 0)) + { + /* Looking at the localname we will call the relevent + * operator function. After that the newly created + * object is wrapped in a neethi_operator and stored in + * the parent's component list */ + + if(axutil_strcmp(local_name, NEETHI_POLICY) == 0) + { + neethi_policy_t *neethi_policy = NULL; + neethi_policy = neethi_engine_get_operator_neethi_policy(env, + child_node, child_element); + if(neethi_policy) + { + operator = neethi_operator_create(env); + neethi_operator_set_value(operator, env, neethi_policy, + OPERATOR_TYPE_POLICY); + neethi_engine_add_policy_component(env, neethi_operator, + operator); + } + else + { + AXIS2_ERROR_SET(env->error, + AXIS2_ERROR_NEETHI_POLICY_CREATION_FAILED_FROM_ELEMENT, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] Policy creation failed from element."); + return AXIS2_FAILURE; + } + } + else if(axutil_strcmp(local_name, NEETHI_ALL) == 0) + { + neethi_all_t *all = NULL; + all + = neethi_engine_get_operator_all(env, child_node, child_element); + if(all) + { + operator = neethi_operator_create(env); + neethi_operator_set_value(operator, env, all, OPERATOR_TYPE_ALL); + neethi_engine_add_policy_component(env, neethi_operator, + operator); + } + else + { + AXIS2_ERROR_SET(env->error, + AXIS2_ERROR_NEETHI_ALL_CREATION_FAILED_FROM_ELEMENT, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] All creation failed from element."); + return AXIS2_FAILURE; + } + } + else if(axutil_strcmp(local_name, NEETHI_EXACTLYONE) == 0) + { + neethi_exactlyone_t *exactlyone = NULL; + exactlyone = neethi_engine_get_operator_exactlyone(env, child_node, + child_element); + if(exactlyone) + { + operator = neethi_operator_create(env); + neethi_operator_set_value(operator, env, exactlyone, + OPERATOR_TYPE_EXACTLYONE); + neethi_engine_add_policy_component(env, neethi_operator, + operator); + } + else + { + AXIS2_ERROR_SET(env->error, + AXIS2_ERROR_NEETHI_EXACTLYONE_CREATION_FAILED_FROM_ELEMENT, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] Exactlyone creation failed from element."); + return AXIS2_FAILURE; + } + } + else if(axutil_strcmp(local_name, NEETHI_REFERENCE) == 0) + { + neethi_reference_t *reference = NULL; + reference = neethi_engine_get_operator_reference(env, child_node, + child_element); + if(reference) + { + operator = neethi_operator_create(env); + neethi_operator_set_value(operator, env, reference, + OPERATOR_TYPE_REFERENCE); + neethi_engine_add_policy_component(env, neethi_operator, + operator); + } + else + { + AXIS2_ERROR_SET(env->error, + AXIS2_ERROR_NEETHI_REFERENCE_CREATION_FAILED_FROM_ELEMENT, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] Reference cretion failed from element."); + return AXIS2_FAILURE; + } + } + } + + else + { + /* This is an assertion in a different domain. Assertion builder + * should be called and that will call the relevent assertion builder + * after looking at the localname and the namespace */ + + neethi_assertion_t *assertion = NULL; + assertion = neethi_assertion_builder_build(env, child_node, + child_element); + if(assertion) + { + operator = neethi_operator_create(env); + neethi_operator_set_value(operator, env, assertion, + OPERATOR_TYPE_ASSERTION); + neethi_engine_add_policy_component(env, neethi_operator, operator); + neethi_assertion_set_node(assertion, env, child_node); + } + else + { + AXIS2_ERROR_SET(env->error, + AXIS2_ERROR_NEETHI_ASSERTION_CREATION_FAILED_FROM_ELEMENT, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] Assertion creation failed from element."); + return AXIS2_FAILURE; + } + } + } + } + } + } + return AXIS2_SUCCESS; + } + else + return AXIS2_FAILURE; +} + +/* After looking at the operator_type this function will + * call the relevent neethi operator's add operator + * function */ + +static axis2_status_t +neethi_engine_add_policy_component( + const axutil_env_t *env, + neethi_operator_t *container_operator, + neethi_operator_t *component) +{ + + neethi_operator_type_t type; + void *value = NULL; + neethi_policy_t *neethi_policy = NULL; + neethi_exactlyone_t *exactlyone = NULL; + neethi_all_t *all = NULL; + neethi_assertion_t *assertion = NULL; + + type = neethi_operator_get_type(container_operator, env); + value = neethi_operator_get_value(container_operator, env); + + if(value) + { + switch(type) + { + case OPERATOR_TYPE_POLICY: + neethi_policy = (neethi_policy_t *)value; + neethi_policy_add_operator(neethi_policy, env, component); + break; + + case OPERATOR_TYPE_ALL: + all = (neethi_all_t *)value; + neethi_all_add_operator(all, env, component); + break; + + case OPERATOR_TYPE_EXACTLYONE: + exactlyone = (neethi_exactlyone_t *)value; + neethi_exactlyone_add_operator(exactlyone, env, component); + break; + + case OPERATOR_TYPE_UNKNOWN: + return AXIS2_FAILURE; + break; + + case OPERATOR_TYPE_ASSERTION: + assertion = (neethi_assertion_t *)value; + neethi_assertion_add_operator(assertion, env, component); + break; + + case OPERATOR_TYPE_REFERENCE: + break; + } + return AXIS2_SUCCESS; + } + else + return AXIS2_FAILURE; +} + +/***************************************/ + +/*This function is only for testing* + *Remove it later*/ +void +check_neethi_policy( + neethi_policy_t *neethi_policy, + const axutil_env_t *env) +{ + axutil_array_list_t *list = NULL; + neethi_operator_t *op = NULL; + neethi_operator_type_t type; + + list = neethi_policy_get_policy_components(neethi_policy, env); + + if(axutil_array_list_size(list, env) > 1) + { + return; + } + op = (neethi_operator_t *)axutil_array_list_get(list, env, 0); + type = neethi_operator_get_type(op, env); + if(type == OPERATOR_TYPE_EXACTLYONE) + { + void *value = neethi_operator_get_value(op, env); + if(value) + { + return; + } + } + else + { + return; + } +} + +/************************************************/ +/* + + Following function will normalize accorading to the + WS-Policy spec. Normalize policy is in the following + format. + + + + ( ( )* )* + + + + */ + +AXIS2_EXTERN neethi_policy_t *AXIS2_CALL +neethi_engine_get_normalize( + const axutil_env_t *env, + axis2_bool_t deep, + neethi_policy_t *neethi_policy) +{ + /* In the first call we pass the registry as null.*/ + + return neethi_engine_normalize(env, neethi_policy, NULL, deep); +} + +AXIS2_EXTERN neethi_policy_t *AXIS2_CALL +neethi_engine_normalize( + const axutil_env_t *env, + neethi_policy_t *neethi_policy, + neethi_registry_t *registry, + axis2_bool_t deep) +{ + neethi_policy_t *resultant_neethi_policy = NULL; + neethi_operator_t *operator = NULL; + neethi_operator_t *component = NULL; + neethi_exactlyone_t *exactlyone = NULL; + axis2_char_t *policy_name = NULL; + axis2_char_t *policy_id = NULL; + + /* Normalize policy will be contained in the new policy + * created below */ + + resultant_neethi_policy = neethi_policy_create(env); + if(!resultant_neethi_policy) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + + policy_name = neethi_policy_get_name(neethi_policy, env); + if(policy_name) + { + neethi_policy_set_name(resultant_neethi_policy, env, policy_name); + } + policy_id = neethi_policy_get_id(neethi_policy, env); + if(policy_id) + { + neethi_policy_set_id(resultant_neethi_policy, env, policy_id); + } + + operator = neethi_operator_create(env); + if(!operator) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + + neethi_operator_set_value(operator, env, neethi_policy, OPERATOR_TYPE_POLICY); + + /* When we call the normalization it should always return an exactlyone as the + * out put. */ + + exactlyone = neethi_engine_normalize_operator(operator, registry, deep, env); + + /* We are frreing the operator used to wrap the object */ + + neethi_operator_set_value_null(operator, env); + neethi_operator_free(operator, env); + operator = NULL; + + /* This exactlyone is set as the first component of the + * normalized policy */ + + if(exactlyone) + { + component = neethi_operator_create(env); + neethi_operator_set_value(component, env, exactlyone, OPERATOR_TYPE_EXACTLYONE); + neethi_policy_add_operator(resultant_neethi_policy, env, component); + + return resultant_neethi_policy; + } + else + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NEETHI_NORMALIZATION_FAILED, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[neethi] Normalization failed."); + return NULL; + } +} + +AXIS2_EXTERN neethi_policy_t *AXIS2_CALL +neethi_engine_merge( + const axutil_env_t *env, + neethi_policy_t *neethi_policy1, + neethi_policy_t *neethi_policy2) +{ + + neethi_exactlyone_t *exactlyone1 = NULL; + neethi_exactlyone_t *exactlyone2 = NULL; + neethi_exactlyone_t *exactlyone = NULL; + neethi_policy_t *neethi_policy = NULL; + neethi_operator_t *component = NULL; + + exactlyone1 = neethi_policy_get_exactlyone(neethi_policy1, env); + exactlyone2 = neethi_policy_get_exactlyone(neethi_policy2, env); + + if(!exactlyone1 || !exactlyone2) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NEETHI_WRONG_INPUT_FOR_MERGE, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[neethi] Wrong input for merge."); + return NULL; + } + exactlyone = neethi_engine_get_cross_product(exactlyone1, exactlyone2, env); + if(exactlyone) + { + neethi_policy = neethi_policy_create(env); + component = neethi_operator_create(env); + if(!neethi_policy || !component) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + neethi_operator_set_value(component, env, exactlyone, OPERATOR_TYPE_EXACTLYONE); + neethi_policy_add_operator(neethi_policy, env, component); + return neethi_policy; + } + else + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NEETHI_CROSS_PRODUCT_FAILED, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[neethi] Cross product failed."); + return NULL; + } +} + +static axis2_bool_t +neethi_engine_operator_is_empty( + neethi_operator_t *operator, + const axutil_env_t *env) +{ + + neethi_operator_type_t type; + void *value = NULL; + neethi_policy_t *neethi_policy = NULL; + neethi_exactlyone_t *exactlyone = NULL; + neethi_all_t *all = NULL; + neethi_assertion_t *assertion = NULL; + + type = neethi_operator_get_type(operator, env); + value = neethi_operator_get_value(operator, env); + + if(value) + { + switch(type) + { + case OPERATOR_TYPE_POLICY: + neethi_policy = (neethi_policy_t *)value; + return neethi_policy_is_empty(neethi_policy, env); + break; + + case OPERATOR_TYPE_ALL: + all = (neethi_all_t *)value; + return neethi_all_is_empty(all, env); + break; + + case OPERATOR_TYPE_EXACTLYONE: + exactlyone = (neethi_exactlyone_t *)value; + return neethi_exactlyone_is_empty(exactlyone, env); + break; + + case OPERATOR_TYPE_UNKNOWN: + return AXIS2_FALSE; + break; + + case OPERATOR_TYPE_ASSERTION: + assertion = (neethi_assertion_t *)value; + return neethi_assertion_is_empty(assertion, env); + break; + + case OPERATOR_TYPE_REFERENCE: + break; + + } + return AXIS2_FALSE; + } + else + return AXIS2_FALSE; +} + +static axutil_array_list_t * +neethi_engine_operator_get_components( + neethi_operator_t *operator, + const axutil_env_t *env) +{ + + neethi_operator_type_t type; + void *value = NULL; + neethi_policy_t *neethi_policy = NULL; + neethi_exactlyone_t *exactlyone = NULL; + neethi_all_t *all = NULL; + neethi_assertion_t *assertion = NULL; + + type = neethi_operator_get_type(operator, env); + value = neethi_operator_get_value(operator, env); + + if(value) + { + switch(type) + { + case OPERATOR_TYPE_POLICY: + neethi_policy = (neethi_policy_t *)value; + return neethi_policy_get_policy_components(neethi_policy, env); + break; + + case OPERATOR_TYPE_ALL: + all = (neethi_all_t *)value; + return neethi_all_get_policy_components(all, env); + break; + + case OPERATOR_TYPE_EXACTLYONE: + exactlyone = (neethi_exactlyone_t *)value; + return neethi_exactlyone_get_policy_components(exactlyone, env); + break; + + case OPERATOR_TYPE_UNKNOWN: + return NULL; + break; + + case OPERATOR_TYPE_ASSERTION: + assertion = (neethi_assertion_t *)value; + return neethi_assertion_get_policy_components(assertion, env); + break; + + case OPERATOR_TYPE_REFERENCE: + break; + } + } + + return NULL; +} + +static neethi_exactlyone_t * +neethi_engine_normalize_operator( + neethi_operator_t *operator, + neethi_registry_t *registry, + axis2_bool_t deep, + const axutil_env_t *env) +{ + axutil_array_list_t *child_component_list = NULL; + neethi_operator_t *child_component = NULL; + axutil_array_list_t *arraylist = NULL; + int i = 0; + + neethi_operator_type_t type = neethi_operator_get_type(operator, env); + + if(neethi_engine_operator_is_empty(operator, env)) + { + /* If this is an empty operator we just add + * an exactlyone and all */ + + neethi_exactlyone_t *exactlyone = NULL; + exactlyone = neethi_exactlyone_create(env); + if(!exactlyone) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + if(type != OPERATOR_TYPE_EXACTLYONE) + { + neethi_all_t *all = NULL; + neethi_operator_t *component = NULL; + all = neethi_all_create(env); + component = neethi_operator_create(env); + if(!all || !component) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + neethi_operator_set_value(component, env, all, OPERATOR_TYPE_ALL); + neethi_exactlyone_add_operator(exactlyone, env, component); + } + return exactlyone; + } + + child_component_list = axutil_array_list_create(env, 0); + arraylist = neethi_engine_operator_get_components(operator, env); + + /* Here we are recursively normalize each and every component */ + + for(i = 0; i < axutil_array_list_size(arraylist, env); i++) + { + neethi_operator_type_t component_type; + child_component = (neethi_operator_t *)axutil_array_list_get(arraylist, env, i); + component_type = neethi_operator_get_type(child_component, env); + + if(component_type == OPERATOR_TYPE_ASSERTION) + { + /*Assertion normalization part comes here */ + if(deep) + { + return NULL; + } + else + { + neethi_exactlyone_t *exactlyone = NULL; + neethi_all_t *all = NULL; + neethi_operator_t *op = NULL; + + exactlyone = neethi_exactlyone_create(env); + all = neethi_all_create(env); + op = neethi_operator_create(env); + + if(!all || !op || !exactlyone) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + + /* We wrap everything inside an exactlyone */ + + neethi_all_add_operator(all, env, child_component); + neethi_operator_set_value(op, env, all, OPERATOR_TYPE_ALL); + neethi_exactlyone_add_operator(exactlyone, env, op); + axutil_array_list_add(child_component_list, env, exactlyone); + } + } + else if(component_type == OPERATOR_TYPE_POLICY) + { + neethi_policy_t *neethi_policy = NULL; + neethi_all_t *all = NULL; + axutil_array_list_t *children = NULL; + neethi_operator_t *to_normalize = NULL; + neethi_exactlyone_t *exactlyone = NULL; + + all = neethi_all_create(env); + if(!all) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + neethi_policy = (neethi_policy_t *)neethi_operator_get_value(child_component, env); + if(neethi_policy) + { + children = neethi_policy_get_policy_components(neethi_policy, env); + if(children) + { + neethi_all_add_policy_components(all, children, env); + to_normalize = neethi_operator_create(env); + if(!to_normalize) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + neethi_operator_set_value(to_normalize, env, all, OPERATOR_TYPE_ALL); + exactlyone + = neethi_engine_normalize_operator(to_normalize, registry, deep, env); + if(exactlyone) + { + axutil_array_list_add(child_component_list, env, exactlyone); + } + } + else + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NEETHI_NO_CHILDREN_POLICY_COMPONENTS, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] No children policy components"); + return NULL; + } + } + } + + else if(component_type == OPERATOR_TYPE_REFERENCE) + { + + /* If the operator is a policy reference we will + * extract the relevent policy from the uri and + * normalize as we are doing for a neethi_policy + * object */ + + neethi_reference_t *policy_ref = NULL; + axis2_char_t *uri = NULL; + neethi_policy_t *policy = NULL; + neethi_all_t *all = NULL; + axutil_array_list_t *children = NULL; + neethi_operator_t *to_normalize = NULL; + neethi_exactlyone_t *exactlyone = NULL; + + policy_ref = (neethi_reference_t *)neethi_operator_get_value(child_component, env); + uri = neethi_reference_get_uri(policy_ref, env); + if(!uri) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NEETHI_URI_NOT_SPECIFIED, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[neethi] Uri not specified"); + return NULL; + } + + if(!registry) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] Cannot resolve the reference.Registry Not provided"); + return NULL; + } + + policy = neethi_registry_lookup(registry, env, uri); + if(!policy) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NEETHI_NO_ENTRY_FOR_THE_GIVEN_URI, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[neethi] No entry for the given uri"); + return NULL; + } + neethi_operator_set_value(child_component, env, policy, OPERATOR_TYPE_POLICY); + + all = neethi_all_create(env); + if(!all) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + + policy = (neethi_policy_t *)neethi_operator_get_value(child_component, env); + if(policy) + { + children = neethi_policy_get_policy_components(policy, env); + if(children) + { + neethi_all_add_policy_components(all, children, env); + to_normalize = neethi_operator_create(env); + if(!to_normalize) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + neethi_operator_set_value(to_normalize, env, all, OPERATOR_TYPE_ALL); + exactlyone + = neethi_engine_normalize_operator(to_normalize, registry, deep, env); + if(exactlyone) + { + axutil_array_list_add(child_component_list, env, exactlyone); + } + } + else + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NEETHI_NO_CHILDREN_POLICY_COMPONENTS, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] No children policy components"); + return NULL; + } + } + } + else + { + neethi_exactlyone_t *exactlyone = NULL; + exactlyone = neethi_engine_normalize_operator(child_component, registry, deep, env); + if(exactlyone) + { + axutil_array_list_add(child_component_list, env, exactlyone); + } + } + } + + /* So at this point we have set of exactlyones in the array_list, So we will + * compute one exactlyone out of those after the following call */ + + return neethi_engine_compute_resultant_component(child_component_list, type, env); +} + +/* This function will return a single exactlyone from all the + * components in the list */ + +static neethi_exactlyone_t * +neethi_engine_compute_resultant_component( + axutil_array_list_t * normalized_inner_components, + neethi_operator_type_t type, + const axutil_env_t * env) +{ + neethi_exactlyone_t *exactlyone = NULL; + int size = 0; + + if(normalized_inner_components) + { + size = axutil_array_list_size(normalized_inner_components, env); + } + + if(type == OPERATOR_TYPE_EXACTLYONE) + { + /* If the operator is an exactlyone then we get all the components + * in the exatlyones and add them to a newly created exactlyone */ + + int i = 0; + neethi_exactlyone_t *inner_exactlyone = NULL; + exactlyone = neethi_exactlyone_create(env); + + for(i = 0; i < size; i++) + { + inner_exactlyone = (neethi_exactlyone_t *)axutil_array_list_get( + normalized_inner_components, env, i); + if(inner_exactlyone) + { + neethi_exactlyone_add_policy_components(exactlyone, + neethi_exactlyone_get_policy_components(inner_exactlyone, env), env); + } + else + { + AXIS2_ERROR_SET(env->error, + AXIS2_ERROR_NEETHI_EXACTLYONE_NOT_FOUND_IN_NORMALIZED_POLICY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] Exactlyone not found in normalized policy"); + return NULL; + } + } + } + else if(type == OPERATOR_TYPE_POLICY || type == OPERATOR_TYPE_ALL) + { + /* Here arry_list contains one exactlyone means this operator + * is already normalized. So we will return that. Otherwise we + * will get the crossproduct. */ + + if(size > 1) + { + /* Get the first one and do the cross product with other + * components */ + + int i = 0; + exactlyone = (neethi_exactlyone_t *)axutil_array_list_get(normalized_inner_components, + env, 0); + if(!exactlyone) + { + AXIS2_ERROR_SET(env->error, + AXIS2_ERROR_NEETHI_EXACTLYONE_NOT_FOUND_IN_NORMALIZED_POLICY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] Exactlyone not found in normalized policy"); + return NULL; + } + if(!neethi_exactlyone_is_empty(exactlyone, env)) + { + neethi_exactlyone_t *current_exactlyone = NULL; + i = 1; + for(i = 1; i < size; i++) + { + current_exactlyone = (neethi_exactlyone_t *)axutil_array_list_get( + normalized_inner_components, env, i); + if(!current_exactlyone) + { + AXIS2_ERROR_SET(env->error, + AXIS2_ERROR_NEETHI_EXACTLYONE_NOT_FOUND_IN_NORMALIZED_POLICY, + AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] Exactlyone not found in normalized policy"); + return NULL; + } + if(neethi_exactlyone_is_empty(current_exactlyone, env)) + { + exactlyone = current_exactlyone; + break; + } + else + { + neethi_exactlyone_t *temp = NULL; + neethi_exactlyone_t *temp1 = NULL; + temp = exactlyone; + temp1 = current_exactlyone; + exactlyone = neethi_engine_get_cross_product(exactlyone, + current_exactlyone, env); + neethi_exactlyone_free(temp, env); + neethi_exactlyone_free(temp1, env); + temp = NULL; + temp1 = NULL; + } + } + } + else + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NEETHI_EXACTLYONE_IS_EMPTY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[neethi] Exactlyone is Empty"); + return NULL; + } + } + else + { + exactlyone = (neethi_exactlyone_t *)axutil_array_list_get(normalized_inner_components, + env, 0); + } + } + axutil_array_list_free(normalized_inner_components, env); + normalized_inner_components = NULL; + + return exactlyone; +} + +/* The cross product will return all the different combinations + * of alternatives and put them into one exactlyone */ + +static neethi_exactlyone_t * +neethi_engine_get_cross_product( + neethi_exactlyone_t *exactlyone1, + neethi_exactlyone_t *exactlyone2, + const axutil_env_t *env) +{ + neethi_exactlyone_t *cross_product = NULL; + neethi_all_t *cross_product_all = NULL; + neethi_all_t *current_all1 = NULL; + neethi_all_t *current_all2 = NULL; + axutil_array_list_t *array_list1 = NULL; + axutil_array_list_t *array_list2 = NULL; + neethi_operator_t *component = NULL; + int i = 0; + int j = 0; + + cross_product = neethi_exactlyone_create(env); + if(!cross_product) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + array_list1 = neethi_exactlyone_get_policy_components(exactlyone1, env); + array_list2 = neethi_exactlyone_get_policy_components(exactlyone2, env); + + if(!array_list1 || !array_list2) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NEETHI_NO_CHILDREN_POLICY_COMPONENTS, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[neethi] No children policy components"); + return NULL; + } + + for(i = 0; i < axutil_array_list_size(array_list1, env); i++) + { + current_all1 = (neethi_all_t *)neethi_operator_get_value( + (neethi_operator_t *)axutil_array_list_get(array_list1, env, i), env); + + if(!current_all1) + { + AXIS2_ERROR_SET(env->error, + AXIS2_ERROR_NEETHI_ALL_NOT_FOUND_WHILE_GETTING_CROSS_PRODUCT, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] All not found while getting cross product"); + return NULL; + } + + for(j = 0; j < axutil_array_list_size(array_list2, env); j++) + { + current_all2 = (neethi_all_t *)neethi_operator_get_value( + (neethi_operator_t *)axutil_array_list_get(array_list2, env, j), env); + + if(!current_all2) + { + AXIS2_ERROR_SET(env->error, + AXIS2_ERROR_NEETHI_ALL_NOT_FOUND_WHILE_GETTING_CROSS_PRODUCT, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[neethi] All not found while getting cross product"); + return NULL; + } + + cross_product_all = neethi_all_create(env); + if(!cross_product_all) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + neethi_all_add_policy_components(cross_product_all, neethi_all_get_policy_components( + current_all1, env), env); + + neethi_all_add_policy_components(cross_product_all, neethi_all_get_policy_components( + current_all2, env), env); + + component = neethi_operator_create(env); + if(!component) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory"); + return NULL; + } + neethi_operator_set_value(component, env, cross_product_all, OPERATOR_TYPE_ALL); + neethi_exactlyone_add_operator(cross_product, env, component); + } + } + return cross_product; +} + +/*These functions are for serializing a policy object*/ + +AXIS2_EXTERN axiom_node_t *AXIS2_CALL +neethi_engine_serialize( + neethi_policy_t *policy, + const axutil_env_t *env) +{ + + return neethi_policy_serialize(policy, NULL, env); +} + +static void +neethi_engine_clear_element_attributes( + axutil_hash_t *attr_hash, + const axutil_env_t *env) +{ + axutil_hash_index_t *hi = NULL; + + for(hi = axutil_hash_first(attr_hash, env); hi; hi = axutil_hash_next(env, hi)) + { + void *val = NULL; + axutil_hash_this(hi, NULL, NULL, &val); + if(val) + { + axiom_attribute_free((axiom_attribute_t *)val, env); + val = NULL; + } + } + axutil_hash_free(attr_hash, env); + attr_hash = NULL; + + return; +} -- cgit v1.1-32-gdbae