Java ORB Portability Interfaces

8


8.1 Introduction

The APIs specified here provide the minimal set of functionality to allow portable stubs and skeletons to be used with a Java ORB. The interoperability requirements for Java go beyond that of other languages. Because Java classes are often downloaded and come from sources that are independent of the ORB in which they will be used, it is essential to define the interfaces that the stubs and skeletons use. Otherwise, use of a stub (or skeleton) will require: either that it have been generated by a tool that was provided by the ORB vendor (or is compatible with the ORB being used), or that the entire ORB runtime be downloaded with the stub or skeleton. Both of these scenarios are unacceptable.

8.1.1 Design Goals

The design balances several goals:

Stubs and skeletons must have a small bytecode footprint in order to make downloading fast in a browser environment and to minimize memory requirements when bundled with a Java VM, particularly in specialized environments such as set-top boxes.
Obviously, the runtime performance of the generated stub code must be excellent. In particular, care must be taken to minimize temporary Java object creation during invocations in order to avoid Java VM garbage collection overhead.
The design does not require adding methods to user-defined types such as structures and exceptions to ensure that stubs and skeletons generated by IDL to Java compilers and reverse Java to IDL mapping tools are interoperable and binary compatible.

A very simple delegation scheme is specified here. Basically, it allows ORB vendors maximum flexibility for their ORB interfaces, as long as they implement the interface APIs. Of course vendors are free to add proprietary extensions to their ORB runtimes. Stubs and skeletons which require proprietary extensions will not necessarily be portable or interoperable and may require download of the corresponding runtime.

8.1.2 Portability Package

The APIs needed to implement portability are found in the org.omg.CORBA.portable package

The portability package contains interfaces and classes that are designed for and intended to be used by ORB implementors. It exposes the publicly defined APIs that are used to connect stubs and skeletons to the ORB.

8.2 Architecture

The stub and skeleton portability architecture allows the use of the DII and DSI as its portability layer. The mapping of the DII and DSI PIDL have operations that support the efficient implementation of portable stubs and skeletons

All stubs shall inherit from a common base class org.omg.CORBA.portable.ObjectImpl. The class is responsible for delegating shared functionality such as is_a() to the vendor specific implementation. This model provides for a variety of vendor dependent implementation choices, while reducing the client-side and server "code bloat".

All DSI-based skeletons inherit from org.omg.CORBA.DynamicImplementation.

8.3 Streamable APIs

The Streamable Interface API provides the support for the reading and writing of complex data types. It is implemented by static methods on the Helper classes. They are also used in the Holder classes for reading and writing complex data types passed as out and inout parameters.

package org.omg.CORBA.portable;
public interface Streamable {
    void _read(org.omg.CORBA.portable.InputStream
istream);
    void _write(org.omg.CORBA.portable.OutputStream
ostream);
    org.omg.CORBA.TypeCode _type();
}

8.4 Streaming APIs

The streaming APIs are Java interfaces that provide for the reading and writing of all of the mapped IDL types to and from streams. Their implementations are used inside the ORB to marshal parameters and to insert and extract complex datatypes into and from Anys.

The streaming APIs are found in the org.omg.CORBA.portable package.

The ORB object is used as a factory to create an output stream. An input stream may be created from an output stream.

package org.omg.CORBA;
interface ORB {
        OutputStream        create_output_stream();
};

package org.omg.CORBA.portable;
public abstract class InputStream {
    public abstract boolean read_boolean();
    public abstract char    read_char();
    public abstract char    read_wchar();
    public abstract byte    read_octet();
    public abstract short   read_short();
    public abstract short   read_ushort();
    public abstract int     read_long();
    public abstract int     read_ulong();
    public abstract long    read_longlong();
    public abstract long    read_ulonglong();
    public abstract float   read_float();
    public abstract double  read_double();
    public abstract String  read_string();
    public abstract String  read_wstring();
    public abstract void    read_boolean_array(boolean[] value,
                            int offset, int length);
    public abstract void    read_char_array(char[] value,
                            int offset, int length);
    public abstract void    read_wchar_array(char[] value,
                            int offset, int length);
    public abstract void    read_octet_array(byte[] value,
                            int offset, int length);
    public abstract void    read_short_array(short[] value,
                            int offset, int length);
    public abstract void    read_ushort_array(short[] value,
                            int offset, int length);
    public abstract void    read_long_array(int[] value,
                            int offset, int length);
    public abstract void    read_ulong_array(int[] value,
                            int offset, int length);
    public abstract void    read_longlong_array(long[] value,
                            int offset, int length);
    public abstract void    read_ulonglong_array(long[] value,
                            int offset, int length);
    public abstract void    read_float_array(float[] value,
                            int offset, int length);
    public abstract void    read_double_array(double[] value,
                            int offset, int length);
    public abstract org.omg.CORBA.Object read_Object();
    public abstract org.omg.CORBA.TypeCode read_TypeCode();
    public abstract org.omg.CORBA.Any read_any();
    public abstract org.omg.CORBA.Principal read_Principal();
}

public abstract class OutputStream {
    public abstract InputStream create_input_stream();
    public abstract void         write_boolean(boolean value);
    public abstract void         write_char(char value);
    public abstract void         write_wchar(char value);
    public abstract void         write_octet(byte value);
    public abstract void         write_short(short value);
    public abstract void         write_ushort(short value);
    public abstract void         write_long(int value);
    public abstract void         write_ulong(int value);
    public abstract void         write_longlong(long value);
    public abstract void         write_ulonglong(long value);
    public abstract void         write_float(float value);
    public abstract void         write_double(double value);
    public abstract void         write_string(String value);
    public abstract void         write_wstring(String value);
    public abstract void         write_boolean_array(boolean[] value,
                                 int offset, int length);
    public abstract void         write_char_array(char[] value,
                                 int offset, int length);
    public abstract void         write_wchar_array(char[] value,
                                 int offset, int length);
    public abstract void         write_octet_array(byte[] value,
                                 int offset, int length);
    public abstract void         write_short_array(short[] value,
                                 int offset, int length);
    public abstract void         write_ushort_array(short[] value,
                                 int offset, int length);
    public abstract void         write_long_array(int[] value,
                                 int offset, int length);
    public abstract void         write_ulong_array(int[]value,
                                 int offset, int length);
    public abstract void         write_longlong_array(long[]value,
                                 int offset, int length);
    public abstract void         write_ulonglong_array(long[] value,
                                 int offset, int length);
    public abstract void         write_float_array(float[] value,
                                 int offset, int length);
    public abstract void         write_double_array(double[]value,
                                 int offset, int length);
    public abstract void         write_Object(org.omg.CORBA.Object value);
    public abstract void         write_TypeCode(org.omg.CORBA.TypeCode value);
    public abstract void         write_any(org.omg.CORBA.Any value);
    public abstract void         write_Principal(org.omg.CORBA.Principal value);
}

8.5 Portability Stub Interfaces

8.5.1 Stub Design

The stub class is implemented on top of the DII..

8.5.2 Portable ObjectImpl

The ObjectImpl class is the base class for stubs and skeletons. It provides the basic delegation mechanism.

The method _ids() returns an array of repository ids that an object implements. The string at the zero index shall represent the most derived interface. The last id, for the generic CORBA object (i.e. "IDL:omg.org/CORBA/Object:1.0"), is implied and not present.

package org.omg.CORBA.portable;
abstract public class ObjectImpl implements
org.omg.CORBA.Object {
    private Delegate __delegate;
    public Delegate _get_delegate() {
        if (__delegate == null) {
            throw new org.omg.CORBA.BAD_OPERATION();
        }
        return _delegate;
    }
    public void _set_delegate(Delegate delegate) {
        __delegate = delegate;
    }
    public abstract String[] _ids() {...}
// methods for standard CORBA stuff
    public org.omg.CORBA.ImplementationDef
      _get_implementation() {
        return _get_delegate().get_implementation(this);
    }
    public org.omg.CORBA.InterfaceDef
      _get_interface() {
        return _get_delegate().get_interface(this);
    }
    public org.omg.CORBA.Object _duplicate() {
        return _get_delegate().duplicate(this);
    }
    public void _release() {
        _get_delegate().release(this);
    }
    public boolean _is_a(String repository_id) {
        return _get_delegate().is_a(this, repository_id);
    }
    public boolean _is_equivalent(org.omg.CORBA.Object rhs) {
        return _get_delegate().is_equivalent(this, rhs);
    }
    public boolean _non_existent() {
        return _get_delegate().non_existent(this);
    }
    public int _hash(int maximum) {
        return _get_delegate().hash(this, maximum);
    }
    public org.omg.CORBA.Request _request(String operation) {
        return _get_delegate().request(this, operation);
    }
    public org.omg.CORBA.Request _create_request(
                 org.omg.CORBA.Context ctx,
                 String operation,
                 org.omg.CORBA.NVList arg_list,
                 org.omg.CORBA.NamedValue result) {
                   return _get_delegate().create_request(this, ctx,
                      operation, arg_list, result);
    }
    public Request _create_request(
                 org.omg.CORBA.Context ctx,
                 String operation,
                 org.omg.CORBA.NVList arg_list,
                 org.omg.CORBA.NamedValue result,
                 org.omg.CORBA.ExceptionList exceptions,
                 org.omg.CORBA.ContextList contexts) {
                   return _get_delegate().create_request(this, ctx, operation,
                     arg_list, result,exceptions, contexts);
    }
}

8.6 Delegate

The delegate class provides the ORB vendor specific implementation of CORBA object.

// Java
package org.omg.CORBA.portable;
public abstract class Delegate {
    public abstract org.omg.CORBA ImplementationDef get_implementation(
                                org.omg.CORBA.Object self);
    public abstract org.omg.CORBA.InterfaceDef get_interface(
                                org.omg.CORBA.Object self);
    public abstract org.omg.CORBA.Object duplicate(
                                org.omg.CORBA.Object self);
    public abstract void release(org.omg.CORBA.Object self);
    public abstract boolean is_a(org.omg.CORBA.Object self,
                                String repository_id);
    public abstract boolean non_existent(org.omg.CORBA.Object self);
    public abstract boolean is_equivalent(org.omg.CORBA.Object self,
                                org.omg.CORBA.Object rhs);
    public abstract int hash(org.omg.CORBA.Object self,
                                int max);
    public abstract org.omg.CORBA.Request request(org.omg.CORBA.Object self,
                                String operation);
    public abstract org.omg.CORBA.Request create_request(
                                org.omg.CORBA.Object self,
                                org.omg.CORBA.Context ctx,
                                String operation,
                                org.omg.CORBA.NVList arg_list,
                                org.omg.CORBA.NamedValue result);
    public abstract org.omg.CORBA.Request create_request(
                                org.omg.CORBA.Object self,
                                org.omg.CORBA.Context ctx,
                                String operation,
                                org.omg.CORBA.NVList arg_list,
                                org.omg.CORBA.NamedValue result,
                                org.omg.CORBA.ExceptionList excepts,
                                org.omg.CORBA.ContextList contexts);
}

8.7 Skeleton

The skeleton uses the DynamicImplementation (see Section 6.10, "ServerRequest and Dynamic Implementation").

See Section 7.2.2, "Servant Class" for more information.

8.8 ORB Initialization

The ORB class represents an implementation of a CORBA ORB. Vendors specific ORB implementations can extend this class to add new features.

There are several cases to consider when creating the ORB instance. An important factor is whether an applet in a browser or an stand-alone Java application is being used.

In any event, when creating an ORB instance, the class names of the ORB implementation are located using the following search order:

8.8.1 Standard Properties

The OMG standard properties are defined in the following table.

Table  8-1
Property Name
Property Value

org.omg.CORBA.ORBClass

class name of an ORB implementation

org.omg.CORBA.ORBSingletonClass

class name of the singleton ORB implementation

8.8.2 ORB Initialization Methods

There are three forms of initialization as shown below. In addition the actual ORB implementation (subclassed from ORB) must implement the set_parameters() methods so that the initialization parameters will be passed into the ORB from the initialization methods.

// Java
package org.omg.CORBA;
abstract public class ORB {
    // Application init
    public static ORB init(String[] args,
      java.util.Properties props) {
        // call to: set_parameters(args, props);
        ...
        }
    // Applet init
    public static ORB init(java.applet.Applet app,
      java.util.Properties props) {
        // call to: set_parameters(app, props);
        ...
        }
    // Default (singleton) init
    public static ORB init()
        {...}
    // Implemented by subclassed ORB implementations
    //  and called by init methods to pass in their params
    abstract protected void set_parameters(String[] args,
        java.util.Properties props);
    abstract protected void set_parameters(Applet app,
        java.util.Properties props);
}

8.8.2.1 Default initialization

The default initialization method returns the singleton ORB. If called multiple times it will always return the same the Java object.

The primary use of the no-argument version of ORB.init() is to provide a factory for TypeCodes for use by Helper classes implementing the type() method, and to create Any instances that are used to describe union labels as part of creating a union TypeCode. These Helper classes may be baked-in to the browser (e.g. for the interface repository stubs or other wildly popular IDL) and so may be shared across untrusted applets downloaded into the browser. The returned ORB instance is shared across all applets and therefore must have sharply restricted capabilities so that unrelated applets can be isolated from each other. It is not intended to be used directly by applets. Therefore, the ORB returned by ORB.init(), if called from a Java applet, may only be used to create Typecodes. An attempt to invoke other "regular" ORB operations shall raise a system exception.

If called from an application a fully functional ORB object is returned.

8.8.2.2 Application initialization

The application initialization method should be used from a stand-alone Java application. It is passed a array of strings which are the command arguments and a list of Java properties. Either the argument array or the properties may be null.

It returns a new fully functional ORB Java object each time it is called.

8.8.2.3 Applet initialization

The applet initialization method should be used from an applet. It is passed "the applet" and a list of Java properties. Either the applet or the properties may be null.

It returns a new fully functional ORB Java object each time it is called.