C++WSP: A C++ Web Services Platform
by Khushnood Naqvi and Yassar Sharaafath C.A. 

Figure 1:
POST /StockQuote HTTP/1.1
Host: www.stockquoteserver.com
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
SOAPAction: "Some-URI"
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
        SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <SOAP-ENV:Body>
        <m:GetLastTradePrice xmlns:m="Some-URI">
                <symbol>DIS</symbol>
            </m:GetLastTradePrice>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>


Figure 2:

HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn

<SOAP-ENV:Envelopexmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
        SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    <SOAP-ENV:Body>
        <m:GetLastTradePriceResponse xmlns:m="Some-URI">
            <Price>34.5</Price>
        </m:GetLastTradePriceResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Example 1:
// Sample SOAP interface.
typedef struct ResponseStruct
{
    int status;
    char * message;
} Response;
// struct ReponseStruct & rS
int ns__trySoap(char * name, Response * rS);

Example 2:
// Implementation of SOAP Interface. This macro is required to be 
// called to register the functions soap_init(), soap_serve(), and 
// soap_end() to the SOAPHandlerFactory
REGISTER_SOAP_RESOURCE("trysoap", trysoap)
int ns__trySoap(struct soap * s, char * name, Response * rS)
{
    rS->status = 1;
    char tempStr[250];
    strcpy(tempStr, "\"Hello ");
    if(name == NULL || strlen(name) > 100)
        return SOAP_CLI_FAULT;
    strcat(tempStr,  name);
    strcat (tempStr, "\" says ns__trySoap");
    rS->message = strdup(tempStr);
    return SOAP_OK;
}

Example 3:
// soap application test client main program
  soap_init(&soap); // must initialize
  Response rs;
  if (soap_call_ns__trySoap(&soap, queryStr, NULL, name, &rs) == 0)
    printf("\nStatus - %d    Message - %s\n", rs.status, rs.message);
  else
  { soap_print_fault(&soap, stderr);
    soap_print_fault_location(&soap, stderr);
  }
  return 0;

Example 4:
typedef  void (*soap_init_fn)(struct soap *); 
typedef  int (*soap_serve_fn)(struct soap *);  
typedef  void (*soap_end_fn)(struct soap*); 
struct SOAPHandlerStruct
{
    soap_init_fn soap_init_fn_ptr;
    soap_serve_fn soap_serve_fn_ptr;
    soap_end_fn soap_end_fn_ptr;
};


Listing One
// Web.xml for SOAP application configuration
    <!-- Context parameters for the web application as key value pairs -- >
    <!-- Information about the SOAP applications deployed -- >
    <context-param>
        <param-name> quote </param-name>
        <param-value> quoteEx.dll </param-value>
    </context-param>
        <context-param>
        <param-name> trysoap </param-name>
        <param-value> trysoap.dll </param-value>
    </context-param>
    <!-- Information about the deployed servlets -->
    <servlet>
       <servlet-name> SOAPServlet </servlet-name>
        <description>
            Handler of SOAP requests. SOAP servlet Application as viewed by 
            servlet container and SOAP handler as viewed by SOAP applications.
        </description>
              <!-Servlet initialization parameters as key value pairs -- >
        <init-param>
            <param-name> soap_app_location </param-name>
            <param-value> 
                C:\Program Files\C++WSP\Apache2\cpp_servlet\soap\apps\
            </param-value>
        </init-param>     
    </servlet>


Listing Two
// Shows gSOAP structure soap containing the function pointers to default 
// implementations in fsend, fparse, frecv, fresponse variables. Also shows 
// user variable of type void *, which we use to pass HttpServletRequest 
// and HttpServletResponse objects
struct soap
{ 
  /*** Some data types deleted (not shown in the listing) ***/
  void *user;        /* reserved for callbacks to pass user-defined data */
  int (*fpost)(struct soap*, const char*, const char*, const char*, 
                                                       const char*, size_t);
  int (*fposthdr)(struct soap*, const char*, const char*);
  int (*fresponse)(struct soap*, int, size_t);
  int (*fparse)(struct soap*);
  int (*fparsehdr)(struct soap*, const char*, const char*);
  int (*fopen)(struct soap*, const char*, const char*, int);
  int (*fclose)(struct soap*);
  int (*fsend)(struct soap*, const char*, size_t);
  size_t (*frecv)(struct soap*, char*, size_t);
  int (*fignore)(struct soap*, const char*);
};


Listing Three
// definition of REGISTER_SOAP_RESOURCE macro. This macro defines a dummy 
// struct after forming a unique struct name. If SOAP_RESOURCE_NAME is Quote, 
// then struct name is dummySoapQuote. struct's constructor first sets 
// application's soap_init, soap_serve and soap_end functions' addresses to
// SOAPHandlerStruct member function pointers. Then it registers SOAP 
// Application's name (key) and application's SOAPHandlerStruct 
// instance(value) to SOAPHandlerFactory by calling registerToFactory method.
// Then invoke constructor by having a dummy instance of defined struct. For 
// instance, if app name is Quote, it evolves to dummySoapQuote 
// dummySoapInstanceQuote; When shared library of application gets loaded, 
// dummySoapInstanceQuote is instantiated. This triggers SOAP application 
// registering to the factory

#define REGISTER_SOAP_RESOURCE(SOAP_RESOURCE_NAME_STR, SOAP_RESOURCE_NAME) \
    SOAPHandlerStruct SOAPHandlerStruct##SOAP_RESOURCE_NAME##Instance; \
\
struct dummySoap##SOAP_RESOURCE_NAME { \
    dummySoap##SOAP_RESOURCE_NAME() \
{\
    SOAPHandlerStruct##SOAP_RESOURCE_NAME##Instance.soap_init_fn_ptr = 
                                                               soap_init; \
    SOAPHandlerStruct##SOAP_RESOURCE_NAME##Instance.soap_serve_fn_ptr = 
                                                               soap_serve; \
    SOAPHandlerStruct##SOAP_RESOURCE_NAME##Instance.soap_end_fn_ptr = 
                                                               soap_end; \
    SOAPHandlerFactory::registerToFactory( SOAP_RESOURCE_NAME_STR, 
                       &SOAPHandlerStruct##SOAP_RESOURCE_NAME##Instance ); \
}\
};\
    struct dummySoap##SOAP_RESOURCE_NAME 
                                    dummySoapInstance##SOAP_RESOURCE_NAME##;

Listing Four
// doGet method of the SOAPServlet.
void SOAPServlet::doGet(HttpServletRequest & req, HttpServletResponse & resp)
    throw( ServletException)
{   
    // Get the output stream object reference
    ServletOutputStream & srvltOpStream = resp.getOutputStream();
    // Get the SOAP resource id value of SOAP_RESOURCE_KEY is "soapres"
    std::string soapRes = req.getParameter(SOAP_RESOURCE_KEY);
    std::string soapResDll;
    bool soapResFound = false;
    // Initialize SOAPHandlerFactory, if not already initialized. Loads all 
    // deployed SOAP applications. Applications on loading, registers to 
    // the SOAPHandlerFactory.
    if(!SOAPHandlerFactory::Initialized())
    {
        initialize();
    }
    // Get the application specific instance of SOAPHandlerStruct
    // which has the function pointers to application's 
    // soap_init(), soap_serve() and soap_end() functions.
struct SOAPHandlerStruct * hdlrStruct = 
                SOAPHandlerFactory::getSOAPHandlerStruct(soapRes.c_str() );
    if(hdlrStruct == NULL)
    {
        // return error  
    resp.sendError(HttpServletResponse::SC_NOT_IMPLEMENTED); 
                                                      // 501 not implemented
        return;
    }
    resp.setContentType("text/xml");
    struct soap psoap;
    gsoapUserData pRqConf;
    pRqConf._srvltReq = &req;
    pRqConf._srvltResp = &resp;
    // Initialize the soap structure
    (*hdlrStruct->soap_init_fn_ptr) (&psoap);
    psoap.user = &pRqConf;
    set_callbacks(&pRqConf, &psoap);
    // Serve the SOAP request
    int nRet = (*hdlrStruct->soap_serve_fn_ptr)(&psoap);
    // cleanup the soap structure
    (*hdlrStruct->soap_end_fn_ptr)(&psoap);
    // Write output back to the client
    resp.flushBuffer();
}






1


