Interceptor Components


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.

Interceptor Types

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:

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

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:

PICurrent

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); 
    }; 
}; 

Tagged Components

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.

Codec

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.

Policy Factory

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 Initializer

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: