Table of Contents Previous Next PDF


Using Oracle Service Architecture Leveraging Tuxedo Plug-Ins

Using Oracle Service Architecture Leveraging Tuxedo Plug-Ins
This chapter contains the following topics:
Understanding Oracle Service Architecture Leveraging Tuxedo Plug-Ins
The Oracle Service Architecture Leveraging Tuxedo (SALT) GWWS server is a configuration-driven process which, for most basic Web service applications, does not require any programming tasks. However, 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. 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.
Plug-In Elements
Four plug-in elements are required to define a plug-in interface:
Plug-In ID
The plug-in ID element is a string used to identify a particular plug-in interface function. Multiple plug-in interfaces can be grouped with the same Plug-in ID for a similar function. Plug-in ID values are predefined by SALT. Arbitrary string values are not permitted.
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 Oracle Tuxedo user ID and group ID into username/password that HTTP Basic Authentication needs.
Plug-In Name
The plug-in Name differentiates one plug-in implementation from another within the same Plug-in ID category.
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 Oracle Tuxedo custom typed buffers and an XML document, the plug-in name is the key element that searches for the proper plug-in interface.
Plug-In Implementation Functions
Actual business logic should reflect the necessary functions defined in a plug-in vtable structure. Necessary functions may be different for different plug-in ID categories.
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);
For more information, see Programming Outbound Authentication Plug-Ins.
Plug-In Register Functions
Plug-in Register functions are a set of common functions (or rules) that a plug-in interface must implement so that the GWWS server can invoke the plug-in implementation. Each plug-in interface must implement three register function These functions are:
Information Providing Function
This function is optional. If it is used, it is first invoked after the plug-in shared library is loaded during GWWS server startup. If you want to implement more than one interface in one plug-in library, you must implement this function and return the counts, IDs, and names of the interfaces in the library.
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.
The function uses the following syntax:
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 “;”.
Initiating Function
The initiating function is invoked after all the implemented interfaces in the plug-in shared library are determined. You can initialize data structures and set up global environments that can be used by the plug-ins.
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.
The initiating function uses the following syntax:
int _ws_pi_init_@ID@_@Name@(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 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).
Exiting Function
The exiting function is called before closing the plug-in shared library when the GWWS server shuts down. You should release all reserved plug-in resources.
The exiting function uses the following syntax:
int _ws_pi_exit_@ID@_@Name@(void * priv);
@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 Setting Function
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.
The vtable setting function uses the following syntax:
int _ws_pi_set_vtbl_@ID@_@Name@(void * priv);
@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 SALT 10gR3 release, P_CUSTOM_TYPE and P_CREDENMAP are the only valid plug-in IDs.
The vtable structures for available plug-in interfaces are shown in Listing 5‑1.
Listing 5‑1 VTable Structure
struct credmap_vtable {
       int (* gwws_pi_map_http_basic) (char * domain, char * realm, char * t_userid, char * t_grpid, Cred_UserPass * credential); /* used for HTTP Basic Authentication */
       /* for future use */
       void * unused_1;
       void * unused_2;
       void * unused_3;
};
 
struct 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.
Listing 5‑2 Setting the vtable Structure with Actual Functions within the vtable Setting Function
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;
}
 
Developing a Plug-In Interface
To develop a comprehensive plug-in interface, do the following steps:
1.
2.
Developing a Plug-In Shared Library
To develop a plug-in shared library, do the following steps:
1.
2.
3.
Defining a Plug-In Interface in SALT Configuration File
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 Creating the SALT Deployment File in the Oracle Service Architecture Leveraging Tuxedo Configuration Guide.
An example of how to define plug-in information in the SALT deployment file is shown in Listing 5‑3.
Listing 5‑3 Defined Plug-In in the SALT Deployment File
<?xml version="1.0" encoding="UTF-8"?>
<Deployment xmlns="http://www.bea.com/Tuxedo/SALTDEPLOY/2007">
       . . . . . . .
       . . . . . . .
       <System>
              <Plugin>
                     <Interface
                            id=”P_CREDENMAP”
                            name=”TEST”
                            library=”credmap_plugin.dll” />
              </Plugin>
       </System>
</Deployment>
 
Notes:
To define multiple plug-in interfaces, multiple <Interface> elements must be specified. Each <Interface> element indicates one plug-in interface.
Multiple plug-in interfaces can be built into one shared library file.
Programming Message Conversion Plug-ins
SALT defines a complete set of default data type conversion rules to convert between Oracle Tuxedo buffers and SOAP message payloads. However, the default data type conversion rules may not meet all your needs in transforming SOAP messages into Oracle Tuxedo typed buffers or vice versa. To accommodate special application requirements, SALT supports customized message level conversion plug-in development to extend the default message conversion.
Note:
The SALT 10gR3 Message Conversion Plug-in is an enhanced successor of the SALT 1.1 Custom Buffer Type Conversion Plug-in.
The following topics are included in this section:
How Message Conversion Plug-ins Work
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 Oracle Tuxedo buffers, and the other is used to convert Oracle Tuxedo buffers to SOAP message payloads. These two function prototypes are defined in Listing 5‑4.
Listing 5‑4 vtable structure for SALT Plug-in “P_CUSTOM_TYPE” (C Language)
/* custtype_pi_ex.h */
struct custtype_vtable {
       CustomerBuffer * (* soap_in_tuxedo__CUSTBUF) (void * xercesDOMTree, CustomerBuffer * tuxbuf, CustType_Ext * extinfo)
       int (* soap_out_tuxedo__CUSTBUF) (void ** xercesDOMTree, CustomerBuffer * tuxbuf, CustType_Ext * extinfo)
       ......
}
 
The function pointer (* soap_in_tuxedo__CUSTBUF) points to the customized function that converts the SOAP message payload to Oracle Tuxedo typed buffer.
The function pointer (* soap_out_tuxedo__CUSTBUF) points to the customized function that converts the Oracle Tuxedo typed buffer to SOAP message payload.
You may implement both functions defined in the message conversion plug-in vtable structure if needed. You may also implement one function and set the other function with a NULL pointer.
How Message Conversion Plug-in Works in an Inbound Call Scenario
An inbound call scenario is an external Web service program that invokes an Oracle Tuxedo service through the SALT gateway. Figure 5‑1 depicts message streaming between a Web service client and an Oracle Tuxedo domain.
Figure 5‑1 Message Conversion Plug-in Works in an Inbound Call Scenario
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 an Oracle Tuxedo response buffer is returned from the Oracle 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.
How Message Conversion Plug-in Works in an Outbound Call Scenario
An outbound call scenario is an Oracle Tuxedo program that invokes an external Web service through the SALT gateway. Figure 5‑2 depicts message streaming between an Oracle Tuxedo domain and a Web service application.
Figure 5‑2 Message Conversion Plug-in Works in an Outbound Call Scenario
When an Oracle 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.
When Do We Need Message Conversion Plug-in
Table 5‑1 lists several message conversion plug-in use cases.
 
From Table 5‑1, the following message conversion plug-ins general rules are applied.
If the input and/or output (no matter returned with TPSUCCESS or TPFAIL) buffer of an Oracle 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 an Oracle Tuxedo Service, see “Defining Tuxedo Service Contract with Service Metadata Repository” in the Oracle Service Architecture Leveraging Tuxedo Administration Guide.
Developing a Message Conversion Plug-in Instance
Converting a SOAP Message Payload to an Oracle Tuxedo Buffer
The following function should be implemented in order to convert a SOAP XML payload to an Oracle Tuxedo buffer:
CustomerBuffer * (* soap_in_tuxedo__CUSTBUF) (void * xercesDOM, CustomerBuffer *a, CustType_Ext * extinfo);
Synopsis
#include <custtype_pi_ex.h>
CustomerBuffer * myxml2buffer (void * xercesDOM, CustomerBuffer *a, CustType_Ext * extinfo);
myxml2buffer is an arbitrary customized function name.
Description
The implemented function should have the capability to parse the given XML buffer and convert concrete data items to an Oracle Tuxedo custom typed buffer instance.
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. An Oracle 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.
Diagnostics
If successful, this function must return the pointer value of input parameter CustomerBuffer * a.
If it fails, this function returns NULL as shown in Listing 5‑5.
Listing 5‑5 Converting XML Effective Payload to Oracle Tuxedo Custom Typed Buffer Pseudo Code
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;
}
 
Tip:
Converting an Oracle Tuxedo Buffer to a SOAP Message Payload
The following function should be implemented in order to convert a custom typed buffer to SOAP XML payload:
int (*soap_out_tuxedo__CUSTBUF)(char ** xmlbuf, CustomerBuffer * a, char * type);
Synopsis
#include <custtype_pi_ex.h>
int * mybuffer2xml (char ** xmlbuf, CustomerBuffer *a, char * type);
"mybuffer2xml" is the function name can be specified with any valid string upon your need.
Description
The implemented function has the capability to convert the given custom typed buffer instance to the single root XML document used by the SOAP message.
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.
Diagnostics
If successful, this function must returns 0.
If it fails, this function must return -1 as shown in Listing 5‑6.
Listing 5‑6 Converting Oracle Tuxedo Custom Typed Buffer to SOAP XML Pseudo Code
int mybuffer2xml (void ** xercesDom, CustomerBuffer *a, CustType_Ext * extinfo)
{
       // Use DOM implementation to create the xml payload
       DOMTree = CreateDOMTree( );
       
       if ( error )
              return -1;

       // fetch data from custom typed buffer instance,
       // and add data to DOMTree according to the client side needed
       // XML format

       a->buf ==> DOMTree;

       // allocate xmlbuf buffer via malloc
* xmlbuf = malloc( expected_len(DOMTree) );
       if ( error ) {
              release ( DOMTree );
              return -1;
       }

       // casting the DOMDocument to void * pointer and returned
       DOMTree >> (* xmlbuf);
       if ( error ) {
              release ( DOMTree );
              free ( (* xmlbuf) );
              return -1;
       }

       return 0;
}
 
WARNING:
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.
SALT 1.1 Custom Buffer Type Conversion Plug-in Compatibility
SALT 1.1 Custom Buffer Type Conversion Plug-in provides the customized message conversion mechanism only for Oracle Tuxedo custom buffer types.
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.
2.
Tip:
Programming Outbound Authentication Plug-Ins
When an Oracle 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 Oracle Tuxedo clients uses tpinit() to send a username and password when registering to the Oracle Tuxedo domain. However, this username is used by Oracle Tuxedo and is not the same as the one used by the Web service (the password may be different as well).
To map the usernames, SALT provides a plug-in interface (Credential-Mapping Interface) that allows you to choose which username and password is sent to the Web service.
How Outbound Authentication Plug-Ins Work
When an Oracle Tuxedo client calls a Web service, it actually calls the GWWS server that declares the Web service as an Oracle 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 Oracle 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
Implementing a Credential Mapping Interface Plug-In
Using the following scenario:
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.
Perform the following steps to implement a SALT plug-in interface:
1.
Write the functions to map the “myrealm” Oracle Tuxedo UID/GID to username/password on www.abc.com.
Use Credmap_HTTP_Basic();
This function is used to return the HTTP username/password. The function prototype defined in credmap_pi_ex.h
2.
This function is invoked when the GWWS server attempts to load the plug-in shared library during startup.
This function is invoked when the GWWS server unloads the plug-in shared library during the shutdown phase.
Set the gwws_pi_map_http_basic entry in vtable structure credmap_vtable with the Credmap_HTTP_Basic() function implemented in step 1.
3.
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.
5.
Configure the plug-in interface as shown in Listing 5‑7.
Listing 5‑7 Custom Typed Buffer Plug-In Interface
<?xml version="1.0" encoding="UTF-8"?>
<Deployment xmlns="http://www.bea.com/Tuxedo/SALTDEPLOY/2007">
       . . . . . . .
       . . . . . . .
       <System>
              <Plugin>
                     <Interface
                            id=”P_CREDENMAP”
                            name=”TEST”
                            library=”credmap_plugin.dll” />
              </Plugin>
       </System>
</Deployment>
 
Mapping the Oracle Tuxedo UID and HTTP Username
The following function should be implemented in order to return username/password for HTTP Basic Authentication:
typedef int (* GWWS_PI_CREDMAP_PASSTEXT) (char * domain, char * realm, char * t_userid, char * t_grpid, Cred_UserPass * credential);
Synopsis
#include <credmap_pi_ex.h>
typedef struct Cred_UserPass_s {
char username[UP_USERNAME_LEN];
char password[UP_PASSWORD_LEN];
} Cred_UserPass;
int gwws_pi_map_http_basic (char * domain, char * realm, char * t_uid, char * t_gid, Cred_UserPass * credential);
The "gwws_pi_map_http_basic" function name can be specified with any valid string as needed.
Description
The implemented function has the capability to determine authorization credentials (usernames and passwords) used for authorizing users with a given Oracle Tuxedo uid and gid for a given domain and realm.
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 Oracle 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:
Oracle 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”.
Diagnostics
If successful, this function returns 0. If it fails, it returns -1 as shown in Listing 5‑8.
Listing 5‑8 Credential Mapping for HTTP Basic Authentication Pseudo Code
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;
}
 
Tip:
 

Copyright © 1994, 2017, Oracle and/or its affiliates. All rights reserved.