AXIS2_EXTERN axis2_status_t AXIS2_CALL
rampart_issued_supporting_token_build(rampart_context_t *rampart_context, const axutil_env_t *env, axiom_node_t *sec_node,
                                      axutil_array_list_t *sign_parts)
{
	rp_property_t *token = NULL;
    issued_token_callback_func issued_func = NULL;
    rampart_issued_token_t *issued_token = NULL;
    void *tok_val = NULL;

	token = rampart_context_get_supporting_token(rampart_context, env, RP_PROPERTY_ISSUED_TOKEN);
	if (!token)
	{
		AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                            "[rampart][issued] Issued token not specified. ERROR");
        return AXIS2_FAILURE;
	}
	issued_func = rampart_context_get_issued_token_aquire_function(rampart_context, env);

    if (!issued_func)
    {
	    AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                            "[rampart][issued] Issued token call back function not set. ERROR");
        return AXIS2_FAILURE;
    }
    issued_token = issued_func(env, token, rampart_context);

    if (!issued_token)
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                            "[rampart][issued] Issued token call back returned NULL. ERROR");
        return AXIS2_FAILURE;
    }
    tok_val = rampart_issued_token_get_token(issued_token, env);
    if (!tok_val)
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                            "[rampart][issued] Issued token call back returned NULL token value. ERROR");
        return AXIS2_FAILURE;
    }

    if (rampart_issued_token_get_token_type(issued_token, env) == RP_PROPERTY_SAML_TOKEN)
    {
        rampart_context_add_saml_token(rampart_context, env, tok_val);        
        if (rampart_saml_supporting_token_build(env, rampart_context, sec_node, sign_parts))
        {
            return AXIS2_SUCCESS;
        }
    }
    AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                        "[rampart][issued] Not supported token type. ERROR");    
	return AXIS2_FAILURE;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
rampart_shb_build_message(
    const axutil_env_t *env,
    axis2_msg_ctx_t *msg_ctx,
    rampart_context_t *rampart_context,
    axiom_soap_envelope_t *soap_envelope)
{
    axis2_status_t status = AXIS2_SUCCESS;
    axiom_soap_header_t *soap_header = NULL;
    axiom_node_t *soap_header_node = NULL;
    axiom_element_t *soap_header_ele = NULL;
    axiom_soap_header_block_t *sec_header_block = NULL;
    axiom_namespace_t *sec_ns_obj = NULL;
    axiom_node_t *sec_node =  NULL;
    axiom_element_t *sec_ele = NULL;
    axis2_bool_t server_side = AXIS2_FALSE;
	/* 
	 * sign parts list. Moved this up the building process. This was originally 
	 * in the rampart_sig_sign_message 
	 */ 
    axutil_array_list_t *sign_parts_list = NULL;
    AXIS2_ENV_CHECK(env,AXIS2_FAILURE);
    soap_header  = axiom_soap_envelope_get_header(soap_envelope, env);
    soap_header_node = axiom_soap_header_get_base_node(soap_header, env);
    soap_header_ele = (axiom_element_t *)axiom_node_get_data_element(
                          soap_header_node, env);


    sec_ns_obj =  axiom_namespace_create(env, RAMPART_WSSE_XMLNS,
                                         RAMPART_WSSE);
    sec_header_block = axiom_soap_header_add_header_block(soap_header,
                       env, RAMPART_SECURITY, sec_ns_obj); /* sec_ns_obj is cloned there */
    server_side = axis2_msg_ctx_get_server_side(msg_ctx, env);
    if(!sec_header_block)
    {
        AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[rampart][shb] Security header block is NULL");
		axiom_namespace_free(sec_ns_obj, env);
        return AXIS2_SUCCESS;
    }

    axiom_soap_header_block_set_must_understand_with_bool(sec_header_block,
            env, AXIS2_TRUE);

    sec_node = axiom_soap_header_block_get_base_node(sec_header_block, env);
    sec_ele = (axiom_element_t *)
              axiom_node_get_data_element(sec_node, env);

    sign_parts_list = axutil_array_list_create(env, 4);
    /*Timestamp Inclusion*/
    if(rampart_context_is_include_timestamp(rampart_context,env))
    {
        int ttl = -1;
        axis2_bool_t need_millisecond = AXIS2_TRUE;

        AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[rampart][shb] Building Timestamp Token");
        AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[rampart][shb] Using default timeToLive value %d",
                       RAMPART_TIMESTAMP_TOKEN_DEFAULT_TIME_TO_LIVE);
        ttl = rampart_context_get_ttl(rampart_context,env);
        need_millisecond = rampart_context_get_need_millisecond_precision(rampart_context, env);

        status = rampart_timestamp_token_build(env, sec_node, ttl, need_millisecond);
        if (status == AXIS2_FAILURE)
        {
            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                            "[rampart][shb] Timestamp Token build failed. ERROR");
			axiom_namespace_free(sec_ns_obj, env);
            return AXIS2_FAILURE;
        }
    }

    /*Check whether we need username token*/
    /*User name tokens includes in messages sent from client to server*/
    if(!axis2_msg_ctx_get_server_side(msg_ctx,env))
    {
        if(rampart_context_is_include_username_token(rampart_context,env))
        {

            /*Now we are passing rampart_context here so inside this method
            relevant parameters are extracted. */

            AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[rampart][shb] Building UsernameToken");
            status = rampart_username_token_build(
                        env,
                        rampart_context,
                        sec_node,
                        sec_ns_obj);
            if (status == AXIS2_FAILURE)
            {
                AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                                "[rampart][shb] UsernameToken build failed. ERROR");
				axiom_namespace_free(sec_ns_obj, env);
                return AXIS2_FAILURE;
            }
        }
    }

    /*Custom tokens are included if its available in the rampart context*/
    if(!axis2_msg_ctx_get_server_side(msg_ctx,env))
    {
        axutil_array_list_t *token_list = NULL;

        token_list = rampart_context_get_custom_tokens(rampart_context, env);
        if(token_list){
            int size = 0, i = 0;
            size = axutil_array_list_size(token_list, env);
            for (i = 0; i < size; i++){
                axiom_node_t *token_node = NULL;
                token_node = (axiom_node_t*)axutil_array_list_get(token_list, env, i);
                if(token_node){
                    axis2_status_t status = AXIS2_FAILURE;
                    status = axiom_node_add_child(sec_node, env, token_node); 
                    if(status != AXIS2_SUCCESS){
                        return AXIS2_FAILURE;
                    }
                }
            }
        }
    }

    if (rampart_context_is_include_supporting_token(rampart_context, env, server_side, AXIS2_FALSE, RP_PROPERTY_SAML_TOKEN))
    {        
        status = rampart_saml_supporting_token_build(env, rampart_context, sec_node, sign_parts_list);    
        if (status == AXIS2_FAILURE)
        {
            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                            "[rampart][shb] SAML Supporting token build failed. ERROR");
            axutil_array_list_free(sign_parts_list, env);
			axiom_namespace_free(sec_ns_obj, env);
            return AXIS2_FAILURE;
        }
    }

	if (rampart_context_is_include_supporting_token(rampart_context, env, server_side, AXIS2_FALSE, RP_PROPERTY_ISSUED_TOKEN))
	{
		status = rampart_issued_supporting_token_build(rampart_context, env, sec_node, sign_parts_list);					
        if (status == AXIS2_FAILURE)
        {
            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                            "[rampart][shb] Issued supporting token build failed. ERROR");
            axutil_array_list_free(sign_parts_list, env);
			axiom_namespace_free(sec_ns_obj, env);
            return AXIS2_FAILURE;
        }
	}

    /*Signature Confirmation support. Only in the server side*/
    if(axis2_msg_ctx_get_server_side(msg_ctx,env)){
        axis2_bool_t sign_conf_reqd = AXIS2_FALSE;
        /*Sign_conf_reqd <- Get from context <- policy*/
        sign_conf_reqd = rampart_context_is_sig_confirmation_reqd(rampart_context, env);
        if(sign_conf_reqd){
            status = rampart_sig_confirm_signature(env, msg_ctx, rampart_context, sec_node);
        }
    }


    /*check the binding*/
    if((rampart_context_get_binding_type(rampart_context,env)) == RP_PROPERTY_ASYMMETRIC_BINDING)
    {
        axis2_status_t status = AXIS2_FAILURE;

        AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[rampart][shb] Asymmetric Binding. ");
        status = rampart_shb_do_asymmetric_binding(env, msg_ctx, rampart_context, soap_envelope, sec_node, sec_ns_obj, sign_parts_list);
		axiom_namespace_free(sec_ns_obj, env);
        if(AXIS2_FAILURE == status){
            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[rampart][shb] Asymmetric Binding failed");
            if(axis2_msg_ctx_get_server_side(msg_ctx,env)){
                AXIS2_ERROR_SET(env->error, RAMPART_ERROR_INVALID_SECURITY , AXIS2_FAILURE);
                AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,  "[rampart][shb] %s", AXIS2_ERROR_GET_MESSAGE(env->error));
                rampart_create_fault_envelope(env, RAMPART_FAULT_INVALID_SECURITY,
                                  " Asymmetric Binding failed. Check configurations ", RAMPART_FAULT_IN_POLICY, msg_ctx);
            }
            axutil_array_list_free(sign_parts_list, env);
            return AXIS2_FAILURE;
        }else{
            axutil_array_list_free(sign_parts_list, env);
            return AXIS2_SUCCESS;
        }

    }
    else if((rampart_context_get_binding_type(rampart_context,env)) == RP_PROPERTY_SYMMETRIC_BINDING)
    {
        axis2_status_t status = AXIS2_FAILURE;

        /*Do Symmetric_binding specific things*/
        AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[rampart][shb] Symmetric Binding. ");
        status = rampart_shb_do_symmetric_binding(env, msg_ctx, rampart_context, soap_envelope, sec_node, sec_ns_obj, sign_parts_list);
		axiom_namespace_free(sec_ns_obj, env);
        if(AXIS2_FAILURE == status){
            AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[rampart][shb] Symmetric Binding failed");
            if(axis2_msg_ctx_get_server_side(msg_ctx,env)){
                AXIS2_ERROR_SET(env->error, RAMPART_ERROR_INVALID_SECURITY, AXIS2_FAILURE);
                rampart_create_fault_envelope(env, RAMPART_FAULT_INVALID_SECURITY,
                                  " Symmetric Binding failed. Check configurations ", RAMPART_FAULT_IN_POLICY, msg_ctx);
            }
            axutil_array_list_free(sign_parts_list, env);
            return AXIS2_FAILURE;
        }else{
            axutil_array_list_free(sign_parts_list, env);
            return AXIS2_SUCCESS;
        }
    }
    else if((rampart_context_get_binding_type(rampart_context,env)) == RP_PROPERTY_TRANSPORT_BINDING)
    {
        AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[rampart][shb] Using transport binding");
		axiom_namespace_free(sec_ns_obj, env);
        axutil_array_list_free(sign_parts_list, env);
        return AXIS2_SUCCESS;
    }else{
        axutil_array_list_free(sign_parts_list, env);
		axiom_namespace_free(sec_ns_obj, env);
        return AXIS2_FAILURE;
    }
}