Previous Next Table of Contents

3. Eiffel Mapping

This chapter is made up of:

The proposed standard consists of the sections from this chapter with the `rationale' sections removed.

3.1 Eiffel Mapping Overview

The mapping presented here shares its design principles with the Eiffel language itself, [ETL]. All IDL basic, constructed and interface types map on to equivalent Eiffel classes. Where possible standard Eiffel classes and styles are used so that the interfaces look as familiar as possible to the Eiffel programmer. This is also in the interests of reuse, as it makes it easier to incorporate existing classes into a CORBA framework.

Using the Eiffel language with CORBA removes many of the complexities and potential pitfalls which some other language bindings present:

3.2 Mapping of OMG IDL to Eiffel

  1. Identifiers
  2. Basic Data Types
  3. Strings
  4. Enumerations
  5. Constructed Types
    1. Structures
    2. Sequences and Arrays
    3. Unions
  6. The CORBA any Type
  7. Typedefs
  8. Constants
  9. Interfaces
    1. Object Reference Operations
  10. Exceptions
  11. Mapping for Operations and Attributes
  12. Implicit Parameters to Operations
  13. Application Environment

Identifiers

The Eiffel language differs from IDL in two respects:

  1. Non-alphabetic characters are explicitly excluded ( [25.16 (ETL)]) while IDL specifies ISO Latin-1 (8859.1) ( [3.2 Lexical Conventions (Corba2.0)]).
  2. Eiffel does not require identifiers to be rendered consistently in terms of letter case. It does however recommend conventions as to case usage which are generally adopted.

With regard to character set, this standard does not specify the required behaviour given IDL containing non Roman alphabetic characters.

Where an IDL identifier is the same as an Eiffel reserved word ( [G.2 (ETL)]) the corresponding Eiffel identifier will have the string idl_ prepended, e.g. export becomes idl_export.

To avoid collisions with names inherited from library classes such as GENERAL, the IDL compiler must provide some means of modifying the names mapped to.

Rationale

The usual practice to avoid reserved words is to prepend an underscore, but Eiffel does not allow this.

The resolution of feature name collisions has been left free to allow a diversity of solution both economical and sophisticated. In the simplest case we envisage using a single mechanism for all renaming requirements.

We considered mandating resolution by renaming the original feature, but this is not simple to implement particularly in the presence of multiple inheritance. We prefer renaming the original rather than the generated feature since this is more likely to yield portability than renaming the IDL entity. While the reserved word list is common to all Eiffel implementations, the list of features of GENERAL is not, and one must also consider the features introduced by the ORB vendor into classes including CORBA_OBJECT.

Name Scoping

Eiffel has only two name spaces: a global one containing the names of all classes, and another for each class containing the names of its features.

Generated names will be the same as the local IDL name. Where this would lead to ambiguities the implementation must provide means to modify the mapped names, either explicitly or by alternative algorithms. For example the name of the enclosing scope could be prepended with a separating underscore, recursively until uniqueness is obtained.

Name collisions are possible as follows.

  1. Where the same name is used in different IDL naming scopes, yielding two Eiffel classes of the same name.
  2. Where the mapped name of an IDL operation or attribute is the same as the identifier derived from some other IDL entity which is subject to one of the transformations above. For example, if an interface has two features export and idl_export. This is directly equivalent to problems which can arise in the C mapping; in the example in [14.13 Mapping for Arrays (Corba2.0)] consider the effect of including an unrelated type definition for the name LongArray_slice.
  3. Where the IDL compiler supports incremental compilation, name collisions may not appear until the compiled units are combined. For example modules A and B may both contain an interface X, yielding a class X in both cases. If a further module C then imports both of these modules it is too late to rename the classes to A_X and B_X.

Rationale

No simple transformation gives guaranteed avoidance of name collisions in all legal IDL. Attempts to automatically cope with collisions (by for example prepending module names) result in problems when a specification is modified. A change in one module can cause the IDL compiler to change the mapped name in a module which has not been changed.

We take the view that it is better to have a simple mapping, and leave it up to the implementation to provide the means for resolving the few collisions that will occur in practice. This is consistent with the Smalltalk mapping, [19.4.1 Avoiding Name Space Collisions (Corba2.0)].

Basic Data Types

The following table summarizes the Eiffel classes which map to each of the OMG basic types.

OMG type Eiffel class
short INTEGER
long INTEGER
unsigned shortINTEGER
unsigned longINTEGER
float REAL
double DOUBLE
char CHARACTER
boolean BOOLEAN
octet CHARACTER
Basic Types

All of these are expanded classes. When one of these types is passed as an out or inout parameter the equivalent reference class will be used, and the client must create an object of the required type prior to the call.

Rationale

[ELS] does not define how many bits an Eiffel INTEGER should have, though all the existing implementations use at least 32. By mapping unsigned long to INTEGER we accept that large values have to be dealt with specially by the programmer. The ideal solution would be to modify [ELS] and then update this standard. The same approach is taken to the pending CORBA type extensions.

The sizes of REAL and DOUBLE are not defined either. Most Eiffel implementations use the underlying C types, though Eiffel/S up to at least version 1.3 uses float for both. An implementation based on Eiffel/S would therefore lose precision when dealing with parameters of type double.

CHARACTER is defined by [ELS] to have at least 7 bits, though all known implementations have a minimum of 8. CORBA requires 8 bits [3.8.1 Basic Types (Corba2.0)] for both char and octet.

Strings

The IDL string type maps to the STRING class, regardless of whether the IDL specifies a bound.

The effect of passing a string longer than the bound as an in parameter, or returning a string longer than the bound as a return value or an out or inout argument is undefined. It is not permitted to pass Void as an out or inout argument or as a return value.

Rationale

This is equivalent to the C mapping, where the same considerations regarding exceeding the string bound apply. An Eiffel IDL compiler has the opportunity to make life safer by providing appropriate assertions.

Enumerations

Enumerations in IDL are represented by constant-valued features in Eiffel. That is, an IDL enum declaration is taken to be equivalent to the declaration of an INTEGER constant for each enumerator, with a name formed by concatenating the enumeration name, an underscore, and the enumerator name.

For example

    // IDL
    enum Color (Red, Green, Blue);
yields Eiffel features such as color_red: INTEGER.

This binding supports the ordering relation specified in [3.8.2 Constructed Types (Corba2.0)].

Rationale

This mapping is the natural one for a language that does not support enumeration types directly.

Constructed Types

Structures

Each IDL struct <identifier> maps to an Eiffel class <IDENTIFIER>. For each member <name> of the structure there are two features:

The class also has creation procedures

Sequences and Arrays

There is little difference between CORBA sequences and arrays as far as operations available to the programmer are concerned, other than the ability to resize a sequence. Both are mapped to the generic class ARRAY.

Implementations may include appropriate require and ensure clauses in operation definitions to check that the arrays passed as parameters or return values are of a valid size.

Rationale

The use of ARRAY to represent sequences as well as arrays is partly for performance reasons. Many Eiffel compilers treat ARRAY specially within Eiffel itself and when exchanging array contents with C code. Some IDL interfaces use sequence<octet> to pass opaque application data, avoiding the overheads of translating it into IDL types. Such applications will benefit from the use of ARRAY rather than an ORB defined class.

Note: the CORBA specification apparently requires a maximum size to be passed for an unbounded sequence: [3.8.3 Template Types (Corba2.0)]. This mapping clearly fails to do this, but then so do all the others, including C. We assume this is an anachronism in the CORBA specification.

Unions

An IDL union declaration generates an Eiffel class of the same name.

For each declarator there is

Other features are:

The CORBA any Type

The any type permits the specification of values that can express any OMG IDL type, including types not explicitly declared in the IDL specification [3.8.1 Basic Types (Corba2.0)]. Its scope is therefore wider than the Eiffel class ANY which can by definition only directly represent objects whose type was known at compile time.

IDL any maps to an Eiffel class CORBA_ANY. Extraction of known types from an instance of CORBA_ANY is by a feature idl_object: ANY which returns the encapsulated object, or Void if the object is not of a type declared in the IDL specification. For types normally represented as expanded classes, the object returned is of the equivalent reference class. For interface types an object conforming to CORBA_OBJECT_REF will be returned, and it may be necessary to use the narrow procedure to obtain a more specific type (see Interfaces).

Information may also be extracted concerning the type encapsulated by a CORBA_ANY via a feature typecode: CORBA_TYPECODE, see typecode.

All structure, union and interface classes have a feature as_corba_any: CORBA_ANY, as does the CORBA_ANY class itself. To create or examine values of arbitrary types the `Dynamic Any' facility proposed in [POA] is supported, see DynAny.

When the any type is used as an out parameter, two more features are required on CORBA_ANY:

To create an instance of CORBA_ANY an application may inherit from CORBA_GENERAL which includes the following features:

The argument type of an as_any is always a reference type. This is because it may be convenient to encapsulate an object within a CORBA_ANY before setting its value. Also when using the Dynamic Invocation Interface it allows us to retain a reference to an encapsulated object so that it's value may be accessed after a call without the overhead of an assignment attempt. Notice that an expression such as short_as_any (42) is permitted by the rules of Eiffel; the creation of an object to contain the value 42 is implied.

Facilities for creating arrays and sequences other than for named types are not provided, as such types are not acceptable as parameters to operations [3.10.2 Parameter Declarations (Corba2.0)].

Rationale

It is tempting to try to model CORBA any using the Eiffel class ANY. This has been rejected for a number of reasons:

  1. Applications must be able to handle objects of types which are not declared in the IDL used to define the application. For example, name servers do not have to know the entire range of interfaces they may have to support. That is, the object is not represented by any class normally visible to the application. Modeling such objects as instances of ANY seems inappropriate.
  2. In order to recover a data object which is of a type known to the application, if ANY were used it would be natural to expect an assignment attempt (?=) to work. However, this implies that known types have to be unmarshalled just in case an assignment attempt is made. This may represent an unacceptable performance cost in applications which would not in fact make the attempt, or make it only rarely. The proposed mapping enables the object to be retained in unmarshalled form until such an attempt is made.
  3. Extraction of type information could not be done in the natural way by calling a feature on the object; ANY should not be encumbered with features specific to CORBA.

Typedefs

IDL typedefs do not appear in Eiffel, other than as features on the CORBA_GENERAL class for creating corresponding instances of CORBA_ANY, see as.any. The IDL compiler will always generate the underlying base type. That is, typedefs are treated like C pre-processor macros rather than implying the creation of a genuine new type (and hence further classes related by inheritance).

Rationale

The typedef keyword associates a name with a data type, it does not introduce a new type [3.8 Type Declaration (Corba2.0)]. Consider the example

typedef module_name::some_type some_type;
which is used to enable easier reference to a type defined in another IDL module. It would be inappropriate to introduce another Eiffel class here, especially as in Eiffel two classes cannot be mutually conformant.

Constants

A constant shall map to a feature of the same name accessible from any instance of an interface class where the constant is visible using its unqualified name in the corresponding IDL.

// IDL
interface machine {
    const long stop=1;
    const long go=2;
    void execute(long command);
}


-- Eiffel
m:MACHINE
...
m.execute (m.stop)

All constants are also accessible from the class CORBA_GENERAL via the feature constant. This gives access to a hierarchy of objects corresponding to the IDL name scopes, and so a constant C within an interface I declared in a module M would be referred to as constant.M.I.C.

Rationale

A constant will normally be used in connection with an interface, and constants which cannot be referred to by their unqualified name within that interface are probably not used. The first mechanism should cope with the majority of circumstances, while the constant feature may be used where name collisions are a problem. It is less important that access to the constant feature is efficient, so qualified feature call is an acceptable way to avoid name space problems, as might otherwise occur for example if a constant M_I_C were to be declared at file level.

Interfaces

CORBA describes two sorts of objects for an interface: the object implementation, and object references through which an implementation is accessed. Both of these support the same interface (as described in the IDL) and so interfaces are modeled as three Eiffel classes, one of them abstract.

The abstract interface class has features corresponding to the attributes and operations appearing in the IDL. Each non read-only attribute also has an associated set_<name> routine. It will be common for an Eiffel application to declare entities of this type, reflecting that as far as is practical the programmer should not be concerned that a reference to an implementation is being used rather than the implementation itself.

Two descendants of this class are required to provide a reference through which clients access the object, and an implementation which implements the object. The classes are named <name>_REF and <name>_IMPL respectively.

The programmer must supply the object implementation class. The exact form of the class and the amount of help available from the IDL compiler are implementation dependent. Implementation classes are not immediately portable to another ORB because the IDL compiler must somehow include information in the class about the IDL type of the corresponding CORBA object. This may mean the introduction of vendor specific features whose names would have to be mentioned in the inheritance clause even if their implementations were obtained from some other class. This is because in Eiffel redefinitions must be done explicitly. In practice thanks to the simple syntax of Eiffel it should be feasible to produce tools to automatically replace the vendor specific parts of implementation classes to convert them for use with another ORB. With this in mind vendors should minimise the complexity of code required in the implementation skeleton.

The reference class adds these features:

Where an inheritance relation exists between interfaces in the IDL, the same relationship will be reflected in the three classes.

Where an IDL operation returns an interface type <name>, the equivalent Eiffel feature will be of type <name>. That is, the return value is defined as being of the interface class in order to allow the implementation to return either a reference or an implementation.

IDL in parameters of interface type also translate to the interface class, again so that either a reference or an implementation may be supplied.

IDL out and inout parameters will be of the reference type because the implementation needs the encapsulate feature in order to supply the return value, and to prevent any attempt to redirect an implementation object.

Rationale

It would be possible to model the CORBA architecture by two classes instead of three: the reference would inherit from the implementation, redefining the operations. This is unsatisfactory on two counts:

Stricter standardisation of the implementation class would allow full source code portability between ORBs, but only at the cost of seriously reducing the scope for worthwhile innovation on the part of ORB vendors. In view of the relative simplicity of automated convertion from one vendor's implementation to another, this option has been rejected.

Exceptions

IDL exceptions are mapped to Eiffel classes of the same name, with attributes corresponding to the structure defined within the exception. They are very similar to structures, with a creation procedure taking a list of attribute values matching the declared members. Three standard exception classes are defined

To raise an exception the application creates an instance of the appropriate class supplying values to the creation procedure to populate the attributes. It then invokes the feature `raise'.

To handle an exception, use the standard Eiffel rescue / retry mechanisms in conjunction with the last_exception feature of the CORBA_GENERAL class ( General class).

Unrescued exceptions in client code will be handled according to the Eiffel system in use. Normally this means termination of the program.

Unrescued CORBA exceptions in the execution of an object implementation operation will cause equivalent exceptions to be raised in the client. The raising of an exception which is declared in the IDL is considered to be correct fulfillment of the contract, and will not cause termination of the server. Unrescued non CORBA exceptions should lead to notification of a generic CORBA exception to the client. Precise behaviour is dependent on the implementation, and may depend on the nature of the exception.

Rationale

CORBA exceptions are normally raised intentionally, so it would seem appropriate to allow an object implementation to continue to serve requests after returning an exception which is declared in the IDL.

Mapping for Operations and Attributes

An operation maps to an Eiffel feature of the same name. A readonly attribute yields a parameterless feature with the same name as the attribute, with result type determined by the type of the attribute. A writable attribute yields an additional feature set_<name> taking a single argument which obeys the rules for an in parameter.

Implicit Parameters to Operations

For context handling [3.10.4 Context Expressions (Corba2.0)] there will be a class CORBA_CONTEXT derived from the IDL in [4.6 Context Object Operations (Corba2.0)]. Note that Status is mapped to void as allowed by [4.1.3 Return Status and Exceptions (Corba2.0)], as the natural thing to do in Eiffel is raise exceptions when operations fail.

class CORBA_CONTEXT
feature

    set_one_value (
            prop_name: STRING      -- property name to add
            value: STRING          -- property value to add
        )

    set_values (
            values: ARRAY [ CORBA_NAMED_VALUE ]
        )

    get_values (
            start_scope: STRING    -- search scope
            prop_name: STRING      -- name of property(s) to retrieve
        ) : ARRAY [ CORBA_NAMED_VALUE ]
                                   -- requested property(s)
            -- search for a property value

    get_values_restricted (
            start_scope: STRING    -- search scope
            prop_name: STRING      -- name of property(s) to retrieve
        ) : ARRAY [ CORBA_NAMED_VALUE ]
                                   -- requested property(s)
            -- search for property value in a specific context object

    delete_values ( prop_name: STRING )

    create_child ( ctx_name: STRING ) : CORBA_CONTEXT

    delete
            -- delete the context object; there must be no child context objects

    delete_descendents
            -- delete the context object, including any children

The delete operations are provided for ORBs which provide persistent storage for context objects. In an Eiffel environment the delete operation does not dispose of the object itself, it can only remove all property values and internal references to child objects.

Application Environment

Eiffel does not have global static variables, so it is necessary to define some way of accessing information such as constants which are not related to a specific object.

The application may inherit from the class CORBA_GENERAL which will include the following features.

3.3 Mapping of Pseudo Objects to Eiffel

This section defines the Eiffel classes which provide access to the services defined in chapters 4 to 8 of [Corba2.0]. This is done in terms of pseudo objects defined in Eiffel. These mappings are largely mechanical applications of the IDL mapping to the PIDL definitions.

  1. Dynamic Invocation Interface
    1. NamedValue
    2. Status codes
    3. Request Operations
    4. List Operations
    5. Context Operations
  2. Dynamic Skeleton Interface
  3. The Interface Repository
    1. TypeCode
  4. ORB Interface
    1. Converting Object References to Strings
    2. Object Reference Operations
  5. Server Side Mapping
    1. The Portable Object Adapter
    2. Lightweight Mapping
  6. Dynamic Any

Dynamic Invocation Interface

NamedValue

A named value is represented by an Eiffel class CORBA_NAMED_VALUE. This is based on [4.1.1 Common Data Structures (Corba2.0)].

class CORBA_NAMED_VALUE

feature

    name: STRING
            -- argument name

    argument: CORBA_ANY
            -- argument value

    is_arg_in: BOOLEAN
            -- is this an "in" argument?

    is_arg_out: BOOLEAN
            -- is this an "out" argument?

    is_arg_inout: BOOLEAN
            -- is this an "inout" argument?

end -- class CORBA_NAMED_VALUE

Instances of this class are obtained from the following features of CORBA_ANY:

NVList is mapped to ARRAY [CORBA_NAMED_VALUE] (see justification in NVList).

Rationale

  1. The len component of CORBA::NamedValue is not appropriate to the Eiffel language, as the programmer should not be aware of the implementation.
  2. Separate feature names are used instead of mapping CORBA::Flags directly, giving implementors more freedom in how to represent this information; for example polymorphism is possible.

Status codes

Eiffel implementations will support the alternative mapping for Status as defined in [4.1.3 Return Status and Exceptions (Corba2.0)]. Failure of any interface will be signaled by an implementation defined Eiffel exception.

Request Operations

Requests are represented by the Eiffel CORBA_REQUEST class, which is based on [4.2 Request Operations (Corba2.0)].

The add_arg features mirror the as_arg features introduced to CORBA_ANY in as arg.

class CORBA_REQUEST
feature
    add_arg_in (
            name: STRING          -- argument name
            value: CORBA_ANY      -- argument value
        )
            -- add an input argument

    add_arg_out (
            name: STRING          -- argument name
            value: CORBA_ANY      -- argument value
        )
            -- add an output argument

    add_arg_inout (
            name: STRING          -- argument name
            value: CORBA_ANY      -- argument value
        )
            -- add an inout argument

    invoke
            -- send request and wait for a response

    send
            -- send request but do not wait for a response

    send_oneway
            -- send request signifying no intention to access any response

    get_response
            -- waits until the request is complete

    poll_response: BOOLEAN
            -- returns True if the request is complete

    delete
            -- signifies that no further response will be accessed, effectively 
            -- turning a `send' into a `send_oneway'

Rationale

Existing mappings, for example C++, interpret the PIDL in a similar way.

The class CORBA_ORB has the following features which deal with requests:

class CORBA_ORB
feature

    send_multiple_requests ( reqs: ARRAY [ CORBA_REQUEST ] )
            -- Issue multiple `sends'.  Responses must be collected using
            -- `get/poll_request', `get/poll_next_request'

    send_multiple_requests_oneway ( reqs: ARRAY [ CORBA_REQUEST ] )
            -- as `send_multiple_requests', but notifies the ORB that the caller 
            -- has no intention of collecting any response

    get_next_response: CORBA_REQUEST
            -- returns the next request that completes

    poll_next_response: CORBA_REQUEST
            -- returns the next completed request if there is one, otherwise Void

Notes.

  1. The behaviour of the IN_COPY_VALUE flag described in [4.2.2 (Corba2.0)] is obtained in Eiffel by the appropriate use of clone.
  2. The delete feature on CORBA_REQUEST allows underlying ORB resources to be released.

List Operations

Memory management issues are not the concern of an Eiffel programmer, so the mapping of NVList is that of a sequence: ARRAY [CORBA_NAMED_VALUE].

The equivalent of using IN_COPY_VALUE when adding to a list is to clone the item being inserted into the array.

The effect of free_memory (retaining the list structure while freeing the items) could be achieved using the clear_all feature of class ARRAY. While this seems to be supported by all the Eiffel vendors, it is not listed in [ELS] and so cannot be regarded as acceptable in a conforming application.

The create_operation_list interface is not supported, as its main function is to allocate appropriate memory for the parameter values of a particular operation. In a type safe language such as Eiffel, inserting values into such a pre created list is much more complicated than constructing the list from scratch.

Context Operations

The interface to CORBA_CONTEXT is defined in Implicit Parameters to Operations.

The default context is obtained by the following feature on the ORB:

class CORBA_ORB
feature
        get_default_context: CORBA_CONTEXT
end

Dynamic Skeleton Interface

The Dynamic Skeleton Interface (DSI) is a way to deliver requests from an ORB to an object implementation that does not have compile-time knowledge of the type of object it is implementing.

The CORBA_SERVER_REQUEST class implements the interface defined in [5.1 Explicit Request State (Corba2.0)], modified by [2.4.2 (POA)].

class CORBA_SERVER_REQUEST
feature
        operation: STRING
        arguments ( args: ARRAY [ CORBA_NAMED_VALUE ] )
        ctx: CORBA_CONTEXT
        set_result ( value: CORBA_ANY )
        set_exception ( exception_value: CORBA_ANY )
end

In order to avoid compile-time knowledge of exceptions a mechanism is required for creating exceptions as an instance of CORBA_ANY. This is unspecified in [Corba2.0] and so the Eiffel mapping will use the mechanisms defined in the Portability proposal [4.3.6 (POA)]. The Eiffel mapping for these is described in DynAny.

Invoking the exception feature does not raise an Eiffel exception. If an exception (Corba or not) is raised by some other means, it will be notified to the caller in the normal way.

Rationale

The normal mode of use would be to call set_exception and then return from the upcall. Raising the exception only for the ORB to have to rescue it for return to the client is an unecessary complication. The application is of course free to invoke the raise feature on the exception object if that is more appropriate.

Dynamic implementations will make use of the class CORBA_DYNAMIC_IMPLEMENTATION which is a descendant of CORBA_SERVANT which is described in Server-side Mapping.

deferred class CORBA_DYNAMIC_IMPLEMENTATION

inherit
        CORBA_SERVANT
feature
        invoke (a_request: CORBA_SERVER_REQUEST) is
                deferred
                end
end

The Interface Repository

TypeCode

Type codes are represented by the Eiffel CORBA_TYPECODE class, described below. The class is based on [6.7 TypeCodes (Corba2.0)].

class CORBA_TYPECODE
feature

    is_equal ( other: CORBA_TYPECODE ) : BOOLEAN
        -- Do 'other' and 'Current' represent the same type?
        -- (Redefinition from GENERAL)

    kind: INTEGER
            -- determines which of the other operations are valid

    id: STRING
            -- returns the RepositoryId globally identifying the type

    name: STRING
            -- returns the simple name identifying the type
            -- within its enclosing scope

    member_count: INTEGER
    member_name ( index: INTEGER ) : STRING
    member_type ( index: INTEGER ) : CORBA_TYPECODE
            -- features for accessing the components of constructed types

    member_label ( index: INTEGER ) : CORBA_ANY
    discriminator_type: CORBA_TYPECODE
    default_index: INTEGER
            -- features for accessing information specific to unions

    length: INTEGER
            -- returns the bound for strings and sequences, or the 
            -- size of an array

    content_type: CORBA_TYPECODE
            -- the type parameter for 'generic' types

TypeCode is a pseudo interface, so following Interfaces there is also a CORBA_TYPECODE_REF class which is used when TypeCode is passed as an out or inout argument.

class CORBA_TYPECODE_REF

inherit
    CORBA_TYPECODE

creation
    encapsulate, make_nil

feature

    encapsulate (typecode: like item)
            -- Create a reference to the given typecode.

    make_nil
            -- Create a reference for use as an "out" argument.

    item: CORBA_TYPECODE
            -- The encapsulated typecode.

end -- class CORBA_TYPECODE

Notes.

  1. CORBA_TCKIND is mapped in the standard manner.
  2. In keeping with accepted Eiffel style, the class interface does not require the explicit raising of the Bounds and BadKind exceptions specified in the PIDL. Instead, the features of this class will be specified with preconditions which perform the same function. It follows that users must not write code which relies on these exceptions being raised.
  3. The IDL types RepositoryId and Identifier are mapped to STRING rather than explicit classes.
  4. The deprecated interface made up of param_count and parameter is omitted. Implementors may provide these features (and any others), but they are not required.

ORB Interface

Converting Object References to Strings

Translating to / from strings is done via an instance of the CORBA_ORB class, derived from the PIDL in [7.1 Converting Object References to Strings (Corba2.0)].

class CORBA_ORB
feature
    object_to_string (obj: CORBA_OBJECT): STRING
    string_to_object (str: STRING): CORBA_OBJECT
end -- class CORBA_ORB

Object Reference Operations

All interface classes (and hence references and implementations too) are descendants of a supplied class CORBA_OBJECT, which will be flat-short compatible with the following, derived from [7.2 Object Reference Operations (Corba2.0)].

class CORBA_OBJECT_REF
feature
    get_implementation: CORBA_IMPLEMENTATION_DEF
    get_interface: CORBA_INTERFACE_DEF
    is_nil: BOOLEAN
    duplicate: like Current
    release
    non_existent: BOOLEAN
    is_equivalent ( other: CORBA_OBJECT )

    create_request (
            ctx: CORBA_CONTEXT;
            operation: STRING;
            arg_list: ARRAY [ CORBA_NAMED_VALUE ];
            idl_result: CORBA_NAMED_VALUE
        ) : CORBA_REQUEST
end -- class CORBA_OBJECT_REF

create_request is used in the dynamic invocation interface.

Server Side Mapping

The OMG is in the process of addressing various portability issues [POA] including that of providing portable access to object adapters. This proposal provides a mapping according to the rules in [3.3.1 The Servant IDL Type (POA)] which must be used by ORBs which support the Portable Object Adapter (POA). We also describe a lightweight mapping limited to transient object implementations which must be implemented by all ORBs. These additional features may be implemented by simple calls on the default POA or by other mechanisms.

The Portable Object Adapter

The eiffel mapping supports the Portable Object Adapter as described in [POA]. As usual the class names derived from the POA IDL are prefixed with CORBA_, and so for example PortableServer::POA maps to CORBA_POA. The mapping is a mechanical translation of the OMG supplied IDL, and so is not reproduced here (so that in the event of changes before the Portability proposal is adopted, there will be no rework).

The Servant native type is mapped to a class CORBA_SERVANT.

class CORBA_SERVANT
    corba_repository_id (a_object_id: ARRAY [CHARACTER]): STRING
            -- Return the repository ID of the most derived interface
            -- corresponding to the given object ID.

    corba_default_poa: CORBA_POA
            -- The default POA for this servant (for use by the ORB to
            -- support implicit activation).

end -- class CORBA_SERVANT

corba_repository_id may be used by the POA to discover the interface supported by the servant, for example to construct an object reference. The argument is necessary for servants which support more than one object, for example when the dynamic server interface is used to implement a bridge. Servants which only implement a single object may ignore the value passed.

corba_default_poa is used by the ORB in cases where implicit activation of the server is required.

CORBA_SERVANT is an ancestor of both CORBA_OBJECT_IMPL (and hence all compiler generated implementations) and CORBA_DYNAMIC_IMPLEMENTATION.

An implementation is supplied for corba_default_poa which returns the root POA object. This feature may be redefined by the programmer to return a different object adapter. This redefinition is propogated through the inheritance hierarchy.

corba_repository_id is implemented in compiler generated classes to return the repository ID derived from the IDL, and should not be redefined. This could not be done portably because the standard does not define whether the feature implementation is inherited or provided in the implementation class itself.

Descendants of CORBA_DYNAMIC_IMPLEMENTATION must provide an implementation of corba_repository_id as this feature is deferred in that class.

Lightweight Mapping

This section decribes additional features of CORBA_OBJECT_IMPL which provide portable means of managing transient objects without explicit access to an object adapter. These features may be mapped directly to calls on the root POA, or to some other mechanism with equivalent semantics for ORBs which do not implement the POA. It is possile for example to map them to the old Basic Object Adapter.

The extra features on CORBA_OBJECT_IMPL are:

Objects managed in this way are transient, i.e. they do not survive the process in which they are created.

Rationale

It may be some time before the recommendations in [POA] are accepted and generally implemented. These additional features provide a simple way of meeting the commonest requirement, for transient objects implemented with static skeletons, without insisting on full support for the POA. For ORBs which support the POA, implementation of these additional features is trivial.

Dynamic Any

The CORBA_ANY class provides the means to create and examine any values which are defined in IDL from which Eiffel code has been derived. This is adequate for many purposes, but does not allow the handling of arbitrary types which are not defined at compile time.

To enable the writing of generic applications such as bridges this section introduces some extra classes associated with the CORBA_ANY type. These are derived from [4 Dynamic management of Any values (POA)].

They are mechanical translations of the IDL given in [POA] with the additional rules:

  1. There is no destroy feature, as the associated semantics are not appropriate to an environment with garbage collection such as Eiffel. The reference semantics specified are preserved.
  2. Classes generated are prefixed with CORBA_, consistent with the other OMG IDL derived classes. For readability the mixed case convention used in the specification is translated as the insertion of underscores. For example CORBA::DynAny maps to CORBA_DYN_ANY.
  3. CORBA_DYN_ANY shall not inherit from CORBA_OBJECT. This makes the illegal operations discussed in [4.3.1 Locality and usage constraints (POA)] impossible.
  4. Implementations may choose to police correct use of the interfaces by Eiffel assertion rather than run time check. For example those conditions which may give rise to an InconsistentTypeCode exception may be expressed as preconditions instead. Incorrect use is not guaranteed to give rise to a CORBA exception.

Rationale

These modifications are consistent with the overall design of the mapping, which takes account of the emphasis in the Eiffel method on mistake-proofing the programming process.


Previous Next Table of Contents