blob: f1d3c2b12d4300bad11bb85afe00dab4fdd2afbf [file] [log] [blame]
/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* Licensed 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 <savan_publisher.h>
#include <axutil_log.h>
#include <axutil_hash.h>
#include <axutil_property.h>
#include <axutil_types.h>
#include <axutil_file_handler.h>
#include <platforms/axutil_platform_auto_sense.h>
#include <axis2_svc_client.h>
#include <axis2_conf.h>
#include <axis2_options.h>
#include <axutil_array_list.h>
#include <savan_constants.h>
#include <savan_util.h>
#include <savan_subscriber.h>
#include <savan_subs_mgr.h>
#include <savan_error.h>
#include <axiom_soap.h>
#include <axiom_soap_const.h>
#include <axiom_soap_envelope.h>
#include <axiom_element.h>
#include <axiom_node.h>
/**
*
*/
/**
* @brief Savan Default Publisher Struct Impl
* Savan Default Publisher
*/
typedef struct savan_default_publisher
{
savan_publisher_t publishermod;
axis2_conf_t *conf;
} savan_default_publisher_t;
#define SAVAN_INTF_TO_IMPL(publishermod) ((savan_default_publisher_t *) publishermod)
AXIS2_EXTERN void AXIS2_CALL
savan_default_publisher_free(
savan_publisher_t *publishermod,
const axutil_env_t *env);
AXIS2_EXTERN void AXIS2_CALL
savan_default_publisher_publish(
savan_publisher_t *publishermod,
const axutil_env_t *env,
void *msg_ctx,
savan_subs_mgr_t *subs_mgr);
static axis2_status_t
savan_default_publisher_publish_to_subscriber(
savan_publisher_t *publishermod,
const axutil_env_t *env,
axis2_svc_client_t *svc_client,
savan_subscriber_t *subscriber,
savan_filter_mod_t *filtermod,
axiom_node_t *payload);
static const savan_publisher_ops_t savan_publisher_ops =
{
savan_default_publisher_free,
savan_default_publisher_publish
};
AXIS2_EXTERN savan_publisher_t * AXIS2_CALL
savan_publisher_create_with_conf(
const axutil_env_t *env,
axis2_conf_t *conf)
{
savan_default_publisher_t *publishermodimpl = NULL;
publishermodimpl = AXIS2_MALLOC(env->allocator, sizeof(savan_default_publisher_t));
if (!publishermodimpl)
{
AXIS2_HANDLE_ERROR(env, SAVAN_ERROR_FILTER_CREATION_FAILED, AXIS2_FAILURE);
return NULL;
}
memset ((void *) publishermodimpl, 0, sizeof(savan_default_publisher_t));
publishermodimpl->conf = conf;
publishermodimpl->publishermod.ops = &savan_publisher_ops;
return (savan_publisher_t *) publishermodimpl;
}
AXIS2_EXTERN savan_publisher_t * AXIS2_CALL
savan_publisher_create(
const axutil_env_t *env)
{
return NULL;
}
AXIS2_EXTERN void AXIS2_CALL
savan_default_publisher_free(
savan_publisher_t *publishermod,
const axutil_env_t *env)
{
savan_default_publisher_t *publishermodimpl = NULL;
publishermodimpl = SAVAN_INTF_TO_IMPL(publishermod);
AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "[savan] Entry:savan_default_publisher_free");
publishermodimpl->conf = NULL;
if(publishermodimpl)
{
AXIS2_FREE(env->allocator, publishermodimpl);
publishermodimpl = NULL;
}
AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "[savan] Exit:savan_default_publisher_free");
}
AXIS2_EXTERN void AXIS2_CALL
savan_default_publisher_publish(
savan_publisher_t *publishermod,
const axutil_env_t *env,
void *msg_ctx,
savan_subs_mgr_t *subs_mgr)
{
savan_default_publisher_t *publishermodimpl = NULL;
axutil_array_list_t *subs_store = NULL;
int i = 0, size = 0;
savan_filter_mod_t *filtermod = NULL;
const axis2_char_t *path = NULL;
axiom_node_t *payload = NULL;
axiom_soap_envelope_t *envelope = NULL;
axiom_soap_body_t *body = NULL;
axiom_node_t *body_node = NULL;
const axis2_char_t *filter = NULL;
axis2_conf_ctx_t *conf_ctx = NULL;
axutil_property_t *topic_property = NULL;
publishermodimpl = SAVAN_INTF_TO_IMPL(publishermod);
AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "[savan] Entry:savan_default_publisher_publish");
topic_property = axis2_msg_ctx_get_property(msg_ctx, env, ELEM_NAME_TOPIC);
if(topic_property)
{
filter = axutil_property_get_value(topic_property, env);
}
axutil_allocator_switch_to_global_pool(env->allocator);
if(subs_mgr)
{
subs_store = savan_subs_mgr_retrieve_all_subscribers(subs_mgr, env, filter);
}
if (!subs_store)
{
axutil_allocator_switch_to_local_pool(env->allocator);
AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, "[savan] Subscriber store is NULL");
}
conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env);
path = axis2_conf_ctx_get_root_dir(conf_ctx, env);
if(!path)
{
path = AXIS2_GETENV("AXIS2C_HOME");
}
envelope = axis2_msg_ctx_get_soap_envelope((axis2_msg_ctx_t *) msg_ctx, env);
if (!envelope)
{
axutil_allocator_switch_to_local_pool(env->allocator);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[savan] Failed to extract the soap envelop");
}
body = axiom_soap_envelope_get_body(envelope, env);
if (!body)
{
axutil_allocator_switch_to_local_pool(env->allocator);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[savan] Failed to extract the soap body");
}
body_node = axiom_soap_body_get_base_node(body, env);
payload = axiom_node_get_first_child(body_node, env);
size = axutil_array_list_size(subs_store, env);
for(i = 0; i < size; i++)
{
axis2_svc_client_t *svc_client = NULL;
savan_subscriber_t *sub = NULL;
sub = (savan_subscriber_t *)axutil_array_list_get(subs_store, env, i);
if (sub)
{
axis2_char_t *id = savan_subscriber_get_id(sub, env);
AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[savan] Publishing to:%s", id);
svc_client = axis2_svc_client_create(env, path);
filtermod = savan_util_get_filter_module(env, publishermodimpl->conf);
/* Ideally publishing to each subscriber should happen within a thread for each
* subscriber. However until Axis2/C provide a good thread pool to handle
* such tasks I use this sequential publishing to subscribers.
*/
if(!savan_default_publisher_publish_to_subscriber(publishermod, env, svc_client, sub,
filtermod, payload))
{
axis2_endpoint_ref_t *notifyto = savan_subscriber_get_notify_to(sub, env);
const axis2_char_t *address = NULL;
if(notifyto)
{
address = axis2_endpoint_ref_get_address(notifyto, env);
}
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"Publishing to the Data Sink:%s proviced by subscriber:%s Failed. Check "\
"whether the Data Sink url is correct", address, id);
}
if(svc_client)
{
axis2_svc_client_free(svc_client, env);
}
}
}
axutil_allocator_switch_to_local_pool(env->allocator);
AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "[savan] Exit:savan_default_publisher_publish");
}
static axis2_status_t
savan_default_publisher_publish_to_subscriber(
savan_publisher_t *publishermod,
const axutil_env_t *env,
axis2_svc_client_t *svc_client,
savan_subscriber_t *subscriber,
savan_filter_mod_t *filtermod,
axiom_node_t *payload)
{
axis2_options_t *options = NULL;
axis2_status_t status = AXIS2_SUCCESS;
axis2_endpoint_ref_t *to = NULL;
const axis2_char_t *address = NULL;
axis2_bool_t filter_apply = AXIS2_TRUE;
axis2_endpoint_ref_t *notifyto = NULL;
AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "[savan] Entry:savan_default_publisher_publish_to_subscriber");
options = (axis2_options_t *) axis2_svc_client_get_options(svc_client, env);
if(!options)
{
options = axis2_options_create(env);
axis2_svc_client_set_options(svc_client, env, options);
}
axis2_options_set_action(options, env, "http://ws.apache.org/ws/2007/05/eventing-extended/Publish");
axis2_svc_client_engage_module(svc_client, env, AXIS2_MODULE_ADDRESSING);
notifyto = savan_subscriber_get_notify_to(subscriber, env);
if(notifyto)
{
address = axis2_endpoint_ref_get_address(notifyto, env);
if(address)
{
AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[savan] Publishing to:%s", address);
to = axis2_endpoint_ref_create(env, address);
axis2_options_set_to(options, env, to);
}
}
axis2_options_set_xml_parser_reset(options, env, AXIS2_FALSE);
#ifdef SAVAN_FILTERING
/* If this is a filtering request and filter module is defined then filter the request.
*/
{
axis2_char_t *filter_dialect = NULL;
filter_dialiect = savan_subscriber_get_filter_dialect(subscriber, env);
if(!axutil_strcmp(filter_dialect, SYNAPSE_FILTER_DIALECT))
{
/* Do nothing */
}
else if(filtermod && savan_subscriber_get_filter(subscriber, env))
{
/* Apply the filter, and check whether it evaluates to success */
filter_apply = savan_filter_mod_apply(filtermod ,env, subscriber, payload);
if(!filter_apply)
{
status = axutil_error_get_status_code(env->error);
if(AXIS2_SUCCESS != status)
{
axiom_node_detach(payload, env);
return status;
}
}
}
else
{
AXIS2_HANDLE_ERROR(env, SAVAN_ERROR_FILTER_MODULE_COULD_NOT_BE_RETRIEVED,
AXIS2_FAILURE);
return AXIS2_FAILURE;
}
}
#endif
if(filter_apply)
{
axis2_svc_client_fire_and_forget(svc_client, env, payload);
}
axiom_node_detach(payload, env); /*insert this to prevent payload corruption in subsequent
"publish" calls with some payload.*/
AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "[savan] Exit:savan_default_publisher_publish_to_subscriber");
return status;
}