HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

With the rapid growth of the Internet, distributed Web-enabled applications are becoming popular. One of the most commonly used architectures for development of such applications is CORBA, which provides a platform, location and an implementation-language-neutral architecture for the development of distributed applications. In addition, the phenomenal interest in component technology has led to the development of CORBA Beans. Such CORBA components and objects will soon be available for use on the Web. When you encounter such a CORBA object, you may wish to use its services by dynamically discovering its properties (something similar to Introspect and Reflection in Java). CORBA supports this.

What Is Dynamic Invocation?
CORBA allows you to discover an object's properties dynamically and use its services by invoking the public methods on the object at runtime. This is known as Dynamic Invocation Interface (DII). It's essential for a CORBA object that allows the client to discover its properties at runtime to publish its interface definition language (IDL) for the client to look up. CORBA architecture provides for an Interface Repository (IR) in which the publisher of an object publishes its IDL. Once the client obtains a reference to an object, it can retrieve the IDL from this IR. The IDL helps the client understand the public attributes and methods of the discovered object. The client then invokes the methods on the object using the DII mechanism.

The use of IR and DII not only benefits the client in discovering and using the object, but also helps its publisher add new features to the object anytime after its deployment. The client can then dynamically discover these new features and use them. The new interface definition is published in the IR by the developer. The client now has access to all the latest features provided by the application using the DII mechanism. DII is the "dream come true" for developers since it allows them to modify previously published CORBA objects without the need to recompile and redistribute client-side stubs.

A practical example: you're developing a CORBA application for setting up an online store where customers visit, make some purchases and pay for purchases with a check "snail-mailed" to your account. You'll supply a client-side application that interfaces with your server application. The client application contains the compiled stubs required to use your server application. At a later time you may wish to provide the facility of payment by credit card. Adding a new purchase method in the IDL definition does this job. However, you'll need to supply the new stubs to all your clients. If you'd used the DII mechanism in the client application, the client would be able to discover the newly added method without the necessity of obtaining the new stub.

Object Browser
To emphasize the practical usability of the DII, we've developed a CORBA object browser using Java and JFC classes. The browser requests that the user enter a reference to an existing CORBA object. Usually a CORBA object registers itself with the CORBA Naming Service using a unique name. We pass this name to the object browser, which looks up the Naming Service to resolve the reference to the object. Once the browser obtains a reference, it displays the IDL to the user. The user can now select an operation from the displayed list and invoke it. (A method is called an operation in CORBA terminology and we use the terms interchangeably in this article.) A method invocation may require one or more parameters and may return a result. The browser determines the types for the required parameters, constructs the parameters of appropriate data types, obtains values for each parameter from the user and, on successful completion of the method, returns the appropriate values to the user. In CORBA each parameter may be of IN, OUT or INOUT type. Since Java supports only pass by value, it supports only IN type parameters, implying that the parameters to a Java method are read-only. In CORBA the method may return the value through OUT or INOUT types of parameters. Our browser takes care of all three types of parameters.

To help understand the complex DII interface of CORBA, we'll discuss the design of the CORBA object browser. But first we'll touch on some aspects of locating the object on the Web using the Naming and URL Naming Services of Visigenic, the IOR (Interoperable Object Reference) and Interface Repository.

Locating Object: CORBA Naming Service and Web Naming Service
Our object browser needs to locate the object before trying to use its services. A CORBA object publishes a reference to itself by registering its name with the Naming Service. This is done with the help of the bind or rebind method, in which the object reference is tied to its symbolic name. Before you use this method you must start the Naming Service. On Visigenic ORB (we use this for our development) you start the Naming Service using the following command line, with the root name specified as ABCOM:

vbj -DORBservices=CosNaming -DSVCnameroot=ABCOM ­DJDKrenameBug
com.visigenic.vbroker.services.CosNaming.
Ext Factory ABCOM namingLog

If you use the Java 2 platform, you start the Naming Service using the following command line:

tnameserv [-ORBInitialPort ]

The default Port_number is 900.

The principal task of the Naming Service is to keep track of the namespace, which is the collection of object names bound to a Naming Service. The namespace may contain a hierarchy of bindings extending over several domains just like a file system on your disk. If the namespace extends over several domains, it's called the Federated NameSpace. The binding is the logical association of the object reference to its symbolic name.

A client obtains a reference to the Naming Service by calling the resolve_initial_references() method of the ORB. Once the initial context of the Naming Service is resolved, it calls the resolve method on the NamingContext to obtain a reference to the desired object. The whole task of name resolution is transparent to the client.

Another way to publish your object is to convert the object reference to a string and store it in a file using ORB's object_to_string method. The method returns a stringified version of the IOR, which contains information such as IIOP version, Host, Port, etc., which helps to uniquely identify the object on the Web. The client reads the IOR from the specified file (usually with the extension .ior) at the given URL, and obtains a reference to the object using the information in the IOR. Visigenic requires that the extension given to the IOR file must be .ior if you wish to use Visigenic GateKeeper.

Visigenic provides the URL Naming Service to locate an object using a URL rather than its generic name. This provides for interoperability among objects bound to ORBs on different machines. The following code segment shows you how to use Visigenic's URL Naming Service to locate an object running on a different ORB:

// create the resolver object
com.visigenic.vbroker.URLNaming.Resolver
URLresolver =
com.visigenic.vbroker.URLNaming.ResolverHelper.narrow
(orb.resolve_initial_references
("URLNamingResolver"));

// locate object using resolver
obj = URLresolver.locate(http_location);

The URL Naming Service uses a Resolver Object to locate the .ior file and resolve the reference to the remote object. In the above code snippet we create a Resolver Object using the ResolverHelper provided with the URL Naming Service. The Resolver uses the locate method to search the specified IOR at a given URL. If the IOR file is found, it's read and the reference to the object running on the remote server is returned to the caller.

The publisher must publish the IOR file on a Web server so the client can locate it using the URL Naming Service. If you're using Microsoft's IIS (Internet Information Server), you'll put this file in the InetPub/www.root folder or the folder defined for public access.

Interface Repository
The Interface Repository is used for storing IDL definitions for various CORBA objects. The IDL definition of a CORBA object forms its skeleton, and the object implementation is developed from this definition. The Interface Repository is the online database that maintains a record of interfaces of all registered objects. On a Visigenic ORB you start the Interface Repository using the following command line:

Prompt> irep IRname fileName

The IRname is the name assigned to the Interface Repository, and fileName is the physical file used for storage. Once the IR is created, you can add your object definitions using the idl2ir utility:

Prompt> idl2ir file.idl

The IDL definition contained in file.idl is now added to the IR. Each entry in the IR contains a header describing the file name, time of creation, user name and location of the file on the machine. The IR stores information in simple text format. You can use a standard text editor to view this.

A typical IR entry is shown below.

/*
File : abcom.ir
Date : Sat Jan 30 06:58:40 GMT+00:00 1999
User : Administrator
Dir : C:\OBJECTBROWSER
*/
module bank {
interface TermDeposit;
interface TermDeposit {
attribute float Interest;
float Compute(
in float Principal,
in short Period
);
};
};

A client obtains the IDL definition from this IR by using the _get_interface() method of the CORBA Object class. This returns the InterfaceDef object. The full description of the interface definition can now be obtained by using the describe_interface() method on this InterfaceDef object.

The following code snippet illustrates this process:

org.omg.CORBA.InterfaceDef objIntfce = obj._get_interface();
org.omg.CORBA.FullInterfaceDescription
fullObjectInterface =
objIntfce.describe_interface();

You may now use the attributes member of the FullInterfaceDescription class to obtain information on the various attributes published by the object. Similarly, you'll use the operations member of the FullInterfaceDescription class to obtain information on the various operations permitted on the object.

To recapitulate, so far you've learned how to:

  • Publish an object by either binding an object to a Naming Service or publishing its IOR on a Web server.
  • Locate an object using either a Naming Service or Visigenic's URL Naming Service.
  • Publish the Interface Definition of the object in the repository (IR).
We've also seen how a client program retrieves this Interface Definition from the IR and discovers all the attributes and operations published by the object. Most important, you've discovered the object and would now like to use its services by invoking one or more of its published methods.

Dynamic Invocation Interface
To invoke a method, you'll first need to construct a list of arguments (parameters) required by the method. CORBA provides an NVList object for constructing such a list. You use the create_list() method of ORB to construct it.

NVList parameterList = orb.create_list(0);

The NVList (Named Value List) contains the names and values for the various parameters required by the method. Initially the list is created with zero elements. You then add elements by using its add_value() method:

parameterList.add_value(name, currentParameter, mode);

where name is the string representing the name of the parameter being added, currentParameter is the object that represents the parameter and mode indicates whether the parameter is of IN, OUT or INOUT type.

You'll need to add the required number of elements to the NVList depending on the number of parameters used by the desired method. Once an NVList is constructed, you create a request object and pass the parameters to it using the constructed NVList object. To create a request object, you use the _create_request() method of the CORBA Object class.

org.omg.CORBA.Object obj = new org.omg.CORBA.Object();
org.omg.CORBA.Request request =
obj._create_request(
null,
nameMethod,
parameterList,
resultField);

where obj is a CORBA Object, the first parameter specifies the CORBA Context, which is set to null; nameMethod is the name of the method being invoked; parameterList is the NVList described above; and resultField is a NamedValue Object through which the result will be returned to the caller.

Once the request object is constructed, you can invoke the method on the server using the invoke() method:

request.invoke();

This invokes the method on the server object and returns the result, if any, in the resultField NamedValue object. If the method uses OUT and INOUT types of parameters, you may examine their contents for the return values.

User Interface
Having seen the various requirements for DII, we'll now discuss the user interface of our object browser, which is used for dynamically invoking the methods on CORBA servers for which the stubs aren't available at runtime. The user interface of the browser is shown in Figure 1.

Figure 1
Figure 1:

The user enters the name of the server object in the input panel of the browser and clicks on the introspect button. The name specified must be the name the object is registered under with the Naming Service. Alternatively, the user can specify the name of the IOR file along with the URL at which the file is located. A typical URL string may be specified as follows:

http://www.abcom.com/abcom.ior

Once an object is located, the browser displays its IDL in the tabbed pane as seen in Figure 1. You can now click on the "Operation and Attribute Listing" tab to see the various operations and attributes published by the server. If you want to examine an attribute, click on the desired one and its various properties will be displayed in a pop-up window. If you decide to invoke a method, click on the method name, which opens a window showing the various parameters required by the method (see Figure 1). If the method doesn't require parameters, it's directly executed. If it does, the type and mode are displayed for each one. Next to each parameter an edit box is provided in which the user can enter the desired parameter value. The browser, however, doesn't provide any validation on the parameter values. Once all the required parameter values are entered, the user clicks on the invoke button to invoke the server method. The program now builds the request object and invokes the method on the server. If the method completes successfully, the results will be displayed in a pop-up window (see Figure 1). The interface is fairly easy to use. We'll now look into the design of the browser.

Browser Design
We used JFC for developing the user interface of the browser. The browser consists of seven public classes:

  • The ObjectBrowser class, which provides the main user interface for the application
  • The InputPanel, OutputPanel and StatusBar classes, which provide various other components of the user interface
  • The BackEnd class, which is responsible for all CORBA-related activities
  • The two helper classes, AttributeDescription and OperationDescriptionTable, which provide the description of attributes and methods, respectively

The various classes and their relationships to each other are shown in Figure 2.

Figure 2
Figure 2:

The ObjectBrowser class (see Listing 1) is the main class of the application and is derived from the JFrame class. It creates instances of InputPanel, OutputPanel, StatusBar and BackEnd classes. The main method creates an instance of ObjectBrowser class and displays the frame to the user. The init() method of the class adds the three user-interface elements ­ InputPanel, OutputPanel and StatusBar ­ to the main display window. The InputPanel is used for accepting the object reference from the user. The OutputPanel shows the IDL listing and the operations/attribute names to the user. The StatusBar provides a status display to the user. The ObjectBrowser class provides a utility method called resolveAndIntrospect(), which is called by the InputPanel class. The method receives the object reference that's to be resolved. The method calls the resolve() method of BackEnd class, and if the object is successfully resolved it calls the introspect() method of BackEnd class to introspect the object and to display the IDL to the user on the OutputPanel.

The InputPanel class (see Listing 2) is derived from the JPanel and provides the user interface for accepting the object name. The user interface consists of an edit box and two buttons ­ Introspect and Exit. The event handler for the Introspect button calls the resolveAndIntrospect() method on the ObjectBrowser class by passing the received object reference. As mentioned earlier, the object reference is either the object's registered name with the Naming Service or the complete URL containing the location of the IOR file.

The OutputPanel class (see Listing 3), derived from JTabbedPane, contains two tab panes: one for displaying the IDL to the user, the other for displaying the lists of operations and attributes. The init() method sets up the two panes. The Interface Definition pane uses a TextArea control to display the IDL to the user. The Operation and Attribute pane creates two Box objects and adds JList control to each for displaying the operations and attributes.

Whenever the user changes the selection in the attributes list control, the showAttribute-Description() method is called. This in turn creates an AttributeDescription object and displays the information about the selected attribute to the user. Similarly, whenever the user changes the selection in the operations list control, the showMethodDescription() method is called. This creates the OperationDescriptionTable object and displays it to the user. The updateList() method updates the contents of the list control by first clearing it and then filling it with the new data.

The AttributeDescription class (see Listing 4) is derived from JFrame and displays the information on the selected attribute to the user. The class constructor receives the name of the attribute as a parameter and a reference to our ObjectBrowser class. The init() method calls its own getDescription() method to get the information on the desired attribute and then displays the information to the user by calling its displayFrame() method. The getDescription() method iterates through all the attributes defined in the fullObjectInterface variable and retrieves the mode and type information for the desired attribute. The displayFrame() method then displays the attribute name, mode and type to the user.

The OperationDescriptionTable class (see Listing 5) derived from JFrame displays in tabular format the names of parameters required by the desired operation. The class also accepts the values for each IN and INOUT type of parameter from the user. In button event handler, if the user has clicked the invoke button, we copy the input parameters from the TextField objects in the table to a String array, which is then sent to the BackEnd object by calling its setParameters() method. The BackEnd will use these parameters while invoking the server method. Once the parameters are set, the program calls the local performDii() method, which passes the request to the processRequest() method of the BackEnd class. The BackEnd processes the request and displays the results.

The StatusBar class (see Listing 6) is derived from the JLabel and is simply a utility class for displaying status messages in the browser window.

Now we come to the most important class, BackEnd, which is responsible for all CORBA-related back-end processing (see Listing 7). The class constructor receives a reference to our ObjectBrowser and copies it into a local variable. The init() method first initializes the ORB by calling its init() method:

orb = org.omg.CORBA.ORB.init (param, null);

If the ORB is successfully initialized, we call resolve_initial_references() method on the ORB to resolve a reference to the Naming Service. We then narrow (type cast) the returned object to the NamingContext object type. The initialization of the BackEnd object is complete and the object now waits for its other methods (resolve, introspect, processRequest) to be invoked. The resolve() method receives the object as a string and tries to locate the object on either the current ORB or the ORB running at the specified URL:

if (!(resolved = resolveUsingName(object)))
resolved = resolveUsingURL(object);

The resolveUsingName() method constructs the NameComponent array and tries to resolve the object reference by calling the resolve method of the Naming Service:

NameComponent[] name = {new NameComponent(object, "")};
obj = nameService.resolve (name);

If this resolution fails, we try to resolve using the URL Naming Service. The method resolveUsingURL() obtains a reference to the URLNamingResolver and narrows it down to the proper data type as follows:

org.omg.CORBA.Object resolverObj =
orb.resolve_initial_references("URLNaming
Resolver");
com.visigenic.vbroker.URLNaming.Resolver
URLresolver =
com.visigenic.vbroker.URLNaming.
ResolverHelper.narrow(resolverObj);

Next, we use the locate method to resolve the object reference:

obj = URLresolver.locate(object);

Once the object is successfully resolved, we obtain its interface definition by calling its _get_interface() method:

InterfaceDef objIntfce =
obj._get_interface();

The describe_interface() method then obtains the full description of this interface:

fullObjectInterface =
objIntfce.describe_interface();

Now we look at the method called introspect(), in which we declare two Vector type variables for storing the methods attribute and operation lists. We obtain the number of attributes and operations from the full interface description as follows:

final int noAttributes =
fullObjectInterface.attributes.length;
final int noOperations =
fullObjectInterface.operations.length;

The program then obtains mode, type and name for each attribute:

for (int i = 0; i {
mode = fullObjectInterface.attributes[i].mode.value
());
type = fullObjectInterface.attributes[i].type;
name =
fullObjectInterface.attributes[i].name;

}

The attribute listing is then added to the TextArea control of the output panel where the IDL listing will be displayed to the user. The names of attributes are also added to the attr vector. This vector is used later to search for a user-selected attribute name. The program updates the list on the output panel by calling its updateList() method. We then construct the method signatures from the fullObjectInterface. This time we use an operations member variable to obtain detailed information on each operation.

Finally, we look at the most important method, processRequest(). This method obtains the name of the operation to be invoked as the parameter and invokes the method on the server object. First we obtain the index of the desired method from the list of operations described in the fullObjectInterface object:

for ( ; i {
if (operationName.equals
(fullObjectInterface.operations[i].name))
break;
}

At this point variable i contains the index for the desired operation in the operations list. Next, we find the number of parameters required by this operation using the statement:

int noParameters =
fullObjectInterface.operations[i].
parameters.length;

For each parameter we now need to construct a proper object and an NVList containing all such parameters for dynamic invocation of the method. The ORB provides a method called create_list() for constructing an NVList object:

NVList parameterList = orb.create_list(0);

The parameter to create_list() method specifies the number of elements in the list. We pass zero as the parameter to construct an empty list. For each parameter we now construct an object of CORBA "Any" type using ORB's create_any() method:

Any currentParameter = orb.create_any();

The special type "Any" defined in CORBA is used to represent the element with any data type. We initialize this object with the proper data type by using the "type" member of parameters[i] variable. The program then examines the mode for the parameter, which can be IN, OUT or INOUT type. The method receives an input value through this parameter and returns the result to the caller through the same parameter.

Depending on the value of the mode, we set our mode variable to the proper CORBA data type. For the IN type of parameter the mode variable is set to org.omg.CORBA.ARG_IN.value; for the OUT type it's set to org.omg.CORBA.ARG_OUT value; and for the INOUT type it's set to org.omg.CORBA.ARG_INOUT value. We also set an "accept" flag for each parameter. If the accept flag is set, it indicates we'll be assigning a value obtained from the user to this object (applicable to the IN and INOUT types of parameters).

The program then retrieves the value entered by the user for the current parameter by using parametersValue array. Note that all parameter values are stored as String data type.

We now set up a switch statement to convert this parameter value to the proper data type and assign it to our parameter object in an NVList. We check the parameter data type by using kind() method on the current parameter:

switch
( currentParameter.type().kind().value())

The CORBA "Any" class provides several insert_xxx types of methods to assign the objects of various data types to the "Any" object. For example, insert_short() method assigns an object of type "short," insert_long() assigns an object of type "long," etc. Thus, in the switch statement, we check for the kind of parameter required and use the corresponding insert_xxx method to assign the appropriate object type to our parameter object. We've programmed most of the cases in the switch statement. Some of the complicated cases are left out due to the complexity involved. For example, if you want to insert a structure data type, you'll need a Java class encapsulating the structure definition. You can then insert a Java object of this class for the desired parameter value.

Once the parameter is initialized with the proper data type and its value, we add the parameter to an NVList using its add_value() method:

parameterList.add_value(
fullObjectInterface.operations[i].

parameters[j].name,
currentParameter, mode);

The add_value() method requires the name of the operation, the value and the mode type of the parameter.

Once the NVList for operation parameters is constructed, we need to create a Named Value object for the return value of the method. We construct and initialize this NamedValue object using the following lines of code:

Any resultParameter = orb.create_any();
resultParameter.type
(fullObjectInterface.operations[i].result);

org.omg.CORBA.NamedValue resultField =
orb.create_named_value("resultField",
resultParameter,
ParameterMode._PARAM_OUT);

We set the proper data type for the result by using the "result" data member of the desired operation. The NamedValue object is constructed using the create_named_value() method of CORBA Object class. At this stage we're ready to build our request object, which we do by calling the _create_request() method on the CORBA object:

Request request =
obj._create_request(null,
fullObjectInterface.operations[i].name,
parameterList, resultField);

The _create_request() method requires four parameters. The first specifies the CORBA context and is set to null in this case; the second specifies the operation name; the third specifies the NVList containing the list of parameters required by the operation; and the fourth is another NVList in which the return value, if any, is returned.

You're now ready to invoke the method on the server, a simple process. You use invoke() method on the request object to invoke the method on the remote server:

request.invoke();

The method is executed on the remote server and the result, if any, will be returned in the result NamedValue object, OUT parameters and INOUT parameters. We now display the results to the user by constructing a JFrame object and displaying the information in label controls. The return value of the method is obtained using the expression request.result().value(). Similarly, the values of OUT and INOUT parameters are obtained using the expression resultList.item(j).value(). If the method invocation fails for any reason, we construct the JFrame object to display the appropriate message to the user.

Having seen the design of the object browser, we now examine how to compile and run the entire application.

Running the Browser
We used JDK 1.1.5 and Swing classes for the development of the object browser. We've created several batch files for compiling and running the code. The swingcompile.bat file (see Listing 8) compiles the entire source. This file contains the following statement:

javac -classpath %SWINGPATH% %1

where SWINGPATH is the system variable defined on our system that sets up the class path for Java, Visigenic CORBA and Swing classes.

The parameter to the batch file is our main Java class ­ ObjectBrowser.java. If your classpath is set properly, running swingcompile batch file should compile all the relevant files.

Before you run the browser, you need to do certain startup operations, such as starting OSAgent, starting the Naming Service, etc., with the help of startup.bat file (see Listing 9). This batch file starts the OSAgent using the following command line:

start OSAgent ­c

Next, it starts the interface repository using the following command line:

start irep InterfaceRepository ABCOM.ir

The command irep starts the repository service. The name of our repository is InterfaceRepository, and it's stored in the file called ABCOM.ir in the current folder. Next, the CORBA Naming Service is started using the following command line:

start vbj -DORBservices=CosNaming
-DSVCnameroot=ABCOM ­DJDKrenameBug
com.visigenic.vbroker.services.CosNaming.
ExtFactory ABCOM namingLog

Our Naming Service starts with the root object set to "ABCOM".

This completes the operation of our startup batch file. When you run this batch file, you'll notice that three windows pop up on your terminal; one is used by OSAgent, the second by Interface Repository and the third by the Naming Service.

Now we're ready to run our object browser, which is started using show.bat file (see Listing 10):

vbj -DORBservices=CosNaming -DSVCnameroot=ABCOM -VBJclasspath
"%SWINGPATH%" ObjectBrowser

Running this batch file starts our object browser. You're now ready to discover any object either in the current ORB or the ORB running at some known URL.

We've provided a test server application for your convenience. It's called SampleServer (see IDL Listing in Sample.idl file) (Listing 11). The server provides three sample methods:

  • DoubleValue(), which takes an IN parameter of type float and returns a float value to the caller as a method return value
  • CountCharacters(), which takes one string parameter of IN type and returns the character count in an OUT type parameter
  • ReverseString(), which takes an INOUT type parameter of type string, reverses the string and sends it to the caller through the same parameter
The implementation files, along with the compiled code, can be downloaded from the JDJ Web site. You'll need to run idl2ir to load the IDL into your IR before running the SampleServer application. The application registers itself with the Naming Service using the name "SampleObject". Type this name in the browser input panel and click on introspect to display the IDL. You can then select any of the three listed methods, invoke them and test the result.

Conclusion
The DII is probably the most complex ­ yet most versatile ­ interface provided in CORBA. It allows you to discover and use a CORBA object at runtime without the need for compiled stubs. We've described the entire DII mechanism and the design of a CORBA object browser that's based on the discussed techniques.

Acknowledgments
We'd like to thank Kamal Shah and Bhakti Mehta for their valuable help in the development and testing of the CORBA object browser.

About the Authors
Dr. Poornachandra G. Sarang is president and CEO of ABCOM Information Systems Pvt. Ltd., a consulting firm specializing in Internet, Java, CORBA, Visual C++ and VB programming and training. He can be reached at [email protected]

Mohan Rajagopalan is currently studying for a degree in computers, and plans to pursue a graduate degree specializing in distributed systems and heterogeneous networks. The CORBA object browser was developed as part of his practical training at ABCOM. He can be reached at [email protected]

	

Listing 1. 

//*********************************************************** 

// File : ObjectBrowser.java 

// This file contains implementation of following classes 

// 1. ObjectBrowser 

// copyright 1999: ABCOM Information Systems Pvt. Ltd., All 
 rights reserved. 

//********************************************************** 
* 

import java.awt.*; 

import java.awt.event.*; 

import com.sun.java.swing.*; 

import com.sun.java.swing.event.*; 

import org.omg.CosNaming.*; 

import org.omg.CORBA.*; 

import org.omg.CORBA.InterfaceDefPackage.*; 
  
  

// 
*********************************************************** 

// Class implemented : ObjectBrowser 

// Derived from  : JFrame 

// Implements   : ActionListener,MouseListener 

// Description   : 

// This class implements the base class of the Object Browser. It forms 
the front 

// end of the Object Browser, all other classes are called from here. 

// 
*********************************************************** 
  

public class ObjectBrowser extends JFrame 

{ 

  // the input panel contains the object name (text field), 

  // the "Introspect" button and the "EXIT" button. 

  private InputPanel inputPanel = new InputPanel(this); 
  
  

  // the ouput panel is enabled once an object has been found. 

  // displays the attributes and the operations of the object. 

  public OutputPanel outputPanel = new OutputPanel(this); 
  
  

  //this bar dsplays the status of the browser. 

  private StatusBar statusBar = new StatusBar("not connected "); 
  
  

  // reference to backend. 

  public BackEnd backEnd = new BackEnd(this); 
  
  

  //constructor for the frame. 

  //   1. display the user interface. 

  //   2. Initialize the back end. 

  public ObjectBrowser() 

  { 

   super("CORBA Object Browser"); 
  
  

   //initialise the front end. 

   init(); 
  
  

   // set the size of the application frame 

   java.awt.Dimension d = getToolkit().getScreenSize(); 

   setSize((d.width),(d.height*2/3)); 
  
  

   if (backEnd.init()) 

    setStatus ("Intialization successful"); 

   else 

    setStatus ("Initialization failed"); 

  } 
  
  

  // 
*********************************************************** 

  //  main entry point for the application 

  // 
********************************************************** 

  public static void main(String args[]) 

  { 

   // display the Obejct browser user interface 

   ObjectBrowser maindisplay = new ObjectBrowser(); 

   maindisplay.setVisible(true); 

  } 
  
  

  // ************************************************* 

  // provide user interface of the application 

  // ************************************************ 

  public void init() 

  { 

   // get a reference to the frames content pane 

   JComponent displayPane = (JComponent) this.getContentPane(); 
  
  

   // set layout manager 

   displayPane.setLayout(new BorderLayout()); 
  
  

   //add input panel to frame. 

   displayPane.add(inputPanel,BorderLayout.NORTH); 
  
  

   //add the outputpanel 

   displayPane.add(outputPanel,BorderLayout.CENTER); 
  
  

   //add the status bar 

   displayPane.add(statusBar,BorderLayout.SOUTH); 
  
  

   // Initialization complete. 

   setStatus("Ready"); 
  
  

  } // end of init method. 
  
  

  // ************************************************* 

  // resolveAndIntrospect method performs two operations 

  //     1. resolve 

  //     2. introspect (provided 
resolve succeeds) 

  // *********************************************** 

  public void resolveAndIntrospect(String name) 

  { 

   setStatus ("Trying to resolve Object: "+name); 

   if (backEnd.resolve(name)) 

   { 

    // object located. 

    setStatus ("Object "+ name + " found - RESOLVE 
SUCCESSFUL"); 
  
  

    //clear the output panel. 

    //clear the text area. 

    outputPanel.clearListing(); 
  
  

    // introspect the object. 

    backEnd.introspect(); 
  
  

    //refresh the display. 

    repaint(); 

   } 

   else    // object not found. 

    setStatus ("Object not found"); 

  }  // end ofResolve and Introspect. 
  
  

  // 
************************************************ 

  // method to set setStatus in the status bar. 

  // ***************************************************** 

  public void setStatus(String s) 

  { 

   // display a message in the status bar. 

   statusBar.SetText(s); 

  } 

 }// end of the main class  ObjectBrowser 

 
Listing 2. 

//************************************************************* 

// File : InputPanel.java 

// This file contains implementation of following classes 

// 1. InputPanel 

// copyright 1999: ABCOM Information Systems Pvt. Ltd., All 
 rights reserved. 

//******************************************************* 
* 

import java.awt.*; 

import java.awt.event.*; 

import com.sun.java.swing.*; 
  
  

// 
********************************************************* 

// Class implemented : InputPanel 

// Derived from  : JPanel 

// Implements   : ActionListener 

// Description   : 

// This class implements the user input area in the main user interface 

// 
************************************************************ 

public class InputPanel extends JPanel implements ActionListener 

{ 

 // define the components 

 //   1. text field : ObjectName 

 //   2. exit button 

 //   3. introspect button 

 private JTextField ObjectName = new JTextField(40); 

 private JButton Introspect = new JButton("Introspect"); 

 private JButton Exit = new JButton("Exit"); 

 private ObjectBrowser objectBrowser; 
  
  

 // 
************************************************************ 

 // constructor 

 // 
*********************************************************** 

 public InputPanel(ObjectBrowser objectBrowser) 

 { 

  this.objectBrowser = objectBrowser; 
  
  

  // put both the button into a panel so that 

  // they get displayed vertically 

  JPanel choicePanel = new JPanel(); 

  choicePanel.setLayout(new GridLayout(2,1)); 

  choicePanel.add(Introspect); 

  choicePanel.add(Exit); 
  
  

  // add to Panel 

  add(ObjectName); 

  add(choicePanel); 
  
  

  Introspect.addActionListener(this); 

  Exit.addActionListener(this); 

 } 
  
  

 // 
*********************************************************** 

 // Process button clicks 

 // if INTROSPECT clicked 1. Locate the object 

 //         2. 
display its IDL listing. 

 // if Exit clicked : quit the application 

 // 
********************************************************* 

 public void actionPerformed (ActionEvent e) 

 { 

  if (e.getSource() == Introspect) 

  { 

   // check if the text field is blank. 

   if (!(ObjectName.getText()).equals("")) 

   { 

    //perform the introspect operation. 
  

 objectBrowser.resolveAndIntrospect(ObjectName.getText()); 

   } 

   // else show error message 

   else      // 
name is not entered. 

   { 

    objectBrowser.setStatus ("Please ENTER NAME 
OF OBJECT"); 

   } 

  } 
  
  

  // if exit chosen  : 
shut down. 

  if (e.getSource() == Exit ) 

  { 

   objectBrowser.setStatus("Shutting Down ......"); 

   objectBrowser.dispose(); 

   System.exit(0); 

  } 

 } 

} 

Listing 3. 

//*********************************************************** 

// File : OutputPanel.java 

// This file contains implementation of following classes 

// 1. OutputPanel 

// copyright 1998: ABCOM Information Systems Pvt. Ltd., All 
 rights reserved. 

//************************************************************ 
* 

import com.sun.java.swing.event.*; 

import com.sun.java.swing.event.ListSelectionListener; 

import com.sun.java.swing.*; 

import java.awt.*; 

import java.awt.event.*; 

import OperationDescriptionTable; 

import AttributeDescription; 
  
  

// 
*********************************************************** 

// Class implemented : OutputPanel 

// Derived from  : JTabbedPane 

// Implements   : ListSelectionListener 

// Description   : 

// This class creates the area where the ObjectBrowser dumps the results 

// of introspection. i.e. the Interface Listing and the 
Attribute/Operation Lists. 

// 
********************************************************* 

public class OutputPanel extends JTabbedPane 

 implements ListSelectionListener 

{ 

 private JList attributeList = new JList(); // list to display 
attributes 

 private JList operationList = new JList(); // list to display 
operations 

 private JTextArea listing; 
    // for IDL listing 

 private Box attributes; 
  

 private Box operations; 

 private ObjectBrowser objectBrowser; 

 private JPanel jpanel; 
  
  

 // 
************************************************************* 

 // constructor 

 // 
************************************************************* 

 public OutputPanel(ObjectBrowser objectBrowser) 

 { 

  setTabPlacement(SwingConstants.TOP); 

  this.objectBrowser = objectBrowser; 
  
  

  init(); 

 } 
  
  

 // 
************************************************************** 

 // intialize the panel 

 // 
************************************************************** 

 private void init() 

 { 

  // create and add the text area to the tabbed pane. 
  

  listing = new JTextArea(); 

  listing.setEditable (false); 
  
  

  // scroll pane for scrolling up down IDL listing. 

  JScrollPane scrollPane = new JScrollPane(listing); 
  
  

  addTab("Interface Definition", scrollPane); 
  
  

  // The next tabbed pane will contain the operation and 

  // attribute list in two boxes arranged in a panel. 

  jpanel = new JPanel(new BorderLayout()); 

  jpanel.setBackground( Color.white ); 
  
  

  // create the attributes box 

  attributes = Box.createVerticalBox(); 

  // add label to the box. 

  attributes.add(new JLabel("Attributes")); 

  attributes.add(attributeList); 

  // add the box to the panel. 
  
  

  jpanel.add(attributes, "East"); 
  
  

  // create operations box. 

  operations = Box.createVerticalBox(); 

  // add label to the box 

  operations.add(new JLabel("Operations")); 

  operations.add(operationList); 

  // add box to the panel. 

  jpanel.add(operations, "West"); 
  
  

  // Add ListSelection listeners to the two lists. 

  attributeList.addListSelectionListener( this ); 

  operationList.addListSelectionListener( this ); 
  
  

  //display the second pane using the panel. 

  addTab("Operation and Attribute Listing", jpanel); 
  

 } 
  
  

 // 
************************************************************* 

 // add data to the text area control 

 // 
************************************************************ 

 public void setListing(String text) 

 { 

  //add the data 

  listing.append(text); 

 } 
  
  

 // *************************************************** 

 // clear the text area control 

 // ************************************************** 

 public void clearListing() 

 { 

  listing.setText(""); 

 } 
  
  

 // 
******************************************************************* 

 // updateList method receives two parameters. The first parameter 

 // supplies data in form of Vector which is added to the JList 

 // control. The second parameter specifies which JList control to 

 // be used. 

 // 
************************************************************** 

 public void updateList(java.util.Vector listData, String whichOne ) 

 { 

  //check if operations list. 

  if (whichOne == "operations") 

  { 

   // clear the list 

   operationList.removeAll(); 

   // add the data to list. 

   operationList.setListData (listData); 

  } 

  else      //update 
the attribute list. 

  { 

   // clear the list 

   attributeList.removeAll(); 

   // add the data to list. 

   attributeList.setListData(listData); 

  } 

 } 
  
  

 // ************************************************** 

 // show the properties of the attributes using 

 // a AttributeDescription object 

 // 
************************************************** 
  

 private void showAttributeDescription(String name) 

 { 

  AttributeDescription ad; 

  ad = new AttributeDescription(name,objectBrowser); 

  ad.setVisible(true); 

 } 
  
  

 // ****************************************************** 

 // show the properties of the method in a new frame 

 // using the OperationDescriptionTable object. 

 // ************************************************** 

 public void showMethodDescription(String name) 

 { 

  OperationDescriptionTable pTable; 

  pTable = new OperationDescriptionTable(name, objectBrowser); 

  pTable.setVisible(true); 

 } 
  
  

 // **************************************************** 

 // process list selection 

 // *************************************************** 

 public void valueChanged (ListSelectionEvent evt) 

 { 

  if (evt.getLastIndex() != -1) { 

   if (evt.getSource() == operationList && 

     !evt.getValueIsAdjusting()) 

   { 

    //get the name of the process 

    //using the index of selected item as index. 

    int j = evt.getLastIndex(); 

    String operationName = 
  

 objectBrowser.backEnd.fullObjectInterface.operations[j].name ; 

    objectBrowser.setStatus( 

     "Showing the description of " 
+operationName); 

    showMethodDescription(operationName); 

   } 
  
  

   // if attribute list selected 

   //  1. display the attribute description in a 
frame. 

   if (evt.getSource() == attributeList && 

     !evt.getValueIsAdjusting()) 

   { 

    // display the contents of the attribute list - 

    // i.e. the properties of attributes 

    // into a new frame. 

    String attributeName = 
  

 (attributeList.getSelectedValue()).toString(); 

    objectBrowser.setStatus( 

      "Showing description of " + 
attributeName); 

    showAttributeDescription(attributeName); 

   } 

  } 

 } 

} 

Listing 4. 

//************************************************************** 

// File : AttributeDescription.java 

// This file contains implementation of following classes 

// 1. AttributeDescription 

// copyright 1999: ABCOM Information Systems Pvt. Ltd., All 
 rights reserved. 

//*************************************************************** 
* 

import java.awt.*; 

import com.sun.java.swing.*; 

import java.awt.event.*; 

import org.omg.CORBA.*; 
  
  

// 
************************************************************ 

// Class implemented : AttributeDescription 

// Derived from  : JFrame 

// Implements   : None 

// Description   : 

// this class represents the frame in which the complete 

// description of the attribute is displayed on being selected. 

// 
************************************************************* 
  

public class AttributeDescription extends JFrame 

{ 

 private ObjectBrowser objectBrowser; 

 private String attributeName; 

 private String type = ""; 

 private String mode; 
  
  

 // 
************************************************************ 

 // constructor 

 // 
*********************************************************** 

 public AttributeDescription(String attributeName, 
  

 ObjectBrowser objectBrowser) 

 { 

  super(attributeName); 
  
  

  this.attributeName = attributeName; 

  this.objectBrowser = objectBrowser; 
  
  

  init(); 

 } 
  
  

 private void init() 

 { 

  getDescription(); 

  displayFrame(); 

 } 
  
  

 // 
**************************************************************** 

 // initializes and shows the attributes frame 

 // 
**************************************************************** 

 private void displayFrame() 

 { 

  // get screen dimensions and set the size for frame 

  Dimension d = getToolkit().getScreenSize(); 

  setBounds(d.width/3,d.height/3,d.width/3,d.height/3); 

  setResizable(false); 
  
  

  // set the layout manager 

  JComponent sp = (JComponent) getContentPane(); 

  sp.setLayout(new BorderLayout()); 
  
  

  // add various labels and desired text 

  JLabel tittle = new JLabel(" Attribute Description "); 

  sp.add(tittle,BorderLayout.NORTH); 
  
  

  JPanel middle = new JPanel(new BorderLayout()); 
  
  

  JLabel nLabel = new JLabel("Name  : " + attributeName); 

  JLabel tLabel = new JLabel("Type  : " + type); 

  JLabel mLabel = new JLabel("Mode  : " + mode); 

  middle.add(nLabel,BorderLayout.NORTH); 

  middle.add(mLabel,BorderLayout.CENTER); 

  middle.add(tLabel,BorderLayout.SOUTH); 
  
  

  sp.add(middle,BorderLayout.CENTER); 
  
  

  setVisible(true); 

 } 
  
  

 // 
**************************************************************** 

 // get the description of attributes from the full 

 // interface description. 

 // 
*************************************************************** 

 private void getDescription() 

 { 

  int i = 0; 

  objectBrowser.setStatus("searching for "+ attributeName ); 
  
  

  // get the  number of attributes 

  int noAttributes = 
  

 objectBrowser.backEnd.fullObjectInterface.attributes.length; 
  
  

  // search for attribute from the full_attribute_description . 

  for (; i < noAttributes ; i++) 

  { 

   if (attributeName == 
  

 objectBrowser.backEnd.fullObjectInterface.attributes[i].name) 

    break; 

  } 
  
  

  mode = ""; 

  // once found. 

  // display its properties . 

  switch 
(objectBrowser.backEnd.fullObjectInterface.attributes[i].mode.value()) 

  { 

  case ParameterMode._PARAM_IN    : mode = "in"; 
  

   break; 

  case ParameterMode._PARAM_OUT   : mode = "out"; 
  

   break; 

  case ParameterMode._PARAM_INOUT : mode = "in-out"; 
  

   break; 

  } 
  

  java.lang.Object obj = 

    (java.lang.Object) 
objectBrowser.backEnd.fullObjectInterface.attributes[i].type; 

  type = obj.toString(); 

 } 

} 

Listing 5. 

//*************************************************************** 

// File : OperationDescriptionTable.java 

// This file contains implementation of following classes 

// 1. OperationDescriptionTable 

// copyright 1999: ABCOM Information Systems Pvt. Ltd., All 
 rights reserved. 

//************************************************************ 
* 

import org.omg.CORBA.*; 

import org.omg.CORBA.InterfaceDefPackage.*; 

import java.awt.*; 

import java.awt.event.*; 

import com.sun.java.swing.*; 

import com.sun.java.swing.table.*; 

import java.util.Vector; 

import com.sun.java.swing.border.*; 
  
  

// 
*************************************************************** 

// Class implemented : OperationDescriptionTable 

// Derived from  : JFrame 

// Implements   : ActionListener 

// Description   : 

// this class does following after 

// an operation has been selected from the operations list. 

//   1. Displaying all the arguments and their 
properties 

//   2. Accepting the input values of the parameters 

// 
************************************************************** 

public class OperationDescriptionTable extends JFrame 

 implements ActionListener 

{ 

 private JComponent cPane;     // 
component pane of the display frame 

 private JButton Invoke,Close;   // buttons to 
invoke and close 

 private String operationName;   // name of selected operation 

 private Box parameterList ;    // Box for 
Textfields accepting parameter values 

 private boolean accept[] ;    // array of 
flags used to check if input is required 

 private JTextField[] textFieldList;    // 
array used to input the text fields 

 private FullInterfaceDescription OBInterface1; //reference to the 
backend- the object's interface 

 private Vector Parameter,labels;  // vectors used for 
creating list 

 private JTable otable = new JTable(); // table 

 private ObjectBrowser objectBrowser;  // reference to ObjectBrowser 
class 

 private int noParameters;     // 
no of parameters 
  
  
  
  

 // *************************************************************** 

 // constructor. 

 // *************************************************************** 

 public OperationDescriptionTable(String operationName, 
  

ObjectBrowser objectBrowser) 

 { 

  // initialization of user interface. 

  super ("Operation Description Table : " + operationName); 

  this.operationName = operationName; 

  this.objectBrowser = objectBrowser; 
  
  

  // initialize the display. 

  init(); 

 } 
  
  

 // *************************************************************** 

 // initialize the display 

 // *************************************************************** 

 private void init() 

 { 

  Dimension d = getToolkit().getScreenSize(); 

  setBounds(d.width/3,d.height/3,d.width/2,d.height/2); 
  
  

  // show the elements on this frame. 

  cPane = (JComponent) getContentPane(); 

  cPane.setLayout(new BorderLayout()); 
  
  

  //create the title bar 

  JLabel titlePanel = new JLabel("Please enter the 
paramerters "); 

  cPane.add(titlePanel,BorderLayout.NORTH); 
  
  

  // create a button panel for displaying Invoke and Close 
buttons 

  JPanel buttonPanel = new JPanel(); 

  buttonPanel.add( Invoke = new JButton("Invoke")); 

  buttonPanel.add( Close  = new JButton("Close")); 

  cPane.add(buttonPanel,BorderLayout.SOUTH); 
  

  //add actionlisteners to both the buttons. 

  Invoke.addActionListener(this); 

  Close.addActionListener(this); 
  
  

  //set the initial values of the variables 

  OBInterface1 = objectBrowser.backEnd.fullObjectInterface; 

  Parameter = new Vector(); 
  
  

  int i = 0; 

  // compare the name of the operation with the input name 

  // to get the correct operation from the array. 

  for ( ; i < OBInterface1.operations.length;i++) 

  { 

   if (operationName.equals 
(OBInterface1.operations[i].name)) 

    break; 

  } 
  
  

  //get the no. of parameters and repeat until j = no of 
parameters. 

  //i.e. initialize the values of the table. 

  noParameters = OBInterface1.operations[i].parameters.length; 
  
  

  // check for no input parameters 

  if (noParameters == 0) 

  { 

   //display message 

   JLabel message = new JLabel ("No Input Parameters"); 

   cPane.add(message, BorderLayout.CENTER); 

   // directly perform dii. 

   performDii(operationName); 

  } 

  else     // there are input 
parameters 

  { 

   //Initialization the table with operation parameters 

   initTable(i); 

   // add the table object to our layout 

   cPane.add(otable,BorderLayout.WEST); 
  
  

   // add the text fields along with table rows to 
input parameters 

   parameterList = Box.createVerticalBox(); 

   cPane.add(parameterList,BorderLayout.CENTER); 
  
  

   // create textfield objects for each parameter 

   textFieldList = new JTextField[otable.getRowCount()]; 
  
  

   // SET THE label : values. 

   textFieldList[0] = new JTextField("Values"); 

   textFieldList[0].setEditable(false); 
  
  

   // create a temp, rectangle 

   Rectangle rect = otable.getCellRect(1,3,false); 
  
  

   //match the height of the cell and the text field 

   textFieldList[0].setSize(rect.width, rect.height); 
  
  

   parameterList.createHorizontalStrut(0); 

   // add to the parameter list. 

   parameterList.add(textFieldList[0]); 
  
  

   for ( int j = 1; j < otable.getRowCount(); j++) 

   { 

    //create new text field 

    textFieldList[j] = new JTextField(20); 

    //match the hieght of the cell and the text 
field 
  

 textFieldList[j].setSize(rect.width,rect.height); 
  
  

    parameterList.createHorizontalStrut(0); 

    // add the text field to the box. 

    parameterList.add(textFieldList[j]); 

    // set editable if IN or INOUT type of 
parameter 

    textFieldList[j].setEditable(accept[j-1]); 

   } 

  } 

  // add the textfield panel to our layout 

  cPane.add(parameterList,BorderLayout.CENTER); 

 } // end of init. 
  
  

 // *************************************************************** 

 // initTable method is responsible for all the 

 // table initialization operations. 

 // *************************************************************** 

 private void initTable (int i) 

 { 

  Parameter.addElement((java.lang.Object) new String("Name")); 

  Parameter.addElement((java.lang.Object) new String("Mode")); 

  Parameter.addElement((java.lang.Object) new String("Type")); 
  
  

  try 

  { 

   // initialize accept to array of row length.. 

   accept = new boolean[noParameters]; 
  
  

   // start filling the vector with parameter properties 

   for (int j = 0; j < noParameters;j++) 

   { 

    // add paramter name 

    Parameter.addElement((java.lang.Object) 
OBInterface1.operations[i].parameters[j].name); 
  
  

    //temp variable used to set mode in table 

    String mode = new String(); 
  
  

    // set mode to appropriate value 
  

    switch ( 
OBInterface1.operations[i].parameters[j].mode.value()) 

    { 

     // input parameter 

    case ParameterMode._PARAM_IN    : mode = 
"in"; 
  
  
  

     accept[j] = true; 
  

     break; 
  
  
  
  

     // output parameter 
  

    case ParameterMode._PARAM_OUT   : mode = 
"out"; 
  

     accept[j] = false; 
  

     break; 
  
  
  
  

     // inout parameter 
  

    case ParameterMode._PARAM_INOUT : mode = 
"in-out"; 
  

     accept[j] = true; 
  

     break; 

    } 

    // add mode to vector 

    Parameter.addElement((java.lang.Object) mode); 

    // add the type of element. 

    Parameter.addElement((java.lang.Object)new 
String(""+ OBInterface1.operations[i].parameters[j].type)); 

   } //end of adding elements into the vector. 
  
  
  

   // create a table with these elements. 

   labels = new Vector(); 

   labels.addElement((java.lang.Object) new 
String("Name")); 

   labels.addElement((java.lang.Object) new 
String("Mode")); 

   labels.addElement((java.lang.Object) new 
String("Type")); 
  
  

   final int rowCount = noParameters+1; 

   // initialise the tablemodel 

   TableModel model = new AbstractTableModel() 

    { 

    public int getRowCount() { return rowCount;} 

    public int getColumnCount() { return 3;} 

    public String getColumnName(int column) 

    { 

    return new String 
((labels.elementAt(column)).toString()); 

    } 

    public java.lang.Object getValueAt(int 
row,int column) 

    { 

    return 
((java.lang.Object)Parameter.elementAt((row*3)+column)); 

    } 

    }; 

   //set model 

   otable.setModel(model); 
  
  

   // create the new table using the "vector constructor" 

   otable = new JTable (Parameter,labels); 

  } 

  catch(Exception e) // exception BAD_KIND may arise while 

  {       // 
operating on fullObjectInterface. 

  } 

 } 
  
  

 // ***************************************************************** 

 //invoke method from server object using DII. 

 // ***************************************************************** 

 private void performDii (String operationName) 

 { 

  // send the DII request to backend . 

  if (objectBrowser.backEnd.processRequest(operationName)) 

   objectBrowser.setStatus("DII Succesful"); 

  else 

   objectBrowser.setStatus("DII Failed"); 

 } 
  
  

 public void actionPerformed(ActionEvent e) 

 { 

  // if Invoke is selected then ask back end to begin DII. 

  if (e.getSource() == Invoke) 

  { 

   //string array to store input parameters 

   String[] parametersValue = new 
String[this.noParameters ]; 
  
  

   // initialize the string array with the values in 
textfields 

   for (int j = 1; j < textFieldList.length; j++) 

   { 

    parametersValue[j-1] = 
textFieldList[j].getText(); 

   } 
  
  

   // call setParameters method to send the parameters 

   // to backEnd object for processing 

   objectBrowser.backEnd.setParameters(parametersValue); 
  
  

   //set status bar 

   objectBrowser.setStatus("DII invoked"); 

   System.out.println(operationName); 

   performDii(operationName); 

  } 

  // close the frame. 

  if (e.getSource() == Close) 

  { 

   dispose(); 

  } 

 }// end of actionperformed. 

} 

Listing 6.
 
//****************************************************************************** 

// File : StatusBar.java 

// This file contains implementation of following classes 

// 1. StatusBar 

// copyright 1999: ABCOM Information Systems Pvt. Ltd., All 
 rights reserved. 

//***************************************************************************** 
* 
  
  

import com.sun.java.swing.JLabel; 
  
  

// 
****************************************************************************** 

// Class implemented : StatusBar 

// Derived from  : JLabel 

// Implements   : None 

// Description   : 

// This class implements the status bar for displaying the status 

// information to the user. 

// 
**************************************************************************** 

public class StatusBar extends JLabel 

{ 

 private String cob; 
  
  

 // class constructor 

 public StatusBar() 

 { 

  cob = "CORBA OBJECT BROWSER :"; 

  setText(cob); 

 } 
  
  

 // construtor that takes String argument 

 public StatusBar(String s) 

 { 

  cob = "CORBA OBJECT BROWSER :"; 

  setText(cob + " " + s); 

 } 
  
  

 // modifier method for cob member 

 public void SetText(String s) 

 { 

  setText(cob + " " + s); 

 } 

} 

Listing 7. 

//****************************************************************************** 

// File : BackEnd.java 

// This file contains implementation of following classes 

// 1. Backend 

// copyright 1999: ABCOM Information Systems Pvt. Ltd., All 
 rights reserved. 

//***************************************************************************** 
* 

import org.omg.CosNaming.*; 

import org.omg.CORBA.*; 

import org.omg.CORBA.InterfaceDefPackage.*; 

import java.awt.*; 

import java.awt.event.*; 

import com.sun.java.swing.*; 

import com.sun.java.swing.event.*; 

import java.util.*; 
  
  

// 
****************************************************************************** 

// Class implemented : BackEnd 

// Derived from  : None 

// Implements   : None 

// Description   : 

// This is the class that handles all the back end activities. 

// All corba work is done in this class. 

// It contains following important public Methods : 

//       1. resolve() 

//       2. introspect() 

//       3. processRequest() 

// 
****************************************************************************** 

public class BackEnd 

{ 

 //declare variables 

 private org.omg.CORBA.ORB orb; 
 // orb object 

 private org.omg.CosNaming.NamingContext nameService; 

 private org.omg.CORBA.Object obj;  // corba object for naming service 

 private ObjectBrowser objectBrowser; // reference to main display 
  
  

 private JFrame opFrame;   // frame to display the 
result of dii 

 private JComponent opFramePane ;   // content 
pane of frame 
  
  

 private int noAttributes ;   // no of attributes 

 private int noOperations ;   // no of methods in 
object 
  
  

 // string containg the values of parameters for DII 

 private String[] parametersValue; 
  
  

 // object to describe the interface defintion 

 public FullInterfaceDescription fullObjectInterface ; 
  
  

 // 
****************************************************************************** 

 // constructor 

 // 
****************************************************************************** 

 public BackEnd(ObjectBrowser objectBrowser) 

 { 

  // get reference to front end. 

  this.objectBrowser = objectBrowser; 

 } 
  
  

 // 
****************************************************************************** 

 //method init : used for initialization. 

 // 
****************************************************************************** 

 public boolean init() 

 { 

  try 

  { 

   String[] param = {""}; 
  
  

   orb = org.omg.CORBA.ORB.init (param, null); 

   objectBrowser.setStatus("ORB object created 
succesfully "); 
  
  

   // Get a reference to the Naming service 

   org.omg.CORBA.Object nameServiceObj = 
  

orb.resolve_initial_references ("NameService"); 

   if (nameServiceObj == null) 

   { 

    objectBrowser.setStatus("ERROR : 
nameServiceObj = null"); 

    return(false); 

   } 
  
  

   nameService = 
  

org.omg.CosNaming.NamingContextHelper.narrow (nameServiceObj); 

   if (nameService == null) 

   { 

    objectBrowser.setStatus("ERROR : 
nameService = null"); 

    return (false); 

   } 

   objectBrowser.setStatus("Naming service resolved "); 

   System.out.println("Initialize - Success"); 

   return (true); 

  } 

  catch (Exception e) 

  { 

   System.out.println("unable to initialize"); 

   objectBrowser.setStatus("Error in initialization"); 

   return (false); 

  } 

 } 
  
  

 // ***************************************************************** 

 // sets the  parameterList. 

 // ***************************************************************** 

 public void setParameters(String[] parametersValue) 

 { 

  // copy the paramters into parametersValue. 

  this.parametersValue = parametersValue; 

 } 
  
  

 // ***************************************************************** 

 // method resolve used to resolve object reference 

 // input parameter: String - name of object 

 // ***************************************************************** 

 public boolean resolve(String object) 

 { 

  boolean resolved = false; 

  // initialize using COS Naming or URL Naming Service 

  if (!(resolved = resolveUsingName(object))) 

   resolved = resolveUsingURL(object); 
  
  

  // if the object reference was resolved 

  if (resolved) 

  { 

   // object resolved. 

   System.out.println("Resolved - Success"); 
  
  
  

   // get the object interface defintion 

   InterfaceDef objIntfce = obj._get_interface(); 

   fullObjectInterface = objIntfce.describe_interface(); 
  
  

   objectBrowser.setStatus("interface " + 
  

 fullObjectInterface.name + "\n"); 
  
  

   return ( true ); 

  } 

  return (false); 

 } 
  
  
  
  

 // ***************************************************************** 

 // resolveUsingName() method resolves any object with name service 

 // input parameter: String - name of object 

 // ***************************************************************** 

 private boolean resolveUsingName(String object) 

 { 

  try 

  { 

   // resolve the Count object reference 

   objectBrowser.setStatus("Locating " + object + " 
object"); 

   NameComponent[] name = {new NameComponent(object, "")}; 
  
  

   // resolve name using namin service 

   obj = nameService.resolve (name); 

   System.out.println("Init succesful"); 
  
  

   return (true); 

  } 

  catch (Exception e) 

  { 

   objectBrowser.setStatus 

    ("Local Resolve failed" + 

    "trying to resolve using urlnaming service "); 

   return (false); 

  } 

 } 
  
  

 // ***************************************************************** 

 // resolveUsingURL method resolves any object with URL name service 

 // input parameter: String - URL + name of IOR 

 // 
***************************************************************** 

 private boolean resolveUsingURL (String object) 

 { 

  try 

  { 

   //create the resolver object 

   org.omg.CORBA.Object resolverObj = 
  

 orb.resolve_initial_references("URLNamingResolver"); 

   // narrow the Object to get URL Resolver 

   com.visigenic.vbroker.URLNaming.Resolver URLresolver = 
  

 com.visigenic.vbroker.URLNaming.ResolverHelper.narrow(resolverObj); 
  
  

   // locate object using resolver 

   obj = URLresolver.locate(object); 
  

   return (true); 

  } 

  catch (Exception e) 

  { 

   System.out.println("Resolve - failed" ); 

   objectBrowser.setStatus("Unable to locate object "); 

   return (false); 

  } 

 } 
  
  

 // 
***************************************************************** 

 // method Introspect : 

 //    used to get the object interface 
description 

 //    and print it 

 // 
***************************************************************** 

 public boolean introspect() 

 { 

  Vector attr = new Vector();   // vector used to create 
attribute list 

  Vector oper = new Vector();  // used for 
operations list. 
  
  

  try 

  { 

   final int noAttributes = 
fullObjectInterface.attributes.length; 

   final int noOperations = 
fullObjectInterface.operations.length; 
  
  

   // get the complete listing for the interface and 
print it in text area 

   objectBrowser.outputPanel.setListing("interface " + 
  

    fullObjectInterface.name + 
  

    "\n{\n"); 
  
  

   //print out all the attributes 

   for (int i = 0; i < noAttributes ; i++) 

   { 

    // check the mode of the parameter. 

    String mode = new String(); 

    switch 
(fullObjectInterface.attributes[i].mode.value()) 

    { 

    case ParameterMode._PARAM_IN    : mode = "in"; 
  

     break; 

    case ParameterMode._PARAM_OUT   : mode = "out"; 
  

     break; 

    case ParameterMode._PARAM_INOUT : mode = 
"inout"; 
  

     break; 

    } 
  
  

    // this string stores the attribute definition 

    String strAttribute = 
  

"\t" + 

          mode + 

          " " + 
  

fullObjectInterface.attributes[i].type + 

          " " + 
  

fullObjectInterface.attributes[i].name + 
  

";\n\t" ; 
  
  
  

 objectBrowser.outputPanel.setListing(strAttribute); 
  
  

    // add element name to the vector (for 
creating list.) 
  

 attr.addElement(fullObjectInterface.attributes[i].name) ; 

   } 

   // add the elements to the attribute list. 
  

 objectBrowser.outputPanel.updateList(attr,"attributes"); 
  
  

   // print out the operation signature and the interface listing. 

   for (int i = 0; i < noOperations ; i++) 

   { 

    // string to hold the operation signature. 

    String signature = 
fullObjectInterface.operations[i].result + 

           " " + 
  

fullObjectInterface.operations[i].name ; 

    signature = signature.trim(); 
  
  

    //display result type of method 
  

 objectBrowser.outputPanel.setListing("\n\t"+signature+"\n\t(\n"); 
  
  

    signature = signature+" ("; 
  
  

    // add the parameters 

    String mode = new String(); 

    for (int j=0 ; 

      j < 
fullObjectInterface.operations[i].parameters.length; 

      j++) 

    { 
  

     // set the mode of parameter. 

     switch 
(fullObjectInterface.operations[i].parameters[j].mode.value()) 

     { 

     case ParameterMode._PARAM_IN    : 
mode = "in"; 
  

      break; 

     case ParameterMode._PARAM_OUT   : 
mode = "out"; 
  

      break; 

     case ParameterMode._PARAM_INOUT : 
mode = "in"; 
  

      break; 

     } 
  
  
  

     // check for next line. 

     if (j != 0 ) 

     { 
  

 objectBrowser.outputPanel.setListing(",\n"); 
  
  

      signature = signature.trim(); 

      // method (parameter1 ,<-- 

      signature = 
signature.concat(", "); 

     } 
  
  

     //string describing the parameters 
of the method. 

     signature = signature.trim(); 

     String strParameter = 
  

  "\t\t" + 
  

  mode + 
  

  " " + 
  

  fullObjectInterface.operations[i].parameters[j].type + 
  

  " " + 
  

  fullObjectInterface.operations[i].parameters[j].name; 
  
  

     // add to display 
  

 objectBrowser.outputPanel.setListing("\t"+strParameter); 
  
  

     strParameter = strParameter.trim(); 

     // add to signature. 

     signature = 
signature.concat(strParameter); 
  
  
  

     signature = signature.trim(); 

    } 
  
  

    // end the listing for current method 
  

 objectBrowser.outputPanel.setListing("\n\t);\n"); 
  

    // end the signature 

    signature = signature.concat(");"); 
  

    oper.addElement(signature); 

   } 

   // add the operations to the list. 
  

 objectBrowser.outputPanel.updateList(oper,"operations"); 
  
  

   // print the final braces. 
  

   objectBrowser.outputPanel.setListing("}\n"); 
  
  

   System.out.println("Introspect - Success"); 

   objectBrowser.setStatus("Introspect - Successful"); 

   return(true); 
  
  

  }//end of try 
  
  

  catch (Exception e) 

  { 

   System.out.println("Introspect - Failed"+e); 

   objectBrowser.setStatus("Introspect - failed"); 

   return (false); 

  }//end of catch 

 } // end of introspect 
  
  
  
  

 // 
***************************************************************** 

 // processRequest receives operation name as the input parameter 

 // and performs DII on the selected operation 

 // 
***************************************************************** 
  

 public boolean processRequest(String operationName) 
  

 { 

  try 

  { 

   System.out.println(operationName); 

   int i = 0; 
  
  

   noOperations = fullObjectInterface.operations.length; 

   // compare the name of the operation with the input 
name 

   // to obtain the index of the operation in the array. 

   for (i = 0 ; i < noOperations;i++) 

   { String name = 
fullObjectInterface.operations[i].name; 

    if (operationName.equals 

     (name)) break; 

   } 
  
  
  

 System.out.println(fullObjectInterface.operations[i].name); 

   int noParameters = 
fullObjectInterface.operations[i].parameters.length; 
  
  

   //create the List and start adding the parameters. 

   NVList parameterList = orb.create_list(0); 

   for (int j = 0; j < noParameters;j++) 

   { 

    // create an ANY object to replicate the 
parameter. 

    // set the correct type and mode and add to 
the list. 

    Any currentParameter = orb.create_any(); 
  
  

    //set the type of any object to match the 
parmater type 

    currentParameter.type ( 
  

 fullObjectInterface.operations[i].parameters[j].type); 
  
  

    int mode = 0; 

    // this flag accept is used to indicate 
values for which 

    // input must be accepted at runtime. 

    boolean accept = false; 
  

    switch ( 
fullObjectInterface.operations[i].parameters[j].mode.value() ) 

    { 

    case ParameterMode._PARAM_IN : 

     mode = org.omg.CORBA.ARG_IN.value; 

     accept = true; 

     break; 
  
  
  

    case ParameterMode._PARAM_OUT : 

     mode = org.omg.CORBA.ARG_OUT.value; 

     accept = false; 

     break; 
  
  
  

    case ParameterMode._PARAM_INOUT : 

     mode = org.omg.CORBA.ARG_INOUT.value; 

     accept = true; 

     break; 

    } 
  
  

    // input the value of the parameter. 

    String inputParameter = new 
String(parametersValue[j]); 
  
  

    // insert the correct value of input 
parameter into the ANY 

    // object. 

    if ( accept ) 

    { 

     switch ( 
currentParameter.type().kind().value()) 

     { 

     case 0 :{ 
     //tk_null 

        // in this 
program we consider null to be a null object 

        // as in 
orb.init <-- init. 

        // Another 
modification may be the null string 

        // for 
structure references. what to do then ??? 
  

 currentParameter.insert_Object( null); 

        break; 

       } 
  
  

     case 1 : 
     //tk_void 

       // this type is not 
implemented as we can't have void as 

       // the object type 
for an input partameter in Java 
  
  
  
  

     case 2 :{ 
     //tk_short 
  

 currentParameter.insert_short((short)Integer.parseInt(inputParameter)); 

  break; 

       } 

     case 4 :{ 
    //tk_ushort 
  

 currentParameter.insert_ushort((short)Integer.parseInt(inputParameter)); 

   break; 

       } 
  
  

     case 3 :{ 
     //tk_long 
  

 currentParameter.insert_long(Integer.parseInt(inputParameter)); 

        break; 

       } 
  
  

     case 5 :{ 
    //tk_ulong 
  

 currentParameter.insert_ulong(Integer.parseInt(inputParameter)); 

        break; 

       } 
  
  

     case 6 :{ 
    //tk_float 
  

 currentParameter.insert_float((float) 
(Float.valueOf(inputParameter)).floatValue()); 

        break; 

       } 
  
  
  
  
  

     case 7 :{ 
     //tk_double 
  

 currentParameter.insert_double((double) 
(Double.valueOf(inputParameter)).doubleValue()); 

        break; 

       } 
  
  

     case 8 :{ 
     //tk_boolean 
  

 currentParameter.insert_boolean ((boolean) 
Boolean.getBoolean(inputParameter)); 

        break; 

       } 
  
  

     case 26:{ 
     //tk_wchar 
  

 currentParameter.insert_wchar((char) (inputParameter).charAt(0)); 

        break; 

       } 
  
  

     case 9 :{ 
     //tk_char 
  

 currentParameter.insert_char((char) (inputParameter).charAt(0)); 

        break; 

       } 

     case 10:{ 
     //tk_octet 
  

 currentParameter.insert_octet((byte) 
((inputParameter).getBytes())[0]); 

        break; 

       } 

     case 11:{ 
     //tk_any 
  

 currentParameter.insert_any( currentParameter ); 

        break; 

       } 

     case 12:{ 
     //tk_TypeCode 

        // get the 
type code of this parameter from its name. 
  

 currentParameter.insert_TypeCode( currentParameter.type() ); 

        break; 

       } 
  
  

     case 13: 
    //tk_Principalcase 

       // not implemented. 
  
  

     case 14:{ 
     //tk_objref 

        // 
Considering only CORBA Objects 

        // 
  

 currentParameter.insert_Object( 
orb.resolve_initial_references(inputParameter)); 

        // 

      break; 

       } 
  
  
  
  

     case 18:{ 
    //tk_string 
  

 currentParameter.insert_string((java.lang.String) inputParameter); 

        break; 

       } 
  
  
  
  

     case 19: 
    //tk_sequence 

     case 20: 
    //tk_array 

     case 21: 
    //tk_alias 

     case 15: 
    //tk_struct 

     case 16: 
   //tk_union 

     case 17: 
    //tk_enum 

     case 22: 
    //tk_except 
  
  

     case 23:{ 
    //tk_longlong 
  

 currentParameter.insert_longlong((long) 
Long.parseLong(inputParameter)); 

        break; 

       } 

     case 24: { 
    //tk_ulonglong 
  

currentParameter.insert_longlong((long) Long.parseLong(inputParameter)); 
  

         break; 

        } 
  
  

     case 27:{ 
    //tk_wstring 
  

 currentParameter.insert_wstring((java.lang.String) inputParameter); 

        break; 

       } 
  
  

     case 25: 
    //tk_longdouble 

       // no java support 
for this type 

     case 28: 
    //tk_fixed 

       // no java support 
for this type. 

     } 

    } 
  
  

    //add the value to the list. 
  

 parameterList.add_value(fullObjectInterface.operations[i].parameters[j].name,cu 
rrentParameter,mode); 

   } // end of populating the NVLIST. 
  
  

   // 
****************************************************************************** 

   // status == NVLISt created and populated 
succesfully. NOW GO and INVOKE 

   // 
****************************************************************************** 
  
  

   // create the any object for the result field and 

   Any resultParameter = orb.create_any(); 

   // set the type of object. 

   resultParameter.type 
(fullObjectInterface.operations[i].result); 

   // create the NamedValue object. 

   org.omg.CORBA.NamedValue resultField = 
  

     orb.create_named_value("resultField", 
  
  

resultParameter, 
  
  

ParameterMode._PARAM_OUT); 

   // create request object 

   Request request = 

        obj._create_request( 
  

  null, 
  

  fullObjectInterface.operations[i].name, 
  

  parameterList, 
  

  resultField); 
  
  
  
  

   // invoke it and display it on a frame. 

   request.invoke(); 
  
  
  

   // to print out the results of DII into a frame. 

   opFrame = new JFrame("Dynamic Invocation : " 
+operationName ); 

   Dimension d = opFrame.getToolkit().getScreenSize(); 
  

 opFrame.setBounds(d.width/6,d.height/3,d.width*2/3,d.height/3); 
  
  

   //get the content pane to this pane. 

   opFramePane = (JComponent) opFrame.getContentPane(); 

   opFramePane.setLayout(new BorderLayout()); 
  
  

   System.out.println("RESULT OF DII " + 
request.result().value()); 

   opFramePane.add( 

     new JLabel("Result of " + 
  

fullObjectInterface.operations[i].name + 

         " : " + 

         request.result().value()), 

       BorderLayout.NORTH ); 
  
  

   Box middleBox = Box.createVerticalBox(); 

   middleBox.add(new JLabel("\n")); 

   middleBox.add(new JLabel("Values of Output 
Arguments")); 
  
  

   // print out - What happened to the inputted NVList. 

   NVList resultList = request.arguments(); 

   boolean empty = true; 

   for ( int j=0 ; j < noParameters ; j++) 

   { 

    if 
((fullObjectInterface.operations[i].parameters[j].mode.value() 

      == ParameterMode._PARAM_OUT ) || 
  

 (fullObjectInterface.operations[i].parameters[j].mode.value() 

      == ParameterMode._PARAM_INOUT )) 

    { 

     middleBox.add(new JLabel( 
resultList.item(j).name() + " : " 
  

    + resultList.item(j).value() + "\n")); 

     empty = false; 

    } 

   } 
  
  

   System.out.println("DII Succesful"); 

   if (empty) 

    middleBox.add( new JLabel("No output 
arguments")); 

   opFramePane.add(middleBox,BorderLayout.CENTER); 
  
  

   //show the opFrame.. 

   opFrame.setVisible(true); 
  
  

   // end of the program. 
  

   objectBrowser.setStatus("DII Succesful"); 

   return(true); 

  } // end of try loop 
  
  

  catch (Exception e) 

  { 

   System.out.println("DII failed" + e.getMessage()); 
  
  

   objectBrowser.setStatus("DII failed"); 
  
  

   // notify user of error through dialog. 

   opFrame = new JFrame("Error"); 
  
  

   java.awt.Dimension d = 
opFrame.getToolkit().getScreenSize(); 
  

 opFrame.setBounds(d.width/3,d.height/2,d.width/2,d.height/6); 

   opFramePane = (JComponent) opFrame.getContentPane(); 

   opFramePane.add( 

    new JLabel("Unable to Complete DII ... 
please check input values")); 
  
  

   opFrame.setVisible(true); 
  
  

   return(false); 
  

  } 
      //end of catch loop 

 }//end of method process request 

}// end of backEnd 

Listing 8. 

javac -classpath %SWINGPATH% %1 

Listing 9. 

echo off 

REM 
*************************************************************************** 

REM File Implements : StartUp.bat 

REM Comments : 

REM           Performs initialisation of IR,Visigenic Naming Service and 

REM           Visigenic osagent. 

REM 
**************************************************************************** 
  
  
  
  

REM start the Visigenic osagent service. 

start OSAgent -c 
  
  

REM initialize the Interface Repository 

REM name of IR : InterfaceRepository 

REM stored in file : ABCOM.ir 

start irep InterfaceRepository ABCOM.ir 
  
  

echo Please register IDL definition with the IR if not yet done so. 
  
  

REM Start COS Naming Service 

REM name of log file : namingLog 

start vbj -DORBservices=CosNaming -DSVCnameroot=ABCOM -DJDKrenameBug 
com.visigenic.vbroker.services.CosNaming.ExtFactory ABCOM namingLog 
  
  

echo start ObjectBrowser using >Show ObjectBrowser 

echo 

Listing 10. 

vbj -DORBservices=CosNaming -DSVCnameroot=ABCOM -VBJclasspath "%SWINGPATH%" 
ObjectBrowser 

Listing 11. 

//************************************************************************* 

// File : Sample.idl 

// copyright 1999: ABCOM Information Systems Pvt. Ltd., All 
 rights reserved. 

//************************************************************************* 

module Sample 

{ 

 interface Test 

 { 

  attribute float SampleValue; 
  
  

  float DoubleValue(in float parameter1); 

  void CountCharacters(in string parameter2,out short 
parameter3); 

    void ReverseString(inout string parameter4); 
  

 }; 

}; 
  

 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.