blob: b925cead76040f852ab798592c6a50a38525d9b1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <neethi_engine.h>
#include <neethi_assertion_builder.h>
#include <axiom_attribute.h>
/*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.
<wsp:Policy>
<wsp:ExactlyOne>
( <wsp:All> ( <Assertion …> … </Assertion> )* </wsp:All> )*
</wsp:ExactlyOne>
</wsp:Policy>
*/
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;
}