Portable interceptors require the following components:
Interceptor implementations that are derived from interface PortableInterceptor::Interceptor.
IOP::ServiceContext supplies the service context data that a client or server needs to identify and access an ORB service.
PortableInterceptor::Current (hereafter referred to as PICurrent) is a table of slots that are available to application threads and interceptors, to store and access service context data.
IOP::TaggedComponent contains information about optional features and ORB services that an IOR interceptor can add to an outgoing object reference. This information is added by server-side IOR interceptors, and is accessible to client interceptors.
IOP::Codec can convert data into an octet sequence, so it can be encoded as a service context or tagged component.
PortableInterceptor::PolicyFactory enables creation of policy objects that are required by ORB services.
PortableInterceptor::ORBInitializer is called on ORB initialization. An ORB initializer obtains the ORB's PICurrent, and registers portable interceptors with the ORB. It can also register policy factories.
All portable interceptors are based on the Interceptor interface:
module PortableInterceptor{ local interface Interceptor{ readonly attribute string name; }; };An interceptor can be named or unnamed. Among an ORB's interceptors of the same type, all names must be unique. Any number of unnamed, or anonymous interceptors can be registered with an ORB.
Note:
At present, Orbix provides no mechanism for administering portable interceptors by name.All interceptors implement one of the interceptor types that inherit from the Interceptor interface:
ClientRequestInterceptor defines the interception points that client-side interceptors can implement.
ServerRequestInterceptor defines the interception points that server-side interceptors can implement.
IORInterceptor defines a single interception point, establish_components. It is called immediately after a POA is created, and pre-assembles the list of tagged components to add to that POA's object references.
Interception Points
Each interceptor type defines a set of interception points, which represent stages in the request/reply sequence. Interception points are specific to each interceptor type, and are discussed fully in later sections that describe these types. Generally, in a successful request-reply sequence, the ORB calls interception points on each interceptor.
For example, Figure 53 shows client-side interceptors A and B. Each interceptor implements interception points send_request and receive_reply. As each outgoing request passes through interceptors A and B, their send_request implementations add service context data a and b to the request before it is transported to the server. The same interceptors' receive_reply implementations evaluate the reply's service context data before the reply returns to the client.
Figure 53: Client interceptors allow services to access outgoing requests and incoming replies.![]()
Interception Point Data
For each interception point, the ORB supplies an object that enables the interceptor to evaluate the request or reply data at its current stage of flow:
- A PortableInterceptor::IORInfo object is supplied to an IOR interceptor's single interception point establish_components (click here).
- A PortableInterceptor::ClientRequestInfo object is supplied to all ClientRequestInterceptor interception points (click here).
- A PortableInterceptor::ServerRequestInfo object is supplied to all ServerRequestInterceptor interception points (click here).
Much of the information that client and server interceptors require is similar; so ClientRequestInfo and ServerRequestInfo both inherit from interface PortableInterceptor::RequestInfo. For more information on RequestInfo, click here.
Service contexts supply the information a client or server needs to identify and access an ORB service. The IOP module defines the ServiceContext structure as follows:
module IOP { // ... typedef unsigned long ServiceId; struct ServiceContext { ServiceId context_id; sequence <octet> context_data; }; };A service context has two member components:
- Service-context IDs are user-defined unsigned long types. The high-order 20 bits of a service-context ID contain a 20-bit vendor service context codeset ID, or VSCID; the low-order 12 bits contain the rest of the service context ID. To define a set of service context IDs:
- Obtain a unique VSCID from the OMG
- Define the service context IDs, using the VSCID for the high-order bits.
- Service context data is encoded and decoded by an IOP::Codec (see Codec).
PICurrent is a table of slots that different services can use to transfer their data to request or reply service contexts. For example, in order to send a request to a password-protected server, a client application can set the required password in PICurrent. On each client invocation, a client interceptor's send_request interception point obtains the password from PICurrent and attaches it as service context data to the request.
Figure 54: PICurrent facilitates transfer of thread context data to a request or reply.![]()
The PortableInterceptor module defines the interface for PICurrent as follows:
module PortableInterceptor { // ... typedef unsigned long SlotId; exception InvalidSlot {}; local interface Current : CORBA::Current { any get_slot(in SlotId id ) raises (InvalidSlot); void set_slot(in SlotId id, in any data ) raises (InvalidSlot); }; };
Object references that support an interoperability protocol such as IIOP or SIOP can include one or more tagged components, which supply information about optional IIOP features and ORB services. A tagged component contains an identifier, or tag, and component data, defined as follows:
typedef unsigned long ComponentId; struct TaggedComponent{ ComponentID tag; sequence<octet> component_data; };An IOR interceptor can define tagged components and add these to an object reference's profile by calling add_ior_component() (see Writing IOR Interceptors). A client interceptor can evaluate tagged components in a request's object reference by calling get_effective_component() or get_effective_components() (see Evaluating Tagged Components).
Note:
The OMG is responsible for allocating and registering the tag IDs of tagged components. Requests to allocate tag IDs can be sent to tag_request@omg.org.
The data of service contexts and tagged components must be encoded as a CDR encapsulation. Therefore, the IOP module defines the Codec interface, so interceptors can encode and decode octet sequences:
local interface Codec { exception InvalidTypeForEncoding {}; exception FormatMismatch {}; exception TypeMismatch {}; CORBA::OctetSeq encode(in any data ) raises (InvalidTypeForEncoding); any decode(in CORBA::OctetSeq data ) raises (FormatMismatch); CORBA::OctetSeq encode_value(in any data ) raises (InvalidTypeForEncoding); any decode_value( in CORBA::OctetSeq data, in CORBA::TypeCode tc ) raises (FormatMismatch, TypeMismatch); };Codec Operations
The Codec interface defines the following operations:
encode converts the supplied any into an octet sequence, based on the encoding format effective for this Codec. The returned octet sequence contains both the TypeCode and the data of the type.
decode decodes the given octet sequence into an any, based on the encoding format effective for this Codec.
encode_value converts the given any into an octet sequence, based on the encoding format effective for this Codec. Only the data from the any is encoded.
decode_value decodes the given octet sequence into an any based on the given TypeCode and the encoding format effective for this Codec.
Creating a Codec
The ORBInitInfo::codec_factory attribute returns a Codec factory, so you can provide Codec objects to interceptors. This operation must be called during ORB initialization, through the ORB initializer.
An ORB service can be associated with a user-defined policy. The PortableInterceptor module provides the PolicyFactory interface, which applications can use to implement their own policy factories:
local interface PolicyFactory { CORBA::Policy create_policy( in CORBA::PolicyType type, in any value ) raises (CORBA::PolicyError); };Policy factories are created during ORB initialization, and registered through the ORB initializer (see Creating and Registering Policy Factories).
ORB initializers implement interface PortableInterceptor::OrbInitializer:
local interface ORBInitializer { void pre_init(in ORBInitInfo info); void post_init(in ORBInitInfo info); };As it initializes, the ORB calls the ORB initializer's pre_init() and post_init() operations. pre_init() and post_init() both receive an ORBInitInfo argument, which enables implementations to perform these tasks: