4. Soporte de ejecución ORB

La especificación de CORBA 2.3 define el soporte de ejecución ORB en forma de pseudo-objetos ORB, el objeto Object, y el objeto de localidad restringida POA. Los pseudo-objetos proporcionan interfaces de igual forma que los objetos CORBA normales, pero no heredan de CORBA::Object, y las operaciones sobre dichas interfaces se implementan en librerías y no se pueden utilizar en invocaciones remotas, es decir, solamente pueden usarse en procesos locales. La definición de los pseudo-objetos se marca con las siglas PIDL en los comentarios IDL.

Los objetos POA son de localidad restringida, lo cual significa que se establece la correspondencia entre la interfaz y el lenguaje destino de acuerdo con las normas establecidas por el lenguaje, pero las referencias a objetos no pueden "externalizarse", bien ser convirtiéndolas en cadena de caracteres, o pasándolas en invocaciones remotas. Los objetos solamente pueden utilizarse en procesos locales.

A continuación vamos a ver cuál es la correspondencia de dichas interfaces con su implementación Java.

4.1. Interfaz ORB

La interfaz ORB proporciona operaciones para soportar aplicaciones CORBA. Incluye la conversión de referencias a objetos a Strings, y viceversa, y la resolución de referencias iniciales. Una de estas referencias iniciales es la referencia a POA, necesaria par apermitir que los objetos estén disponibles para ser invocados.

La interfaz ORB se implementa en Java de la siguiente forma:

package orb.omg.CORBA;
public abstract class ORB {...}

Inicialización ORB. Antes de que una aplicación pueda usar las operaciones del interfaz ORB necesita una referencia a un pseudo-objeto ORB. Los ORBs en applets Java requieren diferentes inicializaciones para que las aplicaciones Java "se salten" las restricciones de seguridad. Dicha inicialización se realiza llamando a métodos estáticos de la clase ORB.

Operación IDL: ORB ORB_init(inout arg_list argv, in ORBid orb_identifier);
Método Java por defecto:       public static ORB init();
Método Java para aplicaciones: 
   public static ORB init(String [] args, Properties props);
Método Java para applets:
   public static ORB init (Applet app, Properties props);

El método por defecto init() devuelve una referencia a un único ORB. Los otros dos métodos se han diseñado específicamente para usarlos en aplicaciones Java y applets, respectivamente. En ambos casos se pueden pasar como parámetros una lista de propiedades. ORB reconocerá cómo interpretar dos propiedades estándar:

Los typecodes pueden representar información de tipo sobre cualquier tipo IDL. Muchos tipos de datos IDL son estructurados y contienen otros tipos dentro de ellos. Estos son representados como TypeCodes anidados.

Conversión de referencias a objetos en Strings. Las referencias a objetos pueden ser externalizadas convirtiéndolas en strings. Una referencia a objeto convertida en string puede ser almacenada convenientemente en un fichero o "enviada" utilizando algún otro mecanismo que no sea CORBA, como por ejemplo e-mail. También puede ser reconvertida en una referencia real al mismo objeto. Las dos operaciones para convertir a String y viceversa una referncia a objeto son:

Operación IDL: string object_to_string(in CORBA::Object obj);
Método Java:  String object_to_string(org.omg.CORBa.Object obj);
Operación IDL: object string_to_object(in string obj);
Método Java:  orb.omg.CORBA.Object string_to_object(String str); 

La operación object_to_string() convierte un IOR en un String. La operación string_to_object() realiza la operación contraria.

Obtención de una referencia POA. ORB proporciona una operación para recuperar una referencia a la raíz de POA, necesaria para conseguir que los objetos estén disponibles para invocaciones remotas.

Operación IDL: CORBA::Object resolve_initial_references(in string name);
Método Java:  public abstract org.omg.CORBA.Object
                                 resolve_initial_references(String name);

Asumiendo que el pseudo-objeto ORB ha sido inicializado correctamente, una ferencia a la raiz POA podría obtenerse de la siguiente forma:

orb.omg.CORBA.Object obj= orb.resolve_initial_references("RootPOA");
org.omg.PortableServer.POA rootPOA =
             org.omg.PortableServer.POAHelper.narrow(obj);

Se debe notar que la raíz POA, al igual que cualquier POA de nueva creación, es inicialmente un estado contenedor y no procesará peticiones de entrada. Para habilitar el proceso de peticiones es necesario realizar una llamada activate() sobre su POAManager:

rootPOA.the_Manager().activate();

4.2. Interfaz POA

La interfaz POA se utiliza para crear referencias a objetos y hacer que dichas referencias estén disponibles para invocaciones remotas. La interfaz POA se define en el módulo PortableServer.

IDL interfaz: module PortableServer {
                  interface POA {//locality-constrained;
Clase Java:   package org.omg.PortableServer;
                  public interface POA {...}

Creación de referencias. La interfaz POA proporciona dos operaciones para crear de forma explícita nuevas referencias a objetos.

Operaciones IDL: Object create_reference(in RepositoryID intf);
                 Object create_reference_with_id(in ObjectID oid,
                                                 in RepositoryID intf);
Métodos Java:  org.omg.CORBA.Object create_reference(String intf);
               org.omg.CORBA.Object create_reference_with_id(byte [] oid,
                                                     String intf);

En ambos casos, el tipo del objeto debe especificarse en forma de RepositoryID. Las nuevas referencias creadas no se asocian con ningún servant todavía, lo cual significa que no son activadas. Mientras que el objeto abstracto existe y su referencia puede ser exportada usando object_to_string() o via el servicio de nombres, todavía es necesario asociar el objeto con un servant.

Activación y desactivación implícita. En muchos casos, la forma más conveniente de crear una referencia a objeto consiste en activarla al mismo tiempo que la referencia es creada, en lugar de llamar a una de las operaciones create_reference y posteriormente activar explícitamente el objeto llamando a activate_object() o activate_object_with_id().

Operación IDL: Object servant_to_reference(in Servant servant);
Método Java:  org.omg.CORBA.Object servant_to_reference(Servant s);

Usando esta operación, una única llamada es suficiente:

MyServerImpl servant= new MyServerImpl();
org.omg.CORBA.Object obj= poa.servant_to_reference(servant);

Mediante la llamada a servant_to_reference() se puede asociar el objeto con el servant y simultáneamente crear una entrada en su Active Object Map. A esto se le denomina activación implícita y requiere las políticas IMPLICIT_ACTIVATION y RETAIN. El servant especificado no debe estar actualmente activo o el POA debe tener también fijada la política MULTIPLE_ID. Se debe notar que para que POA sea capaz de asignar un ID a un objeto para una nueva referencia, la política de asingación de ID debe tener un valor de SYSTEM_ID.

Después de que un programa servidor haya inicializado su ORB, obtenido una referencia a la raiz POA, y activar su objetos, el hijo de control principal del servidor usualmente se queda esperando para esperar peticiones y procesarlas. Esto se realiza normalmente llamando al método run() de ORB.

Un ejemplo de servidor sencillo podría ser éste:

public class Server {
  public static void main (String[] args) {
    //inicializar el ORB
    org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);
    try {
     //obtener la raiz POA
     org.omg.PortableServer.POA poa=
        org.omg.PortableServer.POAHelper.narrow(
            orb.resolve_initial_references("RootPOA"));
     //activar POA
     poa.the_POAManager().activate();
     //activar de forma implícita un objeto
     orb.omg.CORB.Object o = poa.servant_to_reference(new myImpl());
     //esperar peticiones
     orb.run();
    } catch (Exception e) {
       e.printStackTrace();
    }
  }

}

Los objetos pueden desactivarse explícitamente mediante una llamada a deactivate_object() si POA tiene la política RETAIN. Los objetos se desactivan de forma implícita de varias formas: destruyendo su POA con la operación destroy(), desactivando su POA a través de la operación deactivate() de su POAManager, o "cerrando" el ORB. En este último caso, la interfaz ORB proporciona dos operaciones:

Operaciones IDL:  void shutdown (in boolean wait_for_completion);
                  void destroy();
Métodos Java:     void shutdown(boolean wait_for_completionI;
                  void destroy();

Mediante una llamada a shutdown() sobre un pseudo-objeto ORB se consigue que el ORB detenga el procesamiento de peticiones y se prepare para su "destrucción". También se "destruyen" todos su adaptadores de objetos. El parámetro Boolean indica si esta operación debe retornar inmediatamente o solamente cuando el ORB se ha cerrado completamente. Después de que ORB se haya cerrado, los únicos métodos que pueden llamarse son operaciones de gestión de referencias a objetos.

El método destroy() libera todos los recursos de un ORB. Si el ORB no se ha cerrado cuando se llama a destroy(), este método iniciará el cierre.

4.3. Interfaz de invocación dinámica

La interfaz de invocación dinámica (DII: Dynamic Invocation Interface) permite a los clientes invocar operaciones sobre objetos sin conocimiento en tiempo de compilación sobre su tipo IDL, es decir, sin el código stub generado por el compilador IDL. Un cliente crea una petición (Request), que es el equivalente dinámico de una operación. Una Request contiene una referencia a objeto, un nombre de operación, e información de tipo y valores para los argumentos que son proporcionados por el cliente. Una vez inicializado con todos estos parámetros, una Request puede ser invocada, y tiene la misma semántica que la invocación de una operación usando código stub.

Request es una interfaz pseudo-IDL que proporciona las operaciones para inicializar una invocación de una petición de invocación de operación e invoca de forma dinámica una operación sobre un objeto. Las peticiones son creadas por el ORB.

Los métodos Java usados para crear una Request son:

Request _create_request(
   Context ctx,
   String operation,
   NVList arg_list,
   NamedValue result
);
Request _creat_request ( 
   Context ctx,
   String operation,
   NVList arg_list,
   NamedValue result,
   ExceptionLIst exclist,
   ContextList ctxlist
);

Los dos métodos son idénticos, excepto que la segunda versión añade alguna información extra.

El nuevo objeto creado Request se devuelve como resultado del método Java. Hay una operación adicional para crear objetos Request parcialmente inicializados:

Request _request (String operation) throws SystemException

La pseudo-interfaz Request se corresponde con la clase abstracta Java org.omg.CORBA.Request.

El DII proporciona un mecanismo para invocar operaciones desde un cliente sin conocimiento en tiempo de compilación sobre la interfaz. La Dynamic Skeleton Interface (DSI) proporciona un mecanismo similar en el lado del servidor. Permite al ORB invocar una implementación de un objeto sin conocimiento en tiempo de compilación sobre la interfaz, es decir, sin una clase skeleton. Para una implementación de objeto, las llamadas a través de un skeleton generadas por un compilador y las DSI no son distinguibles. La idea subyacente a DSI es invocar todas las implementaciones de objetos a través de la misma operación general. Esto se especifica en la clase abstracta DynamicImplementation que contiene una operación, llamada por el ORB, para transportar la petición original al servidor. Esta clase presenta un pseudo-objeto de tipo ServerRequest para permitir al servidor acceder a la información sobre la operación que está siendo invocada y sus argumentos. También usa referencias a los contenidos de dicho objeto par devolver los resultados de la invocación.