blob: 32e880804325927648098b4db91210cd5efa261e [file]
/*
* 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 Susantha Kumara (skumara@virtusa.com)
*
*/
#ifdef WIN32
#pragma warning (disable : 4786)
#endif
#include <axis/xml/Event.h>
#include <axis/xml/Attribute.h>
#include <axis/xml/StartElement.h>
using namespace axisxml;
#include <axis/soap/SoapParserExpat.h>
/*
#include <axis/common/TypeMapping.h>
#include <axis/soap/URIMapping.h>
#include <axis/soap/Attribute.h>
#include <axis/soap/SoapEnvVersions.h>
#include <axis/soap/CharacterElement.h>
#include <axis/common/AxisUtils.h>
*/
SoapParserExpat::SoapParserExpat()
{
m_pLastEvent = NULL;
m_Parser = XML_ParserCreateNS(NULL, NAMESPACESEPARATOR);
}
SoapParserExpat::~SoapParserExpat()
{
if (m_pLastEvent) delete m_pLastEvent;
}
void SoapParserExpat::startElement(const XMLCh *qname,const XMLCh **attrs)
{
QName qn;
qn.SplitQNameString(qname, NAMESPACESEPARATOR);
StartElement *pSE = new StartElement();
pSE->m_NameOrValue = qn.localname;
pSE->m_Namespace = qn.uri ? qn.uri : "";
qn.MergeQNameString(NAMESPACESEPARATOR);
Attribute *pAt = NULL;
for (int i = 0; attrs[i]; i += 2)
{
qn.SplitQNameString(attrs[i], NAMESPACESEPARATOR);
pAt = new Attribute();
pAt->m_Name = qn.localname;
pAt->m_Namespace = qn.uri;
qn.MergeQNameString(NAMESPACESEPARATOR);
pAt->m_Value = attrs[i+1];
pSE->m_Attributes.push_back(pAt);
}
m_Events.push(pSE);
}
void SoapParserExpat::endElement(const XMLCh *qname)
{
QName qn;
qn.SplitQNameString(qname, NAMESPACESEPARATOR);
EndElement *pEE = new EndElement();
pEE->m_NameOrValue = qn.localname;
pEE->m_Namespace = qn.uri ? qn.uri : "";
m_Events.push(pEE);
qn.MergeQNameString(NAMESPACESEPARATOR);
}
void SoapParserExpat::characters(const XMLCh *chars, int length)
{
XMLCh* pTemp = const_cast<XMLCh*>(chars);
XMLCh replacedchar = pTemp[length]; //copy and keep existing char at length position
pTemp[length] = '\0'; //putting nul charactor so that chars can be used safely
Event* pLastEvent;
if (!m_Events.empty())
{
pLastEvent = m_Events.back();
if (CHARACTER_ELEMENT == pLastEvent->GetType()) /* continuing same character node */
{
pLastEvent->m_NameOrValue += pTemp;
pTemp[length] = replacedchar; //put back the character that was there before putting nul charactor
return;
}
}
pLastEvent = new CharacterElement();
pLastEvent->m_NameOrValue = pTemp;
m_Events.push(pLastEvent);
pTemp[length] = replacedchar; //put back the character that was there before putting nul charactor
}
void SoapParserExpat::startPrefixMapping(const XMLCh *prefix, const XMLCh *uri)
{
StartPrefix* pEvent = new StartPrefix();
pEvent->m_NameOrValue = prefix;
pEvent->m_Namespace = uri;
m_Events.push(pEvent);
}
void SoapParserExpat::endPrefixMapping(const XMLCh *prefix)
{
EndPrefix* pEvent = new EndPrefix();
pEvent->m_NameOrValue = prefix;
m_Events.push(pEvent);
}
const XMLCh* SoapParserExpat::GetNS4Prefix(const XMLCh* prefix)
{
if (m_NsStack.find(prefix) != m_NsStack.end())
{
return m_NsStack[prefix].c_str();
}
return NULL;
}
/**
* This method returning NULL means that there is something wrong with the stream
* and hence parsing should be finished or aborted.
*/
const AnyElement* SoapParserExpat::Next()
{
int nStatus = TRANSPORT_IN_PROGRESS;
if (m_pLastEvent)
{
delete m_pLastEvent;
m_pLastEvent = NULL;
}
do
{
if (m_Events.empty())
{
nStatus = ParseNext();
if (TRANSPORT_FAILED == nStatus) return NULL;
}
if (!m_Events.empty())
{
m_pLastEvent = m_Events.front();
XML_NODE_TYPE type = m_pLastEvent->GetType();
m_Events.pop();
if ((CHARACTER_ELEMENT == type) && m_Events.empty()) /* current character element may not be parsed completly */
{
m_Events.push(m_pLastEvent);
nStatus = ParseNext();
if (TRANSPORT_FAILED == nStatus) return NULL;
}
else
{
int i = 0;
switch(type)
{
case START_ELEMENT:
{
for (list<Attribute*>::iterator it = ((StartElement*)m_pLastEvent)->m_Attributes.begin()
; it != ((StartElement*)m_pLastEvent)->m_Attributes.end(); it++)
{
m_Element.m_pchAttributes[i+0] = (*it)->m_Name.c_str();
m_Element.m_pchAttributes[i+1] = (*it)->m_Namespace.c_str();
m_Element.m_pchAttributes[i+2] = (*it)->m_Value.c_str();
i+=3;
}
m_Element.m_pchAttributes[i+0] = NULL;
m_Element.m_pchAttributes[i+1] = NULL;
m_Element.m_pchAttributes[i+2] = NULL;
}
/* no break */
case END_ELEMENT:
m_Element.m_pchNamespace = ((StartElement*)m_pLastEvent)->m_Namespace.c_str();
/* no break */
case CHARACTER_ELEMENT:
m_Element.m_pchNameOrValue = m_pLastEvent->m_NameOrValue.c_str();
m_Element.m_type = type;
return &m_Element;
case START_PREFIX:
m_NsStack[m_pLastEvent->m_NameOrValue] = ((StartPrefix*)m_pLastEvent)->m_Namespace; //I think the same prifix cannot repeat ???
delete m_pLastEvent;
m_pLastEvent = NULL;
break;
case END_PREFIX:
m_NsStack.erase(m_pLastEvent->m_NameOrValue); //I think the same prifix cannot repeat ??? */
delete m_pLastEvent;
m_pLastEvent = NULL;
break;
}
}
}
} while (TRANSPORT_FAILED != nStatus);
return NULL;
}
int SoapParserExpat::ParseNext()
{
int nStatus;
int nChars = 0;
nStatus = m_pInputStream->transport.pGetFunct(&m_pCurrentBuffer, &nChars, m_pInputStream);
if ((nChars > 0) && m_pCurrentBuffer) /* there can be a buffer or not */
{
if (XML_STATUS_ERROR == XML_Parse(m_Parser, m_pCurrentBuffer, nChars, false))
m_nStatus = AXIS_FAIL;
m_pInputStream->transport.pRelBufFunct(m_pCurrentBuffer, m_pInputStream);
}
if (TRANSPORT_FAILED == nStatus) XML_Parse(m_Parser, NULL, 0, true); /* end of parsing */
return nStatus;
}
int SoapParserExpat::GetStatus()
{
m_nStatus = AXIS_SUCCESS; /*TODO:Check if an error occured in expat */
return m_nStatus;
}
/**
* Resets SoapParserExpat object
*/
int SoapParserExpat::Init()
{
XML_ParserReset(m_Parser, NULL);
XML_SetUserData(m_Parser, this);
XML_SetNamespaceDeclHandler(m_Parser, s_startPrefixMapping, s_endPrefixMapping);
XML_SetElementHandler(m_Parser, s_startElement, s_endElement);
XML_SetCharacterDataHandler(m_Parser, s_characters);
m_nStatus = AXIS_SUCCESS; /*TODO:Check if an error occured in expat */
m_NsStack.clear(); /* this will also delete any strings there */
if (m_pLastEvent) delete m_pLastEvent;
while (!m_Events.empty())
{
m_pLastEvent = m_Events.front();
m_Events.pop();
delete m_pLastEvent;
}
m_pLastEvent = NULL;
return m_nStatus;
}
int SoapParserExpat::SetInputStream(const Ax_soapstream* pInputStream)
{
m_pInputStream = pInputStream;
return AXIS_SUCCESS;
}