/* -*- C++ -*- */

/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,


 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "SOAP" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 *
 *
 *
 * @author Roshan Weerasuriya (roshan@jkcs.slt.lk)
 * @author Susantha Kumara (susantha@opensource.lk, skumara@virtusa.com)
 *
 */

// SoapSerializer.cpp: implementation of the SoapSerializer class.
//
//////////////////////////////////////////////////////////////////////

#ifdef WIN32
#pragma warning (disable : 4786)
#endif

#include <axis/soap/SoapEnvelope.h>
#include <axis/soap/SoapSerializer.h>
#include <axis/soap/HeaderBlock.h>
#include <axis/common/GDefine.h>
#include <axis/common/Packet.h>
#include <axis/common/ArrayBean.h>
#include <axis/common/BasicTypeSerializer.h>
#include <axis/soap/SoapKeywordMapping.h>
#include <stdio.h>
#include <stdarg.h>

#include <axis/common/AxisTrace.h>

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
// Following values should come from axis configuration files.
#define INITIAL_SERIALIZE_BUFFER_SIZE 4096
#define NO_OF_SERIALIZE_BUFFERS 10

IWrapperSoapSerializerFunctions IWrapperSoapSerializer::ms_VFtable;

SoapSerializer::SoapSerializer()
{
	__vfptr = &ms_VFtable;
	m_pSoapEnvelope = NULL;
	m_iSoapVersion = SOAP_VER_1_1;
	m_pOutputStream = NULL;
	m_nMaxBuffersToCreate = NO_OF_SERIALIZE_BUFFERS;
	m_nInitialBufferSize = INITIAL_SERIALIZE_BUFFER_SIZE;
	m_pSZBuffers = new SerializeBuffers[m_nMaxBuffersToCreate];
	for (int x=0; x<m_nMaxBuffersToCreate; x++)
	{
		m_pSZBuffers[x].inuse = 0;
		m_pSZBuffers[x].buffer = NULL;
	}
}

SoapSerializer::~SoapSerializer()
{
	if (m_pSoapEnvelope) delete m_pSoapEnvelope;
}

int SoapSerializer::setSoapEnvelope(SoapEnvelope *pSoapEnvelope)
{
	m_pSoapEnvelope = pSoapEnvelope;

	return AXIS_SUCCESS;
}

int SoapSerializer::setSoapHeader(SoapHeader *pSoapHeader)
{
	int intStatus = AXIS_FAIL;

	if(m_pSoapEnvelope) {

		if((m_pSoapEnvelope)&& (m_pSoapEnvelope->m_pSoapHeader)) {
			//no need to create a SOAP Header, it already exists
			intStatus= AXIS_OBJECT_ALREADY_EXISTS;
		} else {
			m_pSoapEnvelope->setSoapHeader(pSoapHeader);
			intStatus= AXIS_SUCCESS;
		}
	}

	return intStatus;
}

int SoapSerializer::setSoapBody(SoapBody *pSoapBody)
{
	int intStatus= AXIS_FAIL;

	if(m_pSoapEnvelope) {
		m_pSoapEnvelope->setSoapBody(pSoapBody);
		intStatus= AXIS_SUCCESS;
	}

	return intStatus;
}

int SoapSerializer::setSoapMethod(SoapMethod *pSoapMethod)
{
	int intStatus= AXIS_FAIL;

	if(m_pSoapEnvelope && (m_pSoapEnvelope->m_pSoapBody)) {
		m_pSoapEnvelope->m_pSoapBody->m_pSoapMethod= pSoapMethod;
		intStatus= AXIS_SUCCESS;
	}

	return intStatus;
}

int SoapSerializer::AddOutputBasicArrayParam(const Axis_Array* pArray, XSDTYPE nType, const AxisChar* pName)
{
	IArrayBean* pAb = makeArrayBean(nType, (void*)(pArray->m_Array));
	pAb->SetDimension(pArray->m_Size);
	Param* pParam = new Param();
	if (RPC_ENCODED == m_nStyle)
	{
		pAb->SetItemName("item");
		pParam->SetName(pName);
	}
	else
	{
		pAb->SetItemName(pName);
		pParam->SetName("array");		
	}
	pParam->m_Value.pIArray = pAb;
	pParam->m_Type = XSD_ARRAY;
	if(m_pSoapEnvelope && (m_pSoapEnvelope->m_pSoapBody) && (m_pSoapEnvelope->m_pSoapBody->m_pSoapMethod)) 
	{
		m_pSoapEnvelope->m_pSoapBody->m_pSoapMethod->AddOutputParam(pParam);
	}
	return AXIS_SUCCESS;
}

int SoapSerializer::AddOutputCmplxArrayParam(const Axis_Array* pArray, void* pSZFunct, void* pDelFunct, void* pSizeFunct, const AxisChar* pName, const AxisChar* pNamespace)
{
	IArrayBean* pAb = makeArrayBean((void*)(pArray->m_Array), pSZFunct, pDelFunct, pSizeFunct);
	pAb->SetDimension(pArray->m_Size);
	Param* pParam = new Param();
	if (RPC_ENCODED == m_nStyle)
	{
		pAb->SetItemName("item");
		pAb->SetTypeName(pName);
		pAb->SetUri(pNamespace);
		pParam->SetName(pName);
	}
	else
	{
		pAb->SetItemName(pName);
		pParam->SetName("array");		
	}
	pParam->m_Value.pIArray = pAb;
	pParam->m_Type = XSD_ARRAY;
	if(m_pSoapEnvelope && (m_pSoapEnvelope->m_pSoapBody) && (m_pSoapEnvelope->m_pSoapBody->m_pSoapMethod)) 
	{
		m_pSoapEnvelope->m_pSoapBody->m_pSoapMethod->AddOutputParam(pParam);
	}
	pParam->SetName(pName);
	return AXIS_SUCCESS;
}

int SoapSerializer::AddOutputCmplxParam(void* pObject, void* pSZFunct, void* pDelFunct, const AxisChar* pName, const AxisChar* pNamespace )
{ 
	Param* pParam = new Param();
	pParam->m_Value.pCplxObj = new ComplexObjectHandler;
	pParam->m_Value.pCplxObj->pObject = pObject;
	pParam->m_Value.pCplxObj->pSZFunct = (AXIS_SERIALIZE_FUNCT)pSZFunct;
	pParam->m_Value.pCplxObj->pDelFunct = (AXIS_OBJECT_DELETE_FUNCT)pDelFunct;
	if(m_pSoapEnvelope && (m_pSoapEnvelope->m_pSoapBody) && (m_pSoapEnvelope->m_pSoapBody->m_pSoapMethod)) 
	{
		m_pSoapEnvelope->m_pSoapBody->m_pSoapMethod->AddOutputParam(pParam);
	}
	pParam->SetName(pName);
	return AXIS_SUCCESS;
}

int SoapSerializer::setSoapFault(SoapFault *pSoapFault)
{
	int intStatus= AXIS_FAIL;

	if(m_pSoapEnvelope && (m_pSoapEnvelope->m_pSoapBody)) {
		m_pSoapEnvelope->m_pSoapBody->m_pSoapFault= pSoapFault;
		intStatus= AXIS_SUCCESS;
	}

	return intStatus;
}

int SoapSerializer::SetOutputStream(const Ax_soapstream* pStream)
{
	m_pOutputStream = pStream;
	int iStatus= AXIS_SUCCESS;

	if(m_pSoapEnvelope) {
		Serialize("<?xml version='1.0' encoding='utf-8' ?>", NULL);
		iStatus= m_pSoapEnvelope->serialize(*this, (SOAP_VERSION)m_iSoapVersion);
		SendSerializedBuffer();
	}
	return iStatus;
}

/**
 * Some client side transport layer may wait until the end of buffers is acknowladged
 * Use this function to do that.
 */
void SoapSerializer::MarkEndOfStream()
{
	m_pOutputStream->transport.pSendFunct((char*)NULL, NULL, m_pOutputStream);
}

/**
 * Initializing the members of the class. This is needed since
 * the same object instance of this class, may be used to server
 * several SOAP requests.
 */
int SoapSerializer::Init()
{
	m_nStatus = AXIS_SUCCESS;

	if(m_pSoapEnvelope) {
		delete m_pSoapEnvelope;
		m_pSoapEnvelope= NULL;
	}

	/* Adding SoapEnvelop and SoapBody to Serializer */
	m_pSoapEnvelope = new SoapEnvelope();
	m_pSoapEnvelope->setSoapBody(new SoapBody());
	
	SetNextSerilizeBuffer();

	m_nCounter=0;
	m_NsStack.clear();
	return AXIS_SUCCESS;
}

int SoapSerializer::setSoapVersion(SOAP_VERSION nSoapVersion)
{
	m_iSoapVersion = nSoapVersion;
	//here the default namespaces of the SoapEnvelop should be added and intialized as well.
	m_pSoapEnvelope->addStandardNamespaceDecl(SoapKeywordMapping::Map(nSoapVersion).pEnv);
	m_pSoapEnvelope->addStandardNamespaceDecl(SoapKeywordMapping::Map(nSoapVersion).pXsd);
	m_pSoapEnvelope->addStandardNamespaceDecl(SoapKeywordMapping::Map(nSoapVersion).pXsi);
	return AXIS_SUCCESS;
}
void SoapSerializer::RemoveNamespacePrefix(const AxisChar* pNamespace)
{
	if (m_NsStack.find(pNamespace) != m_NsStack.end())
	{
		m_NsStack.erase(pNamespace);
	}
}

const AxisChar* SoapSerializer::GetNamespacePrefix(const AxisChar* pNamespace)
{
	if (m_NsStack.find(pNamespace) == m_NsStack.end())
	{
		m_nCounter++;
		AxisSprintf(m_Buf, 8, "ns%d", m_nCounter);
		m_NsStack[pNamespace] = m_Buf;
	}
	return m_NsStack[pNamespace].c_str();
}

IWrapperSoapSerializer& SoapSerializer::operator <<(const AxisChar* cSerialized)
{
	if (AXIS_SUCCESS != m_nStatus) 
	{
		/* some thing has gone wrong. So do nothing */
		return *this;
	}

	int iTmpSerBufferSize = strlen(cSerialized);
	if((m_nFilledSize + iTmpSerBufferSize)>= m_nCurrentBufferSize) 
	{
		/*
		 * Send the current buffer to the transport and get
		 * another buffer to be filled
		 */
		if (AXIS_SUCCESS == SendSerializedBuffer())
		{
			if (AXIS_SUCCESS == SetNextSerilizeBuffer())
			{
				strcat((char*)m_pSZBuffers[m_nCurrentBufferIndex].buffer, cSerialized);
				m_nFilledSize += iTmpSerBufferSize;
			}
		}
	}
	else
	{
		strcat((char*)m_pSZBuffers[m_nCurrentBufferIndex].buffer, cSerialized);
		m_nFilledSize += iTmpSerBufferSize;
	}
	return *this;
}

int SoapSerializer::SendSerializedBuffer()
{
	int nStatus;
	if (NULL != m_pOutputStream->transport.pSendFunct)
	{
		nStatus = m_pOutputStream->transport.pSendFunct((char*)
		m_pSZBuffers[m_nCurrentBufferIndex].buffer, (void*)(&(m_pSZBuffers[m_nCurrentBufferIndex].inuse)), m_pOutputStream);
		if (TRANSPORT_FINISHED == nStatus) 
		/* transport layer has done with the buffer.So same buffer can be re-used*/
		{
			m_pSZBuffers[m_nCurrentBufferIndex].buffer[0] = '\0'; /* put nul */
			m_pSZBuffers[m_nCurrentBufferIndex].inuse = 0; /* not in use */
		}
		else if (TRANSPORT_FAILED == nStatus) 
		{
			return AXIS_FAIL;
		}
	}
	else
	{
		return AXIS_FAIL;
	}
	return AXIS_SUCCESS;
}

/**
 * This method sets the next buffer to be used for serialization.
 *
 */
int SoapSerializer::SetNextSerilizeBuffer()
{
	for (int x=0;x<m_nMaxBuffersToCreate;x++)
	{
		if (m_pSZBuffers[x].buffer) /* a buffer has been created */
		{
			if (0 == m_pSZBuffers[x].inuse) /* buffer is not being used */ 
			{
				m_nCurrentBufferIndex = x;
				m_pSZBuffers[m_nCurrentBufferIndex].inuse = 1;
				m_pSZBuffers[m_nCurrentBufferIndex].buffer[0] = '\0';
				m_nFilledSize = 0;
				m_nCurrentBufferSize = m_nInitialBufferSize*(1 << m_nCurrentBufferIndex);
				return AXIS_SUCCESS;
			}
		}
		else /* a buffer is not yet created at this array index. So create one and use it */
		{
			m_nCurrentBufferIndex = x;
			m_nCurrentBufferSize = m_nInitialBufferSize*(1 << m_nCurrentBufferIndex);			
			m_pSZBuffers[m_nCurrentBufferIndex].buffer = new char[m_nCurrentBufferSize];
			m_pSZBuffers[m_nCurrentBufferIndex].inuse = 1;
			m_pSZBuffers[m_nCurrentBufferIndex].buffer[0] = '\0';
			m_nFilledSize = 0;
			return AXIS_SUCCESS;
		}
	}
	AXISTRACE1("No buffers left for serialization");
	return AXIS_FAIL;
}

int SoapSerializer::CreateSoapMethod(const AxisChar* sLocalName, const AxisChar* sURI)
{
	SoapMethod* pMethod = new SoapMethod();
	setSoapMethod(pMethod);
	pMethod->setLocalName(sLocalName);
	pMethod->setPrefix(GetNamespacePrefix(sURI));
	pMethod->setUri(sURI);
	return AXIS_SUCCESS;
}

/**
 * Used to create an ArrayBean when the return type of a method is an array
 * of basic types
 */
IArrayBean* SoapSerializer::makeArrayBean(XSDTYPE nType, void* pArray)
{
	ArrayBean* pAb = new ArrayBean();
	pAb->m_type = nType;
	pAb->m_value.sta = pArray;
	return pAb;
}

/**
 * Used to create an ArrayBean when the return type of a method is an array
 * of complex types
 */
IArrayBean* SoapSerializer::makeArrayBean(void* pObject, void* pSZFunct, void* pDelFunct, void* pSizeFunct)
{
	ArrayBean* pAb = new ArrayBean();
	pAb->m_type = USER_TYPE;
	pAb->m_value.cta = new ComplexObjectHandler;
	pAb->m_value.cta->pSZFunct = (AXIS_SERIALIZE_FUNCT)pSZFunct;
	pAb->m_value.cta->pDelFunct = (AXIS_OBJECT_DELETE_FUNCT)pDelFunct;
	pAb->m_value.cta->pSizeFunct = (AXIS_OBJECT_SIZE_FUNCT)pSizeFunct;
	pAb->m_value.cta->pObject = pObject;
	return pAb;
}

IHeaderBlock* SoapSerializer::createHeaderBlock()
{
	HeaderBlock* pHeaderBlock= new HeaderBlock();
	setHeaderBlock(pHeaderBlock);
	return pHeaderBlock;
}

int SoapSerializer::setHeaderBlock(HeaderBlock *pHeaderBlock)
{
	int intStatus= AXIS_FAIL;

	if((m_pSoapEnvelope)&& (m_pSoapEnvelope->m_pSoapHeader)) {
		//no need to create a SOAP Header, it already exists
	} else {
		SoapHeader* pSoapHeader= new SoapHeader();
		setSoapHeader(pSoapHeader);
	}

	m_pSoapEnvelope->m_pSoapHeader->addHeaderBlock(pHeaderBlock);
	intStatus= AXIS_SUCCESS;

	return intStatus;
}

/*
 *This method not only removes the existing SoapHeader, but also removes
 * all the existing HeaderBlocks which are associated with this SoapHeader.
 * Therefore the caller of this method has to be exactly sure whether he wants to
 * do this.
 */
int SoapSerializer::removeSoapHeader()
{
	delete m_pSoapEnvelope->m_pSoapHeader;
	m_pSoapEnvelope->m_pSoapHeader= NULL;

	return AXIS_SUCCESS;
}

/**
 * Used to Serialize an array of complex types inside a complex type. Called from within the Serialize wrapper
 * method of the complex type.
 */
int SoapSerializer::SerializeCmplxArray(const Axis_Array* pArray, void* pSZFunct, void* pDelFunct, void* pSizeFunct, const AxisChar* pName, const AxisChar* pNamespace)
{
	ArrayBean* pAb = (ArrayBean*)makeArrayBean((void*)(pArray->m_Array), pSZFunct, pDelFunct, pSizeFunct);
	pAb->SetDimension(pArray->m_Size);
	Param* pParam = new Param();
	if (RPC_ENCODED == m_nStyle)
	{
		pAb->SetItemName("item");
		pAb->SetTypeName(pName);
		pAb->SetUri(pNamespace);
		pParam->SetName(pName);
	}
	else
	{
		pAb->SetItemName(pName);
		pParam->SetName("array");		
	}
	pParam->m_Value.pIArray = pAb;
	pParam->m_Type = XSD_ARRAY;
	pParam->serialize(*this);
	/* Remove pointer to the array from the ArrayBean to avoid deleting the array when ArrayBean is deleted 
	   Array will be deleted when the complex type that contains this array is deleted */
	pAb->RemoveArrayPointer();
	delete pParam;
	return AXIS_SUCCESS;
}

/**
 * Used to Serialize an array of basic types inside a complex type. Called from within the Serialize wrapper
 * method of the complex type.
 */
int SoapSerializer::SerializeBasicArray(const Axis_Array* pArray, XSDTYPE nType, const AxisChar* pName)
{
	ArrayBean* pAb = (ArrayBean*)makeArrayBean(nType, (void*)(pArray->m_Array));
	pAb->SetDimension(pArray->m_Size);
	Param* pParam = new Param();
	if (RPC_ENCODED == m_nStyle)
	{
		pAb->SetItemName("item");
		pParam->SetName(pName);
	}
	else
	{
		pAb->SetItemName(pName);
		pParam->SetName("array");		
	}
	pParam->m_Value.pIArray = pAb;
	pParam->m_Type = XSD_ARRAY;
	pParam->serialize(*this);
	/* Remove pointer to the array from the ArrayBean to avoid deleting the array when ArrayBean is deleted 
	   Array will be deleted when the complex type that contains this array is deleted */
	pAb->RemoveArrayPointer();
	delete pParam;
	return AXIS_SUCCESS;
}

/**
 * Basic output parameter going to be serialized as an Element later
 */
int SoapSerializer::AddOutputParam(const AxisChar* pchName, void* pValue, XSDTYPE type)
{
	Param* pParam = new Param();
	if (!pParam) return AXIS_FAIL;
	pParam->m_Type = type;
	pParam->m_sName = pchName;
	switch(type)
	{
	case XSD_INT:
	case XSD_BOOLEAN:
		pParam->m_Value.nValue = *((int*)(pValue));
		break; 
    case XSD_UNSIGNEDINT:
		pParam->m_Value.unValue = *((unsigned int*)(pValue));
		break;           
    case XSD_SHORT:
		pParam->m_Value.sValue = *((short*)(pValue));
		break; 
    case XSD_UNSIGNEDSHORT:
		pParam->m_Value.usValue = *((unsigned short*)(pValue));
		break;         
    case XSD_BYTE:
		pParam->m_Value.cValue = *((char*)(pValue));
		break; 
    case XSD_UNSIGNEDBYTE:
		pParam->m_Value.ucValue = *((unsigned char*)(pValue));
		break;
    case XSD_LONG:
    case XSD_INTEGER:
	case XSD_DURATION:
		pParam->m_Value.lValue = *((long*)(pValue));
		break;        
    case XSD_UNSIGNEDLONG:
		pParam->m_Value.ulValue = *((unsigned long*)(pValue));
		break;
	case XSD_FLOAT:
		pParam->m_Value.fValue = *((float*)(pValue));
		break;
    case XSD_DOUBLE:
    case XSD_DECIMAL:
		pParam->m_Value.dValue = *((double*)(pValue));
		break;              
	case XSD_STRING:
		pParam->m_Value.pStrValue = *((char**)(pValue));
		break;
	case XSD_HEXBINARY:
		pParam->m_Value.hbValue = *((xsd__hexBinary*)(pValue));
		break;
	case XSD_BASE64BINARY:
		pParam->m_Value.b64bValue = *((xsd__base64Binary*)(pValue));
		break;
    case XSD_DATETIME:
    case XSD_DATE:
    case XSD_TIME:
		pParam->m_Value.tValue = *((struct tm*)(pValue));
        break; 
	default:
		delete pParam;
		return AXIS_FAIL;
	}
	if(m_pSoapEnvelope && (m_pSoapEnvelope->m_pSoapBody) && (m_pSoapEnvelope->m_pSoapBody->m_pSoapMethod)) 
	{
		m_pSoapEnvelope->m_pSoapBody->m_pSoapMethod->AddOutputParam(pParam);
	}
	else
	{
		delete pParam;
		return AXIS_FAIL;
	}	
	return AXIS_SUCCESS;
}

int SoapSerializer::SerializeAsElement(const AxisChar* pName, void* pValue, XSDTYPE type)
{
	const AxisChar* pSerialized = m_BTSZ.SerializeAsElement(pName, pValue, type);
	if (pSerialized)
	{
		*this << pSerialized;
		return AXIS_SUCCESS;
	}
	else
	{
		return AXIS_FAIL;
	}
}

int SoapSerializer::SerializeAsAttribute(const AxisChar* pName, const AxisChar* pNamespace, void* pValue, XSDTYPE type)
{
	const AxisChar* pPrefix = NULL;
	if (pNamespace)
	{
		pPrefix = GetNamespacePrefix(pNamespace);
	}
	const AxisChar* pSerialized = m_BTSZ.SerializeAsAttribute(pName, pPrefix, pValue, type);
	if (pSerialized)
	{
		*this << pSerialized;
		return AXIS_SUCCESS;
	}
	else
	{
		return AXIS_FAIL;
	}
}

void SoapSerializer::Serialize(const char* pFirst, ...)
{
	va_list vList;
	const char* pArg;
	if (pFirst) *this << pFirst;
	va_start( vList, pFirst );     /* Initialize variable arguments. */
	do
	{
		pArg = va_arg( vList, const char*);
		if (pArg)
			*this << pArg;
	}
	while (pArg != NULL);
	va_end( vList);              /* Reset variable arguments.      */
}

/**
 * Used probably by a handler to add a header block to the Serializer. 
 */
int SoapSerializer::AddHeaderBlock(IHeaderBlock* pBlk)
{
	if (m_pSoapEnvelope)
	{
		if(!m_pSoapEnvelope->m_pSoapHeader) m_pSoapEnvelope->m_pSoapHeader = new SoapHeader();
	}
	else /* error : by this time there should be an envelope */
	{
		return AXIS_FAIL;
	}
	m_pSoapEnvelope->m_pSoapHeader->addHeaderBlock((HeaderBlock*)pBlk);
	return AXIS_SUCCESS;
}

int SoapSerializer::SetBodyAsHexBinary(xsd__hexBinary body)
{
	/*TODO*/
	return AXIS_SUCCESS;
}

int SoapSerializer::SetBodyAsBase64Binary(xsd__base64Binary body)
{
	/*TODO*/	
	return AXIS_SUCCESS;
}

const AxisChar* SoapSerializer::GetBodyAsString()
{
	/*TODO*/	
	return NULL;
}

/**
 * Callback function that should be called by the transport module to release a buffer passed to it by a Serializer. 
 * @param 
 *		buffer - Same buffer passed to transport by calling transport's AXIS_MODULE_CALLBACK_SEND_MESSAGE_BYTES 
 *				 callback
 *		buffer - Same bufferid passed to transport by calling transport's AXIS_MODULE_CALLBACK_SEND_MESSAGE_BYTES 
 *				 callback
 *		stream - Same stream object passed to transport by calling transport's AXIS_MODULE_CALLBACK_SEND_MESSAGE_BYTES 
 *				 callback
 */
void axis_buffer_release(const char* buffer, const void* bufferid, const void* stream)
{
	int* pInt = (int*)bufferid;
	*pInt = 0; /* set that the buffer is not in use */
	char *pChar = const_cast<char*>(buffer);
	pChar[0] = '\0'; /* set nul */ 
}


