blob: 6435102e63046023b6518b902f803f791341ce97 [file] [log] [blame]
/*
* Copyright 2003-2004 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.
*
* @author Sanjaya Singharage
* @author Suasntha Kumara (skumara@virtusa.com, susantha@opensource.lk)
*
*/
// !!! This include file must be first thing in file !!!
#include "../platforms/PlatformAutoSense.hpp"
#include "WSDDDocument.h"
#include "WSDDKeywords.h"
#include "../engine/XMLParserFactory.h"
#include "../common/AxisTrace.h"
#define NAMESPACESEPARATOR 0x03 /* Heart */
#define FILEBUFFSIZE 1024
AXIS_CPP_NAMESPACE_START
WSDDDocument::
WSDDDocument(map<AxisString, int>* pLibNameIdMap)
{
m_lev0 = WSDD_UNKNOWN;
m_lev1 = WSDD_UNKNOWN;
m_lev2 = WSDD_UNKNOWN;
m_CurTrType = APTHTTP1_1; /* default is HTTP */
m_nLibId = 0;
m_pLibNameIdMap = pLibNameIdMap;
/* Get the maximum Lib Id from the entries in the map if available */
for (map<AxisString, int>::iterator itr = m_pLibNameIdMap->begin();
itr != m_pLibNameIdMap->end(); itr++)
{
if (m_nLibId < (*itr).second) m_nLibId = (*itr).second;
}
m_bFatalError = false;
m_bError = false;
}
WSDDDocument::
~WSDDDocument()
{
}
int WSDDDocument::
getDeployment(const AxisChar* pcWSDDFileName, WSDDDeployment* pDeployment)
{
m_pDeployment = pDeployment;
/* this enables the access to Deployment object while parsing */
if (AXIS_SUCCESS != parseDocument(pcWSDDFileName))
{
return AXIS_FAIL;
}
return AXIS_SUCCESS;
}
/* This function is never called. */
AXIS_TRANSPORT_STATUS WSDDDocument::
WSDDFileInputStream::sendBytes(const char* pcSendBuffer, const void* pBufferid)
{
return TRANSPORT_FINISHED;
}
AXIS_TRANSPORT_STATUS WSDDDocument::WSDDFileInputStream::
getBytes(char* pcBuffer, int* piRetSize)
{
/* open in binary because on ebcdic platforms the data will get converted */
if (!m_pFile)
m_pFile = fopen(m_pcWSDDFileName, "rb");
if (NULL == m_pFile)
return TRANSPORT_FAILED;
if (feof(m_pFile))
{
fclose(m_pFile);
pcBuffer[0]=0; /* put null */
*piRetSize = 0;
return TRANSPORT_FINISHED;
}
*piRetSize = fread(pcBuffer, 1, *piRetSize, m_pFile);
if (ferror(m_pFile))
{
fclose(m_pFile);
pcBuffer[0]=0; /* put null */
*piRetSize = 0;
return TRANSPORT_FAILED;
}
return TRANSPORT_IN_PROGRESS;
}
/* This function is never called. */
AXIS_TRANSPORT_STATUS WSDDDocument::
WSDDMemBufInputStream::sendBytes(const char* pcSendBuffer, const void* pBufferid)
{
return TRANSPORT_FINISHED;
}
AXIS_TRANSPORT_STATUS WSDDDocument::
WSDDMemBufInputStream::getBytes(char* pcBuffer, int* piRetSize)
{
if (!m_pcWSDDMemBuffer)
return TRANSPORT_FAILED;
int nBufLen = strlen(m_pcWSDDMemBuffer);
if (0 == nBufLen)
{
pcBuffer[0]=0; /* put null */
*piRetSize = 0;
return TRANSPORT_FINISHED;
}
nBufLen = ((*piRetSize - 1) < nBufLen) ? (*piRetSize - 1) : nBufLen;
strncpy(pcBuffer, m_pcWSDDMemBuffer, nBufLen);
pcBuffer[nBufLen] = 0;
m_pcWSDDMemBuffer+=nBufLen;
*piRetSize = nBufLen;
return TRANSPORT_IN_PROGRESS;
}
int WSDDDocument::
parseDocument(const AxisChar* pcWSDDFileName)
{
if (!pcWSDDFileName)
return AXIS_FAIL;
XMLParser* pParser = XMLParserFactory::getParserObject();
if (!pParser)
{
return AXIS_FAIL;
}
WSDDFileInputStream stream(pcWSDDFileName);
pParser->setInputStream(&stream);
const AnyElement* pNode;
while(true)
{
/* We are lucky as long as there is no useful data as character data
* in wsdd. If there are any we are in trouble and we will not be able
* to use the same parser which is used to parse SOAP. Now we never
* ask for character data events. To support character data in a
* wsdd this entire file will have to be re-written in true
* XML PULL model
*/
pNode = pParser->next();
if (AXIS_FAIL == pParser->getStatus())
{
XMLParserFactory::destroyParserObject(pParser);
return AXIS_FAIL;
}
if (!pNode) break;
switch(pNode->m_type)
{
case START_ELEMENT:
startElement(pNode);
break;
case CHARACTER_ELEMENT:
/* Not used at the moment */
break;
case END_ELEMENT:
endElement(pNode);
break;
default:
break;
}
}
XMLParserFactory::destroyParserObject(pParser);
return AXIS_SUCCESS;
}
int WSDDDocument::
updateDeployment(const AxisChar* pcWSDDMemBuffer, WSDDDeployment* pDeployment)
{
m_pDeployment = pDeployment;/* this enables the access to Deployment
object while parsing */
if (!pcWSDDMemBuffer)
return AXIS_FAIL;
WSDDMemBufInputStream stream(pcWSDDMemBuffer);
XMLParser* pParser = XMLParserFactory::getParserObject();
if (!pParser)
return AXIS_FAIL;
pParser->setInputStream(&stream);
const AnyElement* pNode;
while(true)
{
/* We are lucky as long as there is no useful data as character data
* in wsdd. If there are any we are in trouble and we will not be able
* to use the same parser which is used to parse SOAP. Now we never
* ask for character data events. To support character data in a
* wsdd this entire file will have to be re-written in true
* XML PULL model
*/
pNode = pParser->next();
if (AXIS_FAIL == pParser->getStatus())
return AXIS_FAIL;
if (!pNode)
break;
switch(pNode->m_type)
{
case START_ELEMENT:
startElement(pNode);
break;
case CHARACTER_ELEMENT:
/* Not used at the moment */
break;
case END_ELEMENT:
endElement(pNode);
break;
default:
break;
}
}
XMLParserFactory::destroyParserObject(pParser);
return AXIS_SUCCESS;
}
void WSDDDocument::
endElement(const AnyElement* pEvent)
{
/* just neglect endElement of parameter */
if (0 == strcmp(pEvent->m_pchNameOrValue, kw_param))
return;
if (m_lev1 == WSDD_UNKNOWN)
{
/* not inside a requestFlow or responseFlow elements */
switch(m_lev0)
{
case WSDD_DEPLOYMENT:
m_lev0 = WSDD_UNKNOWN;
break;
case WSDD_GLOBCONF:
m_lev0 = WSDD_DEPLOYMENT;
break;
case WSDD_SERVICE:
if (0 == strcmp(pEvent->m_pchNameOrValue, kw_srv))
{
/* add service object to Deployment object */
if (DT_DEPLOYMENT == m_pDeployment->getDeploymentType())
m_pDeployment->addService(m_pService);
else
m_pDeployment->removeService(m_pService);
m_pService = NULL;
m_lev0 = WSDD_DEPLOYMENT;
}
break;
case WSDD_HANDLER:
/* just ignore the handlers defined outside ??? TODO */
delete m_pHandler;
m_pHandler = NULL;
m_lev0 = WSDD_DEPLOYMENT;
break;
case WSDD_TRANSPORT:
m_CurTrType = APTHTTP1_1; /* default is HTTP */
m_lev0 = WSDD_DEPLOYMENT;
break;
break;
default:
;
}
}
/* inside a requestFlow or responseFlow elements */
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_hdl))
{
m_lev2 = WSDD_UNKNOWN;
/* add handler in m_pHandler to the corresponding container. */
switch (m_lev0)
{
case WSDD_GLOBCONF:
{
if (DT_DEPLOYMENT == m_pDeployment->getDeploymentType())
m_pDeployment->addHandler(true,(m_lev1 == WSDD_REQFLOW), m_pHandler);
else
m_pDeployment->removeHandler(true,(m_lev1 == WSDD_REQFLOW), m_pHandler);
m_pHandler = NULL;
break;
}
case WSDD_TRANSPORT:
{
if (DT_DEPLOYMENT == m_pDeployment->getDeploymentType())
m_pDeployment->addHandler(false,(m_lev1 == WSDD_REQFLOW), m_pHandler, m_CurTrType);
else
m_pDeployment->removeHandler(false,(m_lev1 == WSDD_REQFLOW), m_pHandler, m_CurTrType);
m_pHandler = NULL;
break;
}
case WSDD_SERVICE:
{
if (DT_DEPLOYMENT == m_pDeployment->getDeploymentType())
m_pService->addHandler((m_lev1 == WSDD_REQFLOW), m_pHandler);
else
m_pService->removeHandler((m_lev1 == WSDD_REQFLOW) , m_pHandler);
m_pHandler = NULL;
break;
}
default: ; /* this cannot happen ?? */
}
}
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_rqf))
m_lev1 = WSDD_UNKNOWN;
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_rsf))
m_lev1 = WSDD_UNKNOWN;
}
void WSDDDocument::
processAttributes(WSDDLevels eElementType, const AnyElement* pEvent)
{
const XML_Ch* pcLocalname;
const XML_Ch* pcNamespace;
const XML_Ch* pcValue;
for (int i=0; pEvent->m_pchAttributes[i]; i+=3)
{
pcLocalname = pEvent->m_pchAttributes[i];
pcNamespace = pEvent->m_pchAttributes[i+1];
pcValue = pEvent->m_pchAttributes[i+2];
switch(eElementType)
{
case WSDD_SERVICE:
/* add this attribute to current service object */
if (0 == strcmp(pcLocalname, kw_name))
m_pService->setName(pcValue);
else if (0 == strcmp(pcLocalname, kw_prv))
m_pService->setProvider(pcValue);
else if (0 == strcmp(pcLocalname, kw_desc))
m_pService->setDescription(pcValue);
break;
case WSDD_HANDLER:
/* add this attribute to current handler object */
if (0 == strcmp(pcLocalname, kw_name))
m_pHandler->setName(pcValue);
else if (0 == strcmp(pcLocalname, kw_type))
{
/* we get the libname for the handler here ??? */
m_pHandler->setLibName(pcValue);
/* add to map if libray name not already in the map */
if (m_pLibNameIdMap->find(pcValue) == m_pLibNameIdMap->end())
(*m_pLibNameIdMap)[pcValue] = ++m_nLibId;
m_pHandler->setLibId((*m_pLibNameIdMap)[pcValue]);
}
else if (0 == strcmp(pcLocalname, kw_desc))
m_pHandler->setDescription(pcValue);
break;
case WSDD_REQFLOW:
case WSDD_RESFLOW:
if (0 == strcmp(pcLocalname, kw_name))
{
/* usefull ? ignore for now .. TODO */
}
break;
case WSDD_TRANSPORT:
if (0 == strcmp(pcLocalname, kw_name))
{
/* get tranport type */
if (0 == strcmp(pcValue, kw_http))
m_CurTrType = APTHTTP1_1;
else if (0 == strcmp(pcValue, kw_smtp))
m_CurTrType = APTSMTP;
}
break;
default:;
}
}
}
void WSDDDocument::
getParameters(WSDDLevels eElementType, const AnyElement* pEvent)
{
const XML_Ch* pcLocalname;
const XML_Ch* pcNamespace;
const XML_Ch* pcValue = 0;
const XML_Ch* pcType;
const XML_Ch* pcName = 0;
for (int i=0; pEvent->m_pchAttributes[i]; i+=3)
{
pcLocalname = pEvent->m_pchAttributes[i];
pcNamespace = pEvent->m_pchAttributes[i+1];
pcValue = pEvent->m_pchAttributes[i+2];
if (0 == strcmp(pcLocalname, kw_name))
pcName = pcValue;
else if (0 == strcmp(pcLocalname, kw_type))
pcType = pcValue;
}
switch(eElementType)
{
case WSDD_GLOBCONF: /* parameters just inside globalConfiguration */
/* TODO */
break;
case WSDD_SERVICE:
if (0 == strcmp(pcName, kw_am))
addAllowedMethodsToService(pcValue);
else if(0 == strcmp(pcName, kw_cn))
{
m_pService->setLibName(pcValue);
/* add to map if libray name not already in the map */
if (m_pLibNameIdMap->find(pcValue) == m_pLibNameIdMap->end())
(*m_pLibNameIdMap)[pcValue] = ++m_nLibId;
m_pService->setLibId((*m_pLibNameIdMap)[pcValue]);
}
else if (0 == strcmp(pcName, kw_scope))
m_pService->setScope(pcValue);
else if (0 == strcmp(pcName, kw_ar))
addAllowedRolesToService(pcValue);
else
m_pService->addParameter(pcName, pcValue);
break;
case WSDD_HANDLER:
if (0 == strcmp(pcName, kw_scope))
m_pHandler->setScope(pcValue);
else
m_pHandler->addParameter(pcName, pcValue);
break;
default:;
}
}
void WSDDDocument::
addAllowedRolesToService(const AxisXMLCh* pcValue)
{
AxisString sValue = pcValue;
unsigned int prepos = 0, pos = 0;
if (sValue.find('*') == AxisString::npos)
{
do
{
pos = sValue.find(ROLENAME_SEPARATOR, prepos);
if (AxisString::npos == pos)
break;
m_pService->addAllowedRole(sValue.substr(prepos, pos-prepos).c_str());
prepos = pos + 1;
}
while (true);
}
}
void WSDDDocument::
addAllowedMethodsToService(const AxisXMLCh* pcValue)
{
AxisString sValue = pcValue;
unsigned int prepos = 0, pos = 0;
if (sValue.find('*') == AxisString::npos)
{
do
{
pos = sValue.find(METHODNAME_SEPARATOR, prepos);
if (AxisString::npos == pos) // Handle the case of no trailing space in AllowedMethods
pos = sValue.size();
if (pos <= prepos)
break;
m_pService->addAllowedMethod(sValue.substr(prepos, pos-prepos).c_str());
prepos = pos + 1;
}
while (true);
}
else
m_pService->addAllowedMethod("*");
}
void WSDDDocument::
startElement(const AnyElement* pEvent)
{
if (m_lev1 == WSDD_UNKNOWN)
/* not inside a requestFlow or responseFlow elements */
{
switch(m_lev0)
{
case WSDD_UNKNOWN:
if(0 == strcmp(pEvent->m_pchNameOrValue, kw_depl))
{
m_lev0 = WSDD_DEPLOYMENT;
m_pDeployment->setDeploymentType(DT_DEPLOYMENT);
}
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_undepl))
{
m_lev0 = WSDD_DEPLOYMENT;
m_pDeployment->setDeploymentType(DT_UNDEPLOYMENT);
}
break;
case WSDD_DEPLOYMENT:
if(0 == strcmp(pEvent->m_pchNameOrValue, kw_glconf))
m_lev0 = WSDD_GLOBCONF;
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_srv))
{
/* get service name and provider if any */
m_lev0 = WSDD_SERVICE;
m_pService = new WSDDService();
processAttributes(WSDD_SERVICE, pEvent);
}
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_hdl))
{
/* get handler name and type if any */
m_lev0 = WSDD_HANDLER;
m_pHandler = new WSDDHandler();
processAttributes(WSDD_HANDLER, pEvent);
}
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_tr))
{
m_lev0 = WSDD_TRANSPORT;
processAttributes(WSDD_TRANSPORT, pEvent);
}
break;
case WSDD_GLOBCONF:
if(0 == strcmp(pEvent->m_pchNameOrValue, kw_param))
getParameters(WSDD_GLOBCONF, pEvent);
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_rqf))
{
m_lev1 = WSDD_REQFLOW;
processAttributes(WSDD_REQFLOW, pEvent);
}
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_rsf))
{
m_lev1 = WSDD_RESFLOW;
processAttributes(WSDD_RESFLOW, pEvent);
}
break;
case WSDD_SERVICE:
if(0 == strcmp(pEvent->m_pchNameOrValue, kw_param))
getParameters(WSDD_SERVICE, pEvent);
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_rqf))
{
m_lev1 = WSDD_REQFLOW;
processAttributes(WSDD_REQFLOW, pEvent);
}
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_rsf))
{
m_lev1 = WSDD_RESFLOW;
processAttributes(WSDD_RESFLOW, pEvent);
}
break;
case WSDD_HANDLER:
if(0 == strcmp(pEvent->m_pchNameOrValue, kw_param))
getParameters(WSDD_HANDLER, pEvent);
break;
case WSDD_TRANSPORT:
if(0 == strcmp(pEvent->m_pchNameOrValue, kw_rqf))
{
m_lev1 = WSDD_REQFLOW;
processAttributes(WSDD_REQFLOW, pEvent);
}
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_rsf))
{
m_lev1 = WSDD_RESFLOW;
processAttributes(WSDD_RESFLOW, pEvent);
}
break;
default:;
}
}
/* inside a requestFlow or responseFlow elements */
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_param))
{
/* must be parameters of a handler or a chain */
getParameters(m_lev2, pEvent);
}
else if(0 == strcmp(pEvent->m_pchNameOrValue, kw_hdl))
{
/* get handler name and type if any */
m_lev2 = WSDD_HANDLER;
m_pHandler = new WSDDHandler();
processAttributes(WSDD_HANDLER, pEvent);
}
}
AXIS_CPP_NAMESPACE_END