VisiBroker for C++ Developer’s Guide : Using Interface Repositories

Using Interface Repositories
An Interface Repository (IR) contains descriptions of CORBA object interfaces. The data in an IR is the same as in IDL files, descriptions of modules, interfaces, operations, and parameters, but it is organized for runtime access by clients. A client can browse an Interface Repository (perhaps serving as an online reference tool for developers) or can look up the interface of any object for which it has a reference (perhaps in preparation for invoking the object with the Dynamic Invocation Interface (DII)).
Reading this section will enable you to create an Interface Repository and access it with VisiBroker utilities or with your own code.
What is an Interface Repository?
An Interface Repository (IR) is like a database of CORBA object interface information that enables clients to learn about or update interface descriptions at runtime. In contrast to the VisiBroker Location Service, described in “Using the Location Service” which holds data describing object instances, an IR's data describes interfaces (types). There may or may not be available instances that satisfy the interfaces stored in an IR. The information in an IR is equivalent to the information in an IDL file (or files), but it is represented in a way that is easier for clients to use at runtime.
Clients that use Interface Repositories may also use the Dynamic Invocation Interface (DII) described in “Using the Dynamic Invocation Interface” Such clients use an Interface Repository to learn about an unknown object's interface, and they use the DII to invoke methods on the object. However, there is no necessary connection between an IR and the DII. For example, someone could use the IR to write an “IDL browser” tool for developers; in such a tool, dragging a method description from the browser to an editor would insert a template method invocation into the developer's source code. In this example, the IR is used without the DII.
You create an Interface Repository with the VisiBroker irep program, which is the IR server (implementation). You can update or populate an Interface Repository with the VisiBroker idl2ir program, or you can write your own IR client that inspects an Interface Repository, updates it, or does both.
What does an Interface Repository contain?
An Interface Repository contains hierarchies of objects whose methods divulge information about interfaces. Although interfaces are usually thought of as describing objects, using a collection of objects to describe interfaces makes sense in a CORBA environment because it requires no new mechanism such as a database.
As an example of the kinds of objects an IR can contain, consider that IDL files can contain IDL module definitions, and modules can contain interface definitions, and interfaces can contain operation (method) definitions. Correspondingly, an Interface Repository can contain ModuleDef objects which can contain InterfaceDef objects, which can contain OperationDef objects. Thus, from an IR ModuleDef, you can learn what InterfaceDefs it contains. The reverse is also true; given an InterfaceDef you can learn what ModuleDef it is contained in. All other IDL constructs, including exceptions, attributes, and valuetypes, can be represented in an Interface Repository.
An Interface Repository also contains typecodes. Typecodes are not explicitly listed in IDL files, but are automatically derived from the types (long, string, struct, and so on) that are defined or mentioned in IDL files. Typecodes are used to encode and decode instances of the CORBA any type: a generic type that stands for any type and is used with the dynamic invocation interface.
How many Interface Repositories can you have?
Interface repositories are like other objects; you can create as many as you like. There is no VisiBroker-mandated policy governing the creation or use of IRs. You determine how Interface Repositories are deployed and named at your site. You may, for example, adopt the convention that a central Interface Repository contains the interfaces of all “production” objects, and developers create their own IRs for testing.
Note
Interface repositories are writable and are not protected by access controls. An erroneous or malicious client can corrupt an IR or obtain sensitive information from it.
If you want to use the _get_interface_def method defined for all objects, you must have at least one Interface Repository server running so the VisiBroker ORB can look up the interface in the IR. If no Interface Repository is available, or if the IR that the VisiBroker ORB binds to has not been loaded with an interface definition for the object, _get_interface_def raises a NO_IMPLEMENT exception.
Creating and viewing an Interface Repository with irep
The VisiBroker Interface Repository server is called irep, and is located in the <install_dir>/bin directory. The irep program runs as a daemon. You can register irep with the Object Activation Daemon (OAD) as you would any object implementation. The oadutil tool requires the object ID, for example, IDL:org.omg/CORBA/Repository:2.3 (as opposed to an interface name such as CORBA::Repository).
Note
The irep server needs a rollback file to keep its internal data consistent. The file is created if it does not already exist, for example when launching the irep server for the first time. The IRepName specified in the command line is used to make up the name of the rollback file. Make sure that the name contains only valid file system characters based on your platform. If the specified name contains directory locations that do not exist, they will be automatically created.
Creating an Interface Repository with irep
Use the irep program to create an Interface Repository and view its contents. The usage syntax for the irep program is as follows:
irep <driver_options> <other_options> <IRepName> [file.idl]
The syntax for creating an Interface Repository in the irep is described in the following table:
Specifies the IDL file whose contents irep will load into the Interface Repository it creates and will store the IR contents into when it exits. If no file is specified, irep creates an empty Interface Repository.
The irep arguments are defined in the following table. You may also use the driver options defined in “Programmer tools for C++”.
The following example shows how an Interface Repository named TestIR can be created from a file called Bank.idl.
irep TestIR Bank.idl
Viewing the contents of the Interface Repository
You can view the contents of the Interface Repository with either the VisiBroker ir2idl utility, or the VisiBroker Console application. The syntax for the ir2idl utility is:
ir2idl [-irep <IRname>]
The syntax for viewing the contents of an Interface Repository in the irep is described in the following table:
Updating an Interface Repository with idl2ir
You can update an Interface Repository with the VisiBroker idl2ir utility, which is an IR client. The syntax for the idl2ir utility is:
idl2ir [arguments] <idl_file_list>
The following example shows how the TestIR Interface Repository would be updated with definitions from the Bank.idl file.
idl2ir -irep TestIR -replace Bank.idl
Entries in an Interface Repository cannot be removed using the idl2ir or irep utilities. To remove an item:
Exit or quit the irep program.
Start irep again with the updated file.
Interface repositories have a simple transaction service. If the specified IDL file fails to load, the Interface Repository rolls back its content to its previous state. After loading the IDL, the Interface Repository commits its state to be used in subsequent transactions. For any repository, there is a file <IRname>.rollback in the home directory that contains the state of the last uncommitted transaction.
Note
If you wish to remove all entries in the Interface Repository, you can replace the contents with a new empty IDL file. For example, using an IDL file named Empty.idl, you could run the following command:
idl2ir -irep TestIR -replace Empty.idl
Understanding the structure of the Interface Repository
An Interface Repository organizes the objects it contains into a hierarchy that corresponds to the way interfaces are defined in an IDL specification. Some objects in the Interface Repository contain other objects, just as an IDL module definition might contain several interface definitions. Consider how the example IDL file shown below would translate to a hierarchy of objects in an Interface Repository.
// Bank.idl
module Bank {
interface Account {
float balance();
};
interface AccountManager {
Account open(in string name);
};
};
Figure 31
The OperationDef object contains references to additional data structures (not interfaces) that hold the parameters and return type.
Identifying objects in the Interface Repository
The following table shows the objects that are provided to identify and classify Interface Repository objects.
A character string that uniquely identifies an IRObject. A RepositoryID contains three components, separated by colon (:) delimiters. The first component is IDL: and the last is a version number such as :1.0. The second component is a sequence of identifiers separated by slash (/) characters. The first identifier is typically a unique prefix.
Types of objects that can be stored in the Interface Repository
The following table summarizes the objects that can be contained in an Interface Repository. Most of these objects correspond to IDL syntax elements. A StructDef, for example, contains the same information as an IDL struct declaration, an InterfaceDef contains the same information as an IDL interface declaration, all the way down to a PrimitiveDef which contains the same information as an IDL primitive (boolean, long, and so forth.) declaration.
Represents an IDL module declaration that can contain ModuleDefs, InterfaceDefs, ConstantDefs, AliasDefs, ExceptionDefs, and the IR equivalents of other IDL constructs that can be defined in IDL modules.
Represents an IDL interface declaration and contain OperationDefs, ExceptionDefs, AliasDefs, ConstantDefs, and AttributeDefs.
Represents an IDL typedef declaration. Note that the IR TypedefDef interface is a base interface that defines common operations for StructDefs, UnionDefs, and others.
Represents an IDL primitive declaration: null, void, long, ushort, ulong, float, double, boolean, char, octet, any, TypeCode, Principal, string, objref, longlong, ulonglong, longdouble, wchar, wstring.
Inherited interfaces
Three non-instantiatable (that is, abstract) IDL interfaces define common methods that are inherited by many of the objects contained in an IR (see the table above). The following table summarizes these widely inherited interfaces. For more information on the other methods for these interfaces, see the VisiBroker Programmer's Reference.
def_kind() returns an IR object's definition kind, for example, module or interface
destroy() destroys an IR object
lookup() looks up a contained object by name
contents() lists the objects in a Container
describe_contents()
describes the objects in a Container
name() name of this object
defined_in() Container that contains an object
describe() describes an object
move () moves an object into another container
Accessing an Interface Repository
Your client program can use an Interface Repository's IDL interface to obtain information about the objects it contains. Your client program can bind to the Repository and then invoke the methods shown below. A complete description of this interface can be found in the Programmer's Reference.
Note
A program that uses an Interface Repository must be compiled with the-D_VIS_INCLUDE_IR flag.
class CORBA {
class Repository : public Container {
. . .
CORBA::Contained_ptr lookup_id(const char * search_id);
CORBA::PrimitiveDef_ptr get_primitive(CORBA::PrimitiveKind kind);
CORBA::StringDef_ptr create_string(CORBA::ULong bound);
CORBA::SequenceDef_ptr create_sequence(CORBA::ULong bound,
CORBA::IDLType_ptr element_type);
CORBA::ArrayDef_ptr create_array(CORBA::ULong length,
CORBA::IDLType_ptr element_type);
. . .
};
. . .
};
Interface Repository example program
This section describes a simple Interface Repository example which contains an AccountManager interface to create an account and (re)open an account. This example code can be found in the following directory:
<install_dir>\vbe\examples\ir
At the initialization time the AccountManager implementation bootstraps the Interface Repository definition for the managed Account interface. This exposes the additional operation that has been already implemented by this particular Account implementation to the clients. The clients now can access all known operations (which are described in IDL) and, additionally, they can verify with the Interface Repository support for other operations and invoke them. The example illustrates how we can manage Interface Repository definition objects and how to introspect remote objects using the Interface Repository.
Before this program can be tested, the following conditions should exist:
OSAgent should be up and running. For more information, go to the “Using the Smart Agent” section in “Using the Smart Agent”
Looking up an interface's operations and attributes in an IR:
/* PrintIR.C */
#ifndef _VIS_INCLUDE_IR
#define _VIS_INCLUDE_IR
#endif
#include "corba.h"
#include "strvar.h"
int main(int argc, char *argv[]) {
try {
if (argc != 2) {
cout << "Usage: PrintIR idlName" << endl;
exit(1);
}
CORBA::String_var idlName = (const char *)argv[1];
CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);
CORBA::Repository_var rep = CORBA::Repository::_bind();
CORBA::Contained_var contained = rep->lookup(idlName);
CORBA::InterfaceDef_var intDef = CORBA::InterfaceDef::_narrow(contained);
if (intDef != CORBA::InterfaceDef::_nil()) {
CORBA::InterfaceDef::FullInterfaceDescription_var fullDesc =
           intDef->describe_interface();
cout << "Operations:" << endl;
for(CORBA::ULong i = 0; i < fullDesc->operations.length(); i++)
cout << " " << fullDesc->operations[i].name << endl;
cout << "Attributes:" << endl;
for(i = 0; i < fullDesc->attributes.length(); i++)
cout << " " << fullDesc->attributes[i].name << endl;
} else
cout << "idlName is not an interface: " << idlName << endl;
} catch (const CORBA::Exception& excep) {
cerr << "Exception occurred ..." << endl;
cerr << excep << endl;
exit(1);
}
return 0;
}