summaryrefslogtreecommitdiffstats
path: root/axiom/src/soap/soap_builder.c
diff options
context:
space:
mode:
Diffstat (limited to 'axiom/src/soap/soap_builder.c')
-rw-r--r--axiom/src/soap/soap_builder.c1206
1 files changed, 1206 insertions, 0 deletions
diff --git a/axiom/src/soap/soap_builder.c b/axiom/src/soap/soap_builder.c
new file mode 100644
index 0000000..6960c03
--- /dev/null
+++ b/axiom/src/soap/soap_builder.c
@@ -0,0 +1,1206 @@
+/*
+ * 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 <axiom_soap_builder.h>
+#include "_axiom_soap_envelope.h"
+#include "_axiom_soap_header.h"
+#include "axiom_soap11_builder_helper.h"
+#include "axiom_soap12_builder_helper.h"
+#include <axiom_soap_const.h>
+#include "_axiom_soap_body.h"
+#include "_axiom_soap_header_block.h"
+#include <axiom_stax_builder_internal.h>
+#include "_axiom_soap_fault.h"
+#include <axutil_http_chunked_stream.h>
+
+static axis2_status_t
+axiom_soap_builder_construct_node(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env,
+ axiom_node_t * om_element_node);
+
+static axis2_status_t
+axiom_soap_builder_identify_soap_version(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env,
+ const axis2_char_t * soap_version_uri_from_transport);
+
+static axis2_status_t
+axiom_soap_builder_parse_headers(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env);
+
+static axis2_status_t
+axiom_soap_builder_process_namespace_data(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env,
+ axiom_node_t * om_node);
+
+static axis2_status_t
+axiom_soap_builder_construct_soap_header(
+ axiom_soap_builder_t *soap_builder,
+ const axutil_env_t *env,
+ axiom_node_t *om_node);
+
+static axis2_status_t
+axiom_soap_builder_construct_soap_body(
+ axiom_soap_builder_t *soap_builder,
+ const axutil_env_t *env,
+ axiom_node_t *om_node);
+
+static axis2_status_t
+axiom_soap_builder_construct_soap_fault(
+ axiom_soap_builder_t *soap_builder,
+ const axutil_env_t *env,
+ axiom_node_t *om_node);
+
+static axis2_status_t
+axiom_soap_builder_construct_xop_include(
+ axiom_soap_builder_t *soap_builder,
+ const axutil_env_t *env,
+ axiom_node_t *om_element_node);
+
+struct axiom_soap_builder
+{
+ axiom_stax_builder_t *om_builder;
+
+ axiom_soap_envelope_t *soap_envelope;
+
+ axis2_bool_t header_present;
+
+ axis2_bool_t body_present;
+
+ int element_level;
+
+ axis2_bool_t processing_fault;
+
+ axis2_bool_t processing_detail_elements;
+
+ axis2_char_t *sender_fault_code;
+
+ axis2_char_t *receiver_fault_code;
+
+ axis2_bool_t processing_mandatory_fault_elements;
+
+ void *builder_helper;
+
+ axiom_namespace_t *envelope_ns;
+
+ int soap_version;
+
+ int last_node_status;
+
+ axis2_bool_t done;
+
+ axutil_hash_t *mime_body_parts;
+
+ axiom_mime_parser_t *mime_parser;
+
+ AXIS2_READ_INPUT_CALLBACK callback;
+
+ void *callback_ctx;
+
+};
+
+typedef enum axis2_builder_last_node_states
+{
+ AXIS2_BUILDER_LAST_NODE_NULL = 0,
+ AXIS2_BUILDER_LAST_NODE_NOT_NULL
+} axis2_builder_last_node_states;
+
+#define AXIS2_MAX_EVENT 100
+
+AXIS2_EXTERN axiom_soap_builder_t *AXIS2_CALL
+axiom_soap_builder_create(
+ const axutil_env_t * env,
+ axiom_stax_builder_t * stax_builder,
+ const axis2_char_t * soap_version)
+{
+ axiom_soap_builder_t *soap_builder = NULL;
+ axis2_status_t status = AXIS2_SUCCESS;
+
+ AXIS2_PARAM_CHECK(env->error, stax_builder, NULL);
+
+ soap_builder = (axiom_soap_builder_t *)AXIS2_MALLOC(env->allocator,
+ sizeof(axiom_soap_builder_t));
+
+ if(soap_builder == NULL)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ return NULL;
+ }
+
+ soap_builder->done = AXIS2_FALSE;
+ soap_builder->body_present = AXIS2_FALSE;
+ soap_builder->builder_helper = NULL;
+ soap_builder->element_level = 0;
+ soap_builder->header_present = AXIS2_FALSE;
+ soap_builder->processing_detail_elements = AXIS2_FALSE;
+ soap_builder->processing_fault = AXIS2_FALSE;
+ soap_builder->processing_mandatory_fault_elements = AXIS2_FALSE;
+ soap_builder->receiver_fault_code = NULL;
+ soap_builder->sender_fault_code = NULL;
+ soap_builder->soap_version = AXIOM_SOAP12;
+ soap_builder->last_node_status = -1;
+ soap_builder->envelope_ns = NULL;
+ soap_builder->soap_envelope = NULL;
+ soap_builder->mime_body_parts = NULL;
+ soap_builder->om_builder = stax_builder;
+ soap_builder->mime_parser = NULL;
+ soap_builder->callback = NULL;
+ soap_builder->callback_ctx = NULL;
+
+ status = axiom_soap_builder_identify_soap_version(soap_builder, env, soap_version);
+ if(status == AXIS2_FAILURE)
+ {
+ axiom_soap_builder_free(soap_builder, env);
+ return NULL;
+ }
+ status = axiom_soap_builder_parse_headers(soap_builder, env);
+ if(status == AXIS2_FAILURE)
+ {
+ axiom_soap_builder_free(soap_builder, env);
+ return NULL;
+ }
+ return soap_builder;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_soap_builder_free(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env)
+{
+ if(!soap_builder)
+ {
+ return;
+ }
+ if(soap_builder->builder_helper)
+ {
+ if(soap_builder->soap_version == AXIOM_SOAP11 && soap_builder->builder_helper)
+ {
+ axiom_soap11_builder_helper_free(
+ (axiom_soap11_builder_helper_t *)(soap_builder->builder_helper), env);
+ soap_builder->builder_helper = NULL;
+ }
+ else if(soap_builder->soap_version == AXIOM_SOAP12 && soap_builder->builder_helper)
+ {
+ axiom_soap12_builder_helper_free(
+ (axiom_soap12_builder_helper_t *)(soap_builder->builder_helper), env);
+ soap_builder->builder_helper = NULL;
+ }
+ }
+
+ if(soap_builder->om_builder)
+ {
+ axiom_stax_builder_free(soap_builder->om_builder, env);
+ soap_builder->om_builder = NULL;
+ }
+
+ if(soap_builder->mime_body_parts)
+ {
+ axutil_hash_index_t *hi = NULL;
+ void *val = NULL;
+ const void *key = NULL;
+ for(hi = axutil_hash_first(soap_builder->mime_body_parts, env); hi; hi = axutil_hash_next(
+ env, hi))
+ {
+ axutil_hash_this(hi, &key, NULL, &val);
+
+ if(key)
+ {
+ AXIS2_FREE(env->allocator, (char *)key);
+ }
+
+ val = NULL;
+ key = NULL;
+ }
+
+ axutil_hash_free(soap_builder->mime_body_parts, env);
+ soap_builder->mime_body_parts = NULL;
+ }
+
+ if(soap_builder->mime_parser)
+ {
+ axiom_mime_parser_free(soap_builder->mime_parser, env);
+ soap_builder->mime_parser = NULL;
+ }
+
+ if(soap_builder->callback_ctx)
+ {
+ axis2_callback_info_t *callback_info = NULL;
+
+ callback_info = (axis2_callback_info_t *)(soap_builder->callback_ctx);
+ if(callback_info)
+ {
+ if(callback_info->chunked_stream)
+ {
+ axutil_http_chunked_stream_free(callback_info->chunked_stream, env);
+ callback_info->chunked_stream = NULL;
+ }
+
+ AXIS2_FREE(env->allocator, callback_info);
+ callback_info = NULL;
+ soap_builder->callback_ctx = NULL;
+ }
+ }
+
+ if(soap_builder)
+ {
+ AXIS2_FREE(env->allocator, soap_builder);
+ soap_builder = NULL;
+ }
+
+ return;
+}
+
+AXIS2_EXTERN axiom_soap_envelope_t *AXIS2_CALL
+axiom_soap_builder_get_soap_envelope(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env)
+{
+ int status = AXIS2_SUCCESS;
+
+ if(!soap_builder)
+ {
+ return NULL;
+ }
+ if(!(soap_builder->om_builder))
+ {
+ return NULL;
+ }
+ while(!(soap_builder->soap_envelope) && !axiom_stax_builder_is_complete(
+ soap_builder->om_builder, env))
+ {
+ status = axiom_soap_builder_next(soap_builder, env);
+ if(status == AXIS2_FAILURE)
+ {
+ break;
+ }
+ }
+
+ return soap_builder->soap_envelope;
+}
+
+AXIS2_EXTERN axiom_document_t *AXIS2_CALL axiom_soap_builder_get_document(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env)
+{
+ if (!soap_builder)
+ {
+ return NULL;
+ }
+ if (soap_builder->om_builder)
+ {
+ return axiom_stax_builder_get_document(soap_builder->om_builder, env);
+ }
+ else
+ return NULL;
+}
+
+/**
+ * Builds next element of the OM structure
+ * @param builder pointer to the SOAP Builder struct
+ * @param env Environment. MUST NOT be NULL
+ * @return AXIS2_SUCCESS if the next element is present else AXIS2_FAILURE
+ */
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_soap_builder_next(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env)
+{
+ int current_event = AXIS2_MAX_EVENT;
+ int status = AXIS2_SUCCESS;
+
+ if((!soap_builder) || (soap_builder->done) || (!soap_builder->om_builder))
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Invalid soap builder");
+ return AXIS2_FAILURE;
+ }
+
+ /* Get the status of previous node before building next node. We need the previous state of the
+ * node to identify very first element, which is SOAP Envelope. If last_node_status is
+ * AXIS2_BUILDER_LAST_NODE_NULL, then it means next node is SOAP Envelope
+ */
+ if(axiom_stax_builder_get_lastnode(soap_builder->om_builder, env))
+ {
+ soap_builder->last_node_status = AXIS2_BUILDER_LAST_NODE_NOT_NULL;
+ }
+ else
+ {
+ soap_builder->last_node_status = AXIS2_BUILDER_LAST_NODE_NULL;
+ }
+
+ current_event = axiom_stax_builder_next_with_token(soap_builder->om_builder, env);
+ if(current_event == AXIOM_XML_READER_START_ELEMENT
+ || current_event == AXIOM_XML_READER_EMPTY_ELEMENT)
+ {
+ axiom_node_t *current_node = axiom_stax_builder_get_lastnode(soap_builder->om_builder, env);
+ if(current_node)
+ {
+ status = axiom_soap_builder_construct_node(soap_builder, env, current_node);
+ }
+ else
+ {
+ /* there is an error. So, don't continue building it */
+ soap_builder->done = AXIS2_TRUE;
+ status = AXIS2_FAILURE;
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error occurred when building node");
+ }
+ }
+ else if(current_event == -1)
+ {
+ /* there is an error. So, don't continue building it */
+ soap_builder->done = AXIS2_TRUE;
+ status = AXIS2_FAILURE;
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error occurred when building node");
+ }
+
+ /* for any other event types, return AXIS2_SUCCESS as the return value. */
+
+ return status;
+}
+
+AXIS2_EXTERN axiom_node_t *AXIS2_CALL
+axiom_soap_builder_get_document_element(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env)
+{
+ axiom_node_t *document_node = NULL;
+ if(soap_builder->soap_envelope)
+ {
+ document_node = axiom_soap_envelope_get_base_node(soap_builder->soap_envelope, env);
+ }
+
+ return document_node;
+}
+
+static axis2_status_t
+axiom_soap_builder_construct_node(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env,
+ axiom_node_t * om_element_node)
+{
+ axiom_element_t *om_element = NULL;
+ const axis2_char_t *ele_localname = NULL;
+ int element_level = 0;
+ int status = AXIS2_SUCCESS;
+ axiom_node_t *parent = NULL;
+
+ /* get OM element struct from node */
+ om_element = (axiom_element_t *)axiom_node_get_data_element(om_element_node, env);
+ if(!om_element)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot construct node. Invalid element");
+ return AXIS2_FAILURE;
+ }
+
+ /* get element local name */
+ ele_localname = axiom_element_get_localname(om_element, env);
+ if(!ele_localname)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot construct node. Invalid element name");
+ return AXIS2_FAILURE;
+ }
+
+ parent = axiom_node_get_parent(om_element_node, env);
+ if(!parent)
+ {
+ /* parent node doesn't exist means, this should be SOAP Envelope */
+ if(soap_builder->last_node_status != AXIS2_BUILDER_LAST_NODE_NULL)
+ {
+ /* this means, there are two elements in the first level */
+ AXIS2_ERROR_SET(env->error,
+ AXIS2_ERROR_SOAP_MESSAGE_FIRST_ELEMENT_MUST_CONTAIN_LOCAL_NAME, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "Soap message can contain only one SOAP Envelope as the top level element");
+ return AXIS2_FAILURE;
+ }
+
+ if(axutil_strcasecmp(ele_localname, AXIOM_SOAP_ENVELOPE_LOCAL_NAME) != 0)
+ {
+ AXIS2_ERROR_SET(env->error,
+ AXIS2_ERROR_SOAP_MESSAGE_FIRST_ELEMENT_MUST_CONTAIN_LOCAL_NAME, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "SOAP message first element must be Envelope");
+ return AXIS2_FAILURE;
+ }
+
+ /** create a null soap envelope struct */
+ soap_builder->soap_envelope = axiom_soap_envelope_create_null(env);
+ if(!soap_builder->soap_envelope)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Unable to create SOAP Envelope");
+ return AXIS2_FAILURE;
+ }
+
+ /** wrap this OM node in it */
+ axiom_soap_envelope_set_base_node(soap_builder->soap_envelope, env, om_element_node);
+ axiom_soap_envelope_set_builder(soap_builder->soap_envelope, env, soap_builder);
+ status = axiom_soap_builder_process_namespace_data(soap_builder, env, om_element_node);
+ if(status != AXIS2_SUCCESS)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "SOAP Envelope is having invalid namespace");
+ }
+
+ return status;
+ }
+
+ /** a parent node exist , so not soap envelope. Can be either header/body/children of them */
+
+ /* get element level of this OM element. Envelope will be in element_level 1. Body and Header
+ * will be in element level 2. SOAP fault will be child of Body, so it will be in level 3*/
+ element_level = axiom_stax_builder_get_element_level(soap_builder->om_builder, env);
+ if(axiom_stax_builder_get_current_event(soap_builder->om_builder, env)
+ == AXIOM_XML_READER_EMPTY_ELEMENT)
+ {
+ /* if it is an empty element, increase the element level. This is because the element level
+ * is incremented by STAX builder only if <element> tag is identified. It will not be
+ * incremented if <element/> tag is seen. But for our logic, even empty element should be
+ * considered as full element. so, <element/> = <element> </element>. */
+ ++element_level;
+ }
+
+ if(element_level == 2)
+ {
+ /* At this level, we can only have soap:Header or soap:Body */
+ status = axiom_soap_builder_process_namespace_data(soap_builder, env, om_element_node);
+ if(status != AXIS2_SUCCESS)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "invalid SOAP namespace");
+ return AXIS2_FAILURE;
+ }
+
+ if(axutil_strcmp(ele_localname, AXIOM_SOAP_HEADER_LOCAL_NAME) == 0)
+ {
+ /* this is the soap header element */
+ status = axiom_soap_builder_construct_soap_header(soap_builder, env, om_element_node);
+ }
+ else if(axutil_strcmp(ele_localname, AXIOM_SOAP_BODY_LOCAL_NAME) == 0)
+ {
+ /* This is the SOAP Body element */
+ status = axiom_soap_builder_construct_soap_body(soap_builder, env, om_element_node);
+ }
+ else
+ {
+ AXIS2_ERROR_SET(env->error,
+ AXIS2_ERROR_SOAP_BUILDER_ENVELOPE_CAN_HAVE_ONLY_HEADER_AND_BODY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "SOAP builder found a child element other than header or body in envelope element");
+ return AXIS2_FAILURE;
+ }
+ }
+ else if(element_level == 3)
+ {
+ axiom_element_t *parent_ele = NULL;
+ axis2_char_t *parent_localname = NULL;
+
+ parent_ele = (axiom_element_t *)axiom_node_get_data_element(parent, env);
+ if(parent_ele)
+ {
+ parent_localname = axiom_element_get_localname(parent_ele, env);
+ }
+
+ if(!parent_localname)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot identify parent element local name");
+ return AXIS2_FAILURE;
+ }
+
+ if(axutil_strcasecmp(parent_localname, AXIOM_SOAP_HEADER_LOCAL_NAME) == 0)
+ {
+ axiom_soap_header_block_t *header_block = NULL;
+ axiom_soap_header_t *soap_header = NULL;
+
+ soap_header = axiom_soap_envelope_get_header(soap_builder->soap_envelope, env);
+ if(!soap_header)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot get SOAP Header from OM Envelope");
+ return AXIS2_FAILURE;
+ }
+
+ header_block = axiom_soap_header_block_create(env);
+ if(!header_block)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot create SOAP Header block");
+ return AXIS2_FAILURE;
+ }
+
+ axiom_soap_header_block_set_base_node(header_block, env, om_element_node);
+ axiom_soap_header_set_header_block(soap_header, env, header_block);
+ axiom_soap_header_block_set_soap_version(header_block, env, soap_builder->soap_version);
+ }
+ else if(axutil_strcasecmp(parent_localname, AXIOM_SOAP_BODY_LOCAL_NAME) == 0)
+ {
+ /* if the node is <xop:Include> or MTOM message */
+ if(axutil_strcmp(ele_localname, AXIS2_XOP_INCLUDE) == 0)
+ {
+ return axiom_soap_builder_construct_xop_include(soap_builder, env, om_element_node);
+ }
+
+ if(axutil_strcasecmp(ele_localname, AXIOM_SOAP_BODY_FAULT_LOCAL_NAME) == 0)
+ {
+ return axiom_soap_builder_construct_soap_fault(soap_builder, env, om_element_node);
+ }
+
+ /* We don't need to process any other children of SOAP Body. */
+ }
+ else
+ {
+ AXIS2_ERROR_SET(env->error,
+ AXIS2_ERROR_SOAP_BUILDER_ENVELOPE_CAN_HAVE_ONLY_HEADER_AND_BODY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "SOAP builder found a child element other than header or body in envelope element");
+ return AXIS2_FAILURE;
+ }
+
+ return AXIS2_SUCCESS;
+ }
+ else if(element_level > 3)
+ {
+ if(soap_builder->processing_fault)
+ {
+ if(soap_builder->soap_version == AXIOM_SOAP11)
+ {
+ status = axiom_soap11_builder_helper_handle_event((axiom_soap11_builder_helper_t *)
+ soap_builder->builder_helper, env, om_element_node, element_level);
+ }
+ else if(soap_builder->soap_version == AXIOM_SOAP12)
+ {
+ status = axiom_soap12_builder_helper_handle_event((axiom_soap12_builder_helper_t *)
+ soap_builder->builder_helper, env, om_element_node, element_level);
+ }
+ else
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Unknown SOAP Version");
+ status = AXIS2_FAILURE;
+ }
+ }
+
+ /* if the node is <xop:Include> or MTOM message */
+ else if(axutil_strcmp(ele_localname, AXIS2_XOP_INCLUDE) == 0)
+ {
+ return axiom_soap_builder_construct_xop_include(soap_builder, env, om_element_node);
+ }
+
+ /* we don't need to consider any other elements at this level. */
+ }
+ return status;
+}
+
+static axis2_status_t
+axiom_soap_builder_construct_soap_header(
+ axiom_soap_builder_t *soap_builder,
+ const axutil_env_t *env,
+ axiom_node_t *om_node)
+{
+ axiom_soap_header_t *soap_header = NULL;
+ if(soap_builder->header_present)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOAP_BUILDER_MULTIPLE_HEADERS_ENCOUNTERED,
+ AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "SOAP builder encountered multiple headers");
+ return AXIS2_FAILURE;
+ }
+ if(soap_builder->body_present)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOAP_BUILDER_HEADER_BODY_WRONG_ORDER,
+ AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "SOAP builder encountered body element first and header next");
+ return AXIS2_FAILURE;
+ }
+
+ soap_builder->header_present = AXIS2_TRUE;
+ soap_header = axiom_soap_header_create(env);
+ if(!soap_header)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Unable to create SOAP Header");
+ return AXIS2_FAILURE;
+ }
+
+ axiom_soap_header_set_base_node(soap_header, env, om_node);
+ axiom_soap_envelope_set_header(soap_builder->soap_envelope, env, soap_header);
+ axiom_soap_header_set_builder(soap_header, env, soap_builder);
+ axiom_soap_header_set_soap_version(soap_header, env, soap_builder->soap_version);
+
+ return AXIS2_SUCCESS;
+}
+
+static axis2_status_t
+axiom_soap_builder_construct_soap_body(
+ axiom_soap_builder_t *soap_builder,
+ const axutil_env_t *env,
+ axiom_node_t *om_node)
+{
+ axiom_soap_body_t *soap_body = NULL;
+ if(soap_builder->body_present)
+ {
+ AXIS2_ERROR_SET(env->error,
+ AXIS2_ERROR_SOAP_BUILDER_MULTIPLE_BODY_ELEMENTS_ENCOUNTERED, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "SOAP builder multiple body elements encountered");
+ return AXIS2_FAILURE;
+ }
+
+ soap_builder->body_present = AXIS2_TRUE;
+ soap_body = axiom_soap_body_create(env);
+ if(!soap_body)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Unable to create SOAP Body");
+ return AXIS2_FAILURE;
+ }
+
+ axiom_soap_body_set_base_node(soap_body, env, om_node);
+ axiom_soap_body_set_builder(soap_body, env, soap_builder);
+ axiom_soap_envelope_set_body(soap_builder->soap_envelope, env, soap_body);
+
+ return AXIS2_SUCCESS;
+}
+
+static axis2_status_t
+axiom_soap_builder_construct_soap_fault(
+ axiom_soap_builder_t *soap_builder,
+ const axutil_env_t *env,
+ axiom_node_t *om_node)
+{
+ axiom_soap_body_t *soap_body = NULL;
+ axiom_soap_fault_t *soap_fault = NULL;
+ axiom_namespace_t *env_ns = NULL;
+
+ env_ns = axiom_soap_envelope_get_namespace(soap_builder->soap_envelope, env);
+ if(!env_ns)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot get soap envelope namespace");
+ return AXIS2_FAILURE;
+ }
+
+ soap_body = axiom_soap_envelope_get_body(soap_builder->soap_envelope, env);
+ if(!soap_body)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot get soap body from OM Envelope");
+ return AXIS2_FAILURE;
+ }
+
+ soap_fault = axiom_soap_fault_create(env);
+ if(!soap_fault)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot create SOAP Fault structure");
+ return AXIS2_FAILURE;
+ }
+
+ axiom_soap_fault_set_base_node(soap_fault, env, om_node);
+ axiom_soap_body_set_fault(soap_body, env, soap_fault);
+ axiom_soap_fault_set_builder(soap_fault, env, soap_builder);
+ soap_builder->processing_fault = AXIS2_TRUE;
+ soap_builder->processing_mandatory_fault_elements = AXIS2_TRUE;
+
+ if(axutil_strcmp(AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI,
+ axiom_namespace_get_uri(env_ns, env)) == 0)
+ {
+ soap_builder->builder_helper = axiom_soap12_builder_helper_create(env, soap_builder);
+ }
+ else if(axutil_strcmp(AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI,
+ axiom_namespace_get_uri(env_ns, env)) == 0)
+ {
+ soap_builder->builder_helper = axiom_soap11_builder_helper_create(
+ env, soap_builder,soap_builder->om_builder);
+ }
+
+ if(!soap_builder->builder_helper)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot create soap builder helper");
+ return AXIS2_FAILURE;
+ }
+ return AXIS2_SUCCESS;
+}
+
+static axis2_status_t
+axiom_soap_builder_construct_xop_include(
+ axiom_soap_builder_t *soap_builder,
+ const axutil_env_t *env,
+ axiom_node_t *om_element_node)
+{
+ axiom_namespace_t *ns = NULL;
+ axis2_char_t *uri = NULL;
+ axiom_element_t *om_element = NULL;
+ axutil_qname_t *qname = NULL;
+ axis2_char_t *id = NULL;
+
+ om_element = (axiom_element_t *)axiom_node_get_data_element(om_element_node, env);
+ ns = axiom_element_get_namespace(om_element, env, om_element_node);
+ if(!ns)
+ {
+ /* this is not a xop:include element. so, we can safely return success */
+ return AXIS2_SUCCESS;
+ }
+
+ uri = axiom_namespace_get_uri(ns, env);
+ if((!uri) || (axutil_strcmp(uri, AXIS2_XOP_NAMESPACE_URI) != 0))
+ {
+ /* this is not a xop:include element. so, we can safely return success */
+ return AXIS2_SUCCESS;
+ }
+
+ qname = axutil_qname_create(env, "href", NULL, NULL);
+ if(!qname)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot create qname with value href");
+ return AXIS2_FAILURE;
+ }
+
+ id = axiom_element_get_attribute_value(om_element, env, qname);
+ axutil_qname_free(qname, env);
+ if(!id)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot get href ID of the xop:include element");
+ return AXIS2_FAILURE;
+ }
+
+ if(!axutil_strstr(id, "cid:"))
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "ID of xop:include doesn't include 'cid:' part");
+ return AXIS2_FAILURE;
+ }
+
+ /* everything looks fine, so recursively build the OM tree, so that we can get data handlers */
+ while(!axiom_node_is_complete(om_element_node, env))
+ {
+ axiom_stax_builder_next_with_token(soap_builder->om_builder, env);
+ }
+
+ if(soap_builder->mime_body_parts)
+ {
+ axiom_data_handler_t *data_handler = NULL;
+ axis2_char_t *id_decoded = NULL;
+ axiom_text_t *data_text = NULL;
+ axiom_node_t *data_om_node = NULL;
+ axiom_node_t *parent = NULL;
+
+ /* Get the value of href id, after "cid:" */
+ id += 4;
+ id_decoded = axutil_strdup(env, id);
+ axutil_url_decode(env, id_decoded, id_decoded);
+
+ /* Find the data handler of given xop:include */
+ data_handler = (axiom_data_handler_t *)axutil_hash_get(
+ soap_builder-> mime_body_parts, (void *)id_decoded, AXIS2_HASH_KEY_STRING);
+ if(!data_handler)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "Cannot find data handler corresponding to id %s", id_decoded);
+ AXIS2_FREE(env->allocator, id_decoded);
+ return AXIS2_FAILURE;
+ }
+
+ /* remove the <xop:Include> element, and add the data handler as the child of
+ * xop:include's parent */
+ parent = axiom_node_get_parent(om_element_node, env);
+ axiom_node_free_tree(om_element_node, env);
+ data_text = axiom_text_create_with_data_handler(env, parent, data_handler, &data_om_node);
+ axiom_text_set_content_id(data_text, env, id_decoded);
+ axiom_stax_builder_set_lastnode(soap_builder->om_builder,env, parent);
+ AXIS2_FREE(env->allocator, id_decoded);
+ }
+ else
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot find mime_body_part in soap builder");
+ return AXIS2_FAILURE;
+ }
+
+ return AXIS2_SUCCESS;
+}
+
+/* check whether the namespace of given node is either SOAP11 or SOAP12 namespace */
+static axis2_status_t
+axiom_soap_builder_process_namespace_data(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env,
+ axiom_node_t * om_node)
+{
+ axiom_element_t *om_ele = NULL;
+ axiom_namespace_t *om_ns = NULL;
+
+ om_ele = (axiom_element_t *)axiom_node_get_data_element(om_node, env);
+ om_ns = axiom_element_get_namespace(om_ele, env, om_node);
+ if(om_ns)
+ {
+ axis2_char_t *ns_uri = NULL;
+ ns_uri = axiom_namespace_get_uri(om_ns, env);
+ if(ns_uri)
+ {
+ if((axutil_strcmp(ns_uri, AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI) == 0)
+ || (axutil_strcmp(ns_uri, AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI) == 0))
+ {
+ return AXIS2_SUCCESS;
+ }
+ }
+ }
+
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_SOAP_NAMESPACE_URI, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Invalid SOAP Namespace URI");
+ return AXIS2_FAILURE;
+}
+
+static axis2_status_t
+axiom_soap_builder_identify_soap_version(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env,
+ const axis2_char_t * soap_version_uri_from_transport)
+{
+ axiom_namespace_t *om_ns = NULL;
+ axiom_node_t *envelope_node = NULL;
+ axiom_element_t *om_ele = NULL;
+ axis2_char_t *ns_uri = NULL;
+
+ AXIS2_PARAM_CHECK(env->error, soap_version_uri_from_transport, AXIS2_FAILURE);
+ if(!soap_builder)
+ {
+ return AXIS2_FAILURE;
+ }
+ soap_builder->soap_envelope = axiom_soap_builder_get_soap_envelope(soap_builder, env);
+
+ if(soap_builder->soap_envelope == NULL)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOAP_MESSAGE_DOES_NOT_CONTAIN_AN_ENVELOPE,
+ AXIS2_FAILURE);
+ AXIS2_LOG_CRITICAL(env->log, AXIS2_LOG_SI,
+ "SOAP message does not have a SOAP envelope element ");
+ return AXIS2_FAILURE;
+ }
+
+ envelope_node = axiom_soap_envelope_get_base_node(soap_builder->soap_envelope, env);
+
+ if(!envelope_node)
+ {
+ return AXIS2_FAILURE;
+ }
+ om_ele = (axiom_element_t *)axiom_node_get_data_element(envelope_node, env);
+ if(!om_ele)
+ {
+ return AXIS2_FAILURE;
+ }
+ om_ns = axiom_element_get_namespace(om_ele, env, envelope_node);
+ if(!om_ns)
+ {
+ return AXIS2_FAILURE;
+ }
+ ns_uri = axiom_namespace_get_uri(om_ns, env);
+
+ if(ns_uri)
+ {
+ if(soap_version_uri_from_transport
+ && axutil_strcmp(soap_version_uri_from_transport, ns_uri) != 0)
+ {
+ AXIS2_ERROR_SET(env->error,
+ AXIS2_ERROR_TRANSPORT_LEVEL_INFORMATION_DOES_NOT_MATCH_WITH_SOAP, AXIS2_FAILURE);
+
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "AXIS2_ERROR_TRANSPORT_LEVEL_INFORMATION_DOES_NOT_MATCH_WITH_SOAP");
+ return AXIS2_FAILURE;
+ }
+ if(axutil_strcmp(AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI, ns_uri) == 0)
+ {
+ soap_builder->soap_version = AXIOM_SOAP11;
+
+ AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Identified soap version is soap11");
+
+ axiom_soap_envelope_set_soap_version_internal(soap_builder-> soap_envelope, env,
+ soap_builder-> soap_version);
+
+ return AXIS2_SUCCESS;
+ }
+ else if(axutil_strcmp(AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI, ns_uri) == 0)
+ {
+ soap_builder->soap_version = AXIOM_SOAP12;
+
+ AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "identified soap version is soap12");
+
+ axiom_soap_envelope_set_soap_version_internal(soap_builder-> soap_envelope, env,
+ soap_builder-> soap_version);
+
+ return AXIS2_SUCCESS;
+ }
+ }
+ return AXIS2_FAILURE;
+}
+
+static axis2_status_t
+axiom_soap_builder_parse_headers(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env)
+{
+ axiom_node_t *om_node = NULL;
+ axiom_soap_header_t *soap_header = NULL;
+ int status = AXIS2_SUCCESS;
+ if(!soap_builder)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_NULL_PARAM, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Soap Builder is NULL");
+ return AXIS2_FAILURE;
+ }
+ if(!soap_builder->soap_envelope)
+ {
+ return AXIS2_FAILURE;
+ }
+ soap_header = axiom_soap_envelope_get_header(soap_builder->soap_envelope, env);
+
+ if(soap_header)
+ {
+ om_node = axiom_soap_header_get_base_node(soap_header, env);
+ if(om_node)
+ {
+ while(!axiom_node_is_complete(om_node, env))
+ {
+ status = axiom_soap_builder_next(soap_builder, env);
+ if(status == AXIS2_FAILURE)
+ return AXIS2_FAILURE;
+ }
+ /*HACK: to fix AXIS2C-129 - Samisa */
+ /*
+ axiom_stax_builder_set_element_level(
+ soap_builder->om_builder, env, 1);
+ */
+ }
+ }
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_soap_builder_set_bool_processing_mandatory_fault_elements(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env,
+ axis2_bool_t value)
+{
+ soap_builder->processing_mandatory_fault_elements = value;
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_soap_builder_set_processing_detail_elements(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env,
+ axis2_bool_t value)
+{
+ soap_builder->processing_detail_elements = value;
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axis2_bool_t AXIS2_CALL
+axiom_soap_builder_is_processing_detail_elements(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env)
+{
+ return soap_builder->processing_detail_elements;
+}
+
+AXIS2_EXTERN int AXIS2_CALL
+axiom_soap_builder_get_soap_version(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env)
+{
+ return soap_builder->soap_version;
+}
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_soap_builder_set_mime_body_parts(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env,
+ axutil_hash_t * map)
+{
+ soap_builder->mime_body_parts = map;
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axutil_hash_t *AXIS2_CALL
+axiom_soap_builder_get_mime_body_parts(
+ axiom_soap_builder_t * builder,
+ const axutil_env_t * env)
+{
+ return builder->mime_body_parts;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_soap_builder_set_mime_parser(
+ axiom_soap_builder_t * builder,
+ const axutil_env_t * env,
+ axiom_mime_parser_t *mime_parser)
+{
+ builder->mime_parser = mime_parser;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_soap_builder_set_callback_function(
+ axiom_soap_builder_t * builder,
+ const axutil_env_t * env,
+ AXIS2_READ_INPUT_CALLBACK callback)
+{
+ builder->callback = callback;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_soap_builder_set_callback_ctx(
+ axiom_soap_builder_t * builder,
+ const axutil_env_t * env,
+ void *callback_ctx)
+{
+ builder->callback_ctx = callback_ctx;
+}
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_soap_builder_create_attachments(
+ axiom_soap_builder_t * builder,
+ const axutil_env_t * env,
+ void *user_param,
+ axis2_char_t *callback_name)
+{
+ axutil_hash_t *attachments_map = NULL;
+ axis2_char_t *mime_boundary = NULL;
+
+ if(builder->mime_parser)
+ {
+ if(builder->callback_ctx)
+ {
+ mime_boundary = axiom_mime_parser_get_mime_boundary(builder->mime_parser, env);
+
+ if(mime_boundary)
+ {
+ if(callback_name)
+ {
+ axiom_mime_parser_set_caching_callback_name(builder->mime_parser, env,
+ callback_name);
+ }
+ attachments_map = axiom_mime_parser_parse_for_attachments(builder->mime_parser,
+ env, builder->callback, builder->callback_ctx, mime_boundary, user_param);
+
+ if(attachments_map)
+ {
+ builder->mime_body_parts = attachments_map;
+ return AXIS2_SUCCESS;
+ }
+ else
+ {
+ return AXIS2_FAILURE;
+ }
+ }
+ else
+ {
+ return AXIS2_FAILURE;
+ }
+ }
+ else
+ {
+ return AXIS2_FAILURE;
+ }
+ }
+ else
+ {
+ return AXIS2_FAILURE;
+ }
+}
+
+AXIS2_EXTERN axis2_bool_t AXIS2_CALL
+axiom_soap_builder_replace_xop(
+ axiom_soap_builder_t * builder,
+ const axutil_env_t * env,
+ axiom_node_t *om_element_node,
+ axiom_element_t *om_element)
+{
+ axiom_namespace_t *ns = NULL;
+ axis2_bool_t is_replaced = AXIS2_FALSE;
+
+ ns = axiom_element_get_namespace(om_element, env, om_element_node);
+ if(ns)
+ {
+ axis2_char_t *uri = axiom_namespace_get_uri(ns, env);
+ if(uri)
+ {
+ if(axutil_strcmp(uri, AXIS2_XOP_NAMESPACE_URI) == 0)
+ {
+ axutil_qname_t *qname = NULL;
+ qname = axutil_qname_create(env, "href", NULL, NULL);
+ if(qname)
+ {
+ axis2_char_t *id = NULL;
+ id = axiom_element_get_attribute_value(om_element, env, qname);
+ if(id)
+ {
+ axis2_char_t *pos = NULL;
+ pos = axutil_strstr(id, "cid:");
+ if(pos)
+ {
+ axiom_data_handler_t *data_handler = NULL;
+ id += 4;
+
+ if(builder->mime_body_parts)
+ {
+
+ axis2_char_t *id_decoded = NULL;
+
+ id_decoded = axutil_strdup(env, id);
+
+ axutil_url_decode(env, id_decoded, id_decoded);
+
+ data_handler = (axiom_data_handler_t *)axutil_hash_get(
+ builder-> mime_body_parts, (void *)id_decoded,
+ AXIS2_HASH_KEY_STRING);
+ if(data_handler)
+ {
+ axiom_text_t *data_text = NULL;
+ axiom_node_t *data_om_node = NULL;
+ axiom_node_t *parent = NULL;
+
+ parent = axiom_node_get_parent(om_element_node, env);
+
+ /*remove the <xop:Include> element */
+ axiom_node_free_tree(om_element_node, env);
+
+ data_text = axiom_text_create_with_data_handler(env, parent,
+ data_handler, &data_om_node);
+
+ axiom_text_set_content_id(data_text, env, id_decoded);
+ /*axiom_stax_builder_set_lastnode
+ (soap_builder->om_builder, env,
+ parent);*/
+ is_replaced = AXIS2_TRUE;
+ }
+ if(id_decoded)
+ {
+ AXIS2_FREE(env->allocator, id_decoded);
+ }
+ }
+ }
+ }
+ }
+ axutil_qname_free(qname, env);
+ }
+ }
+ }
+
+ return is_replaced;
+}
+
+AXIS2_EXTERN axiom_stax_builder_t *AXIS2_CALL
+axiom_soap_builder_get_om_builder(
+ axiom_soap_builder_t * soap_builder,
+ const axutil_env_t * env)
+{
+ if(!soap_builder)
+ {
+ return NULL;
+ }
+ return soap_builder->om_builder;
+}
+