The Oracle SALT GWWS server is a configuration-driven process which, for most basic Web service applications, does not require any programming tasks. However, Oracle SALT functionality can be enhanced by developing plug-in interfaces which utilize custom typed buffer data and customized shared libraries to extend the GWWS server.A plug-in interface is a set of functions exported by a shared library that can be loaded and invoked by GWWS processes to achieve special functionality. Oracle SALT provides a plug-in framework as a common interface for defining and implementing a plug-in interface. Plug-in implementation is carried out by a shared library which contains the actual functions. The plug-in implementation library is configured in the SALT Deployment file and is loaded dynamically during GWWS server startup.Oracle SALT 10gR3 supports the P_CUSTOM_TYPE and P_CREDENMAP plug-in ID, which is used to define plug-in interfaces for custom typed buffer data handling, and map Tuxedo user ID and group ID into username/password that HTTP Basic Authentication needs.For the P_CUSTOM_TYPE Plug-in ID, the plug-in name is used to indicate the actual custom buffer type name. When the GWWS server attempts to convert data between Tuxedo custom typed buffers and an XML document, the plug-in name is the key element that searches for the proper plug-in interface.For the P_CREDENMAP ID category, one function needs to be implemented:
• int (* gwws_pi_map_http_basic) (char * domain, char * realm, char * t_userid, char * t_grpid, Cred_UserPass * credential);Returning a 0 value indicates the function has executed successfully. Returning a value other than 0 indicates failure. If this functions fails, the plug-in is not loaded and the GWWS server will not start.int _ws_pi_get_Id_and_Names(int * count, char **ids, char **names);You must return the total count of implementation in the library in arguments count. The arguments IDs and names should contains all implemented interface IDs and names, separated by a semicolon “;”.Returning a 0 value indicates the initiating function has executed successfully. Returning a value other than 0 indicates initiation has failed. If plug-in interface initiation fails, the GWWS server will not start.@ID@ indicates the actual plug-in ID value. @Name@ indicates the actual plug-in name value. For example, the initiating function of a plug-in with P_CUSTOM_TYPE as a plug-in ID and MyType as a plug-in name is: _ws_pi_init_P_CUSTOM_TYPE_MyType (char * params, void **priv_ptr).@ID@ indicates the actual plug-in ID value. @Name@ indicates the actual plug-in name value. For example, the initiating exiting function name of a plug-in with P_CUSTOM_TYPE as a plug-in ID and MyType as a plug-in name is: _ws_pi_exit_P_CUSTOM_TYPE_MyType(void * priv).vtable is a particular C structure that stores the necessary function pointers for the actual businesss logic of a plug-in interface. In other words, a valid plug-in interface must implement all the functions defined by the corresponding vtable.@ID@ indicates the actual plug-in ID value. @Name@ indicates the actual plug-in name value. For example, the vtable setting function of a plug-in with P_CUSTOM_TYPE as a plug-in ID and MyType as a plug-in name is: _ws_pi_set_vtbl_P_CUSTOM_TYPE_MyType(void * priv).The vtable structures may be different for different plug-in ID categories. For the Oracle SALT 10gR3 release, P_CUSTOM_TYPE and P_CREDENMAP are the only valid plug-in IDs.Listing 5‑1 VTable Structurestruct credmap_vtable indicates that one function need to be implemented for a P_CREDENMAP plug-in interface. For more information, see Programming Outbound Authentication Plug-Ins.The function input parameter void * priv points to a concrete vtable instance. You should set the vtable structure with the actual functions within the vtable setting function.An example of setting the vtable structure with the actual functions within the vtable setting function is shown in Listing 5‑2.int _DLLEXPORT_ _ws_pi_set_vtbl_P_CREDENMAP_TEST (void * vtbl){
struct credmap_vtable * vtable;
if ( ! vtbl )
return -1;
vtable = (struct credmap_vtable *) vtbl;
vtable->gwws_pi_map_http_basic = Credmap_HTTP_Basic;
return 0;
}
1. To define a plug-in shared library that is loaded by the GWWS server, the corresponding plug-in library path must be configured in the SALT deployment file. For more information, see Setting Up a Oracle SALT Application in the Oracle SALT Administration Guide.An example of how to define plug-in information in the Oracle SALT deployment file is shown in Listing 5‑3.
Notes: To define multiple plug-in interfaces, multiple <Interface> elements must be specified. Each <Interface> element indicates one plug-in interface.
Note: The SALT 10gR3 Message Conversion Plug-in is an enhanced successor of the SALT 1.1 Custom Buffer Type Conversion Plug-in.Message Conversion Plug-in is a SALT supported Plug-in defined within the SALT plug-in framework. All Message Conversion Plug-in instances have the same Plug-In ID, “P_CUSTOM_TYPE“. Each particular Message Conversion Plug-in instance may implement two functions, one is used to convert SOAP message payloads to Tuxedo buffers, and the other is used to convert Tuxedo buffers to SOAP message payloads. These two function prototypes are defined in Listing 5‑4.The function pointer (* soap_in_tuxedo__CUSTBUF) points to the customized function that converts the SOAP message payload to Tuxedo typed buffer.The function pointer (* soap_out_tuxedo__CUSTBUF) points to the customized function that converts the Tuxedo typed buffer to SOAP message payload.An inbound call scenario is an external Web service program that invokes a Tuxedo service through the Oracle SALT gateway. Figure 5‑1 depicts message streaming between a Web service client and a Tuxedo domain.When a SOAP request message is delivered to the GWWS server, GWWS tries to find if there is a message conversion plug-in instance associated with the input message conversion of the target service. If there is an associated instance, the GWWS invokes the customized (*soap_in_tuxedo__CUSTBUF) function implemented in the plug-in instance.When a Tuxedo response buffer is returned from the Tuxedo service, GWWS tries to find if there is a message conversion plug-in instance associated with the output message conversion of the target service. If there is an associated instance, GWWS invokes the customized (*soap_out_tuxedo__CUSTBUF) function implemented in the plug-in instance.An outbound call scenario is a Tuxedo program that invokes an external Web service through the Oracle SALT gateway. Figure 5‑2 depicts message streaming between a Tuxedo domain and a Web service application.When a Tuxedo request buffer is delivered to the GWWS server, GWWS tries to find if there is a message conversion plug-in instance associated with the input message conversion of the target service. If there is an associated instance, GWWS invokes the customized (*soap_out_tuxedo__CUSTBUF) function implemented in the plug-in instance.When a SOAP response message is returned from the external Web service application, GWWS tries to find if there is a message conversion plug-in instance associated with the output message conversion of the target service. If there is an associated instance, GWWS invokes the customized (*soap_in_tuxedo__CUSTBUF) function implemented in the plug-in instance.Table 5‑1 lists several message conversion plug-in use cases.
Table 5‑1 Message Conversion Plug-in Use Cases
• If the input and/or output (no matter returned with TPSUCCESS or TPFAIL) buffer of a Tuxedo originated service is associated with an external XML Schema, you should develop the message conversion plug-ins to handle the transformation manually, unless you are sure that the SALT default buffer type-based conversion rules can handle it correctly.For more information about how to associate external XML Schema definition with the input, output and error buffer of a Tuxedo Service, see “Defining Tuxedo Service Contract with Service Metadata Repository” in the Oracle SALT Administration Guide.myxml2buffer is an arbitrary customized function name.The input parameter, char * xmlbuf, indicates a NULL terminated string with the XML format data stream. Please note that the XML data is the actual XML payload for the custom typed buffer, not the whole SOAP envelop document or the whole SOAP body document.The input parameter, char * type, indicates the custom typed buffer type name, this parameter is used to verify that the GWWS server expected custom typed buffer handler matches the current plug-in function.The output parameter, CustomerBuffer *a, is used to store the allocated custom typed buffer instance. A Tuxedo custom typed buffer must be allocated by this plug-in function via the ATMI function tpalloc(). Plug-in code is not responsible to free the allocated custom typed buffer, it is automatically destroyed by the GWWS server if it is not used.If successful, this function must return the pointer value of input parameter CustomerBuffer * a.CustomerBuffer * myxml2buffer (void * xercesDOM, CustomerBuffer *a, CustType_Ext * extinfo)
{
// casting the input void * xercesDOM to class DOMDocument object
DOMDocument * DOMTree =
// allocate custom typed buffer via tpalloc
a->buf = tpalloc("MYTYPE", "MYSUBTYPE", 1024);
a->len = 1024;
// fetch data from DOMTree and set it into custom typed buffer
DOMTree ==> a->buf;
if ( error ) {
release ( DOMTree );
tpfree(a->buf);
a->buf = NULL;
a->len = 0;
return NULL;
}
release ( DOMTree );
return a;
}"mybuffer2xml" is the function name can be specified with any valid string upon your need.The input parameter, CustomerBuffer *a, is used to store the custom typed buffer response instance. Plug-in code is not responsible to free the allocated custom typed buffer, it is automatically destroyed by the GWWS server if it is not used.The input parameter, char * type, indicates the custom typed buffer type name, this parameter can be used to verify if the SALT GWWS server expected custom typed buffer handler matches the current plug-in function.The output parameter, char ** xmlbuf, is a pointer that indicates the newly converted XML payload. The XML payload buffer must be allocated by this function and use the malloc () system API. Plug-in code is not responsible to free the allocated XML payload buffer, it is automatically destroyed by the GWWS server if it is not used.If the DOMDocument is constructed from an XML string through XercesDOMParser::parse() API. You must use XercesDOMParser::adoptDocument() to get the pointer of the DOMDocument object. You must not use XercesDOMParser::getDocument() to get the pointer of the DOMDocument object because the DOMDocument object is maintained by the XercesDOMParser object and is released when deleting the XercesDOMParser object if you do not de-couple the DOMDocument from the XercesDOMParser via the XercesDOMParser::getDocument() function.Table 5‑2 compares the SALT Message Conversion Plug-in and the SALT 1.1 Custom Buffer Type Conversion Plug-in.
Table 5‑2 SALT 10gR3 Message Conversion Plug-in / SALT 1.1 Custom Buffer Type Conversion Plug-in Comparison SALT 10gR3 Message Conversion Plug-in Plug-in ID is “P_CUSTOM_TYPE” Plug-in ID is “P_CUSTOM_TYPE” Please note that the SALT 1.1 Custom Buffer Type Plug-in shared library cannot be used directly in SALT 10gR3. You must perform the following tasks to upgrade it to a SALT 10gR3 message conversion plug-in:
1. Re-implement function (*soap_in_tuxedo__CUSTBUF) and (*soap_out_tuxedo__CUSTBUF) according to new SALT 10gR3 message conversion plug-in vtable function prototype API. The major change is that SOAP message payload is saved as an Xerces class DOMDocument object instead of the old string value.When a Tuxedo client accesses Web services via SOAP/HTTP, the client may be required to send a username and password to the server to perform HTTP Basic Authentication. The Tuxedo clients uses tpinit() to send a username and password when registering to the Tuxedo domain. However, this username is used by Tuxedo and is not the same as the one used by the Web service (the password may be different as well).When a Tuxedo client calls a Web service, it actually calls the GWWS server that declares the Web service as a Tuxedo service. The user id and group id (defined in tpusr and tpgrp files) are sent to the GWWS. The GWWS then checks whether the Web service has a configuration item <Realm>. If it does, the GWWS:tries to invoke the vtable gwws_pi_map_http_basic function to map the Tuxedo userid into the username and password for the HTTP Realm of the server.
• for successful calls, encodes the returned username and password with Base64 and sends it in the HTTP header field “Authorization: Basic” if the call is successful
• An existing Web service, myservice, sited on http://www.abc.com/webservice, requires HTTP Basic Authentication. The username is “test”, the password is “1234,” and the realm is “myrealm”.
• After converting the Web service WSDL into the SALT configuration file (using wsdlcvt), add the <Realm>myrealm</Ream> element to the endpoint definition in the WSDF file.
1.
• Use Credmap_HTTP_Basic();This function is used to return the HTTP username/password. The function prototype defined in credmap_pi_ex.h
2. Set the gwws_pi_map_http_basic entry in vtable structure credmap_vtable with the Credmap_HTTP_Basic() function implemented in step 1.This function is invoked when the GWWS server attempts to load the plug-in shared library during startup to determine what library interfaces are implemented. For more information, see Plug-In Register Functions.
4. Compile the previous four or five functions into one shared library, credmap_plugin.so.Listing 5‑7 Custom Typed Buffer Plug-In InterfaceThe "gwws_pi_map_http_basic" function name can be specified with any valid string as needed.The input parameters, char * domain and char * realm, represent the domain name and HTTP Realm that the Web service belongs to. The plug-in code must use them to determine the scope to find appropriate credentials.The input parameters, char * t_uid and char * t_gid, are strings that contain Tuxedo user ID and group ID number values respectively. These two parameters may be used to find the username.The output parameter, Cred_UserPass * credential, is a pointer that indicates a pre-allocated buffer storing the returned username/password. The plug-in code is not responsible to allocate the buffer.
Notes: Tuxedo user ID is available only when *SECURITY is set as USER_AUTH or higher in the UBBCONFIG file. Group ID is available when *SECURITY is set as ACL or higher. The default is “0”.int Credmap_HTTP_Basic(char * domain, char * realm, char * t_uid, char * t_gid, Cred_UserPass * credential)
{
// Use domain and realm to determine scope
credentialList = FindAllCredentialForDomainAndRealm(domain, realm);
if ( error happens )
return -1;
// find appropriate credential in the scope
foreach cred in credentialList {
if (t_uid and t_gid match) {
*credential = cred;
return 0;
}
}
if ( not found and no default credential) {
return -1;
}
*credential = default_credential;
return 0;
}