blob: 5b1fde77db2de8a79a9ab48219f950b3a62ba478 [file] [log] [blame]
/* -*- C++ -*- */
/*
* 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.
*/
// !!! This include file must be first thing in file !!!
#include "../../platforms/PlatformAutoSense.hpp"
#include "../../soap/SoapBody.h"
#include "../../soap/SoapMethod.h"
#include "ServerAxisEngine.h"
#include <stdio.h>
#include "../../common/AxisUtils.h"
#include "../../wsdd/WSDDDeployment.h"
#include "../HandlerPool.h"
#include "../../common/AxisTrace.h"
extern AXIS_CPP_NAMESPACE_PREFIX HandlerPool *g_pHandlerPool;
extern AXIS_CPP_NAMESPACE_PREFIX WSDDDeployment *g_pWSDDDeployment;
AXIS_CPP_NAMESPACE_START
ServerAxisEngine::
ServerAxisEngine ()
{
logEntryEngine("ServerAxisEngine::ServerAxisEngine")
m_pWebService = NULL;
logExit()
}
ServerAxisEngine::
~ServerAxisEngine ()
{
logEntryEngine("ServerAxisEngine::~ServerAxisEngine")
logExit()
}
int ServerAxisEngine::
process (SOAPTransport * pStream)
{
logEntryEngine("ServerAxisEngine::process")
int Status = 0;
int nSoapVersion;
try
{
if (!pStream)
{
logThrowException("AxisConfigException - SERVER_CONFIG_TRANSPORT_CONF_FAILED")
throw AxisConfigException (SERVER_CONFIG_TRANSPORT_CONF_FAILED);
}
string sSessionId = pStream->getSessionId ();
// After this point we should return AXIS_SUCCESS. Otherwise the transport
// layer may not send the response back (either soap fault or result).
do
{
/* populate MessageData with transport information */
m_pMsgData->m_Protocol = pStream->getProtocol ();
if (AXIS_SUCCESS != m_pDZ->setInputStream (pStream))
{
nSoapVersion = m_pDZ->getVersion ();
nSoapVersion = (nSoapVersion == VERSION_LAST) ? SOAP_VER_1_2 : nSoapVersion;
m_pSZ->setSoapVersion ((SOAP_VERSION) nSoapVersion);
logThrowException("AxisSoapException - CLIENT_SOAP_SOAP_CONTENT_ERROR")
throw AxisSoapException (CLIENT_SOAP_SOAP_CONTENT_ERROR);
}
const char *cService = pStream->getTransportProperty (SERVICE_URI);
if (!cService)
{
logThrowException("AxisSoapException - CLIENT_SOAP_SOAP_CONTENT_ERROR")
throw AxisSoapException (CLIENT_SOAP_SOAP_CONTENT_ERROR);
}
AxisString service = (cService == NULL) ? "" : cService;
if (service.empty ())
{
nSoapVersion = m_pMsgData->m_pDZ->getVersion ();
nSoapVersion = (nSoapVersion == VERSION_LAST) ? SOAP_VER_1_2 : nSoapVersion;
m_pSZ->setSoapVersion ((SOAP_VERSION) nSoapVersion);
logThrowException("AxisSoapException - CLIENT_SOAP_SOAP_ACTION_EMTPY")
throw AxisSoapException (CLIENT_SOAP_SOAP_ACTION_EMTPY);
}
// if there are quotes remove them.
if (service.find ('\"') != string::npos)
{
service = service.substr (1, service.length () - 2);
}
// get service description object from the WSDD Deployment object
m_pService = g_pWSDDDeployment->getService (service.c_str ());
if (!m_pService)
{
nSoapVersion = m_pMsgData->m_pDZ->getVersion ();
nSoapVersion = (nSoapVersion == VERSION_LAST) ? SOAP_VER_1_2 : nSoapVersion;
m_pSZ->setSoapVersion ((SOAP_VERSION) nSoapVersion);
logThrowExceptionWithData("AxisWsddException - CLIENT_WSDD_SERVICE_NOT_FOUND", service.c_str())
throw AxisWsddException (CLIENT_WSDD_SERVICE_NOT_FOUND, service.c_str());
}
m_CurrentProviderType = m_pService->getProvider ();
m_pSZ->setCurrentProviderType (m_CurrentProviderType);
m_pDZ->setCurrentProviderType (m_CurrentProviderType);
switch (m_CurrentProviderType)
{
case C_RPC_PROVIDER:
case CPP_RPC_PROVIDER:
m_pSZ->setStyle (RPC_ENCODED);
m_pDZ->setStyle (RPC_ENCODED);
break;
case C_DOC_PROVIDER:
case CPP_DOC_PROVIDER:
m_pSZ->setStyle (DOC_LITERAL);
m_pDZ->setStyle (DOC_LITERAL);
break;
case COM_PROVIDER:
// TODO: ??
break;
default:;
// TODO: ??
}
/* Check for stream version in the request and decide whether we support
* it or not. If we do not support send a soapfault with version
* mismatch.
*/
nSoapVersion = m_pDZ->getVersion ();
if (m_pDZ->getStatus () != AXIS_SUCCESS)
{
logThrowException("AxisSoapException - CLIENT_SOAP_MESSAGE_INCOMPLETE")
throw AxisSoapException (CLIENT_SOAP_MESSAGE_INCOMPLETE);
}
if (nSoapVersion == VERSION_LAST) // version not supported
{
m_pSZ->setSoapVersion (SOAP_VER_1_2);
logThrowException("AxisSoapException - SOAP_VERSION_MISMATCH")
throw AxisSoapException (SOAP_VERSION_MISMATCH);
}
/* Set Soap version in the Serializer and the envelope */
if (AXIS_SUCCESS != m_pSZ->setSoapVersion ((SOAP_VERSION) nSoapVersion))
{
logThrowException("AxisSoapException - CLIENT_SOAP_SOAP_CONTENT_ERROR")
throw AxisSoapException (CLIENT_SOAP_SOAP_CONTENT_ERROR);
}
/* Get the operation name from transport information Ex: from
* SOAPAction header
*/
if (AXIS_SUCCESS != m_pDZ->getHeader ())
{
logThrowException("AxisSoapException - CLIENT_SOAP_SOAP_CONTENT_ERROR")
throw AxisSoapException (CLIENT_SOAP_SOAP_CONTENT_ERROR);
}
if (AXIS_SUCCESS != m_pDZ->getBody ())
{
logThrowException("AxisSoapException - CLIENT_SOAP_SOAP_CONTENT_ERROR")
throw AxisSoapException (CLIENT_SOAP_SOAP_CONTENT_ERROR);
}
AxisString sOperation = m_pDZ->getMethodNameToInvoke ();
if (sOperation.empty ())
{
logThrowException("AxisSoapException - CLIENT_SOAP_NO_SOAP_METHOD")
throw AxisSoapException (CLIENT_SOAP_NO_SOAP_METHOD);
}
/* remove any quotes in the operation name */
if (sOperation.rfind ('\"') != string::npos)
{
sOperation = sOperation.substr (0, sOperation.length () - 1);
}
AxisString operationToInvoke = sOperation;
m_pMsgData->setOperationName (operationToInvoke.c_str ());
if (m_pService->isAllowedMethod (operationToInvoke.c_str ()))
{
/* load actual web service handler */
if (AXIS_SUCCESS != g_pHandlerPool->getWebService (&m_pWebService, sSessionId, m_pService))
{
logThrowException("AxisEngineException - SERVER_ENGINE_COULD_NOT_LOAD_SRV")
throw AxisEngineException(SERVER_ENGINE_COULD_NOT_LOAD_SRV);
}
/* Check whether the provider type in the wsdd matchs the service's
* binding style
*/
AXIS_BINDING_STYLE nBindingStyle = RPC_ENCODED;
if (0 != m_pWebService->_functions)
/* C service */
{
nBindingStyle = m_pWebService->_functions->getBindingStyle (m_pWebService->_object);
}
else if (0 != m_pWebService->_object)
{
nBindingStyle = ((WrapperClassHandler *)m_pWebService->_object)->getBindingStyle ();
}
if (m_pSZ->getStyle () != nBindingStyle)
{
logThrowException("AxisSoapException - CLIENT_SOAP_SOAP_CONTENT_ERROR")
throw AxisSoapException (CLIENT_SOAP_SOAP_CONTENT_ERROR);
}
}
else
{
logThrowException("AxisWsddException - CLIENT_WSDD_METHOD_NOT_ALLOWED")
throw AxisWsddException (CLIENT_WSDD_METHOD_NOT_ALLOWED);
}
// Get Global and Transport Handlers
if (AXIS_SUCCESS != (Status = initializeHandlers (sSessionId,pStream->getProtocol())))
{
logThrowException("AxisEngineException - SERVER_ENGINE_COULD_NOT_LOAD_HDL")
throw AxisEngineException (SERVER_ENGINE_COULD_NOT_LOAD_HDL);
}
// Get Service specific Handlers from the pool if configured any
if (AXIS_SUCCESS != (Status = g_pHandlerPool->getRequestFlowHandlerChain (&m_pSReqFChain,sSessionId,m_pService)))
{
logThrowException("AxisEngineException - SERVER_ENGINE_COULD_NOT_LOAD_HDL")
throw AxisEngineException (SERVER_ENGINE_COULD_NOT_LOAD_HDL);
}
if (AXIS_SUCCESS != (Status = g_pHandlerPool->getResponseFlowHandlerChain (&m_pSResFChain,sSessionId,m_pService)))
{
logThrowException("AxisEngineException - SERVER_ENGINE_COULD_NOT_LOAD_HDL")
throw AxisEngineException (SERVER_ENGINE_COULD_NOT_LOAD_HDL);
}
// Invoke all handlers
Status = invoke (m_pMsgData);
}
while (0);
if (AXIS_SUCCESS != m_pDZ->flushInputStream ())
{
}
// Get any header blocks unprocessed (left) in the Deserializer and add them
// to the Serializer. They may be headers targetted to next soap processors.
HeaderBlock *pHderBlk = NULL;
while (true)
{
pHderBlk = m_pDZ->getHeaderBlock ();
if (pHderBlk)
m_pSZ->addHeaderBlock (pHderBlk);
else
break;
}
m_pSZ->setOutputStream (pStream);
// Pool back the handlers and services
releaseHandlers (pStream);
//todo
/* An exception derived from exception which is not handled will be
* handled here. You can call a method in AxisModule which may unload
* the ServerAxisEngine from the webserver and report the error. You can
* also write this in a logfile specific to axis.
*/
}
catch (AxisException & e)
{
// An exception which is not handled will be handled here.
int iExceptionCode = e.getExceptionCode ();
if (AXISC_SERVICE_THROWN_EXCEPTION == iExceptionCode)
{
// Writes the SoapMessage in which soap body contains only Fault
m_pSZ->setOutputStream (pStream);
releaseHandlers (pStream);
return AXIS_SUCCESS;
}
else
{
/* An exception has occurred inside Axis C++ engine.(not in a
* webservice or handler). Later we handle this by coming back in here
* and serialising the fault out
*/
throw e;
}
}
catch (exception& e)
{
e = e;
logExitWithReturnCode(SERVER_UNKNOWN_ERROR)
return SERVER_UNKNOWN_ERROR;
}
catch (...)
{
logExitWithReturnCode(SERVER_UNKNOWN_ERROR)
return SERVER_UNKNOWN_ERROR;
}
logExitWithReturnCode(AXIS_SUCCESS)
return AXIS_SUCCESS;
}
int ServerAxisEngine::
invoke (MessageData * pMsg)
{
logEntryEngine("ServerAxisEngine::invoke")
enum AE_LEVEL { AE_START = 1, AE_TRH, AE_GLH, AE_SERH, AE_SERV };
int Status = AXIS_FAIL;
int level = AE_START;
do
{
// Invoke transport request handlers
if (m_pTReqFChain)
if (AXIS_SUCCESS != (Status = m_pTReqFChain->invoke (pMsg)))
{
logThrowException("AxisEngineException - SERVER_ENGINE_HANDLER_FAILED")
throw AxisEngineException (SERVER_ENGINE_HANDLER_FAILED);
}
level++; // AE_TRH
// Invoke global request handlers
if (m_pGReqFChain)
if (AXIS_SUCCESS != (Status = m_pGReqFChain->invoke (pMsg)))
{
logThrowException("AxisEngineException - SERVER_ENGINE_HANDLER_FAILED")
throw AxisEngineException (SERVER_ENGINE_HANDLER_FAILED);
}
level++; // AE_GLH
// Invoke service specific request handlers
if (m_pSReqFChain)
if (AXIS_SUCCESS != (Status = m_pSReqFChain->invoke (pMsg)))
{
logThrowException("AxisEngineException - SERVER_ENGINE_HANDLER_FAILED")
throw AxisEngineException (SERVER_ENGINE_HANDLER_FAILED);
}
level++; // AE_SERH
/*
* Before processing the soap body check whether there is any header
* blocks with mustUnderstand attribute left unprocessed in the
* Deserializer. If so return a soap fault.
*/
if (m_pDZ->isAnyMustUnderstandHeadersLeft ())
{
logThrowException("AxisSoapException - SOAP_MUST_UNDERSTAND")
throw AxisSoapException (SOAP_MUST_UNDERSTAND);
}
// Call actual web service handler
if (m_pWebService)
{
if (0 != m_pWebService->_functions)
/* C web service */
{
// Disable C support
//IMessageData_C cMC = { 0, 0 };
//cMC._object = pMsg;
//cMC._functions = &IMessageData::ms_VFtable;
//Status = m_pWebService->_functions->invoke (m_pWebService->
// _object, &cMC);
}
else if (0 != m_pWebService->_object)
Status = ((WrapperClassHandler *) m_pWebService->_object)->invoke (pMsg);
else
Status = AXIS_FAIL;
if (AXIS_SUCCESS != Status)
{
logThrowException("AxisEngineException - SERVER_ENGINE_WEBSERVICE_FAILED")
throw AxisEngineException (SERVER_ENGINE_WEBSERVICE_FAILED);
}
}
level++; // AE_SERV
}
while (0);
pMsg->setPastPivotState (true);
/*
* The case clauses in this switch statement have no breaks.
* Hence, if Everything up to web service invocation was successful
* then all response handlers are invoked. If there was a failure
* at some point the response handlers from that point onwards
* are invoked.
*/
switch (level)
{
case AE_SERV: // Everything Success.
Status = AXIS_SUCCESS;
// no break;
case AE_SERH: // Actual web service handler has failed
// Invoke web service specific response handlers
if (m_pSResFChain)
m_pSResFChain->invoke (pMsg);
// no break;
case AE_GLH: // web service specific handlers have failed
// invoke global response handlers
if (m_pGResFChain)
m_pGResFChain->invoke (pMsg);
// no break;
case AE_TRH: // Global handlers have failed
if (m_pTResFChain)
m_pTResFChain->invoke (pMsg);
// no break;
case AE_START:; // Transport handlers have failed
};
logExitWithReturnCode(Status)
return Status;
}
void ServerAxisEngine::
onFault (MessageData * pMsg)
{
logEntryEngine("ServerAxisEngine::onFault")
logExit()
}
int ServerAxisEngine::
setFaultOutputStream (int iFaultCode, SOAPTransport * pStream)
{
logEntryEngine("ServerAxisEngine::setFaultOutputStream")
string sMessage = AxisException::getMessageForExceptionCode(iFaultCode);
SoapFault *pObjSoapFault = SoapFault::getSoapFault (iFaultCode);
pObjSoapFault->setFaultDetail (sMessage.c_str ());
m_pSZ->setSoapFault (pObjSoapFault);
m_pSZ->setOutputStream (pStream);
releaseHandlers (pStream);
logExitWithReturnCode(AXIS_SUCCESS)
return AXIS_SUCCESS;
}
int ServerAxisEngine::
setFaultOutputStream (AxisException iFault, SOAPTransport * pStream)
{
logEntryEngine("ServerAxisEngine::setFaultOutputStream")
SoapFault *pObjSoapFault = SoapFault::getSoapFault (iFault.getExceptionCode());
pObjSoapFault->setFaultDetail (iFault.what());
m_pSZ->setSoapFault (pObjSoapFault);
m_pSZ->setOutputStream (pStream);
releaseHandlers (pStream);
logExitWithReturnCode(AXIS_SUCCESS)
return AXIS_SUCCESS;
}
int ServerAxisEngine::
releaseHandlers (SOAPTransport * pStream)
{
logEntryEngine("ServerAxisEngine::releaseHandlers")
string sSessionId = pStream->getSessionId ();
// Pool back the Service specific handlers
if (m_pSReqFChain)
g_pHandlerPool->poolHandlerChain (m_pSReqFChain, sSessionId);
if (m_pSResFChain)
g_pHandlerPool->poolHandlerChain (m_pSResFChain, sSessionId);
/* Pool back the Global and Transport handlers
* UnInitializeHandlers(sSessionId, stream->trtype);
* Pool back the webservice
*/
if (m_pWebService)
g_pHandlerPool->poolWebService (sSessionId, m_pWebService, m_pService);
logExitWithReturnCode(AXIS_SUCCESS)
return AXIS_SUCCESS;
}
AXIS_CPP_NAMESPACE_END