Interface Definition Language. IDL keywords. Quick examples. Interface Definition Language. OMG Interface Definition Language IDL

OMG Interface Definition Language IDL Escher's "Tower of Babel" – uhm, the little white builders and little black builders have communications diffic...
9 downloads 2 Views 491KB Size
OMG Interface Definition Language

IDL Escher's "Tower of Babel" – uhm, the little white builders and little black builders have communications difficulties; they need some language independent specifications!

• IDL is the language used to describe the interfaces that client objects call and object implementations provide. – An interface definition written in OMG IDL completely defines the interface and fully specifies each operation’s parameters.

• IDL is purely a descriptive language • Implementation is done in languages for which mappings from OMG IDL concepts have been defined. 1

IDL keywords

2

Interface Definition Language

abstract

exception

inout

provides

truncatable

any

emits

interface

public

typedef

attribute

enum

local

publishes

typeid

boolean

eventtype

long

raises

typeprefix

case

factory

module

readonly

unsigned

char

FALSE

multiple

setraises

union

component

finder

native

sequence

uses

const

fixed

Object

short

ValueBase

consumes

float

octet

string

valuetype

context

getraises

oneway

struct

void

custom

home

out

supports

wchar

default

import

primarykey

switch

wstring

double

in

private

TRUE

• Like all of CORBA, IDL evolves with CORBA versions. • It originated with a model based on “C” (changed to “C++” at an early stage) – C (C++) with good software engineering disciplines! – An IDL module definition was similar to a well written “header” file for a C module

3

4

Interface Definition Language

Quick examples

• An IDL module definition was similar to a well written “header” file for a C module

• Following are fragments from the IDL defining various services that are implemented through CORBA server objects

– define a “name space” – include typedef declarations for alias types (eg “size” as alias for “unsigned long”) – define constants and enumerations – declare the forms of simple data aggregates (structs), and aggregates with variant forms (unions) – declare the “interfaces” (classes) with their member functions – declares exceptions associated with functions (in a distributed

– Notifications – Naming

• (Note use of nested declarations – C++ style, also used in Java; you may not have encountered much in your programming.)

world, exceptions can arise in any function - network problems etc) 5

6

1

Fragments from CosNotification module CosNotification { typePrefix CosNotification "omg.org"; typedef string Istring; typedef Istring PropertyName; typedef any PropertyValue; struct Property { PropertyName name; PropertyValue value; }; typedef sequence PropertySeq; … enum QoSError_code { UNSUPPORTED_PROPERTY, UNAVAILABLE_PROPERTY, UNSUPPORTED_VALUE, UNAVAILABLE_VALUE, BAD_PROPERTY, BAD_TYPE, BAD_VALUE }; … exception UnsupportedQoS { PropertyErrorSeq qos_err; }; .. const string EventReliability = "EventReliability"; const short BestEffort = 0; const short Persistent = 1; …

module CosNotification { … /** * The AdminPropertiesAdmin interface defines operations which enable clients to get * and set the values of administrative properties. */ interface AdminPropertiesAdmin { AdminProperties get_admin(); void set_admin (in AdminProperties admin) raises ( UnsupportedAdmin); }; // AdminPropertiesAdmin }; // CosNotification

7

Fragments from CosNaming

8

Fragments from CosNaming module CosNaming { … interface NamingContext { enum NotFoundReason { missing_node, not_context, not_object }; … exception NotFound { NotFoundReason why; Name rest_of_name; }; … void bind(in Name n, in Object obj) raises(NotFound, CannotProceed, InvalidName, AlreadyBound); void bind_context(in Name n, in NamingContext nc) raises(NotFound, CannotProceed, InvalidName, AlreadyBound); … void list(in unsigned long how_many, out BindingList bl, out BindingIterator bi); … };

module CosNaming { typePrefix CosNaming "omg.org"; typedef string Istring; struct NameComponent { Istring id; Istring kind; }; typedef sequence Name; enum BindingType {nobject, ncontext}; struct Binding { Name binding_name; BindingType binding_type; }; typedef sequence BindingList; interface BindingIterator; // forward declaration interface NamingContext { … }; 9



Fragments from CosNotification



10

IDL’s design : 1

IDL

• IDL’s designers

• Constants, enumerations, structs, sequences, arrays, etc etc

– distinguished interface (~class - something with behaviors) from “struct” (a simple data aggregate, no behaviors, no use of inheritance) – chose that interfaces

– All quite useful for defining data etc

• But interfaces are the important thing – they define the functionality of the "server" • Decisions on interfaces with regard to inheritance hierarchies, argument passing etc are essentially what make up the CORBA model for distributed computing.

• could be defined using (multiple) inheritance • described objects that potentially existed in different address spaces - remote objects • implicitly inherited from a base “Object” interface whose member functions would define operations essential for remote invocations etc

–… 11

12

2

IDL’s design : 2

IDL design : 3

• IDL’s designers

• Passing arguments …

–… – assumed the existence of the normal “built in” data types (integer, floating point, character, boolean, ...) – assumed the existence of strings, and “collection” classes – permitted (multi-dimensional) arrays whose size would be known at compile time – ...

– in C (C++) arguments (apart from arrays) are passed by value - the called function gets a copy of the integer, float, or struct passed as an argument – in a single address space C program, a function can be passed the address of an argument and can work with the caller’s integer, float, or struct data item (C++’s “pass by reference” scheme uses the same implementation, just makes it more readable) – such reference arguments can be changed as a side effect of the function call; a function is not limited to being something that returns a single value, it can return a value and, as side effect, modify all its reference arguments – IDL supports • arguments passed by value (copies) • arguments that can be modified as a side effect of a function

13

Difference from RMI

14

IDL Design : 4

• RMI

• IDL’s “in” “out” and “inout” parameter qualifiers

– Data by value – Stubs for objects that can be called remotely

– a member function declaration (an “operation” in IDLspeak) lists the required parameters by type, name, and “directional” qualifier

• CORBA – Data by value – Stubs for objects that can be called remotely – Simulated pass by reference

• an “in” argument (integer, fixed size array, struct, union, …) will be copied into the request message, sent to the remote object, used there, and get discarded • an “inout” argument is sent in the same way as part of the request, but before the handling of the request is finished, the data, presumably modified as a side effect of the operation, are copied into the reply message and returned to the caller where code handling the reply will use the returned data to overwrite the original arguments • an “out” argument is similar to “inout”, but the current values of the data are not sent, the called object starts with an uninitialized integer, structure, ...

• Current value sent across network to server along with request, • New value returned by server along with any "result" value for request., • New value overwrites old value in client (calling environment) 15

16

IDL Design : 5 • Passing objects:

IDL: objects by value • This can get quite complex: valuetype Whatever {

– originally, objects (instances of “interfaces” derived from CORBA’s Object “interface”) were always passed by reference • “in” : the caller supplied a form of object reference, when the request was decoded an appropriate “client stub” object was created, the called function could access the object remotely via this stub • “inout” and “out” : the reply from the called function could include an object reference that replaced the value in the reference variable used by the caller (use of “out” and “inout” with object references is relatively rare)

– couldn’t pass objects by value (not an overwhelming problem, solution was to use an auxiliary struct to package the data, send it, use it to initialize a new object)

– revised CORBA (2.3+) does have an “objects by value” scheme • revised CORBA basically allows IDL to include interface declarations for classes unrelated to CORBA::Object - so you can have your class Date etc; but this class Date is NOT the class date from your favorite library – it's a new class that you will have to 17 implement building it out of primitive strings, numbers etc.

Data members Factory functions Public functions Private functions

}

– Valuetype derive from an omg class so you can’t simply use existing classes – Can inherit from omg.CORBA.Object and then you have a class that can be passed by value or by CORBA reference – this is atypical usage 18

3

Valuetype factories?

IDL Design : 6 "PseudoIDL" (PIDL) for ORB and adapters

• Java’s class Class:

• OMG defines IDL interfaces (in the CORBA module) for major components in an object request broker

– Instance created for each class that you define – Acts as factory – Object newInstance()

– ORB interface – Object adapter interface(s)

• These were “pseudo interfaces” in the sense that they didn't have quite the same semantics as application interfaces. A PIDL qualifier tag was used to flag such interfaces as special • These specifications used to be incomplete - an ORB supplier almost always had to include additional functionality or modify function signatures to include extra parameters.

• Other languages? – Nothing like that! – So need to define factory objects

Most of classes in current specifications are “complete”.

19

IDL Design : 7

20

local interface example module PortableServer { typeprefix PortableServer “org.omg”; local interface POA; // forward declaration typedef sequence POAList; native Servant; typedef CORBA::OctetSeq ObjectId; … // POAManager local interface POAManager { exception AdapterInactive{}; … void hold_requests( in boolean wait_for_completion) raises(AdapterInactive); void discard_requests( in boolean wait_for_completion) raises(AdapterInactive); … };

• "Pseudo-IDL" was confusing. – Current specification requires that such interfaces be specified as "local interface" • The class generated is still derived from org.omg.CORBA.Object • The identifiers of objects in such a class cannot be exported from the process in which they are defined

21

22

IDL Design : 8 ORB etc

"local" and "native" • PIDL tag deprecated; instead

• Although some gaps are inevitable, these specifications for interface ORB { … } etc try to standardize how code implementing other interfaces should link to an ORB mechanism.

– local similar to derivation from Object but instances can only be referenced in local address space (cannot have an exportable IOR) – native tag for classes that must be instances of host language classes (not derived from org.omg.CORBA.Object

23

24

4

IDL Design and language mappings : 1

IDL Design and language mappings :2 • Java

• Design choices impact on how readily IDL maps onto an implementation language. • C++

– There are a few problems, and the consequence is some rather unnatural Java constructs • examples of problem areas IDL->Java

– on the whole, this mapping looks easy, but which C++? !

– an IDL file can contain free const declarations (not defined as part of any specific interface), but all Java’s “consts” (final … ) must be class members

• IDL’s “module” construct maps onto C++ namespaces, but when CORBA's C++ mapping was defined many of the compilers still didn't support namespaces (so have to have alternative “name mangling”

– – – – – – –

schemes that add the module name to every entity name in the IDL file, or even uglier schemes with nested class declarations)

• could IDL’s string and sequence constructs map onto the STL library classes, or must we use something else? • ….

25

typedefs: typedef string Istring; // create a C type alias; but what in Java? enumerations unions “unsigned” built in types passing integers, floats, arrays etc by reference (inout and out) other issues with passing arguments 26 … And which Java? Java 1.4 added enumerations – too late to be used in the defined mapping

IDL declaration files • Typically use “.idl” file extension eg MyServer.idl. • Can contain C/C++ style “#…” macros

IDL constructs

– #include – #pragma •

to include other IDL declaration files to set options

Quite common for the standard C macro preprocessor (cpp) to be used to perform the first steps in the compilation of IDL to a target language.

• Of course, IDL files can contain comments - these are inevitably modeled on C++ comment styles – /* … */ block comments, – // line comments 27

28

module

modules • Usually an idl file defines a variety of entities in a single module

• module – role: to partition and organize your “name space”

module Mine { … };

• Entity names are in effect qualified by their module name, and so need only be distinct within each module. This allows you to have: – struct Link – struct Link – struct Link

• but a file can contain definitions for more than one module; also, a module can be “re-opened”¶

in module DataStructures in module HyperText in module Telephony

module A { /* Some A stuff */ … }; module B { … }; module A { /* other bits of A */ … }

as their effective names are “DataStructures::Link”, “HyperText::Link”, etc •

File Mine.idl

File AB.idl

A programmer, writing a telephony related program that uses data structures in support of a hypertext help system, simply has to make clear exactly what type of “Link” a particular Link variable is! 29

¶Not all idl compilers support re-opening.

30

5

modules : pragma prefix

Built in types

• Module names are used when entering definitions in the “Interface Repository”¶

• The following data types are used - in constants, as argument and

– Name of entity in interface repository will be IDL:module_name/entity_name

• The interface repository contains entries for many applications and it’s possible that identical module and entity names could arise. • “prefix” pragma can be used to prepend additional name components - #pragma prefix “eBooks.accounts” • This doesn’t affect names in code but does change the name in the IR. ¶Remember, Interface Repository contains structures describing defined classes that are similar to those Java gets via “reflection”

result types for operations, as member types in structs and unions … – short, long, long long (plus unsigned versions of all) - to avoid confusion, there is no int type; minimum precisions are defined for each – float, double based on standard IEEE definitions – char ISO-Latin alphabet – string ISO-Latin character sequence (no ‘nul’ character) – boolean – octet byte 0…255 – fixed precision arithmetic types – any

31

(mainly for “dynamic” invocations or for generic services, block of data sent along with some type identification info.) 32

Java mapping simply ignores the existence of "unsigned"

string

Sequence • IDL has “sequence” as a kind of parameterized type; you can use typedefs to declare sequences whose members are of a specified type (built in, structure, …) • A “sequence” corresponds to a dynamic array

• The string type does not have any associated behaviors. • It looks much like a nul-terminated C-style char* character sequence. • Appears commonly in const declarations and can be used as struct data member, argument to or result from a function call.

– you can specify a sequence of arbitrary length, or define a maximum size

• IDL doesn’t mandate how you can use a sequence, but basically you should be able to

const string greeting = “Hi mom”;

– find its size – access each member, using something akin to array subscripting

• Example 33

typedef sequence UserNames; // now use UserNames as a return type typedef sequence Scores; // at most 25 entries

34

Programmer defined types: typedef ...

Arrays

• typedef types: – C/C++ typedefs are used to define arrays and sequences – they are also used to define “alias” types

• You can have arrays (with arbitrary number of dimensions) containing data of any type (built in or programmer defined). • But, the presumed mapping onto C/C++ native arrays meant that an array would not include any “meta-data” defining its dimension sizes. • Consequently, arrays must be defined with fixed sizes in all dimensions. • Arrays are specified using typedefs:

typedef long long CashAmount; // funds in cents typedef unsigned long TimeDiff; // time in msecs typedef unsigned long DiskLocation; // byte offset

– after these typedefs, you can declare CashAmount variables, parameters etc.

• Cautions:

typedef short chessBoard[8][8]; typedef string sectionNames[15];

• Arrays and sequences have generally similar uses; sequences have advantage of not having to define size at IDL compile time.

35

– Remember that alias types give no security - you can add a DiskLocation to a TimeDiff – It is questionable whether they enhance the readability of a program – The suggestion that they permit easy change of type (eg make DiskLocation and unsigned long long) is fallacious - you end up with two incompatible lots of software in your distributed system.

36

6

Programmer defined types: enumerations

Programmer defined types: struct

• struct:

• enum: – Basically, these are C++ enum declarations (except you can’t specify

– Define a C/C++ data aggregate by listing its members (no C style anonymous structures)

– More often, enum declarations will appear within interfaces

struct simpledate { short year; short month; short day; }; struct customerprospect { string name; string phonedial; string address; long contactingRepsId; simpledate firstContact; simpledate recentContact; };

values for the members of the enumeration, which you can do with C++ though it is rare for this to be justified) enum Faculty { arts, science, engineering, law, medicine, commerce }; – enum declarations can appear at module level (the enumerator names get defined at the module level name space) interface WWW_Online_Game { enum ConnectionFailure { InvalidPlayerName, PasswordIncorrect, SubscriptionExpired, MembershipCancelled, SystemFull }; … }; – the names of these enumerators belong in the interface’s name space, so for example the name SystemFull could be used elsewhere in the same module

– structs introduce subsidiary name spaces, so a name like “year” can also be used for a member in another struct 37

Programmer defined types: union

Programmer defined types: “recursive types”

• union:

– Limited use – Unlike C/C++, there must be a discriminator (you needed one in practice with C/C++ unions - for how else would the function passed an instance of a union know what to do with it) enum MonitorEventType { IntruderAlarm, SmokeDetector, PowerFail }; union MonitorEvent switch(MonitorEventType) { case IntruderAlarm: short alarmNumber; short watchmanRoute; short idNearestCamera; case SmokeDetector: short zoneIdentifier; … case PowerFail: short circuitNumber; … };

38

• IDL doesn’t let you define “pointers”. • So, how do you define something like an element of a linked list - where you need a “pointer to next element” • IDL allows a “recursive” definition where a data member can be a sequence of the type being defined: struct LinkedListItem { Data sequence };

content; nextItem;

• That definition has an “anonymous sequence declaration”, still legal but deprecated. 39

Note

40

Recursive structures? • To be honest, this isn’t the sort of thing you are likely to want to define as an IDL struct mostly you are defining simple data blobs that need to be shuffled back and forth between different processes. • You aren't likely to want to pass binary trees, lists, queues etc!

• Better definition avoiding anonymous type struct LinkedList; typedef sequence LinkedListSeq1; struct LinkedList { Data content; LinkedListSeq1 nextItem; };

41

42

7

IDL interfaces

interfaces

• Of course, IDL’s main role is the description of services provided by server objects. • These descriptions take the form of “interface” declarations. • An interface declaration is, naturally, the “public” interface of a server - so there is no need for access qualifiers; anything listed is inherently public. • An interface declaration provides no guide as to implementation – nothing about data owned, – nothing about private implementation functions called from functions in the public interface – no code.

• An interface will typically contain – some constant definitions – declarations of types used for arguments and results (typedef types, enumerations, structs, arrays); if only used for communication with one server, it is better to declare these auxiliary types within that server’s interface rather than at module level

– exception definitions – “attribute” definitions – operation declarations (“operation” is IDL-speak for member function, method, …)

43

interfaces

44

Attributes in interfaces : 1

• Example interface WWW_OnLineGame { enum ConnectionFailure { … }; enum MoveDirection { … } exception InvalidAction { … }; struct possession { short value; short weight; string description; … } typedef sequence Possessions; const short levelMax = 20; … boolean tryMove(in MoveDirection move); void pickupObject() raises (InvalidAction); Possessions getPossessions(); ... };

• It is possible for an interface to include “attributes” interface ThermostatControlledContainer { readonly attribute string ContainerName; attribute short Temperature; … };

• It looks as if you are declaring data members here, but you aren’t.

45

Attributes in interfaces : 2

46

Attributes in interfaces : 3

• An “attribute declaration” is simply short hand for declaring “get…( )” and “set…(... )” functions. • The readonly attribute ContainerName will result in a generated class declaration with a getContainerName() function. • The attribute temperature results in getTemperature( ) and setTemperature(... ) functions (eg for Java):

• Attributes don’t necessarily correspond to member variables in the implementing class. • A Java class for ThermostatControlledContainer might – have a java.lang.String myName data field for its name, – have getContainerName( ) function of the form return myName

public class ThermostatControlledContainer { public String getContainerName(); public int getTemperature(); public void setTemperature(int newsetting); … 47

• But it is possible that the name resides in a database, and the getContainerName() function uses JDBC/SQL to retrieve the value. • Similarly, there might be an int myTemperature data member that is simply set and fetched; but maybe settemperature(…) involves code to activate heater/cooler circuits to achieve a desired temperature while gettemperature() has code that reads a sensor 48

8

IDL operations “oneway”

IDL operations • An operation declaration (member function declaration) has – (optional) synchronization qualifier – a return type (“void” if nothing else) – a name – (optional) parameter declarations – (optional) raises list for programmer defined exceptions – (optional) “context” specifier

• Normally, invocation of an operation in CORBA is “synchronous” – the calling thread composes the message representing the operation request and dispatches it via the local ORB – the calling thread blocks until either a reply is received or an exception is signaled (a reply carries the function result and returned values for out and inout arguments, but a handshake reply is received even for void procedures with only in arguments) – the calling thread deals with the reply or exception

• But, subject to a number of restrictions, you can make an operation “asynchronous”

49

50

IDL operations parameters

IDL operations “oneway”

• An operation can be declared “oneway”

• Parameter list can be empty ( ) (not (void)) • Otherwise, list of

– calling thread composes request and dispatches it via the local ORB – thread continues with whatever it wants

– directional attribute – type – name

• Restrictions

in, inout, out

• IDL does not support C++ style function overloading

– nothing should come back from the called function

– you can’t have void save(in string name) and void save(in

• it is a void procedure • only “in” parameters • no application specific “raises” clauses • (ORB related exceptions? Those raised during dispatch of request are thrown, those raised later are swallowed by ORB.)

unsigned long id)

– must be void saveName(in string name) and void saveId(in •

unsigned long id) (too hard to map overloaded names onto some of IDL’s target languages)

51

IDL exceptions • IDL’s programmer defined exceptions are not represented in terms of classes with inheritance. • Mostly they are similar to structs with data members that help a client identify the nature of a problem, but can be empty tags exception UserError { }; exception UnrecognisedCommand { string unparsedCommandData; };

52

IDL exceptions : raises clause

• Any programmer defined exceptions that may be thrown by implementation code of a function must be specified in a raises( ) clause in the corresponding operation declaration void pickupObject() raises (InvalidAction);

• Although not specified, every operation has an implicit raises(CORBA::…, …)

• There are about 30 different standard system defined exceptions: – ORB failures, communication failures, object not present, resources not available, transaction related failures, ... 53

54

9

IDL operation context

IDL standard exceptions

• An operation declaration can include a “context clause” - this will list a series of property names (represented by quoted strings in the declaration)

• These CORBA exceptions contain

– an indication of status of operation (completed, not completed, who knows) – a minor code which may or may not be informative.

RegistrationInfo register( ) context (“MEMBERID”, “ACCOUNT”)

• There will be a means for a client programmer to bind values to these names. • The bound name/value pairs are sent with the operation request.

• It is considered generally poor practice for implementation code to simply throw a CORBA BadParam exception when something goes wrong, make your own exception classes (but since you can’t specify raises clauses along with attributes, code for getX( ) setX( ) attribute related functions is limited to throwing BadParams)

• How? • Well, it varies a bit with the language mapping.

55

56

inheritance

IDL contexts • There is no type security on contexts (no means to check

• Interfaces can specify inheritance relationships: interface MotorCar { … }; interface ElectricMotorCar : MotorCar { void recharge(in short numKillowats); … }; interface FuelMotorCar : MotorCar { enum Fuel { Hydrogen, Petrol, Diesel }; void refill(in Fuel fueltype, in short numLitres); … };

the validity any value provided by a client programmer, no way of enforcing that the client programmer binds any values).

• Contexts are not much used in standard application programs. • However, one possible area of use is in transaction processing; contexts can be used to pass data identifying any transactional context for an operation. Interfaces relating to transactions are most likely to arise in the implementation of the ORB itself. 57

58

IDL the CORBA module • The IDL specification includes a CORBA module with IDL interfaces for such things as – – – – – –

IDL compilation

Object a few standard functions, eg duplicate ORB orb.init(…) etc PortableServer and others (for POA compliant ORBs) Name - Value lists (low-level implementation stuff) Request ...

59

60

10

IDL compiling into Java or C++

IDL • What is IDL for? – It is there to provide a description of services from which we can generate - some code that runs in the client that will permit the invocation of the services - some code that runs in the server that will receive requests and use them to invoke functions in whatever is the real service implementer

• With OO languages like Java and C++, we are going to “compile” to produce – client stub class – server skeleton class – and various classes defined for the structs, sequences, arrays etc that the service provider uses for specifying its arguments and results

61

Client side

Server side • The server side is more complex. • Basically, you get a class for a server skeleton

• The IDL compiler’s output for the client side is usually simple in structure: – you get a stub (proxy) class that implements the server’s interface, and has code • • • •

– derived from some generic server side skeleton class for that ORB – instance(s) of this class get created by the ORB – an instance gets called by ORB runtime code to decode a request, perform the operation, and build the response

that marshals arguments, that invokes ORB functions to send a request and receive a response, that decodes a response that forwards exceptions to the calling environment

• But the server developer has to add the code that performs the actual operations as defined in the server interface. • And there are different ways that this can be done ...

– instances of the proxy class will also be able to do things like say whether they represent the same remote object

• All the code for the client side can be generated by the IDL compiler - of course, while down-calls to the ORB must comply with CORBA specification, other details of the code are ORB specific and are not prescribed in the OMG documents.

62

63

Inheritance or ...

64

Inheritance or delegation

• The toy AphorismServer example used inheritance – idlj gave us the abstract class GuruPOA • this implemented all the functions that would be invoked by the ORB, including the actual invoke( ) function that, via a switch statement, could call service functions (only 1 branch in this switch!) • the enlightenMe( ) function was not defined

– we created a concrete implementation class WorkingGuru that extended GuruPOA and had an effective definition for englightenMe()

• This is typical use of inheritance. • But there is an alternative ... 65

• You can have a class that implements the required interface and which is completely independent of CORBA class system public class Enlightener { java.util.Random r = new java.util.Random(); String[ ] stockphrases; String enlightenMe() { … }; ... };

• A Skeleton object can have a reference to an Enlightener • When asked to generate a string, the Skeleton object delegates the work to its associated Enlightener.

66

11

Tie classes

Tie classes

• The IDL compilers are required to allow the server-developer to chose between inheritance and delegation models. • The default compilation mode will generate an abstract server skeleton class from which the developer can derive a concrete implementation class. • The alternative mode generates “tie” classes – there is a concrete skeleton class that will have • a data member that references an instance of the real implementation class • a public member that can be used to set this reference • an “invoke” function that delegates requests to the tied implementation object

• Delegation, using “tied” classes, has some advantages: – separation of implementation and CORBA related concerns may • make development easier • make it easier to serialize an object (it won’t try to save any of its links into the ORB run time!)

– can sometimes allow the use of existing classes whose instances can provide the necessary services

– the developer supplies an implementation class with a public interface that matches the required server interface 67

IDL compilers code generation

68

Code generation just add class ...

• Code generated by an IDL compiler is very much “boilerplate” code - essentially the same code for every service provider and its clients. • The code generator can use textual templates with slots where class names and function names can be inserted – each slot gets filled with either a class name, or with a set of entries one for each operation name etc.

69

IDL compilers code generation and ...

public abstract class ???POA extends org.omg.PortableServer.Servant implements ????.????Operations, org.omg.CORBA.portable.InvokeHandler { private static java.util.Hashtable _methods = new java.util.Hashtable (); static { _methods.put ("????", new java.lang.Integer (0)); … } public org.omg.CORBA.portable.OutputStream _invoke (String $method, org.omg.CORBA.portable.InputStream in, org.omg.CORBA.portable.ResponseHandler $rh) { … switch (__method.intValue ()) { …; } return out; } // _invoke private static String[] __ids = { "IDL:????/????:1.0"};

public abstract class GuruPOA extends org.omg.PortableServer.Servant implements Aphorism.GuruOperations, org.omg.CORBA.portable.InvokeHandler { private static java.util.Hashtable _methods = new java.util.Hashtable (); static { _methods.put ("enlightenMe", new java.lang.Integer (0)); } public org.omg.CORBA.portable.OutputStream _invoke (String $method, org.omg.CORBA.portable.InputStream in, org.omg.CORBA.portable.ResponseHandler $rh) { … switch (__method.intValue ()) { …; } return out; } // _invoke private static String[] __ids = { 70 "IDL:Aphorism/Guru:1.0"};

IDL compilation and resource management

• The files with the ORB specific stub and skeleton classes must also contain definitions of all the constants, enumerations, structs etc defined in the IDL file. • These must be mapped into implementation language constructs so that developers can create and manipulate the data items that must be exchanged between client and server. • The mapping should be standardized, not ORB dependent.

• Control of resources (mainly heap space) is a major issue in CORBA applications – almost every operation invocation involves creating dynamic structures in the heap for both messages sent and responses received.

• Memory leaks (and other resource leaks) can easily occur (Java’s garbage collection reduces problems but does not eliminate them, it is easy to write code that keeps live pointers to objects that really should be discarded). • The mappings from IDL to a language have to be designed to help minimize such problems

– by highlighting issues related to resource ownership – and, as far as possible, aiding in the automatic management of resources. 71

72

12

OMG’s language mappings • The Object Management Group has defined the correct mappings for languages including Java, C++ (and Ada, C, Cobol, Smalltalk) • These language mapping specifications are long and complex. • They are available at the OMG web site. – http://www.omg.org/technology/documents/idl2x_ spec_catalog.htm • 158 pages on C++ mapping • 138 pages on Java mapping

IDL  Java

73

Mapping to Java

74

Mapping to Java

• IDL names and identifiers are mapped to Java names and identifiers – Ideally, with no change. – If a name collision could be generated in the mapped Java code, the name collision is resolved by pre-pending an underscore (_) to the mapped name, e.g. you define an IDL interface that you called "native" (this would clash with the Java reserved word native)

• IDL modules map directly into Java packages. • OMG's example: // IDL module Example {...} // generated Java package Example;

– Some IDL construct have to be be mapped to several (differently named) Java constructs. • E.g. interface foo is mapped to the Java interfaces foo and fooOperations, and additional Java classes fooHelper, fooHolder, fooPOA, and optionally fooPOATie. Holder and Helper classes will get explained shortly; meantime, there will be several forward references! Basically Helper classes deal with aspects like type casting, interface repository names etc. Holder classes are involved in the implementation of CORBA's 'pass by reference' style of function arguments.

75

IDL -> Java Basic types

char (and string)

• Numeric types

• IDL char and string limited to ISO Latin characters.

– Java doesn’t have unsigned values (so, for example, an IDL “unsigned short” is mapped as a “short”) – otherwise mapping is as expected • IDL short unsigned short long … long long float fixed

• Mapping is onto Java’s 16-bit Unicode format.

Java short short int

• Some checking is done, may get CORBA::DATA_CONVERSION exceptions if try to use anything other than an ISO Latin character in char or string.

long float java.math.BigDecimal

Holder classes exist for these basic types; these are needed for the pass by reference system; suppose you want a function that gets passed and integer value that it is to adjust – can't pass a Java int (because would just get a copy of current value placed on stack, modifying that value would have no affect on original integer variable)

76

– Checking is done when value is sent over the network

77

78

13

IDL->Java strings

IDL->Java Sequences • Sequences (assume “Thing” as name of builtin type or user defined type)

• IDL string maps to java.lang.String (along with the necessary StringHolder class) • IDL can specify maximum size of string; naturally this doesn't apply to Java strings so you can create strings that exceed allowed length.

IDL

typedef sequence Things;

• Java Thing[ ] class ThingHolder

However, a check is made when the string is finally packaged for transfer across the network.

class ThingHelper

if IDL operation returns a sequence, Java method will return an array; needed if IDL specifies an inout or out Sequence parameter; conversion to/from Any etc

• No problems in Java, arrays "know" their size. • Again, an IDL definition of a "fixed size" sequence doesn't result in any restrictions on the size of the array – instead exceptions get thrown if the array is too large when it gets serialized for transfer over the network.

79

80

Example for "any" types

“Any”

• Notifications service – It is a messaging service that delivers data from producer to consumer – One of the data types that it uses is "Property"

• Essentially: – A block of bytes starting with a length specifier. – Containing a series of entries each of form • Length • Type specification • Data bytes

• A Property has a name – obviously a String • And a value.

Metadata

• Role: – Generic type, as in notification services where must return a data object of some application specific type

– What kind of value? – Well, that depends on the application. » (The value wouldn't normally be a CORBA object – i.e. data for constructing stub. Instead, it is some application defined data – maybe a built in type, a string, sequence, …; or possibly a struct.) – Producer and consumer code will both know the kind of value they want; but service knows only that it is some kind of data. – Hence use of Any

81

Part of service specification using "any"

82

Java "any" abstract public class Any implements org.omg.CORBA.portable.IDLEntity { abstract public boolean equal(org.omg.CORBA.Any a); abstract public org.omg.CORBA.TypeCode type(); abstract public void type(org.omg.CORBA.TypeCode t); abstract public void read_value( org.omg.CORBA.portable.InputStream is, org.omg.CORBA.TypeCode t); … // insert and extract each primitive type abstract public short extract_short(); abstract public void insert_short(short s); abstract public int extract_long(); abstract public void insert_long(int i); …

module CosNotification { typedef string Istring; typedef Istring PropertyName; typedef any PropertyValue; struct Property { PropertyName name; PropertyValue value; }; typedef sequence PropertySeq;

83

84

14

Generated Helper classes can transfer data to/from an "any"

Use of any

• Application defined data types get Helper classes with insert and extract methods

• Suppose you wanted to package up something with a long, a string, and an instance of a user defined struct Mystruct

– e.g. for the following type

– Producer would

// IDL - typedef sequence typedef sequence IntSeq;

• Create an "any" • Insert the long with class Any's insert_long, then insert string with Any's insert_string • Use MystructHelper class's static insert method to insert the instance of a Mystruct

– Will get a helper class public abstract class IntSeqHelper { public static void insert( org.omg.CORBA.Any a,int[] t) public static int[] extract(Any a){...}

– Consumer (which must understand what was sent!) will extract the long and the string using the methods in the Any class, then use MystructHelper's static extract method

… 85

86

IDL->Java constants

Code fragments with "Any" • Producer:

• IDL constants (remember, these are mostly strings or numeric constants) map directly into equivalent Java constants. • Curiously, the standard mapping doesn’t make them static final. • But, where do you put these constants? • If they are declared within an IDL interface, they go into (one of) the Java classes generated for that interface. • If declared at module level, you get a silly little Java class with a single “public X value = …;” member).

Any myAny= orb.create_any(); myAny.insert_string(message); org.omg.CosNotification.StructuredEvent event = new org.omg.CosNotification.StructuredEvent( eventHeader, filterableData, myAny );

• Consumer: System.out.println( "Received an event" ); String msg = event.remainder_of_body.extract_string(); An "Any" forms the main data-body of a CosNotification event message 87

88

Module level constants

Typedefs for aliases • IDL

IDL

Java module Example { package Example { const short maxAttributeValue = public interface 25; maxAttributeValue { } short value = (short) 25; }

89

typedef long long Money;

• Java ? • You can’t do it. • IDL to Java mapping simply eliminates a “typedefed” type like Money, replacing all uses by inherent type. – Sometimes a bit disconcerting! You see the interface functions as returning data of specific defined type e.g. Money, and try to declare an instance that type in your program – and your program won't compile! The "defined type" was simply a typedef that has vanished.

If you "typedef" an array or a struct, you will end up with a defined "Holder" class.

90

15

Enumerations

struct

• Java’s lack of enumerations (at time of mapping definition!) makes the mapping clumsy. • IDL

• IDL struct results in – Java class implementing IDLEntity – Holder class – Helper class

enum Faculty { arts, science, medical, law, engineering };

• Java (also get associated Holder & Helper classes) public class FacultyType implement org.omg.CORBA.portable.idlEntity { private int _value; public static final int _arts = 0; public static final FacultyType arts = new FacultyType(_arts); … public int value() { return _value; } public static EnumType from_int(int value) { switch() … }; protected Faculty(int value) { _value = value; }

• Main Java class is declared – as final public class ... – Public data members for all fields – two constructors - one empty, the other with arguments corresponding to each member

91

92

struct

unions

• OMG example struct StructType { long field1; string field2; }; // generated Java final public class StructType implements org.omg.CORBA.portable.IDLEntity { public int field1; public String field2 = ""; public StructType() {} public StructType(int f1, String f2){...} } final public class StructTypeHolder implements org.omg.CORBA.portable.Streamable { … } abstract public class StructTypeHelper { … }

• An IDL union maps to a final public Java class along with auxiliary Holder and Helper classes. • The union class itself – a member of type java.lang.Object that holds whatever data currently exists within the union – has an EnumType field for the discriminator and associated access function – accessor method for each possible value of discriminator (checks that discriminator type corresponds to current value, returns data Object coerced to appropriate type) – modifier methods (change Object and discriminator value) – ... 93

Unions – historical anomaly; a 1970s C programming construct that ended up in the CORBA definition; extremely rare for anyone to use one.

Union

94

arrays

• OMG example // (Uses an enum, EnumType, defined in an earlier OMG example union UnionType switch (EnumType) { case first: long win; case second: short place; case third: case fourth: octet show; default: boolean other; }; // generated Java final public class UnionType implements org.omg.CORBA.portable.IDLEntity { public UnionType() {....} public EnumType discriminator() {....} public int win() {....} public void win(int value) {....} public short place() {....} public void place(short value) {....} … } final public class UnionTypeHolder implements org.omg.CORBA.portable.Streamable { … } abstract public class UnionTypeHelper { … }

• An IDL typedef for an array results in the creation of Java “Holder” and “Helper” classes for that array type. • There is no actual Java class corresponding to the array, you use native Java arrays. • IDL typedef short chessboard[8][8]

• Java final public class chessboardHolder … { … } abstract public class chessboardHelper { … }

• Can’t declare chessboard myBoard; instead use short myBoard = new short[8][8]; 95

96

16

Exceptions

Holder classes

• User defined exception mapped to a Java class with public data members and constructors. • CORBA system exceptions and user defined exceptions are both threaded into the Java exception hierarchy.

• Remember RMI – you could pass a reference to a Remote object (what got sent was an object-id that could be used to create a proxy in the callee) – otherwise, all data values were passed by value (int parameters sent as

– System exceptions inherit from RunTimeException (therefore not listed in method signatures and don’t have to have catch blocks) – User defined exception classes defined as extending org.omg.CORBA.UserException

97

Why holders?

integer value used to initialize an int in callee, a class instance eg an instance of java.lang.Date would be serialized and deserialized in callee to create a new Date object)

• “out” parameters don’t really fit the Java model. • But “out” (and “inout”) are part of the IDL definition, so there has to be a mapping into Java. • Enter Holder classes. 98

“out” & “inout” in Java

• An “inout” argument (built in or class type) must be serialized and its contents sent with the invocation. • When the remote operation finishes it will return a “response” structure containing data that must be used to change original “out” and “inout” arguments. • This is somewhat problematic – consider the case of an integer argument to a method of a Java stub object – an integer value will have been taken from a variable in the caller and placed on the stack before the call is made to the stub object – nothing remains to identify the original source of that integer – so, what gets overwritten for an inout or out integer argument? 99

“out” and “inout” parameters

• To support “out” and “inout” in Java, we are going to have to have a scheme where we pass the stub a reference to an object – this object “holds” a value of the required type – it can write its value an output stream (when we are serializing the data to construct the original request) – it can read a replacement value from an input stream (when we are dealing with the response) final public class IntHolder implements org.omg.CORBA.portable.Streambable { public int value; public IntHolder(int initial) { value = initial; } public void _read(…) { … } … }

100

Holder classes

• An IDL operation signature using inout and out parameters will have to map to a Java method signature using parameters that are instances of “Holder” classes. • A caller invoking such a method must

• Holder classes are pre-defined for all built-in types. • Holder classes are generated for all structs, sequences, etc defined in the IDL

– create a suitable Holder object, initializing it with the value of a data element if it is an “inout” – pass this Holder object in the method call to the stub – retrieve the value from the Holder object after the method call 101

102

17

Generated Holder class

Helper classes

• The Holder class for a user defined type is shown below: // Java final public class Holder implements org.omg.CORBA.portable.Streamable { public value; public Holder() {} public Holder( initial) {...} public void _read( org.omg.CORBA.portable.InputStream is) {...} public void _write( org.omg.CORBA.portable.OutputStream os) {...} public org.omg.CORBA.TypeCode _type() {...} }

• In addition to the “Holder”s, auxiliary “Helper” classes are generated for all user defined IDL types. • A “Helper” is a static class (all its methods are static) • Its methods include: – – – –

String id( ) insert(…), extract(…) read(stream, obj), write(…) narrow( )

get Interface Repository identifier conversion to/from Any for transfer over network really just for interfaces does type-safe downcast as with C++ (narrow() functions are not generated unless needed)

103

Helper class • For a user defined IDL type , the following Helper class is generated (there are many special cases for different kinds of abstract interface and other definitions).

// generated Java helper abstract public class Helper { public static void insert(org.omg.CORBA.Any a, t) {...} public static extract(Any a) {...} public static org.omg.CORBA.TypeCode type() {...} public static String id() {...} public static read( org.omg.CORBA.portable.InputStream is) {...} public static void write( org.omg.CORBA.portable.OutputStream os, val) {...} // only helpers for abstract interface public static narrow(java.lang.Object obj) {...} … // for each factory declaration in non abstract value type public static (org.omg.CORBA.ORB orb [ "," ] ) {...} }

104

org.omg.CORBA.portable.IDLEntity • The OMG standard mapping for IDL to Java requires that almost all generated Java classes implement the portable.IDLEntity interface. package org.omg.CORBA.portable; public interface IDLEntity extends java.io.Serializable {}

• This is an empty interface, that simply acts as a tag identifying a class as being IDL related.

(Also, in an indirect way, specifies that anything that you define is going to be "serializable" – so can be written using Java's object i/o run-time code)

• Some tools might need to use the fact that something is IDL related to determine how to generate code (also relevant to regeneration of IDL from Java).

105

Valuetypes

Valuetypes • Java "serializable" objects coming off wire can be re-instantiated into class:

• Original CORBA idea – Arguments passed to operations of remote objects can be: • "References" to other CORBA objects (i.e. the data needed for recipient to build a stub and then use this to invoke operations on "remote object") – e.g. NamingService returns references to CORBA object found by name

• Built-in types, sequences, arrays etc • "structs"

• By time Java mapping was required, view had changed a bit (maybe Java RMI had some influence); why not pass "objects" (instances of application classes)? This would be better than copying data into some artificial little Java version of a data-transfer struct.

In simple learning exercises on CORBA, can probably ignore value types; data for arguments/results will mostly be simple strings, numbers etc.

106

107

– Identify class from serializable data – Used "newInstance" method of Class object – Fill it with de-serialized data

• But that is Java specific. OMG needed to define a language neutral version of the same thing hence "Valuetypes" and type factories. • Result is very similar to passing ordinary objects in Java RMI (except that in principle C++/Cobol/Java objects of valuetypes are all compatible). – Caller constructs instance – Instance gets serialized as argument to request – Receiver recognizes type, invokes appropriate factory to get new object that initializes itself from serialized data. – With help of appropriate Holders, valuetypes can be also used as out and inout arguments.

108

18

Valuetype

Valuetype •

• OMG example typedef sequence WeightSeq; module ExampleA { valuetype WeightedBinaryTree { private long weight; private WeightedBinaryTree left; private WeightedBinaryTree right; factory createWBT(in long w); WeightSeq preOrder(); WeightSeq postOrder(); }; }; 109

Java version

public abstract class WeightedBinaryTree implements org.omg.CORBA.portable.StreamableValue { protected int weight; protected WeightedBinaryTree left; protected WeightedBinaryTree right; public abstract int[] preOrder(); public abstract int[] postOrder(); public String[] _truncatable_ids() {...} public void _read( org.omg.CORBA.portable.InputStream is) {...} public void _write( org.omg.CORBA.portable.OutputStream os) {...} public org.omg.CORBA.TypeCode _type() {...} } public interface WeightedBinaryTreeValueFactory extends org.omg.CORBA.portable.ValueFactory { WeightedBinaryTree createWBT(int weight) {...} } abstract public class WeightedBinaryTreeHelper { … } final public class WeightedBinaryTreeHolder implements org.omg.CORBA.portable.Streamable { … }

Valuetype

110

IDL->Java interfaces

• You have to define new "valuetype" classes – So cannot just use java.util.Date, or java.util.Hashmap or whatever.

• An interface should map into – signature Java interface – operations Java interface

• Valuetypes derived from omg classes like org.omg.CORBA.portable.StreamableValue

• in addition will have the standard Holder and Helper classes.

• If you want to pass around instances of things like Date objects (or instances of other Java data types) – Define IDL interface with the actual parameter as string – Serialize real data object into canonical string form – Receiver reads String and uses it in constructor of appropriate data type

111

112

IDL->Java interfaces

Operations interface • The Operations interface is the one that will contain the declarations of the Java methods corresponding to the IDL operations. • The signature interface extends – the operations interface – CORBA OMG Object – IDLEntity • (Signature interface is base for proxy stub class, operations interface will also be used by both “tie” and “inheritance” implementation classes) 113

• IDL

• Java

public interface interface Player { PlayerOperations { string getName(); java.lang.String getName(); … … } } public interface Player extends PlayerOperations, org.omg.CORBA.Object, org.omg.portable.IDLEntity { } abstract public class PlayerHelper { … } final public class PlayerHolder … { … } 114

19

IDL->Java operations

“oneway”

• “in” parameters become corresponding Java type. • “inout” and “out” parameters become corresponding Java Holder type. • If a context is specified, an extra parameter of type or.omg.CORBA.context is added to the function signature. • “raises” qualifiers map into throws(exceptions) as expected. • ‘get’ / ‘set’ methods are generated for attributes in the obvious manner.

• IDL’s “oneway” operation qualifier simply disappears in the both the C++ and Java mappings. • There is no way to identify “oneway” member functions (methods) in the C++ or Java class declarations. • The information is in the Interface Repository and there are “send_oneway” functions in ORB related classes so, presumably, there is a mechanism for forcing the ORB to check the Interface Repository and use the required synchronization scheme. It isn’t obvious from the materials I have seen.

115

Memory management operations

116

Interfaces use in client & server

• Original target for IDL mapping was C++ where, of course, have to consider memory management issues! This resulted in operations like "duplicate()" and "release()" being defined for org.omg.CORBA.Object. Java's automatic garbage collection means that these operations have no implementation. • Java’s null can be used whenever an object reference is required; in other language mappings, such as the C++ mapping, there have to be class specific nil( ) operations to test whether a reference to a CORBA Object is null.

• An IDL compiler will generate a client stub Java class that extends the Java signature interface – Client stub should be named _NAMEStub – It should extend or.omg.CORBA.portable.ObjectImpl.

• A compliant implementation must generate server side skeleton Java classes etc for both implementationinheritance and “tie” models; the developer may then select the most appropriate model. • Package org.omg.PortableServer defines base classes from which these skeletons must be derived (two sets of classes, they vary in how invocations are handled - using “dynamic invocation” or “streams”)

117

IDL->Java org.omg.CORBA • OMG standards document defines Java classes for the interfaces (and pseudo interfaces) in org.omg.CORBA – Object, ORB, NVList, Context, NamedValue, etc

118

IDL  C++

119

Just a brief overview; no details because you will not be doing any CORBA programming with C++

120

20

Mapping to C++

IDL->C++ Memory management • Possibly hardest parts of C++ mapping for IDL relate to the built-in support for memory management. • Issue is simple

• IDL looks so similar to C++ that you’d likely expect few problems. • But problems there are … – silly little things like an IDL enum (or other IDLconstruct) using a C++ reserved word enum incovenient { while, for, if, continue, else };

– technical things like sensible forms for client stub and server skeleton classes and supporting classes – big serious complex things like how best to deal with variable sized structures (string, sequence)

– Data structures are being created in heap, and references passed around within program as addresses that get saved in pointers. – Which part of code is responsible for freeing structures? – Can mapping be defined in such a way that these responsibilities more clearly specified?

121

122

IDL->C++ Memory management

IDL->C++ Memory management

• Forget to free memory:

• Smart pointers.

– You die slowly from some complication of obesity • Help keep track of usage

• Free memory too soon:

– One common mechanism is a use count associated with structure in heap; structure only released if use count gets to zero. – Another common mechanism is to have an extra intermediary that owns a reference to actual heap object and which understands issues of copying, assignment, etc.

– You die suddenly, hanging from a dangling pointer.

• Solution?

• Idea is simple enough, but … 123

IDL->C++ Memory management • Need for smart pointers appears at several different places – Management of proxies for remote objects – Management of data structures (structs and class instances) being passed between functions and used for various times.

• Support for smart pointers associated with different usage patterns was built into CORBA at varying stages

124

… and another problem • When the mapping was defined, the "namespace" concept for C++ was being finalized but essentially no compilers implemented namespaces. – Some "C++" compilers still couldn't handle "exceptions" despite these having been around for a few years.

• Consequently, mapping is made more complex in places by having to allow alternative constructs for cases where a compiler cannot handle a feature.

– Different approaches used in different contexts – Somewhat confusing terminology (similar terms signifying the different mechanisms used in the different contexts) 125

126

21

… and still more

C++ mapping - complex

• C++ compilers used different definitions of int etc (for some it was 16-bit, for others it was 32-bit) • Early versions of Standard Template Library existed but – Not all C++ compilers then available handled template classes, those that did handled them poorly – STL not particularly popular at the time – certainly not really a widely regarded "standard"

• If you do end up maintaining some C++ CORBA code: – Read the OMG mapping document – Read • “Pure CORBA” • “Advanced CORBA Programming with C++”

• So

– Look at Doug Schmidt’s ACE project

– How to map the simple types consistently? – How to map "string", "fixed" etc? – How will variable length sequences be represented? 127

128

22

Suggest Documents