1. Arquitectura CORBA

CORBA (Common Object Request Broquer Architecture) es la especificación de la funcionalidad de ORB (Object Request Broker). ORB actúa como un bus de mensajes que transporta peticiones de invocación de operaciones y sus resultados sobre objetos CORBA, residentes en cualquier máquina, implementados en cualquier lenguaje, y ejecutados sobre cualquier plataforma hardware o sistema operativo.

La noción de transparencia es fundamental en CORBA. La transparencia de localización es la capacidad de acceder e invocar operaciones sobre un objeto CORBA sin necesidad de conocer dónde reside dicho objeto. La idea es que debería ser igualmente sencillo invocar una operación residente en una máquina remota que un método de un objeto en el mismo espacio de direcciones. La transparencia de lenguaje de programación proporciona la libertad de implementar la funcionalidad encapsulada un un objeto usando el lenguaje más adecuado, bien por las habilidades de los programadores, la idoneidad del lenguaje para la tarea específica, o la elección de un "tercer" desarrollador que proporciona componentes ya creados (off-the-shelf components). La clave de este grado de libertad es un lenguaje de definición de interfaces que es neutral con respeco a la implementación, y que proporciona una separación entre la interfaz y su implementación.

Dicho lenguaje se denomina Interface Denifition Language (IDL), que proporciona la forma de definir las interfaces de los objetos, independientemente del lenguaje de programación en el que estén implementados. Es un lenguaje fuertemente declarativo, con un rico conjunto de tipos de datos para describir parámetros complejos. Una interfaz IDL actúa como un contrato entre los desarrolladores de objetos y los eventuales usuarios de dichos interfaces. También permite a los usuarios de CORBA compilar las definiciones de las interfaces en código oculto para la tranmisión de peticiones de invocaciones a través de las redes y las arquitecturas de las máquinas sin necesitar ningún conocimiento sobre el protocolo de red utilizado, o incluso la localización del objeto involucrado.

Las definiciones de interfaz IDL informan a los clientes de un objeto que oferta una interfaz sobre qué operaciones soporta dicho objeto, los tipos de sus parámetros y qué tipos de resultados se esperan. Un programador clientes solamente necesita el IDL para escribir código cliente listo para incovar operaciones sobre un objeto remoto.

El compilador IDL genera código stub que el cliente deberá linkar, y los tipos de datos del lenguaje en un formato adecuado para su transmisión por la red (marshals). La implementación del objeto remoto se debe linkar con un código similar denominado skeleton, que decodifica (unmarshals) la petición en tipos de datos de un determianado lenguaje de programación. La Figura 1.1 muestra el uso de subs, skeletons y ORB para realizar una invocación remota. Las interfaces con los componentes de ORB son especificados en IDL.

Figura 1.1. Invocación remota a través de ORB.

Finalmente, destacamos los protolos de transmisión utilizados por CORBA. CORBA define tres protocolos por capas para enviar mensajes entre clientes y objetos: (a) Common Data Representation (CDR), (b) General Inter-ORB protocol (GIOP), que incluye CDR y además especifica formatos de mensajes GIOP y ciertas asunciones sobre el transporte, e (c) IIOP (Internet Inter-ORB Protocol), que especializa GIOP para TCP/IP, especificando como los agentes abren conexiones y las usan para transferencias GIOP de mensajes.

1.1. Modelo de objetos

El OMA (Core Object Model) proporciona algunas definiciones fundamentales de conceptos que son extendidos por la especificación CORBA.

En primer lugar, es necesario distinguir entre servants y referencias a objetos. El primero es una entidad del lenguaje de programación que contiene código que implementa las operaciones definidas por una definición de interfaz IDL (por ejemplo un objeto Java), proporcionando la semántica de uno o más objetos CORBA. La segunda es una identidad de objeto que es usada por los clientes para invocar operaciones sobre el objeto. Es importante no pensar en un servant como un objeto CORBA, debido a que un objeto CORBA puede ser representado como diferentes servants durante su ciclo de vida.

Un código servant, la implementación del objeto, es la parte de un objeto CORBA proporcionada por el desarrollador de la aplicación. Suele incluir un estado interno, y a menudo causa efectos laterales en elementos que no son objetos, tales como una base de datos, la pantalla, o un elemento de la red de telecomunicaciones. Los métodos de esta implementación pueden ser accedidos por cualquier mecanismo, pero en la práctica muchos servants serán invocados mediante el código skeleton generado por un compilador IDL.

Las referencias de objetos son manejadores de los objetos. Una rerencia de objetos denotará siempre a un único objeto, pero varias referencias distintas de objetos pueden denotar el mismo objeto. Las referencias de objetos son "opacas" para sus usuarios. Es decir, contienen suficiente información para el ORB para enviar una petición al correspondiente servant, pero esta información es inaccesible para sus usuarios. Las referencias de objetos contienen información sobe la localización y tipo del objeto denotado, pero lo hacen de forma que si el objeto ha migrado, o ya no está activo, el ORB puede realizar las tareas necesarias para redirigir la petición a un nuevo lugar o activar a un objeto para recibir la petición.

A menos que un objeto sea explícitamente destruido, o la red subyacente o infraestructura del sistema operativo no funcione bien, el ORB debería ser capaz de transmitir una invocación de operación y transmitir el resultado.

Con respecto a los tipos de objetos, éstos están relacionados en una jerarquía de herencia, con el tipo Object como raíz. Se definen tipos básicos numéricos, string y boolean. También se define un tipo any como tipo básico, el cual puede almacenar cualquier valor.

1.2. Estructura ORB

Los compiladores IDL usan la definición de interfaces para crear los mecanismos mediante los cuales un cliente puede invocar una función local, que se ejecutará sobre un objeto en otra máquina. El código generado por el cliente se denomina stub, y el código generado por la implementación del objeto se denomina skeleton. La figura 1.2 muestra el núcleo ORB, los códigos stub y skeleton, y los interfaces con ORB.

Figura 1.2. Arquitectura CORBA.

Una vez linkados los códigos stub y skeleton, con las implementaciones correspondientes del cliente y del objeto remoto, el soporte de ejecución (run-tyme-system) de ORB transporta las peticiones y resultados como invocaciones estáticas. Estáticas significa que la IDL es estáticamente definida en tiempo de compilación, y solamente las operaciones sobre tipos conocidos de interfaz pueden ser invocadas.

El estándar CORBA también define un interfaz que permite construir las peticiones desde un cliente de forma dinámica. Esto se conoce como Dynamic Invocation Interface (DII). Se define una interfaz simétrica para responder a peticiones arbitrarias denominada Dynamic Skeleton Interface (DSI).

CORBA define una interfaz para la comunicación con ORB, tanto desde el sevidor como desde el cliente. Esta interfaz trata principalmente con la inicialización de ORB y la manipulación de referencias de objetos.

Finalmente, las implementaciones de objetos necesitan facilidades extra para manejar sus interacciones con ORB. Un componente llamado Object Adapter realiza este papel y es responsable de la búsqueda y potencial activación de implementaciones para ejecutar las operaciones. Actualmente CORBA define un Object Adapter denominado POA (Portable Object Adapter).

Además de responsabilizarse de proporcionar las facilidades para la creación y transmisión de mensajes de petición y de respuestas entre clientes y objetos, ORB proporciona funcionalidades para el cliente y el objeto en cuanto a manipulación de referencias a objetos remotos y uso de servicios necesarios. ORB se implementa normalmente como un conjunto de librerías (o paquetes) incluidos con cada aplicación cliente y servidor. Además, algunas implementaciones ORB incluyen procesos "demonio" usados para localización de objetos y/o lanzamiento de procesos servidores remotos. Una de las propiedades más importantes de un producto ORB es el nivel de cumplimiento con la especificación CORBA que proporciona. Este nivel de cumplimiento garantiza la funcionalidad que ofrece ORB.

1.3. IDL

IDL es un lenguaje declarativo para la definición de interfaces de objetos CORBA. Es una forma independiente del lenguaje en la que los programadores y los usuarios de los objetos pueden estar seguros de que se invoca a la operación correcta del objeto correcto, aunque la única información adicional que se necesita es la referencia al objeto.

IDL genera código stub y/o skeleton que convierten estructuras de datos en memoria en un lenguaje de programación en flujos de datos que son enviados por la red, posteriormente los "desempaqueta" en otra máquina en estructuras de datos equivalentes en otro (o el mismo) lenguaje, realiza la llamada al método, y transmite los resultados en dirección contraria.

La sintaxis de IDL se toma de C++, pero contiene palabras clave diferentes. No hay sentencias de programación, y su único propósito es definir signaturas del lenguaje. Para hacer esto se utilizan un cierto número de construcciones: constantes, declaraciones de tipos de datos, atributos, operaciones, interfaces, valuetypes y módulos. Todas las declaraciones hechas en IDL pueden estar disponibles a través del Repositorio de Interfaz (IR: Interfaz Repository).

Las interfaces agrupan tipos de datos, atributos y declaraciones de operaciones.

Los valuetypes agrupan tipos de datos, estados (describen un estado accesible para un cliente), y declaraciones de operaciones. Las instancias de valuetypes son siempre implementaciones locales y, a diferencia de los objetos, se pasan por valor en las invocaciones de las operaciones.

Los módulos se utilizan para separar espacios de nombres.

1.4. POA

POA (Portable Object Adapter) proporciona un conjunto de interfaces para el manejo de referencias y servants. El código escrito usando las interfaces POA son portables a través de las implementaciones ORB y tienen la misma semántica en cada ORB que cumple las especificaciones de CORBA 2.2 o superior.

POA define interfaces estándar para realizar lo siguiente:

El propósito de POA es desviar peticiciones de invocación entrantes al servant correcto (ver Figura 1.3). Para realizar esta tarea se utilizan políticas determinadas por el programador del servidor CORBA. Puede haber más de un POA activo en un servidor particular. Sin embargo, siempre hay una raiz, a partir de la cual el resto de POAs son creados. Cada POA tiene un nombre relativo al POA en el cual fue creado, y una operación de búsqueda definida para permitir la localización y activación de POAs por sus padres. Un POA puede tener un Default Servant Manager al que van redirigidos todas las peticiones a objetos cuyos IDs no se encuentran en el Active Object Map (tabla de asociaciones entre identificadores de objetos y servants mantenidas por el POA).

Figura 1.3. Arquitectura POA.

Cada POA tiene asociado una combinación específica de valores de políticas que no pueden ser modificadas después de que éste es creado. Desde un punto de vista de gestión, las instancias POA pueden verse como dominios de políticas: todos los objetos manejados por un POA están sujetos a la misma combinación de políticas. La razón de peritir varios POAs en un mismo servidor es simplemente permitir a un servidor contener varios objetos con diferentes políticas.

Las políticas de CORBA se dividen en varias categorías:

Una interfaz IDL puede compilarse utilizando un complador IDL para generar los stubs en el cliente y los skeletons en el servidor, en un determinado lenguaje de programación. El uso de diferentes compiladores IDL para diferentes lenguajes, junto con las interfaces definidas en IDL, permite que los clientes escriban en un lenguaje de programación para acceder a objetos escritos en otro lenguaje diferente.

1.5. Interoperabilidad

La especificación de CORBA tiene una sección llamada interoperabilidad, que hace referencia al hecho de que diferentes clientes y objetos ejecutándose en diferentes ORBs de distintos vendedores pueden comunicarse como si estuviesen en el mismo ORB.

La arquitectura ORB contiene definiciones de dominios ORB, bridges (mecanismos para permitir el trasvase entre protocolos), y referencias a objetos interoperables (Interoperable objects references: IORs). Define los dominios como "islas", dentro de las cuales los objetos son accesibles debido al uso de los mismos protocolos de comunicación, la misma seguridad, y el mismo modo de identificar a los objetos. Para establecer la interoperabilidad entre dominios, uno de estos elementos debe ser reemplazado con un elemento común, o se debe fijar un bridge para facilitar la conversión del protocolo, identidad o autoridad entre dominios.

Se identifican elementos que pueden usarse como representaciones comunes (formas canónicas) entre diferentes dominios y se sugieren los mecanismos con los que los dominios ORB pueden crear bridges para que puedan comunicarse a través de dichas representaciones. Se define un formato de referencia de objetos como parte de la arquitectura. Un IOR contiene la misma información que una referencia a un objeto del dominio, pero añade una lista de perfiles de protocolos, indicando con qué protocolos el dominio del origen puede aceptar peticiones. La interoperabilidad del protocolo se trata como un componente separado denominado General Inter ORB Protocol (GIOP).

1.6. Ejecución de una invocación de un objeto CORBA

Cuando un cliente quiere invocar métodos sobre el objeto remoto, primero obtiene una referencia interoperable al objeto (IOR), o simplemente, una referencia al objeto remoto. La referencia al objeto se representará en el cliente como un objeto local (una instancia de una clase en el lenguaje de programación del cliente), conteniendo datos usados por el ORB para localizar el objeto remoto en la red. Los datos dentro de la referencia al objeto se consideran opacos, lo que significa que su formato y valor no son importantes en el nivel código de aplicación del cliente. Los contenidos reales y formato de los datos del objeto referenciado se definen por el OMG en la especificación de CORBA/IIOP para asegurar que una referencia al objeto sea interoperable, significando que una IOR puede usarse para acceder al objeto remoto desde cualquier marco ORB, sin tener en cuenta dónde se creó dicho IOR. El tipo real de la referencia al objeto se define en el lenguaje de programación del cliente dentro del stub IDL del cliente.

Puede ser útil pensar en una referencia al objeto como en un objeto proxy del objeto remoto. Una vez obtenido, la aplicación cliente puede invocar métodos de la referencia al objeto como si fuese el objeto real: