/* * 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; }