Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Extensión Del Estándar de para Proveer Servicios de Estado Persistente Con Acceso Remoto Análisis, Diseño e Implementación
Extensión Del Estándar de para Proveer Servicios de Estado Persistente Con Acceso Remoto Análisis, Diseño e Implementación
Pablo M. Ilardi
INFORMACIN DE CONTACTO
PABLO MAXIMILIANO ILARDI: PILARDI@FI.UBA.AR O PILARDI@GMAIL.COM
MARA FELDGEN: MFELDGEN@IEEE .ORG O MARIA.FELDGEN@GMAIL.COM
Abstract
Pablo M. Ilardi
RESUMEN
Muchas de las aplicaciones distribuidas tienen requerimientos de persistencia y se encuentran
desarrolladas en lenguajes de programacin orientados a objetos (POO) tales como Java. Una de las
arquitecturas, CORBA de OMG, define un estndar de persistencia denominado
(PSS), siendo una de sus alternativas con un lenguaje PSDL. En este trabajo se analiz el estado
del arte de la persistencia, en particular en el marco de las aplicaciones CORBA desarrolladas en
lenguaje Java y la especificacin del servicio PSS. Para estas aplicaciones, se dise y construy un
servicio de estado persistente, junto con un compilador de lenguaje PSDL. Este servicio, adems de la
persistencia, permite compartir objetos persistentes entre servants ubicados en distintas mquinas o
procesos, caracterstica que no est prevista en la especificacin PSS de CORBA. El compilador y el
servicio construidos se caracterizan por ser extensibles y configurables, soportando distintas formas de
lograr persistencia. Finalmente, los resultados obtenidos fueron comparados con otros servicios PSS.
Palabras clave: Persistencia, OMG, CORBA, Servicio, POO, Java, PSS, PSDL, Compilador, Servant,
Conector, OODB
ABSTRACT
A large number of distributed applications require persistence. Many of these applications are
developed using object oriented programming languages (OOP) like Java. The OMG CORBA
architecture defines the
(PSS) as a standard for persistence. One of the options
is using a language PSDL. In this work, the state of art of persistence was analyzed specifically in the
context of CORBA applications developed in Java, altogether with the PSS specification itself. For these
applications, a persistent state service with a PSDL language compiler was designed and built. The
service includes in addition of persistence, the sharing of persistent objects with servants existing in
different machines or processes, a feature which is not provided by the PSS specification. The built
compiler and service are characterized for being extensible and configurable, supporting different ways
for persisting objects. Finally, the works results were compared to other existing PSS services.
Keywords: Persistence, OMG, CORBA, Service, POO, Java, PSS, PSDL, Compiler, Servant, Connector,
OODB
Pablo M. Ilardi
CONTENIDO
Introduccin ................................................................................................................... 9
Introduccin a POO - Programacin Orientada a Objetos ............................................ 13
Introduccin a CORBA................................................................................................... 21
Servicio de Estado Persistente CORBA - PSS ................................................................. 31
Implementacin del servicio de estado persistente CORBA - PSS................................. 47
Comparacin con otras implementaciones del servicio de estado persistente de
CORBA ........................................................................................................................ 121
Trabajos adicionales ................................................................................................... 131
ndice de Grficos ....................................................................................................... 133
Glosario ...................................................................................................................... 135
Pablo M. Ilardi
INTRODUCCIN
os juegos, sistemas de bases de datos distribuidas, multimedia, aplicaciones grficas y los sistemas
distribuidos en general, almacenan informacin que requiere persistencia. La mayora de los
sistemas de informacin, requieren de algn soporte para mantener su estado en forma
persistente. Persistencia en la programacin orientada a objetos (POO), significa almacenar los objetos y
por consiguiente el valor de sus atributos para uso futuro.
El soporte de persistencia no es trivial, ya que la representacin de un objeto en memoria puede
variar en tamao y estructura de una plataforma a otra. Adems, no est soportado en forma nativa por
todos los lenguajes de programacin (por ejemplo, C++), plataformas de desarrollo y sistemas operativos.
Por consiguiente, es necesario el uso de frameworks, como por ejemplo, CORBA, para su
implementacin.
CORBA (Common Object Request Broker Architecture) o
[CR01] es la propuesta del OMG (Object Management Group) para la construccin de
software interoperable, portable y reusable. OMG define una arquitectura de software detallada, que
consta de interfases claramente definidas. Esta arquitectura, llamada OMA (Object Management
Architecture) [OM0], est dividida en dos modelos fundamentales. El primero, llamado
(
), permite el desarrollo de aplicaciones distribuidas basadas en un
u ORB (Object Request Broker). El segundo modelo, llamado
(
), define un marco para el desarrollo de las aplicaciones junto a un conjunto de
interfases estandarizadas llamadas
( ) que utilizan la ORB.
Uno de los servicios que CORBA provee, tiene el objeto de facilitar y unificar la forma de hacer
persistentes a los objetos utilizados por los servants [CRO1], por medio de una interfase comn para el
manejo de persistencia. Los servants son aquellos objetos que estn bajo el control de la ORB. Todo
servant tiene una interfase definida en lenguaje IDL (Interface Definition Language o
y puede ser accedido en forma remota por medio de los mecanismos que la ORB
provee a tal fin.
El servicio de CORBA que da soporte de persistencia de objetos se denomina:
!
Pablo M. Ilardi
Para usar el lenguaje PSDL se requiere de un compilador que traduzca las definiciones PSDL en
las definiciones del lenguaje de programacin que se utiliza. En cambio, la persistencia transparente,
permite persistir objetos directamente en el lenguaje nativo, pero a costa de perder muchas
funcionalidades que solo estn disponibles en las definiciones PSDL.
Si bien PSS es un estndar cuya ltima revisin es del ao 2002, no existen muchas
implementaciones del mismo, dado que no se trata de una de las especificaciones ms difundidas.
El problema a resolver es: Cmo hacer uso de objetos que requieran estado persistente en
CORBA? Se deben analizar las soluciones existentes, viendo que alternativas son viables de construir. Las
especificaciones son ambiguas en algunas definiciones, en las cuales se pierde la idea de interfase de
servicio CORBA. En particular, sucede cuando se trata de soportar dos modelos de persistencia, como lo
son el transparente y el de definicin por PSDL, por medio de una misma interfase de servicio.
Sin embargo, la construccin de un servicio siguiendo la especificacin PSS se plantea como una
idea atractiva y desafiante. Es atractiva, porque permite tener una interfase o modelo estndar para
solucionar este problema no trivial, lo cual es algo muy til y valioso. Es desafiante, porque se trata de un
problema complejo con muchos matices a considerar, tales como la construccin de un compilador del
lenguaje PSDL, proveer persistencia transparente sin uso de un lenguaje nuevo, definir dnde y cmo
almacenar el estado que define a los objetos utilizando una base de datos u otro medio, evaluar cmo se
podra extender el servicio para que soporte el acceso remoto de los objetos almacenados, no
contemplado en el estndar actual, etc.
OBJETIVOS
Se realiz un estudio del estado del arte de la persistencia en objetos, focalizado principalmente
en CORBA y el lenguaje de programacin Java.
Se realiz un anlisis de la especificacin del servicio de estado persistente (PSS) CORBA,
evaluando sus posibles usos, ventajas y desventajas. Se analizaron las distintas alternativas que plantea el
estndar, considerando los beneficios y las desventajas de la . Se evaluaron las
diferentes estrategias a seguir frente a ambigedades en las definiciones. Se evaluaron las distintas
herramientas que pueden utilizarse para mantener el estado persistente, y su posible uso en un servicio
de persistencia.
Se dise y construy un servicio de persistencia, que soporta el estndar CORBA, utilizando el
lenguaje de programacin Java y patrones de diseo adecuados para este fin [GA0]. Se provey de un
mecanismo bsico que permite a dos o ms servants acceder en forma remota a un repositorio definido
en otra mquina, pudiendo as acceder a objetos almacenados definidos por otros servants, extendiendo
el servicio que propone el estndar. El servicio de persistencia que se construy, soporta definiciones
PSDL, junto con las funcionalidades que este lenguaje provee. Para ello, fue necesaria la construccin de
un compilador [CooperRice00] PSDL que genera cdigo Java que es compatible con el servicio construido.
Finalmente, se realiz una comparacin entre otras implementaciones del servicio de
persistencia de CORBA y la construida.
10
Pablo M. Ilardi
2. A NLISIS
Se realiz un anlisis completo de la especificacin del servicio de estado persistente de CORBA.
Se evalu el aporte del servicio al desarrollo de aplicaciones CORBA, valorizando sus beneficios y
desventajas. Se analizaron los requerimientos para la construccin de un servicio CORBA que cumple con
este estndar y permite compartir un repositorio por ms de una ORB. Se consideraron las diferentes
herramientas, lenguajes de programacin y que podran utilizarse en la construccin. Esta
etapa defini los requerimientos del servicio a construir.
3. D ISEO
En esta etapa se dise una solucin que cumple con los requerimientos relevados durante la
etapa de anlisis. Esta solucin incluye el diseo de un compilador de lenguaje PSDL a Java, y varios
conectores para el servicio. El diseo obtenido es lo suficientemente amplio, como para permitir futuras
extensiones al servicio en forma de nuevos conectores para distintos tipos de repositorios, tales como
archivos o bases de datos relacionales. La solucin tambin contempla el soporte para su funcionamiento
en distintas ORBs y no slo para una en particular. El diseo hace uso de distintos patrones de diseo
adecuados para resolver los problemas que se presentaron.
4. C ONSTRUCCIN
En esta etapa se construyeron los artefactos definidos en la etapa de diseo. La construccin se
realiz en forma incremental, y se proveyeron pruebas unitarias que permiten futuras extensiones al
servicio con otros conectores. Esta forma de construccin se realiz en dos iteraciones entre la etapa de
diseo y construccin, focalizando la primera en el compilador y las herramientas. Entre los artefactos
construidos se encuentran el compilador y el conector que permite compartir repositorios entre distintas
ORBs. Tambin se construyeron herramientas para la generacin de cdigo y junto con sus respectivas
pruebas unitarias.
11
Pablo M. Ilardi
REFERENCIAS
. Third Edition June 13, 1995. Richard Mark Soley,
OM0
Ph.D. (ed.) Christopher M. Stone
BM0
629155-4.
OMG.
CR01
http://www.omg.org/technology/documents/corba_spec_catalog.htm
PS0 Persistent State Service, V2.0 OMG 2002. http://www.omg.org/cgi-bin/doc?formal/02-09-06
GA0 Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley
Professional Computing Series - by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides,
January 15, 1995.
BgVaDk Java Programming with CORBA, Advanced Techniques for Building Distributed
Applications, 3rd Edition Gerald Brose, Andreas Vogel, Keith Duddy, Wiley 2001.
TS01 Transaction Service Specification, OMG 2003.
http://www.omg.org/technology/documents/corbaservices_spec_catalog.htm
EisenbergMelton01 SQL: 1999, formerly known as SQL3. Andrew Eisenberg, Sybase, Concord,
MA 01742 andrew.eisenberg@sybase.com; Jim Melton Sandy UT 84093 jim.melton@acm.org
Ramakanth01 Object-Relational Database Systems - The Road Ahead; Ramakanth S.
Devarakonda; http://www.acm.org/crossroads/xrds7-3/ordbms.html
CooperRice00 Engineering A Compiler, Keith Cooper - Rice University, Houston, Texas; Linda
Torczon - Rice University, Houston, Texas. http://www.cs.rice.edu/~keith/
12
Pablo M. Ilardi
13
14
Pablo M. Ilardi
ELEMENTOS PRINCIPALES
Todo lenguaje que se base en POO debe proveer de algunas herramientas o construcciones
bsicas como son las: clases, objetos, mtodos, mensajes y atributos.
CLASE
Una clase define o modela las caractersticas de una cosa. Las caractersticas incluyen los
atributos o propiedades junto con su comportamiento (mtodos). El tpico ejemplo es el de un Animal, el
cual tiene propiedades tales como: edad, ubicacin, forma de alimentacin, etc. su comportamiento
podra estar definido por: alimentarse, dormir, procrear, etc.
OBJETO
Un objeto es un individuo de una clase. Los individuos en POO se denominan instancias. En el
ejemplo de los animales un objeto seria un Animal concreto, por ejemplo, un animal en el zoolgico, que
tiene un estado determinado, como por ejemplo, 2 aos de vida.
ATRIBUTO
Un atributo de una clase es anlogo a una variable en la programacin estructurada, con la
diferencia del contexto donde se define. Los atributos son accesibles desde una instancia de una clase u
objeto, mientras que las variables son accesibles desde el contexto en el que se definieron. En la
programacin ms estricta todo es un objeto, o sea un entero o un string es un objeto. Los atributos son
tipados. Se puede tener un atributo de tipo Animal y otro de tipo Entero, o un atributo de tipo Objeto,
que podra referenciar tanto una instancia de un Animal como de un Entero. Los valores de los atributos
de una instancia de un objeto determinan su estado.
15
Pablo M. Ilardi
MTODO
Los mtodos de POO son anlogos a las funciones de programacin estructurada. La diferencia
fundamental es que las funciones o procedimientos se ejecutan en un contexto global, mientras que los
mtodos se ejecutan en el contexto del objeto en el cual se llam al mtodo. Se dice que el conjunto de
mtodos de un objeto determinan su comportamiento.
MENSAJE
Se entiende por mensaje, a la invocacin a un mtodo de un objeto. Esta invocacin se realiza
con los parmetros aceptados por el mtodo. El mensaje es el equivalente a una llamada a una funcin en
el paradigma estructurado.
CARACTERSTICAS:
La POO se basa en cuatro caractersticas: Encapsulamiento, Herencia, Abstraccin y
Polimorfismo.
ENCAPSULAMIENTO
El encapsulamiento es una forma de ocultar y agrupar informacin de forma tal de unificar el
acceso a la misma. El encapsulamiento es generalmente equiparado a ocultamiento de la informacin.
Segn [BM0]:
Debiera ser posible para el autor de una clase especificar los atributos que estarn disponibles
para todos, ninguno o algunos de los clientes de la clase.
Pero ocultar informacin, no se refiere solamente a los aspectos fsicos de la misma. Por
ejemplo, que una clase Lista utilice un array para almacenar sus elementos no debiera ser visible para un
usuario de esta clase. Los usuarios de la clase debieran acceder a los elementos de una Lista por medio
las operaciones de la misma, por ejemplo: obtenerElementoX. Esto garantiza que los clientes de las clases
se comuniquen por medio de su interfase o contrato sin depender de la implementacin de la misma.
HERENCIA
La herencia es una caracterstica que permite agrupar funcionalidades comunes en lugares
comunes, es la forma ms natural de reutilizacin en POO. Al igual que en el mundo real, la herencia
refleja que una clase hereda de otra. En POO las clases pueden heredar de otras clases sus caractersticas
y comportamiento. Por ejemplo, en la familia de los animales, algunos son de tipo carnvoro y otros de
tipo herbvoro. Una forma de herencia se podra definir como que las clases Carnvoro y Herbvoro
heredan de la clase Animal. Esto implica que ambas tiene las mismas caractersticas que cualquier animal
como la edad, peso, etc. pero adems cada una tiene sus caractersticas propias, por ejemplo, un
Carnvoro se alimenta de distinta forma que un Herbvoro.
Existen dos tipos distintos de herencia: la herencia simple y la herencia mltiple. La primera,
implica que una clase solo puede heredar a lo sumo de una nica clase, mientras que la segunda, permite
que una clase pueda heredar de ms de una clase al mismo tiempo. No todos los lenguajes de
programacin soportan el segundo tipo de herencia, por ejemplo, C++ la soporta y Java no lo hace.
La herencia incluye un nuevo concepto llamado redefinicin. Bsicamente significa que una clase
hija puede redefinir una caracterstica de la clase padre, por ejemplo un atributo o un mtodo.
ABSTRACCIN
La abstraccin permite que dos objetos sean tratados de forma uniforme sin que importe cual
clase sea. Por ejemplo, dos animales, uno Carnvoro y otro Herbvoro como un Perro y un Caballo, pueden
16
Pablo M. Ilardi
interpretar un mensaje como dormir. Para quien enva el mensaje dormir, es indistinto si es un Perro o un
Caballo el que lo recibe.
POLIMORFISMO
El polimorfismo es una de las caractersticas esenciales de POO y est muy asociada a la
redefinicin y a la abstraccin. Cuando un Animal recibe el mensaje alimentarse, que debe hacer,
depende bsicamente del tipo de Animal. Los Carnvoros consumirn carne y los Herbvoros vegetales.
Desde el punto de vista del cliente o usuario de una clase de tipo Animal, el mensaje enviado es el mismo,
pero los resultados son muy distintos.
La forma de conseguir un comportamiento similar en programacin estructurada, sera mediante
una condicin. Por ejemplo, se tiene la funcin alimentar(animal, alimento): dentro del cdigo fuente de
la funcin se debe preguntar si animal es carnvoro alimentar_carne() sino alimentar_vegetal(). Mientras
que en objetos slo sera necesario escribir: animal.alimentar(alimento). El polimorfismo es la propiedad
que permite que un objeto, dado un mismo mensaje responda de manera distinta en funcin del tipo de
objeto.
CICLO DE VIDA
Para utilizar una instancia de una clase es necesario tener una referencia al objeto, o construir
una instancia de la misma. Para construir una instancia de una clase, se utilizan mtodos especiales de las
clases llamados constructores. Todo constructor devuelve como resultado una instancia de la clase
donde est definido. Cuando la instancia es creada se dice que es referenciada por la variable a la que se
asign. Una vez creada la instancia de la clase, ya est lista para ser utilizada mediante sus mtodos y
atributos.
Toda instancia que est creada ocupa un espacio en memoria. La forma de liberar este espacio
depende principalmente del lenguaje de programacin utilizado. Cuando se libera esta memoria, se dice
que es el objeto se destruye.
Los primeros lenguajes de POO requeran que el usuario de los mismos se encargara de alocar y
liberar la memoria utilizada por las instancias de los objetos. Por ejemplo, en C++ es necesario llamar
explcitamente al operador delete para liberar la memoria que el objeto utiliza. Algunos lenguajes ms
modernos, liberan la memoria que utilizan los objetos de forma automtica, este es el caso de Java, o C#.
PERSISTENCIA
Muchas aplicaciones desarrolladas utilizando POO requieren mantener los objetos utilizados
entre distintas sesiones o ejecuciones de la aplicacin. Los objetos que deben ser compartidos entre
distintas sesiones se dicen que son Persistentes, mientras que los que no lo son se dice que son
Transientes. Los objetos no pueden ser mantenidos en memoria entre distintas sesiones, ya que la
memoria es liberada cada vez que se cierre la aplicacin donde se utilizan los objetos. Es necesario
almacenar los objetos en algn repositorio permanente.
Si el estado de un objeto est definido por el valor de sus atributos, se puede asumir que para
recuperar un objeto de un repositorio permanente, es suficiente con almacenar los valores de sus
atributos. Pero esto no es suficiente cuando estos atributos son otros objetos con sus propios atributos o
cuando estos atributos referencian a otros objetos que pueden referenciar al objeto inicial que se quera
presistir. Los objetos en memoria pueden constituir un grafo de dependencias complejo que puede incluir
ciclos definidos por referencias cruzadas. Un mecanismo de persitencia que pueda almacenar en forma
automtica el objeto junto con estas dependecinas cruzadas, se dice que soporta persistence closure o
persitencia cerrada [BM0].
17
Pablo M. Ilardi
Cuando los objetos necesitan ser compartidos entre distintas sesiones, y adems ser
compartidos entre distintas aplicaciones, se agrega la necesidad de la existencia de una bases de datos u
objetos. Las bases de datos pueden ser de tipo relacional (RDBMS) que require un mecanismo de
traduccin entre el modelo de objetos y el modelo relacional, o pueden ser sistemas de bases de datos
orientadas a objetos (OODBS) que soportan los objetos en forma nativa.
Algunos mecanismos de persitencia proveen soluciones para la evolucin del esquema [BM0]. La
evolucin del esquema se aplica cuando se modifica una clase y para dicha clases ya existen instancias de
objetos con la estructura original de la clase almacenadas en un repositorio. Cuando se recuperan dichas
intancias puede ocurrir que ya no est disponible la clase original y no sea posible recuperarla con la
nueva clase ya que no existe algn atributo de la misma. A este problema se lo denomina object
mismatch o incompatibilidad de objeto. La incompatibilidad de objetos no ocurre solamente cuando se
recupera un objeto de un repositorio donde persiste, tambin puede ocurrir cuando se transmite un
objeto por la red, y el receptor del mismo posee una versin distinta de la clase a la que pertenece el
objeto transmitido.
La persistencia de los objetos no est ligada directamente a la POO, cada lenguaje puede proveer
o no, herramientas que permitan la persistencia de los objetos utilizados.
JAVA
Java es un lenguaje de programacin orientado a objetos cuya sintaxis deriva de C y C++, pero
que provee un modelo de objetos ms simple que C++. Java fue creado por James Gosling [JavaTech01] y
por la empresa SUN en el ao 1995, como parte de una plataforma llamada Java Virtual Machine o
Mquina Virtual Java. Desde entonces ha evolucionado hasta su versin 6. La mquina virtual permite
que un programa escrito y compilado en Java pueda ejecutarse en cualquier sistema operativo y
arquitectura sin ser modificado. El sistema operativo requiere tener una implementacin de la mquina
virtual instalada. Java se compila en cdigo de bytes o bytecode, y no en cdigo binario. El bytecode es la
representacin interna que entiende la mquina virtual, y es lo que permite la independencia de
arquitectura y sistema operativo.
Una de las caractersticas principales de Java y que lo diferencian fundamentalmente de C++, es
el manejo de memoria. Java provee manejo automtico de memoria, lo que implica que el programador
no debe encargarse de pedir y liberar la memoria necesaria para la creacin y destruccin de los objetos.
Esta caracterstica se implementa por medio de automatic garbage collection o recoleccin automtica
de basura [HoskingMoss01]. Este mecanismo permite que un objeto sea eliminado cuando no existan
referencias accesibles a l desde los objetos activos. La mquina virtual es la encargada de llevar el
control de las referencias a los objetos y de administrar la memoria utilizada.
Existen algunas otras diferencias importantes con C++ [TateB01]. Java no permite herencia
mltiple de clases, aunque si permite herencia mltiple de interfases. Las interfases son definiciones de
comportamientos que pueden tener o implementar las clases, pero sin su implementacin. Son anlogas
a las clases abstractas con todos sus mtodos abstractos de C++. En Java todos los mtodos son
potencialmente polimrficos, mientras que en C++, un mtodo debe ser declarado virtual para que pueda
comportarse en forma polimrfica. Java no posee destructores ni operadores redefinibles por el
programador. En Java las clases son definidas en paquetes y un paquete puede contener mltiples clases
y sub paquetes.
PATRONES DE DISEO
El diseo de sistemas en lenguajes orientados a objetos no es una tarea simple, se deben
considerar mltiples factores que permitan reutilizacin, bajo acoplamiento y alta cohesin de las clases
que conformen el sistema.
18
Pablo M. Ilardi
Generalmente, el mejor diseo no se obtiene en un solo paso, sino a travs de iteraciones que lo
refinen. Cuando se plantea disear una solucin a un problema, se trata de reutilizar soluciones
anteriores buscando analogas a otros problemas similares. Muchos de los problemas que se plantean al
realizar un diseo, fueron afrontados por otros diseos anteriores de la misma u otras personas. Las
soluciones a estos problemas recurrentes siguen patrones de comunicacin y estructuras de clases
comunes.
Estos patrones son los llamados Design Patterns o Patrones de Diseo que permiten reutilizar
diseos y arquitecturas exitosas. Un patrn de diseo fue definido por Erich Gamma [GA01] como:
Un patrn de diseo nombra, motiva y explica en forma sistemtica un diseo general que
soluciona un problema recurrente en sistemas orientados a objetos. Describe el problema, da su solucin,
y define cuando es aplicable, determinando las consecuencias de la solucin. Tambin da ejemplos y
lineamientos para su implementacin. La solucin es un esquema general de objetos y clases que
solucionan el problema. La solucin se debe adaptar e implementar para resolver el problema en el
contexto particular.
Los patrones de diseo se popularizaron a partir de la tesis doctoral de Erich Gamma [GA02], que
luego fue ampliada con nuevos patrones y publicada en el libro Design Patterns: Elements of Reusable
Object-Oriented Software [GA01] o Patrones de Diseo: Elementos de Software Orientado a Objetos
Reutilizable.
Algunos de los patrones de diseo ms difundidos son: Abstract Factory, Adapter, Composite,
Decorator, Factory Method, Observer, Strategy, Template Method, etc.
19
Pablo M. Ilardi
REFERENCIAS
AD0 Armstrong, Deborah J. The Quarks of Object-Oriented Development. Communications of the
ACM 49 (February 2006): 123-128. ISSN 0001-0782.
BM0 Meyer, Bertrand. Object-Oriented Software Construction. Prentice Hall PTR, 1997, 2da
Edicin, ISBN 0136291554.
CO0 Software engineering: Report of a conference sponsored by the NATO Science Committee.
Peter Naur, Brian Randell (eds.) Garmisch, Germany, 711 October 1968, Brussels, Scientific Affairs
Division, NATO (1969).
HJ0 John Hunt. Samlltalk and Object Orientation: An Introduction. JayDee Technology Ltd,
Hartham Park Corsham, Wiltshire, SN13 0RP United Kingdom.
PD0 David Parnas, "On the Criteria to Be Used in Decomposing Systems Into Modules".
Communications of the ACM in December, 1972.
VRH0 Peter Van Roy, Seif Haridi, Concepts Techniques and Models of Computer Programming. The
MIT Press, Cambridge, Massachusetts. London, England 2004. ISBN 0-262-22069-5
JavaTech01
Java
Technology:
The
http://java.sun.com/features/1998/05/birthday.html
Early
Years",
by
Jon
Byous.
20
Introduccin a CORBA
Pablo M. Ilardi
INTRODUCCIN A CORBA
OMG y CORBA _______________________________________________________ 23
OMA _______________________________________________________________ 23
Object Services _____________________________________________________ 23
Common Facilities __________________________________________________ 23
Domain Interfases __________________________________________________ 24
Principios de Diseo en CORBA__________________________________________ 24
Caractersticas de CORBA ______________________________________________ 24
IDL Interface Definition Language ______________________________________ 24
Pasaje de Parmetros: _______________________________________________ 25
Mapeos de lenguajes (Language Mappings) ______________________________ 25
Invocacin de Operaciones y facilidades de despacho (dispatching) ___________ 25
Object Adapters (OA) ________________________________________________ 26
Protocolo Inter-ORB _________________________________________________ 26
Un request en CORBA _________________________________________________ 27
Object References __________________________________________________ 27
Adquisicin de OR ________________________________________________ 27
Proceso para la invocacin de un request ________________________________ 27
Las caractersticas de la invocacin _____________________________________ 27
Contenedor de Componentes CORBA ____________________________________ 28
Referencias _________________________________________________________ 29
21
22
Introduccin a CORBA
Pablo M. Ilardi
OMG Y CORBA
OMG (Object Management Group) o Grupo de Administracin de Objetos, es una organizacin o
consorcio internacional fundado en 1989 que trata de establecer los lineamientos y modelos para el
desarrollo de aplicaciones reusables, portables e interoperables en ambientes distribuidos heterogneos,
bajo un modelo de objetos e interfases claramente definidas. OMG ha recibido un gran apoyo de la
industria, transformndose en el consorcio de software ms grande del mundo.
CORBA (Common Object Request Broker Arquitecture) o Arquitectura Comn para el Agente de
Pedidos de Objetos [CR0] es el ncleo del modelo de arquitectura propuesto por OMG, llamado OMA.
OMA
Esta arquitectura, llamada OMA (Object Management Architecture) [OM0], est dividida en dos
modelos fundamentales. El primer modelo, llamado Modelo Central de Objetos (Core Object Model),
permite el desarrollo de aplicaciones distribuidas basadas en un Agente de Pedidos a Objetos u ORB
(Object Request Broker). Se trata de un modelo con definiciones abstractas que no poseen ninguna
implementacin y permiten interpretar el modelo de objetos e interfases. Este modelo fija las bases para
CORBA. Est enfocado en el diseo e implementacin de la ORB y no en la construccin de aplicaciones.
CORBA es una especializacin de los conceptos definidos en este modelo, llevando las definiciones
abstractas a construcciones concretas.
El segundo modelo, llamado Modelo de Referencia (Reference Model), define a la ORB junto a un
grupo de interfases estandarizadas, como el ncleo para la construccin de aplicaciones distribuidas.
Estas interfases son: los Servicios de Objetos (Object Services) [COS0], las Utilidades Comunes (Common
Facilities) [CCF0] y las Interfases de Dominio (Application Domain Interfases). El modelo de referencia es el
utilizado por los desarrolladores de aplicaciones.
OBJECT SERVICES
Los servicios de objetos (Object Services) son un conjunto de interfases de servicios y objetos que
soportan operaciones bsicas para la implementacin y utilizacin de objetos. Estos servicios permiten la
construccin de aplicaciones distribuidas independientes del dominio. Los servicios definen operaciones
genricas que se aplican a objetos de cualquier dominio, por ejemplo acceder a un objeto por algn
identificador. Existen servicios, tales como Naming Service o Trading Service, que proveen referencias a
objetos que permiten accederlos desde cualquier ubicacin. Algunos de los servicios de objetos son:
Naming Service [NS01], Persistence State Service [PSS01], Transaction Service [TSS01], etc.
COMMON FACILITIES
23
Introduccin a CORBA
Pablo M. Ilardi
Las utilidades comunes (Common Facilities), son tambin servicios u objetos, pero no esenciales
para la construccin de aplicaciones, como los servicios de objetos. Su existencia permite que diferentes
aplicaciones puedan beneficiarse compartindolos, sin tener que implementar su funcionalidad en cada
aplicacin. Un ejemplo de estas utilidades son los servicios para el manejo de correo electrnico.
DOMAIN INTERFASES
Las interfases de dominio corresponden a grupos de interfases generalizadas para dominios de
aplicacin particulares, tales como: telecomunicaciones, internet, salud, etc.
CARACTERSTICAS DE CORBA
La ORB se puede interpretar como un canal de comunicacin que transporta pedidos y
respuestas desde y hacia objetos en cualquier ubicacin, sin importar como estn implementados. La
nocin de transparencia es fundamental en CORBA. Un objeto puede ser invocado independientemente
de su ubicacin fsica, por medio de este canal. La transparencia tambin se aplica al lenguaje de
programacin. Se pueden realizar pedidos a objetos independientemente del lenguaje en el cual estn
implementados, por medio del lenguaje de definicin de interfases o IDL que es comn a todas las
implementaciones y usuarios.
24
Introduccin a CORBA
Pablo M. Ilardi
base del servidor o esqueleto (skeleton) de la misma, ya que el cuerpo de cada funcin en particular es lo
que se desarrolla a posteriori.
Cuando se comunican diferentes implementaciones de ORBs, no se pueden compartir los
archivos generados por el compilador IDL, ya que el cdigo que ste genera es propietario. No tiene
sentido hablar de compartir cdigo si se comunica una ORB que funciona con Java y otra con C++.
Mediante el uso del IDL, se puede llamar a una operacin definida en una interfase IDL, que est
implementada en un objeto programado en otro lenguaje y corriendo en otra ORB.
PASAJE DE PARMETROS:
La definicin de una operacin requiere que se especifique el modo de pasaje de sus
parmetros. Las formas permitidas son: in, out, e inout.
-
Dado que IDL, carece del concepto de punteros, tiene que existir una forma ms eficiente de
pasar por parmetro, estructuras ms complejas que un tipo de dato simple. Cuando se compila una
operacin de una interfase que recibe como parmetro a otra interfase, se pasa una referencia al objeto
que implemente este parmetro, lo que es anlogo a un puntero.
Invocacin esttica: se realiza mediante una llamada a los stubs generados por el compilador
IDL. El servant hereda o modifica el skeleton generado por el compilador IDL.
Invocacin dinmica: este mecanismo requiere la construccin del request en tiempo de
ejecucin. Dado que no se tiene informacin en tiempo de compilacin, la creacin e
interpretacin de los requests, requiere el acceso a los servicios que permitan obtener dicha
informacin. Este servicio puede estar implementado, por ejemplo, mediante la interrogacin a
un operador que brinde la informacin necesaria, o utilizando el Interfase Repository Service,
que es un servicio que provee acceso a interfases IDL en tiempo de ejecucin.
25
Introduccin a CORBA
Pablo M. Ilardi
PROTOCOLO INTER-ORB
Antes de CORBA 2.0, una de las principales desventajas que se le criticaban a CORBA, era la
inexistencia de una especificacin de protocolo para comunicar ORBs. Por ello, cada proveedor de ORB
deba definir el protocolo de red que usaba para comunicar la ORB. Lo que daba como resultado el
aislamiento de las distintas implementaciones de ORB, ya que cada una contaba con un protocolo
propietario.
En CORBA 2.0, se introdujo una arquitectura para la interoperabilidad de distintas
implementaciones de la ORB llamada General Inter-ORB Protocol (GIOP se pronuncia gee-op). GIOP es
un protocolo abstracto que define la sintaxis para la transmisin y el conjunto de formatos de mensajes
que permite a cualquier implementacin de ORB comunicarse sobre una capa de transporte orientada a
la conexin. Internet Inter-ORB Protocol (IIOP se pronuncia eye-op) especifica como GIOP se mapea
sobre TCP/IP.
Para la interoperabilidad de las ORBs se requiere un formato estndar de Object References. Este
formato se denomina Interoperable Object Reference (IOR), y es lo suficientemente flexible como para
permite almacenar cualquier tipo de IOP. Los IOR, identifican uno o ms protocolos soportados (IOPs).
Para cada protocolo, el paquete IOR contiene la informacin propietaria del mismo. En el caso de IIOP, el
26
Introduccin a CORBA
Pablo M. Ilardi
IOR contiene el nombre del host, el puerto TCP/IP, y una clave de objeto que identifica al objeto target,
para la combinacin host - puerto.
UN REQUEST EN CORBA
OBJECT REFERENCES
Las Object References (OR), son anlogas a los punteros a objetos de C++ o las referencias de
Java.
-
A DQUISICIN DE OR
La nica forma de acceder a un objeto CORBA es a travs de las OR. Cada servidor puede
publicar las ORs que contiene. La forma ms natural de adquirir una OR por un cliente es la de recibirla
como respuesta a una invocacin a un servicio. Otra forma es la de buscarla en un servicio como Naming
o Trading Service.
27
Introduccin a CORBA
-
Pablo M. Ilardi
28
Introduccin a CORBA
Pablo M. Ilardi
REFERENCIAS
Tanenbaum01 Distributed Operating Systems, Andrew, S. Tanenbaum, Practice-Hall Inc 1996.
ISBN 0-13-219908-4
TariBukhers01 Fundamentals of Distributed Object Systems, the CORBA Perspective, Zahir Tari,
Omran Bukhers, Willey Inc. 2001. ISBN 0-471-35198-9
CR0 Object Management Group, Common Object Request Broker Architecture, version 3.0.3,
OMG document number formal/04-03-01. http://www.omg.org/cgi-bin/doc?ptc/04-03-01
OM0 Richard Mark Soley, Object Management Architecture Guide, June 13, 1995, Ph.D. (ed.)
Christopher M. Stone
COS0 CORBAservices: Common Object Services Specification, Updated: November 1997.
ftp://ftp.omg.org/pub/docs/formal/98-07-05.pdf
CCF0 CORBAfacilities: Common Facilities Architecture.
ftp://ftp.omg.org/pub/docs/formal/97-06-08.pdf
NS01 Object Management Group, Naming Service Specification, version 1.1. February 2001.
OMG document number formal/01-02-65.
http://www.omg.org/cgi-bin/doc?formal/01-02-65
PSS01 Object Management Group, Persistent State Service, version 2.0. September 2002. OMG
document number formal/02-09-06.
http://www.omg.org/cgi-bin/doc?formal/02-09-06
TSS01 Object Management Group, Transaction Service Specification, version 1.4. September
2003. OMG document number formal/03-09-02.
http://www.omg.org/cgi-bin/doc?formal/03-09-02
IDJ0 - Object Management Group, Java to IDL Language Mapping Specification, version 1.3.
September 2003. OMG document number formal/03-09-04. http://www.omg.org/cgibin/doc?formal/03-09-04
GA0 Erich Gamma, Design Patterns: Elements of Reusable Object-Oriented Software, AddisonWesley Professional Computing Series, Richard Helm, Ralph Johnson, John Vlissides, January 15,
1995.
BgVaDk0 Gerald Brose, Andreas Vogel, Keith Duddy, Java Programming with CORBA, Advanced
Techniques for Building Distributed Applications, 3rd Edition, Wiley 2001.
HeVi0 Michi Henning, Steve Vinoski, Advanced CORBA Programming with C++. Addison Wesley.
February 12, 1999. ISBN: 0-201-37927-9
CCM01 CORBA Component Model Specification, OMG Available Specification Version 4.0
formal/06-04-01. http://www.omg.org/cgi-bin/doc?formal/06-04-01
29
30
Pablo M. Ilardi
31
32
Pablo M. Ilardi
n 1997 OMG cre un RFP (Request for Proposal) para la creacin de un servicio CORBA. Se trat de
un servicio de persistencia de objetos [PSS01]; Una RFP consiste en el llamado a entidades a
participar en la creacin de una nueva especificacin.
Servant
Cliente
ORB
Dominio de PSS
Objeto del
dominio
PSS
33
Pablo M. Ilardi
Almacen o Storage
Home
Objeto
Almacenado
Objeto
Almacenado
Objeto
Almacenado
Objeto
Almacenado
Dentro de un repositorio de datos pueden existir mltiples almacenes y a su vez dentro de los
almacenes pueden existir mltiples objetos almacenados. Conceptualmente, un repositorio de datos es
un conjunto de almacenes, cada almacn contiene objetos de un tipo definido dentro del repositorio.
Dentro del repositorio, un almacn es un Singleton [Gamma01], es decir que existe a lo sumo una nica
instancia de un almacn por tipo de objeto almacenado.
Los objetos almacenados se manipulan a travs de instancias de una clase definida en el lenguaje
de implementacin del programa o proceso que utilice el servicio. Estas instancias representan en un
momento dado un objeto existente en el repositorio de datos, mediante el cual se accede al estado
persistido. Las instancias de objetos que estn ligadas a un objeto en el repositorio se llaman
encarnaciones, al cambiar un atributo de una de estas instancias se est cambiando el estado del objeto
almacenado en el repositorio.
Los almacenes de objetos tambin son manipulados mediante instancias de los mismos. Estas
instancias son provistas por catlogos. Para acceder a las instancias de los objetos almacenados desde del
proceso o programa se requiere de una conexin con el repositorio de datos, denominada sesin. El
Grfico 3 define la relacin entre el modelo lgico y el modelo real de la aplicacin.
Programa o Proceso
Catlogo
Almacenes o
Storage Homes
Instancia de
Almacen
Encarnaciones
Objetos
Almacenados
Instancia de
Almacen
sesin
Objetos
Almacenados
Encarnaciones
Muchos de los conceptos existentes en PSS, fueron tomados del estndar SQL3 o SQL 1999
[EisenbergMelton01]. SQL3 fue una extensin propuesta al estndar SQL en el ao 1999, que agrega
conceptos de los lenguajes de programacin orientados a objetos. Las bases de datos que lo soportan son
llamadas Object-Relational DBMS u ORDBMS [Ramakanth01]. Las tablas en SQL3 permiten tipos de datos
34
Pablo M. Ilardi
ms ricos llamados ADT (Abstract Data Type) que soportan herencia. Los almacenes de PSS son el
anlogo a las tablas de SQL3, mientras que los objetos almacenados son los registros o tipos de datos de
SQL3.
Todos los objetos definidos por el servicio de persistencia implementan la interfase
LocalInterface [CORBA01]. Segn la especificacin de CORBA, todos los objetos que implementen dicha
interfase tienen su ciclo de vida limitado al proceso en el que fueron engendrados. De esta forma, es
imposible para un servant exportar un objeto definido en el dominio del servicio de persistencia. Esta es
otra forma de encapsular el servicio de persistencia slo dentro de la implementacin de los servants.
IDENTIFICACIN
Dado que existen mltiples instancias de objetos dentro de un repositorio y de un almacn, es
necesaria una forma de diferenciarlos.
Cada objeto almacenado posee un nmero nico que lo identifica dentro del almacn al que
pertenece denominado short-pid (Short Process Identifier o Identificador corto de Proceso). Adems
posee un identificador nico dentro del repositorio en el que existe, que es denominado pid (Process
Identifier o Identificador de Proceso). El alcance de este pid est limitado a todas las instancias que
pueden ser accedidas por el mismo catlogo.
El concepto de pid es anlogo al de oid dentro de CORBA. Una forma simple de relacionar un
objeto CORBA con un objeto del servicio de persistencia (un objeto persistente) es directamente por sus
identificadores (oid igual al pid).
TIPOS Y HERENCIAS.
Los tipos estn separados en dos grandes categoras abstractos y concretos, los primeros
implican definiciones que no pueden ser instanciadas, las segundas son las construcciones que sern
instanciadas en el programa que utilice el servicio.
custom Herencia Diamante
i nterface
interface
A'
i nterface
interface
i nterface
interface
i nterface
B'
E'
C'
i nterface
interface
D'
Este modelo es muy similar al modelo de herencia del lenguaje de programacin Java, los tipos
abstractos son anlogos a las interfases de Java, mientras que los concretos son anlogos a las clases. Al
igual que las interfases, los tipos abstractos admiten herencia mltiple, mientras que los concretos solo
pueden heredar a lo sumo de un nico tipo concreto. De igual forma que las clases, los tipos concretos
pueden implementar mltiples interfases. La herencia mltiple incluye el modelo de herencia diamante.
35
Pablo M. Ilardi
AlmacenTipoA
Hereda
AlmacenTipoB
TipoA
Hereda
Hereda
almacena
TipoB
AlmacenTipoC
Hereda
TipoC
almacena
Implementa
Implementa
Implementa
AlmacenConcreto
Implementa
almacena
TipoConreto
Tanto los objetos almacenados como los almacenes son tipados con tipos abstractos o concretos,
segn si son abstractos o concretos respectivamente.
Cada objeto almacenado tiene un tipo asociado, este tipo define el estado y las operaciones que
poseen todas las instancias de este tipo. A su vez un tipo puede ser derivado de otros tipos definidos en el
repositorio.
Cada almacn a su vez est definido por un tipo, el cual define los tipos de objetos que el
almacn puede contener o manejar junto con las operaciones que pueda realizar. De igual forma que los
tipos de objetos, los tipos de almacenes tambin pueden derivar de otros tipos de almacenes definidos
dentro del repositorio.
Dentro de un repositorio, un almacn puede manejar tanto las instancias de sus objetos
almacenados como las de sus subtipos, que se denomina familia de almacenes.
En el grfico 5 se muestra la herencia de tipo diamante soportada por el servicio de persistencia
CORBA.
CLAVES
Un almacn puede definir que una serie de atributos de los objetos que maneja, definen una
clave que representa un identificador nico para cualquier instancia de los objetos existentes en el
almacn. Los almacenes pueden definir tantas claves como deseen. Hay una clave implcita que es el
short-pid. Un concepto muy importante, es que las claves no estn definidas por los objetos
almacenados, sino por el almacn donde se encuentran. Esto permite que diferentes almacenes definan
diferentes claves. Una implicacin importante es que la unicidad de los objetos slo es vlida dentro del
almacn en el que existen.
36
Pablo M. Ilardi
PSDL es una ampliacin al IDL estndar de CORBA, que agrega cuatro construcciones: abstract
storage object, abstract storage home, storage object y storage home. En el caso de utilizar la primera
forma de definir los tipos, la implementacin del servicio deber proveer una herramienta o compilador
que transforme el cdigo definido en PSDL al cdigo fuente que utilice el servicio.
En el caso de utilizar la segunda, tambin llamada persistencia transparente, el usuario ser
responsable de programar las clases que usar el servicio de persistencia.
Ambas alternativas son igualmente vlidas, la segunda no requiere que el usuario entienda el
lenguaje PSDL. Tiene algunas limitaciones ya que no hay un estndar para cada lenguaje, que defina cmo
hacer uso de algunas de las funcionalidades que provee el servicio, tales como definir claves adicionales a
las implcitas. Este problema surge porque el servicio requiere que el usuario sea quien defina y provea
los tipos y no alcanza con solo llamar a una rutina del servicio. A cualquier usuario acostumbrado a
trabajar con CORBA le es natural utilizar el lenguaje IDL y por consiguiente le debiera ser relativamente
sencillo aprender a utilizar PSDL.
Segn la especificacin del servicio, las aplicaciones que utilicen el servicio de persistencia solo
deberan tratar con los tipos abstractos, de esta forma se puede lograr una aplicacin aislada o separada
de la implementacin del servicio. Por otro lado, los tipos concretos son mapeados a construcciones
definidas en el lenguaje de implementacin del servicio (Java o C++). Algunas de estas construcciones
estn definidas en el mapeo de PSDL al lenguaje concreto, pero otras no, y en este punto es donde se
pierde la independencia de la implementacin del servicio de persistencia.
ConectorRegistry
Tiene
registrados
Refencia inicial
Connector
Provee
ORB
CatalogBase
Session
SessionPool
TransactionalSession
El conector (Connector) determina el tipo de servicio de persistencia que se usar. Se dice que el
conector define la implementacin del servicio de persistencia a utilizar. Un conector tpico podra ser uno
que se conecte a una base de datos relacional o uno que utilice un sistema de archivos para almacenar el
estado de los objetos. Los conectores son responsables de crear los catlogos (CatalogBase) que se
37
Pablo M. Ilardi
usarn para trabajar con el servicio de persistencia. El tipo de catlogo que se cree, ser dependiente del
conector y el mtodo que se utilice para crearlo.
La sesin, o sea la conexin lgica entre el o los repositorios y el proceso, tiene credenciales de
uso, como por ejemplo, solo lectura o lectura-escritura. Las sesiones pueden a su vez ser de tipo
transaccional (TransactionalSession) mediante el uso del servicio de transacciones CORBA, o sesiones
donde la atomicidad de las operaciones dependa del conector utilizado, por ejemplo, con acceso de tipo
archivo (Session), donde cada operacin se hace inmediatamente persistente.
El acceso a las sesiones puede ser en forma explcita o implcita. Cuando se trabaja con sesiones
implcitas (ya sean transaccionales o no) el usuario del servicio de persistencia es el encargado de
crearlas, escribiendo cdigo en el lenguaje utilizado. Cuando se maneja en forma implcita, un pool de
sesiones es el encargado de administrarlas (SessionPool). Un pool de sesiones tiene el objeto de permitir
la reutilizacin de las conexiones o sesiones a un repositorio, ya sea dentro de la misma aplicacin o no.
Por lo general, su existencia tiene dos justificaciones: la creacin de una sesin puede ser costosa en
trminos de recursos involucrados para crearla, y cmo y dnde conectarse puede ser centralizado en un
slo punto, permitindole a la aplicacin desentenderse de ello.
El servicio de persistencia puede ser utilizado tambin mediante un contenedor de componentes
CORBA [CCM01, CCM02], tanto en forma explcita como implcita.
TRANSACCIONES
Las transacciones en el servicio de persistencia estn presentes a travs del servicio de
transacciones CORBA [TS01]. Esto implica que los objetos almacenados pueden ser accedidos en el
contexto de una transaccin. Para interactuar con el servicio de transacciones es necesario registrar en l
los recursos que sern utilizados en la transaccin.
En el caso de que se trate de sesiones explcitas, las instancias de los objetos almacenados estn
relacionadas con una transaccin por medio de una sesin transaccional. Esta sesin est asociada a una
transaccin de datos (datastore transaction), que es el recurso que se registra con el servicio de
transacciones. En el modo de trabajo explcito, la sesin transaccional provee operaciones explcitas para
interactuar directamente con el servicio de transacciones.
El escenario anterior no es el ms tpico, por lo general, cuando se trabaja con transacciones se
utiliza un proveedor de las mismas, y es el pool de sesiones el que se comunica con este servicio. En el
caso de utilizar el pool (sesiones implcitas), ste es el encargado de verificar cuando es necesario iniciar
una transaccin y no se tiene control programado del manejo de transacciones.
CONSTRUCCIONES EN PSDL
PSDL define el mdulo CosPersistentState, que contiene todas las construcciones propias del
lenguaje. Las principales son:
CatalogBase, Connector, Session, SessionPool, TransactionalSession, AccessMode,
ParameterList, StorageHomeBase, StorageObjectBase, StorageObjectFactory, StorageHomeFactory,
SessionFactory, NotFound, TypeId, Pid, ShortPid, ConnectorRegistry.
A continuacin, voy a hacer una breve descripcin de las construcciones que agrega PSDL a IDL
no definidas hasta este punto.
38
Pablo M. Ilardi
AccessMode define el modo de acceso que tendr garantizado el usuario del servicio sobre una
sesin al momento de crearla, mediante el uso de un conector. Puede ser solo lectura, o lectura
escritura.
ParameterList es simplemente una lista de parmetros variables que le permiten al conector
recibir parmetros propios de la implementacin del mismo para crear una sesin. Por ejemplo,
un conector podra requerir un nombre de usuario y clave para conectarse a un repositorio, si el
repositorio es de tipo remoto, podra ser necesario indicarle la ubicacin del mismo en la red.
NotFound es una excepcin utilizada para indicar que un objeto que se quiere localizar no existe
o no est disponible. Es utilizada tanto por el registro de conectores para indicar que un conector
no existe, como por una sesin cuando se quiere ubicar un objeto por su pid.
TypeId es una cadena de caracteres que identifica un tipo PSDL. El formato de la misma es
similar a los ids de los repositorios IDL [CORBA01 ver seccin 10.7.1], pero en vez de comenzar
con IDL lo hacen con PSDL. Al igual que los ids de repositorios, estos ids incluyen el nmero de
versin al que corresponden. Estos ids son utilizados por los conectores para registrar las
fbricas de objetos de un tipo PSDL. Por ejemplo, para un tipo persistido:
ar.uba.fi.pmi.corba.pss.prueba1.Persona, en su primer versin podra tener asociado un tipo
persistido: PSDL:ar.uba.fi.pmi.corba.pss.prueba1.Persona:1.0. Esta cadena de caracteres ser
utilizada por el usuario final para registrar la clase Persona en el conector donde quiera utilizarla.
39
Pablo M. Ilardi
S TORAGE O BJECT
Se permite la herencia de a lo sumo un objeto almacenado por definicin, mientras que es
posible implementar mltiples definiciones de objetos almacenados abstractos. Se dice que el objeto
almacenado implementa directamente una definicin de un objeto almacenado abstracto cuando se
define en forma explcita que lo implementa. Tambin puede implementarlo en forma indirecta, si
hereda de otro objeto almacenado que implemente la definicin abstracta. Esta definicin es importante,
40
Pablo M. Ilardi
ya que existen mltiples restricciones que se aplican cuando se implementa en forma directa otra
definicin.
Por ejemplo, cuando un objeto almacenado implemente directamente un objeto almacenado
abstracto, que defina un estado que sea otro objeto almacenado abstracto o una referencia, la definicin,
deber declarar una directiva de almacenamiento (store directive) al compilador. Esta directiva indica
cual es el objeto almacenado concreto que ser referenciado o utilizado en dicho estado, y
adicionalmente, si se trata de una referencia, cual ser el almacn concreto donde se albergar a dicho
objeto almacenado. Esto le permite al compilador, por ejemplo, optimizar el espacio requerido para
almacenar el objeto conociendo de antemano de que tipo de objeto se trata.
Toda definicin de objeto almacenado que sea la primera en la jerarqua, podr indicarle al
compilador los estados que definen una referencia a un objeto almacenado de este tipo. Esta lista de
estados, adems constituir una clave nica dentro del almacn de objetos almacenados que contenga
objetos de este tipo.
S TORAGE H OME
La definicin de un objeto almacenado requiere indicar que tipo de objeto almacenado concreto
ser el que manejar este almacn. El almacn puede heredar de a lo sumo un almacn y el tipo
almacenado de dicho almacn deber ser un supertipo del tipo almacenado definido por el almacn.
Adems, dos almacenes dentro de la misma jerarqua no podrn tener definido el mismo tipo de objeto
almacenado.
El almacn puede implementar mltiples almacenes abstractos, siempre y cuando los tipos
almacenados de los almacenes abstractos sean implementados por el objeto almacenado definido por el
almacn.
Al igual que los objetos almacenados, para los almacenes tambin se define el concepto de
implementar en forma directa. Se dice que un almacn implementa en forma directa una definicin del
almacn abstracto, cuando el almacn sea el primero dentro de la jerarqua que lo implemente.
Tambin, se dice que un almacn implementa directamente un objeto almacenado abstracto
cuando ste sea el primero en su jerarqua en implementar dicha definicin. Y en base a esto, el almacn
implementar en forma directa un estado, cuando implemente en forma directa el objeto almacenado
abstracto donde dicho estado est definido.
Estas definiciones se aplican en restricciones a la jerarqua del almacn. Cada clave definida en
un almacn abstracto, que sea implementado directamente por un almacn, deber tener como mnimo
un estado implementado directamente por el almacn. Esto evita que existan almacenes que definan
claves nicas sin contener estados definidos en l. Es como si en una base de datos relacional, una tabla
definiera una clave nica que no tenga columnas de dicha tabla, sino todas columnas de una tabla con la
que se tiene una clave fornea (foreign key).
Todo almacn, que sea el primero dentro de la jerarqua, puede definir una de sus claves o la
representacin de la referencia del tipo de objeto que almacena, como la clave primaria.
41
Pablo M. Ilardi
El mapeo de PSDL a C++ requiere agregar estructuras que en Java ya se encuentran presentes.
Algunos de los mapeos de tipo nativo a Java se traducen en clases ya existentes en el lenguaje, mientras
que en C++, son construcciones nuevas. Por ejemplo, en Java, toda clase hereda implcitamente de la
clase Object, mientras que en C++ no existe una clase base a todas las clases, por lo que se requiere
agregar la construccin CosPersistentState::StorageObject. Otro ejemplo, es el de las fbricas (factories),
para instanciar o crear objetos de los tipos definidos por los usuarios (mapeo nativo): en Java se traduce
directamente en un objeto de tipo Class, mientras que en C++ se traduce a una clase Factory definida por
el servicio de persistencia, que deber crear objetos en forma programtica. Esta es una de las diferencias
de mapeo del servicio a los lenguajes de programacin, donde se muestra que el servicio se adapta ms
naturalmente al lenguaje Java. Dado que Java es un lenguaje ms moderno que C++, provee de
herramientas que hacen ms simple los programas escritos en este lenguaje.
Otro tem importante, es el manejo automtico de la memoria. En Java, el ciclo de vida es
manejado automticamente por la mquina virtual, mientras que en C++, el programador es el encargado
de reservar y liberar la memoria requerida por los objetos. El servicio de persistencia provee mtodos
para liberar referencias a objetos accedidos en una sesin y que ya no son utilizados. En C++ se requiere
de esta operacin, ya que es el programador el encargado de liberar la memoria que ha alocado, en Java
sta operatoria es automtica.
CRTICAS A LA ESPECIFICACIN
El servicio de persistencia define un tipo persistido llamado StorageObject, que tiene una serie
de mtodos, tales como get_pid() o get_short_pid(), entre otros. Segn la especificacin (seccin 3,
pgina 8[PSS01]), toda definicin de un objeto persistido abstracto que no herede explcitamente de otro,
hereda de la clase StorageObject. Sin embargo, de acuerdo a la especificacin, todos los objetos
almacenados concretos heredan implcitamente de la clase StorageObjectBase. En Java, esta clase est
representada por la clase java.lang.Object, mientras que en C++, al no existir una clase base de todos los
objetos, se define una nueva clase CosPersistentState::StorageObjectBase. Ninguna de estas dos clases
(tanto en Java como en C++) definen los mtodos que tiene definidos la clase abstracta StorageObject.
Dado que no es obligatorio que la definicin de un objeto almacenado concreto, implemente
alguna definicin de un objeto almacenado abstracto, lo expresado en el prrafo anterior sobre
StorageObject y StorageObjectBase, no constituye una contradiccin.
Esto implica que no est definido que ocurre cuando un objeto almacenado concreto
implementa alguna definicin abstracta. Qu pasa con las operaciones definidas en StorageObject?
Queda completamente libre y depende puramente de la implementacin del servicio de persistencia.
Tampoco est claro, por qu es necesaria la existencia de la definicin de StorageObject, ya que todas las
operaciones del servicio de persistencia estn basadas en la clase StorageObjectBase.
La existencia de StorageObject, hace que los usuarios del servicio de persistencia estn obligados
a atarse a una implementacin del servicio, si es que quieren utilizar las definiciones abstractas. Esto
contradice uno de los principales objetivos de PSDL, que es el de liberar al usuario final del servicio de
usar una implementacin particular del mismo.
Gran parte de las inconsistencias surgen de tratar de dar soporte de persistencia transparente y
por PSDL, en forma simultnea. Si bien la idea de la persistencia transparente es potencialmente muy
atractiva, al tener que coexistir con el mundo de PSDL, crea un modelo hbrido difcil de compatibilizar.
Las excepciones, cdigos de error, o condiciones de error no estn especificadas en todos los
casos, cada implementacin es libre de generar los tipos de error que considere apropiados. Por ejemplo,
42
Pablo M. Ilardi
qu sucede cuando se trata de registrar una clase como factory de un tipo de objeto almacenado que no
es compatible con la implementacin del servicio o conector?
Otro tipo de errores que tambin son muy importantes, son los relacionados con la integridad
referencial y el ciclo de vida de los objetos. Qu pasa cuando se trata de eliminar un objeto que esta
referenciado en otro como un estado del mismo?. Qu pasa si se quiere asignar un objeto empotrado
como un atributo de otro objeto almacenado? De acuerdo con la especificacin, los estados no pueden
ser compartidos. Esto implica que cuando se asignan objetos empotrados a otros objetos, se debera
realizar una copia implcita de dicho objeto, el modo e implicancia de la copia no se encuentra definido,
por lo que cada implementacin puede tener formas distintas de realizarlo.
Existe tambin una indefinicin en cuando a los tipos de datos que soportan los estados. Un
estado puede ser de una interfase o estructura IDL definida dentro del archivo PSDL compilado. Como se
almacena dicha interfase o estructura no se encuentra definido en la especificacin.
Otro punto problemtico, son los mapeos de los estados al lenguaje Java. En Java existe una
convencin que la definicin de los mtodos que permiten acceder a los atributos que definen el estado
de los objetos. Si un atributo se llama nombre, el mtodo para acceder al nombre, se debe llamar
getNombre(), y el mtodo para modificarlo debe llamarse setNombre(nombre). En el mapeo de PSLD a
Java, se define que un estado se lee por un mtodo generado por el compilador, que para el caso de un
estado llamado nombre, ser nombre(), y para modificarlo el mtodo deber llamarse nombre(nombre).
Esta diferencia entre Java estndar, y el mapeo de PSDL, puede traer problemas al integrar los objetos
generados por el compilador con otras herramientas que esperen mtodos estndar.
La especificacin es amplia en muchos sentidos, dejando puntos libres que pueden ser resueltos
de diferentes formas en distintas implementaciones del servicio. Este tipo de situaciones, hacen ms
complicada la portabilidad entre distintas implementaciones del servicio, y van en contra del objetivo
inicial de lograr una interfase comn con la que se pueda lograr independencia de la implementacin del
servicio.
43
Pablo M. Ilardi
encuentran Hibernate [KingG01], JDO [RoodsR01], entre otras. Estas dos herramientas forman parte de
un gran grupo herramientas similares que permiten persistir objetos en una base de datos Relacional,
llamadas genricamente ORM (Object Relation Mapping o Mapeo objeto - relacin). Este tipo de
herramientas no estn directamente relacionadas con CORBA, por lo que su integracin con CORBA
requiere de trabajo especfico del programador sobre la aplicacin. Por ejemplo, la integracin con el
servicio de transacciones de CORBA deber ser programada directamente.
Existe otra alternativa en Java denominada J2EE (Java2 Enterprise Edition o edicin empresarial
de Java2). J2EE es una especificacin de SUN que extiende a Java agregando una serie de servicios entre
los que se encuentran un modelo de componentes (en el que se base CCM [CCM01]) que permiten lograr
un estado persistente. Este modelo de componentes est integrado con CORBA y el servicio de
transacciones. Permiten funcionalidades mucho ms avanzadas que PSS, como por ejemplo, acceso
remoto a los objetos almacenados mediante diferentes protocolos entre los que se encuentran GIOP. La
nica desventaja de este modelo es que se requiere utilizar un contenedor de componentes, no es
suficiente con la mquina virtual misma. Este modelo debe ser comparado con el modelo de
componentes CORBA CCM.
Tambin sera posible utilizar una base de datos orientada a objetos tal como DB4O [DBO401]
directamente sin PSS, pero nuevamente esta alternativa queda fuera del alcance de CORBA, por lo que la
integracin debe ser implementada explcitamente por el programador. Esta y otras alternativa ser
analizada en ms detalle en la siguiente seccin.
44
Pablo M. Ilardi
REFERENCIAS
PSS01 Persistence State Service V2.0 OMG 2002. http://www.omg.org/cgi-bin/doc?formal/0209-06
CORBA01 Common Object Request Broker Architecture, Core Specification OMG.
http://www.omg.org/technology/documents/corba_spec_catalog.htm
POS01 Persistent Object Service POS, OMG 2000.
http://www.omg.org/technology/documents/corbaservices_spec_catalog.htm
TS01 Transaction Service Specification, OMG 2003.
http://www.omg.org/technology/documents/corbaservices_spec_catalog.htm
BgVaDk Gerald Brose, Andreas Vogel, Keith Duddy Java Programming with CORBA, Advanced
Techniques for Building Distributed Applications. 3rd Edition.- Wiley 2001.
KjPfTp Jan Kleindienst, Frantiek Plil, Petr Tuma What we are missing in the CORBA
Persistent Object Service Specification.
EisenbergMelton01 SQL:1999, formerly known as SQL3. Andrew Eisenberg, Sybase, Concord,
MA 01742 andrew.eisenberg@sybase.com; Jim Melton Sandy UT 84093 jim.melton@acm.org
Ramakanth01 Object-Relational Database Systems - The Road Ahead; Ramakanth S.
Devarakonda; http://www.acm.org/crossroads/xrds7-3/ordbms.html
Gamma01 Design Patterns: Elements of Reusable Object-Oriented Software - Addison-Wesley
Professional Computing Series - by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides,
January 15, 1995
CCM01 CORBA Component Model (CCM) Specification, OMG
http://www.omg.org/technology/documents/formal/components.htm
CCM02 CORBA Component Model Tutorial, Yokohama OMG Meeting Wednesday, April 24th,
2002. http://www.omg.org/docs/ccm/02-04-01.ppt
KingG01 Hibernate in Action, Christian Bauer, Gavin King; Manning, 2005. ISBN: 1932394-15-X.
http://www.hibernate.org
RoodsR01 Java Data Objects, Robin M. Roods; Addison-Wesley, 2003. ISBN 0-321-12380-8.
http://java.sun.com/javaee/technologies/jdo
DBO401 Database for Objects. http://www.db4o.com/about/productinformation
DEVQTC01 Developing Quality Technical Information. A handbook for Writers and Editors.
Second Edition. G. Hargis, M. Carey, A. Hernandez, P. Hughes, D. Longo, S. Rouiller, E. Wide. ISBN
0-13-1477490.
45
46
Pablo M. Ilardi
47
Pablo M. Ilardi
48
Pablo M. Ilardi
PersonaHome ..............................................................................................109
PersonaBase ................................................................................................110
PersonHomeBase .........................................................................................112
PersonaBaseImpl .........................................................................................112
Uso del modelo en una aplicacin CORBA .......................................................113
Referencias .............................................................................................................117
Referencias a Bibliotecas ........................................................................................119
49
50
Pablo M. Ilardi
CONSIDERACINES INICIALES
Mi idea original para este trabajo fue utilizar C++, pero despus de un tiempo de trabajar en un
prototipo del servicio, desist y comenc a utilizar Java. Las razones fueron sencillas ya que la
especificacin se adapta mucho ms fcil a Java que a C++ y el modelo de objetos es anlogo al de Java.
Java provee de muchas ms herramientas de uso libre que C++. Por ejemplo, por el slo hecho de utilizar
Java, se cuenta con una ORB lista para ser utilizada que es parte de la especificacin del lenguaje.
El servicio de estado persistente de CORBA tiene como objetivo principal proveer estado
persistente a los servants. Mi implementacin cumple con ese cometido, pero tambin plantea la forma
de compartir ese estado desde distintas ubicaciones y servants.
PARTES
El trabajo se puede dividir en dos partes principales. La primera se fundamenta en que el servicio
de persistencia requiere que el usuario sea quin defina los tipos o clases que estarn disponibles. Y la
segunda es el servicio de persistencia propiamente dicho. Para la primer parte, el estndar define las dos
alternativas: Persistencia Transparente y uso del lenguaje PSDL.
PERSISTENCIA TRANSPARENTE
La persistencia transparente es atractiva ya que parece ms simple, slo es necesario definir los
objetos tal cual se hara en cualquier aplicacin. Sin embargo no es completa, tiene algunas limitaciones
tales como la definicin de las claves que definen la unicidad de los objetos, la definicin de operaciones
que pueden realizar los almacenes de objetos (storage homes), etc. El otro inconveniente que trae
acarreado esta alternativa es el cmo se integra en tiempo de ejecucin.
Segn la especificacin [PSS01] existen cuatro alternativas para integrar la persistencia
transparente:
1-
234-
Un pre procesador que agregue las construcciones necesarias del servicio de persistencia al
cdigo fuente Java. Por ejemplo, tome un atributo de la clase y modifique el cdigo donde
se utilice dicho estado.
Un compilador Java especial que haga algo similar al pre procesador antes mencionado.
Un pos procesador que realice modificaciones similares al cdigo binario resultante de la
compilacin (llamado bytecode en Java), pero en forma binaria.
O una mquina virtual Java especial que intercepte los accesos a los atributos de las clases.
El problema de las primeras dos opciones es que requieren que se tenga a mano el cdigo fuente
de las clases, lo cual no es siempre posible. Por consiguiente, las nicas dos opciones posibles son la 3 y 4.
A partir de la versin 5 de Java se han incorporado una serie de alternativas que le permiten a la
mquina virtual exportar puntos de control, que podran ser utilizados por un posible servicio de
persistencia que implemente persistencia transparente.
Uno de ellos se denomina JVMTI o JVM Tool interface [JVMTI01] (interfase de herramienta para
la mquina virtual), que consiste en que la mquina virtual permite configurar en el momento del inicio
de la misma, una biblioteca nativa llamada agente, que implementar dicha interfase. A grandes rasgos
dicha interfase exporta puntos de control de ejecucin del cdigo que se ejecuta dentro de la mquina
virtual. De esta forma, se podra seguir utilizando la misma mquina virtual para lograr lo mismo que lo
descrito en el punto 4. La desventaja es que se trata de una biblioteca implementada en cdigo nativo,
que debe entre otros, soportar las convenciones de las llamadas a funciones definidas en C y C++. Esto
agrega complejidad a la solucin ya que no solo se trata de una solucin escrita en Java.
51
Pablo M. Ilardi
COMPILADOR PSDL
El compilador del servicio de persistencia tiene que transformar el cdigo fuente PSDL en cdigo
fuente Java que cumpla con la especificacin del servicio y adems debe hacer que las construcciones
concretas construidas por ste, cumplan con alguna implementacin del servicio.
Segn el objetivo de mi trabajo, el compilador debe proveer la funcionalidad necesaria para
interactuar con el servicio de persistencia. Si bien, un compilador PSDL podra ser utilizado para compilar
archivos IDL, mi compilador se limitar a compilar las construcciones especficas del PSDL junto con
algunas otras del IDL que podran ser requeridas por PSDL. Si se quiere utilizar IDL siempre est
disponible el compilador IDL de la ORB que se utilice. De todas formas el compilador necesita entender
las construcciones IDL para cumplir con el estndar, aunque no genere cdigo Java para las mismas.
52
Pablo M. Ilardi
El lenguaje PSDL es una extensin al lenguaje estndar de CORBA, IDL. La especificacin del
servicio define completamente el mapeo de las construcciones abstractas como almacenes y objetos,
mientras que las concretas son ms abiertas y dependen de la implementacin del servicio.
La especificacin del servicio contiene la gramtica del lenguaje. Dicha definicin utiliza la
notacin EBNF (Extended Backus-Naur form), la cul es una extensin a BNF (Backus-Naur form).
BNF es la notacin formal estndar, definida por John Backus, utilizada para definir la gramtica
de los lenguajes [Garshol00]. Algol 60 fue el primer lenguaje popular en utilizarla. EBNF agrega pocos
cambios, pero que simplifican mucho su uso, entre los que se destacan los operadores: ?, * y + que
reducen la necesidad de utilizar definiciones recursivas.
Debido a que BNF realiza una definicin formal del lenguaje (con fundamentos matemticos y sin
ambigedades), es posible a partir de ella construir de forma mecnica un parser del lenguaje sin hacer
prcticamente cambios a la definicin.
Un parser es una herramienta que toma una entrada de texto realizando un anlisis gramatical
del mismo y validando su sintaxis.
Representacin
Interna
Entender Cdigo de
Entrada
Cdigo
Fuente
Generar Cdigo de
Salida
Errores
Cdigo Salida
Estos dos pasos se comunican mediante una Representacin Interna del cdigo fuente que
ambos conocen, el primero la genera y el segundo la utiliza. Ambos pasos pueden generar errores que
impidan o no, la generacin del cdigo de salida. Estos errores son, por lo general, de distinta naturaleza,
el primero detecta errores de sintaxis mientras que el segundo detecta errores semnticos que no son
visibles sintcticamente.
Dependiendo de la complejidad del compilador, se pueden agregar ms pasos intermedios al
proceso. Por ejemplo, un paso que realice una optimizacin de la representacin interna que permita
generar un cdigo de salida ms ptimo que la solucin trivial.
53
Pablo M. Ilardi
estndar de realizar este paso [CooperRice00]. Se realiza con dos herramientas, la primera es un
analizador lexicogrfico y la segunda es un parser.
Un analizador lexicogrfico, descompone una secuencia de caracteres en sub-secuencias de los
mismos llamadas tokens (smbolo en ingls) y a su vez clasifica estos tokens segn la categora a la que
correspondan. A esta herramienta tambin se lo denomina scanner.
El parser toma estas secuencias de tokens, y las analiza para determinar la estructura del cdigo
fuente. El resultado del parser es un rbol que refleja esta estructura.
Analizador Lxico
Parser
Cdigo
Fuente
Representacin
Interna
Errores
COMPILADOR 2 - PRIMER PASO
Tanto el parser como el analizador lexicogrfico son responsables de generar los errores cuando
el cdigo fuente de entrada no respete las reglas sintcticas del lenguaje.
Existen dos tcnicas ampliamente utilizadas en la construccin de parsers, TOP-DOWN y
BOTTOM-UP. La mayora de los parsers utilizan alguna de estas dos tcnicas.
- TOP-DOWN: (de arriba hacia abajo en ingls) estos parsers tienen la estrategia de separar la
secuencia de entrada en grupos de caracteres grandes, para luego ir separndolos
sucesivamente en los elementos fundamentales o tokens. Es bsicamente un juego de prueba y
error donde se plantea la hiptesis de que una secuencia de caracteres representan una
determinada construccin del lenguaje.
- BOTTOM-UP: (de abajo hacia arriba) estos parsers tratan de ubicar los elementos fundamentales
o tokens, y en base a ellos tratan de enmarcarlos en las construcciones ms grandes definidas en
el lenguaje.
La complejidad de los parsers radica en como tomar la decisin de que construccin es la que
corresponde a una secuencia de caracteres determinados.
Por lo general, la construccin tanto del parser como del analizador lexicogrfico no es una tarea
simple y puede llevar mucho tiempo. Ambas estrategias de procesamiento, se pueden escribir en forma
de algoritmo y en base a l construir un programa que realice el proceso sobre un archivo.
Existen herramientas que tienen el objeto de generar el analizador lexicogrfico y el parser en
base a una definicin del lenguaje de forma ms o menos automtica. Esta definicin se realiza en
notacin EBNF, con algunos agregados propios de la herramienta.
54
Pablo M. Ilardi
Para la construccin del parser decid utilizar una herramienta denominada javacc (Java Compiler
Compiler) [Javacc00]. Javacc es una herramienta de uso libre bajo licencia BSD (Berkely Software
Distribution), publicada en la comunidad abierta: java.net, que es patrocinada por la empresa SUN,
creadora del lenguaje Java. Al tener licencia BSD se puede construir y distribuir cualquier tipo de software
construido mediante esta herramienta (tanto comercial como libre) sin tener que pagar por ello.
Javacc es una herramienta que permite generar un parser de tipo TOP-DOWN a partir de una
definicin gramatical. Javacc toma como entrada un archivo fuente (generalmente con extensin jj) y lo
transforma en uno o ms archivos Java que representan un programa que es capaz de procesar y
entender archivos fuente escritos mediante el lenguaje que defina la gramtica. Este programa no tiene
utilidad prctica, tan solo se limita a reportar si existe un error en el archivo fuente procesado.
Javacc utiliza la notacin EBNF junto con agregados que le indican a su pre procesador algunos
parmetros que son utilizados para generar las dos rutinas a construir: el parser y el analizador
lexicogrfico [JavaccTu00].
Si bien tericamente con la gramtica del lenguaje es posible definir un parser de forma
sistemtica [Garshol00], en la prctica es posible que el tiempo en determinar la validez o no de un
archivo o secuencia de caracteres relativamente grande, sea prohibitiva para un parser generado en
forma genrica. Un parser genrico utiliza habitualmente la tcnica de backtracking [Dasgupta00] para
analizar la validez de una secuencia de caracteres. Backtracking se aplica cuando al analizar una
secuencia de caracteres se llega a un punto donde se debe tomar una decisin sobre dos o ms caminos a
tomar. Se toma la decisin de seguir un camino, luego de un tiempo de seguirlo se llega a un punto donde
se determina que la secuencia de caracteres es invlida, pero entonces es necesario considerar que la
decisin tomada originalmente podra haber sido incorrecta. Se debe volver a dicho punto para
considerar la otra alternativa. Bsicamente, cada punto de bifurcacin debe ser registrado para poder
volver a l en caso de que se llegue a un punto que determine un error. Esta tcnica requiere de mucho
tiempo de procesamiento y memoria, y en muchos casos eso lleva a un programa o sistema que consume
recursos inadmisibles.
Por esto los parsers generados por javacc no utilizan la tcnica de backtracking, lo que hacen es
tratar de recaudar la mayor cantidad de informacin para tomar la decisin correcta, de forma tal de no
tener que volver atrs. Javacc lee los N tokens siguientes en la secuencia para determinar si es vlido o no
el rbol. La cantidad de niveles del rbol a procesar por cada nodo, es determinada por el parmetro
LOOKAHEAD del pre procesador. Un valor muy bajo puede determinar que el parser de cmo invlido
algo que no lo es, en cambio, uno muy alto puede hacer que el parser consuma mucha memoria y tiempo
en analizar y procesar el archivo. Por lo general, se define un LOOKAHEAD global y para ciertas
definiciones se pueden aumentar este valor, esto es necesario sobre todo en las definiciones recursivas.
Javacc toma como entrada un archivo de texto que contiene las directivas al pre procesador, la
notacin EBNF que define el lenguaje y cdigo Java que ser ejecutado por cada construccin que el
parser detecte en tiempo de ejecucin. Al ejecutar javacc sobre el archivo, se generan algunas clases Java
que sern utilizadas internamente por el parser y una clase Parser, que es la base para la construccin del
compilador.
La clase Parser generada solamente valida la sintaxis del archivo. Una forma prctica de utilizar el
Parser es utilizar javacc combinado con otra herramienta denominada jjtree. JJtree es un pre procesador
para javacc, que toma como entrada un archivo fuente javacc, y lo adapta de forma tal que el parser
generado por javacc genere un rbol con la estructura del archivo fuente procesado. Este pre procesador
inserta acciones que construirn el rbol a medida que el documento de entrada con cdigo fuente es
procesado.
55
Pablo M. Ilardi
Primer
Paso
Segundo
Paso
jjtree
javacc
PSDL.jjt
PSDL.jj
Usa
Node*,java
PSDLParserVisitor.java
PSDLParser,java
COMPILADOR 3 - JAVACC
El rbol generado por jjtree estar compuesto por nodos. El tipo de nodo variar en funcin de la
estructura que el parser haya detectado en el archivo fuente. Se le puede indicar a la herramienta que
genere una clase para cada tipo de nodo que pueda existir en el rbol, este es el caso de mi compilador.
Por lo general, el tipo de nodo se corresponde uno a uno con las definiciones de la gramtica del
lenguaje. Por ejemplo:
La definicin que se le haya otorgado a jjtree, y javacc para que generen el parser.
El archivo fuente procesado
56
Pablo M. Ilardi
Segn mi definicin del lenguaje PSDL en notacin EBNF, todo rbol generado por el parser tendr
como raz un nodo de tipo: Nodepsdl_specification. Este nodo contendr nodos hijos con las
construcciones encontradas en el archivo procesado. En el caso de PSDL, las construcciones sern las
bsicas definidas por el lenguaje ms las existentes en IDL.
Todos los nodos generados por jjtree heredan de una clase base generada llamada SimpleNode.
Esta clase tiene como atributos el nodo padre y los nodos hijos junto con operaciones que permitirn
construir el rbol a medida que se procese el archivo de entrada. Adems, se le pueden agregar atributos
que podrn ser utilizados cuando se procese el rbol para reportar errores, por ejemplo, los tokens que
definieron la creacin del nodo. Los tokens aportan informacin importante como el nmero de lnea y
columna donde se encuentran en el archivo de entrada.
57
Pablo M. Ilardi
El patrn de diseo Visitor permite que un rbol de nodos sea recorrido o visitado por diferentes
objetos sin que los nodos tengan que estar al tanto de ello. Un ejemplo, sera recorrer el rbol para
generar una representacin del mismo en texto o para validar la estructura y la relacin entre los nodos,
o generar el cdigo de salida en base al mismo.
Este patrn es utilizado para recorrer estructuras, en este caso un rbol y su beneficio radica en
que la estructura o los elementos que la conforman no tienen que estar al tanto de que se hace con ese
procesamiento. Por otro lado, quien visita la estructura tampoco requiere conocer como est compuesta.
Podran existir diferentes implementaciones del visitante, sin que los nodos sean afectados por ellos. El
compilador representa una implementacin del visitante, y a la par podran existir otras
implementaciones, por ejemplo, un optimizador del rbol o para buscar errores en el mismo.
class Visitor
i nterface
i nterface
parser::PSDLParserVisitor
parser::Node
-chi
-parent
l dren
reali ze
compiler::
PSDLCompiler
real i ze
-parser
parser::
PSDLParser
-parser
parser::
SimpleNode
parser::
Nodepsdl_module
parser::
Nodepsdl_directiv e
Bsicamente, existe un objeto Visitor, que visitar los nodos del rbol. Todos los nodos heredan
de una clase comn o implementan la misma interfase, que define un mtodo aceptar(Visitor), el cual
ser implementado por cada tipo de nodo invocando al mtodo visitar en el Visitor pasndose a s mismo
como parmetro: visitor.visitar(this). El Visitor tendr que implementar un mtodo visitar distinto por
cada tipo de nodo que quiera manejar de forma distinta o particular.
En el contexto del compilador, el Visitor est representado por la interfase PSDLParserVisitor, la
clase PDLCompiler es una implementacin del mismo. La interfase Node define todo aquello que puede
ser visitado. Para cada nodo que sea visitado, existir una clase concreta que implementar el mtodo
aceptar, que solamente deber llamar al mtodo visitar del Visitor que reciba como parmetro.
IDENTIFICADORES
La gramtica de PSDL contiene mltiples definiciones que referencian identificadores. Este
concepto es compartido o heredado de la definicin del IDL y por consiguiente del PSDL. Muchos tipos de
construcciones del IDL y PSDL utilizan el concepto de identificador, pero la definicin del mismo vara en
funcin del lugar donde se lo utilice. Por ejemplo, un identificador puede identificar a un tipo de objeto
almacenado o a un mtodo en un almacn. En otros casos, como por ejemplo, cuando se hace referencia
a una entidad definida anteriormente en el cdigo fuente (como en la declaracin de un estado), es
58
Pablo M. Ilardi
posible utilizar mltiples identificadores para identificarla, dado que la referencia puede ser dada tanto
en forma absoluta como relativa.
Existen mltiples reglas que determinan cuando un identificador es vlido y cuando no. Las
mismas estn asociadas a la definicin que utilice el identificador, y no son explcitas en la definicin
gramatical del lenguaje.
El hecho de que el concepto de identificador est presente, es un buen punto para definir un
diseo que permita un grado alto de reutilizacin de funcionalidades, ya que ser utilizado prcticamente
en todas las construcciones que procese y/o genere el compilador.
PROCESO DE COMPILACIN
La recorrida del rbol generado plantea algunos obstculos que tuvieron una gran influencia en
mi diseo del compilador:
1
2
Era necesario detectar aquellos errores que no fueran detectados por el parser
El rbol puede requerir incluir archivos externos, que se definen como #include en el cdigo
fuente de entrada. Este proceso puede ser recursivo y adems puede llevar a ciclos, que deben
ser contemplados.
El cdigo a generar para las construcciones concretas depende fuertemente de la
implementacin del servicio de persistencia, mientras que el cdigo a generar para las
construcciones abstractas es independiente de la implementacin (segn la especificacin del
servicio).
Las referencias a otros elementos puede hacerse tanto en forma absoluta como relativa
mediante en uso de los identificadores. Por ejemplo, en Java se puede referenciar a la clase
String por java.lang.String o simplemente por String. El compilador de Java determina las
referencias relativas en base a los imports de la clase. En PSDL, las referencias relativas se
resuelven en base al mdulo en el que se est referenciando a esta otra entidad.
Las definiciones pueden hacerse en forma directa, o en dos pasos mediante las declaraciones
forward o hacia adelante. Las definiciones forward permiten que la definicin sea referenciada,
sin estar completa su definicin, por ejemplo, para objetos almacenados que tengan declarados
estados de su mismo tipo.
Los errores que no detecta el parser son diversos y a veces no son simples de detectar. Algunos
de ellos son:
-
Para procesar los archivos incluidos por el archivo fuente original, es necesario procesar cada
uno de ellos de forma tal que se recaude la informacin necesaria para las validaciones antes descriptas.
Este proceso debe ejecutar el parser sobre estos archivos y no debe generar el cdigo de salida, adems
el proceso ejecutado por el parser debe lidiar con referencias circulares de archivos incluidos.
La existencia de definiciones forward, requiere al menos de dos pasos para poder recolectar toda
la informacin necesaria para determinar cuando una definicin es vlida y cuando no.
Por ltimo, pero no menos importante, el cdigo de salida depende fuertemente del servicio de
persistencia, se requiere que el compilador o una parte de l conozca el servicio de persistencia para el
59
Pablo M. Ilardi
que generar cdigo. Por ende, se requiere tener un servicio de persistencia totalmente definido para
poder construir el compilador. Como este no era mi caso, yo fui construyendo el compilador y la
implementacin del servicio en paralelo, por consiguiente tuve que desacoplar las partes del compilador
que requeran generar cdigo particular de la implementacin del servicio.
0 Parseo
ArchivoFuente
1 Procesamiento
2 Validacin
3 Generacin
Objetos Al macenados
Almacenes
PSDLC OMPILER
Esta clase modela al compilador en s mismo, es la cara visible. Toma como entrada un archivo
fuente que ser compilado y da como resultado los archivos fuentes generados. El archivo fuente es
procesado por el parser, el cual genera el rbol que describe el archivo fuente original. Este rbol ser
procesado por esta clase mediante el patrn Visitor descripto anteriormente, dado que PSDLCompiler
implementa la interfase PSDLParserVisitor.
PSDLP ARSER
Esta clase es la encargada de procesar el archivo de entrada generando el rbol que lo
represente. El compilador tiene una instancia de esta clase como atributo.
N ODE PROCESSOR
Algunos nodos del rbol requieren de varios niveles del mismo para completar una definicin, por
lo general, para cada nodo del rbol de este tipo que el compilador visite, ste crear una instancia del
procesador de nodo que es responsable de tomar acciones con la rama del rbol que se est visitando.
60
Pablo M. Ilardi
Estas clases implementan la interfase NodeProcessor. Cuando se termine de procesar este nodo, el
compilador se lo har saber al procesador con un mensaje de tipo finalizarProceso.
C OMPILE PROCESS
El compilador crear un CompileProcess inicial para procesar el rbol. Esta clase modela el
proceso de compilacin de un archivo. El proceso tiene como objetivo recolectar las definiciones
declaradas en el rbol. Estas definiciones sern instancias de FullTypeDefinition. Existir una instancia de
CompileProcess por cada archivo procesado, es decir, si se incluye un archivo en el archivo fuente
original, esto resultar en la creacin en otro proceso de compilacin para dicho archivo. Adicionalmente,
el proceso mantiene informacin de estado del procesamiento del rbol, que es muy importante para
realizar las validaciones.
T ARGET C OMPILER
TargetCompiler es una interfase que define las operaciones requeridas para generar definiciones
concretas (clases Java) que dependen de la implementacin del servicio. Por ejemplo, de cual clase debe
heredar una clase que represente un objeto almacenado concreto que deba ser utilizado por una
implementacin del servicio de persistencia que se basa en archivos.
I DENTIFIER PROCESSOR
Cada proceso de compilacin necesita de un objeto que ser el encargado de procesar los nodos
que representen un identificador en el rbol. Esta clase es necesaria debido que los identificadores
pueden ser definidos tanto en forma absoluta como relativa. Cuando estn en forma relativa, qu
identifican, estar dado por el mdulo que el proceso est navegando.
Cada proceso tiene un procesador de identificadores que lleva la cuenta de los identificadores que
no fueron procesados realmente, es decir, si este objeto tiene que procesar un nodo de identificador es
porque se produjo un error interno en el compilador, y alguna definicin no fue contemplada o fue mal
procesada. Cuando el compilador visite un nodo que defina una entidad, el objeto que procese ese nodo
61
Pablo M. Ilardi
ser responsable de indicarle al proceso cual es el objeto que procesar el siguiente nodo de identificador
en el rbol.
De esta forma cada vez que se visite un nodo que represente un identificador, el procesador que
est definido en el proceso ser notificado de ello.
62
Pablo M. Ilardi
class ClassDefinitions
parser::SimpleNode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
parser::Nodepsdl_specification
+
+
Todos los nodos del rbol heredan de la clase SimpleNode. Las dos clases que se muestran en el
diagrama anterior, fueron generadas por el procesador jjtree. A los efectos de procesar el rbol, los
nicos mtodos que importan son jjAccept y childrenAccept. El primero tiene que estar implementado
en cada clase de nodo en particular, dado que as lo requiere el patrn Visitor. El segundo ser invocado
por el compilador para procesar el siguiente nivel del rbol. La implementacin es tan simple como tomar
cada nodo hijo e invocar al mtodo jjAccept sobre l.
Entonces el proceso comienza cuando se invoca al mtodo jjAccept sobre el nodo raz, con dos
parmetros, el primero el compilador mismo y el segundo el proceso de compilacin. Para cada nodo los
pasos son:
o
o
o
Se visita el nodo. El nodo le indica al compilador que se est visitando un nodo del tipo que
corresponde.
El compilador realiza una operacin en base al tipo de nodo,
Se visitan a los hijos del nodo, donde el proceso comienza nuevamente, hasta que no queden
nodos por visitar.
En este punto, el proceso de compilacin habr recolectado todas las definiciones generadas al
visitar nodos de definicin.
El siguiente diagrama de objetos muestra la interaccin entre los objetos para concretar la
primera fase, donde se tendr como resultado el proceso de compilacin.
63
Pablo M. Ilardi
object SimpleCompileProcess
w riter :
CompilerDefinitionWriter
endUser
aCompiler :
PSDLCompiler
1.2: l ookup
aSpecification :
Nodepsdl_specification
interface
target :
TargetCompiler
process :
CompileProcess
2.4: new
identifierProcessor :
CounterIdentifierProcessor
En el cdigo anterior se define un objeto almacenado dentro de un mdulo con un nico estado
llamado nombre y de tipo string (secuencia de caracteres).
64
Pablo M. Ilardi
Nodepsdl_specification
|-->Nodepsdl_module
|-->Nodeidentifier(ejemploFaseUno)
|-->Nodeabstract_storagetype
|-->Nodeidentifier(Prueba)
|-->Nodepsdl_state_dcl
|-->Nodepsdl_state_type_spec
|
|-->Nodestring_type
|-->Nodesimple_declarator
|-->Nodeidentifier(nombre)
PASOS REQUERIDOS
1- El compilador genera un CompileProcess, inicialmente con un IdentifierProcessor que llevar la
cuenta de los identificadores no procesados, una instancia de CounterIdentifierProcessor.
2- Se inicia el proceso de recorrido del rbol con el nodo raz Nodepsdl_specification, llamando al
mtodo jjAccept con el proceso creado anteriormente.
3- El nodo Nodepsdl_specification le indica al compilador que se visita a este tipo de nodo
llamando al mtodo visit con s mismo como parmetro y el proceso que recibi anteriormente.
Como el compilador no necesita realizar otra tarea adicional, sigue el proceso de recorrido del
rbol llamando al mtodo childrenAccept en el nodo visitado.
4- El primer nodo hijo es Nodepsdl_module, el cual termina llamando al mtodo visit del
compilador. Al visitar este nodo el compilador instancia un objeto de tipo
ModuleIdentifierProcessor. Cuando el ModuleIdentifierProcessor es creado, ste le indica al
proceso que el nuevo procesador de identificadores ser l. Luego de esto, se sigue procesando
la rama del rbol debajo del mdulo.
5- El primer nodo debajo del nodo del mdulo es Nodeidentifier. Al visitar este tipo de nodo el
compilador le pide al proceso, el procesador de identificadores para procesar este nodo, que en
este caso ser ModuleIdentifierProcessor (definido en el paso anterior). Esta clase toma el
identificador y genera una definicin de paquete Java indicndole al proceso actual cual es el
paquete que corresponde, en este caso: ser ejemploFaseUno. Luego restaura el procesador
anterior y sigue procesando los nodos hijos. Como el nodo de identificador no tiene nodos hijos,
se vuelve a procesar los nodos hijos del nodo que defini el mdulo.
6- El siguiente nodo hijo es Nodeabstract_storagetype. Cuando el compilador visita este tipo de
nodos, crea una instancia de AbstractStorageTypeBuilder. Cuando este tipo de nodo es creado,
ste le pide al proceso actual el paquete Java procesado (definido en el paso anterior),
inicializando la definicin del objeto con l. Adems le indica al proceso actual que l mismo ser
el procesador de identificadores. Luego de ello se procesan el nodo con sus hijos.
7- El primer nodo hijo ser Nodeidentifier. Cuando se visite este nodo se terminar utilizando el
identificador de procesos definido en el proceso, que es justamente el nodo
Nodeabstract_storagetype, definido en el paso anterior. Este nodo tomar el identificador
definido, en este caso Prueba, y lo asociar a la definicin que se est construyendo del objeto
almacenado. Restaura nuevamente el procesador de identificadores anterior y sigue procesando
los nodos hijos.
8- El siguiente nodo hijo de Nodeabstract_storagetype es Nodepsdl_state_dcl, en este caso el
compilador crear una instancia de objeto de tipo StateMemberBuilder, y luego procesar los
nodos hijos de ste.
9- El primer nodo hijo ser Nodepsdl_state_type_spec, el cul define el tipo de dato del estado que
se est definiendo. En este caso, el compilador instancia un objeto de tipo
StorageTypeStateDeclarationProcessor, que al ser creado le indica al proceso actual que l ser
65
Pablo M. Ilardi
el objeto encargado de registrar los prximos identificadores a procesar del rbol. Luego de esto
se procede a procesar los nodos hijos del nodo.
10- El nico nodo hijo de Nodepsdl_state_type_spec, en este caso es Nodestring_type, que al ser
procesado por el compilador lo nico que hace es indicarle al builder actual que el tipo de dato
es STRING.
11- Como no hay ms nodos hijos del Nodepsdl_state_type_spec, se le indica a este nodo que se ha
completado el procesamiento de sus hijos. En este punto, el nodo tiene la oportunidad de armar
la definicin completa del tipo de dato del estado. Como en este caso es un STRING no hay ms
nada que hacer, pero si se tratara de un tipo de dato, como por ejemplo, una referencia a otro
tipo de objeto almacenado definida en forma relativa al paquete actual, se transformara en una
referencia a un tipo absoluto. Luego se restaura el procesador de identificadores anterior. Y se
siguen procesando los nodos hijos de Nodepsdl_state_dcl.
12- El prximo nodo hijo es Nodesimple_declarator. Cuando el compilador detecta este tipo de
nodos instancia un objeto de tipo SimpleDeclaratorIdentifierProcessor, que simplemente se
pone a s mismo como procesador de identificadores. Al procesar el siguiente nodo de
identificador se almacenar el valor nombre.
13- Como no hay ms nodos por procesar, StateMemberBuilder tomar el identificador generado
por SimpleDeclaratorIdentifierProcessor, y definir el nombre del estado. En este punto, el
nodo puede realizar una validacin simple, que es que no exista otro estado con ese nombre
dentro de la lista de estados que se pueden definir agrupadamente. Este tipo de validaciones no
pueden ser realizadas por el parser, ya que no son parte de la definicin gramatical del lenguaje.
14- Luego de que se procesaron todos los nodos por AbstractStorageTypeBuilder, ste tomar como
resultado de visitar la rama, lo que define al StateMemberBuilder, y lo agregar como definicin
de un estado. Adems, realizar una serie de validaciones, por ejemplo, si el tipo de estado es
una referencia a otro tipo de objeto, ste debe estar definido previamente. Nuevamente estas
validaciones se hacen en este punto ya que no es estn definidas en la gramtica del lenguaje
que define al parser. De todas formas esta validacin ser parcial ya que es tambin necesario
validar la unicidad de los estados dentro de la jerarqua a la que pertenezca el objeto
almacenado. Esta validacin ser realizada en la siguiente fase, dado que en este punto no est
definida dicha jerarqua.
15- En este punto AbstractStorageTypeBuilder termin de procesar todos los nodos hijos y puede
registrarse con el proceso actual como un tipo de objeto almacenado definido durante el
proceso. Al procesar el registro, el proceso tiene la oportunidad de realizar algunas operaciones,
como validar definiciones duplicadas o reemplazar una definicin anterior parciales (forward). El
caso de las definiciones parciales se da cuando en el archivo fuente se encuentra una definicin
con solamente un identificador, de forma tal que pueda ser referenciada en otras definiciones
sin estar an definida completamente en el documento.
16- Se han terminado de procesar todos los nodos. El compilador le indica al procesador de
identificadores actual, que se ha completado el proceso. CounterIdentifierProcessor sabr en
este punto si alguno de los identificadores no ha sido considerado, en cuyo caso generar un
error interno de compilacin.
17- Finalmente, el proceso de compilacin est completo y la primera fase del compilador.
66
Pablo M. Ilardi
Como puede verse, la compilacin de una estructura simple como la descripta anteriormente
requiere de mltiples objetos e interacciones entre los mismos.
Resumiendo, el resultado siempre es un objeto de tipo CompileProcess. Dicho objeto almacena la
lista de definiciones existentes en el archivo original. Estas definiciones se concretan siempre en objetos
que heredan de la clase BaseStorageElementBuilder. Esta familia de clases sigue el patrn Builder
(constructor) definido en Gamma01. Estos objetos sern utilizados en la ltima fase para generar los
archivos fuente resultantes.
67
Pablo M. Ilardi
class exceptions
RuntimeException
PSDLCompilerException
DefinitionNotFoundException
+
+
+
IllegalFactoryMethodException
+
IllegalKeyDefinitionException
DuplicateDefinitionFoundException
+
IncludeFileException
IllegalDefinitionFoundException
+
IllegalStateException
+
+
IllegalStateExcepti on(message)
IllegalStateExcepti on(message, e)
+
+
Existen dos clases de excepciones de validacin que representan errores mas generales de la
definicin, que son: IllegalDefinitionFoundException y IllegalStateException.
La primera excepcin se genera cuando se llega a un punto del procesamiento en el que la
definicin que se esta procesando debe ser marcada como invlida dado que viola alguna regla. Pero esto
no se debe a, por ejemplo, un estado mal definido o un estado duplicado, sino a que la suma de atributos
de la definicin la hacen invlida. Por ejemplo, cuando en la definicin de una herencia de almacenes se
detecta que el tipo almacenado de un almacn hijo no es un subtipo de tipo almacenado por alguno de
los almacenes padres. O cuando se trata de agregar una clave primaria a un nodo que no es la raz de la
familia de almacenes. Por lo general, como este tipo de errores no se pueden atribuir a una parte de la
definicin, el usuario final tendr que verificar a que corresponde el error.
La segunda excepcin IllegalStateException est asociada a potenciales errores internos del
compilador. Por ejemplo, tratar de construir definicines en base a definiciones no validadas, o tratar de
agregar una definicin ms de una vez a un proceso de compilacin, etc. Este tipo de errores es probable
que se produzcan cuando se agreguen extensiones al compilador para generar cdigo para otros servicios
de persistencia.
A continuacin voy a ejemplificar la serie de pasos para la validacin del ejemplo de la fase
anterior.
68
Pablo M. Ilardi
Generacin de
Cdigo
Comn a todo
Serv icio
Cualquier implementacin del servicio requerir generar cdigo fuente. La forma de lograr un alto
grado de reutilizacin entre diferentes implementaciones del servicio es definir un modelo comn que
puedan utilizar todas las implementaciones. El grfico 10 muestra el qu generar, bsicamente es un
modelo casi completo de cualquier elemento que se quiera definir en lenguaje Java, una clase, interfase,
etc.
Se trata de una serie de clases que modelan las distintas partes que podran componer un archivo
fuente. Las clases representadas en el grfico son la base para un generador de cdigo fuente
independiente del compilador. A continuacin, dar una breve descripcin de algunas de las clases ms
importantes.
Type Definition: la definicin de un tipo de objeto en Java est dada por un paquete y un nombre.
Import Declaration: todo archivo fuente Java puede importar otras definiciones para poder
utilizarlas directamente. Considero que siempre se importan tipos de objetos, por lo cual, una
declaracin de import es simplemente una referencia a una definicin de un tipo. Tambin se
podran importar paquetes enteros pero no creo que sea algo necesario, por lo que esta definicin
no lo soporta.
69
Pablo M. Ilardi
Instance Definition: es simplemente una definicin de un tipo nombrada, de forma tal que puede
ser utilizada como parmetro a un mtodo o en la declaracin de un atributo.
class generationLite
TypeDefinition
Comparabl e
ImportDeclaration
NestedGenerator
PackageDefinition
InstanceDefinition
OperationDefinition
NestedGenerator
AccessibilityDefinition
M ethodDefinition
AttributeDefinition
ConstructorDefinition
FullTypeDefinition
Keyw ord
DefinitionFactory
ElementTypeKeyw ord
InterfaceDefinition
ClassDefinition
COMPILADOR 10 - QU GENERAR
Cada implementacin del servicio, ser responsable de generar sus clases mediante el uso de
este modelo.
70
Pablo M. Ilardi
Desde la perspectiva del CompileProcess, cada builder generado en la primer fase generar al
menos un FullTypeDefinition cada uno. Cada una de estas definiciones de tipos genera un archivo fuente.
Como se construyen estos tipos es transparente para el compilador y ser la tarea del TargetCompiler.
class fileBuilding
generation::CompilerDefinitionWriter
compiler::CompileProcess
+
-
+
#
#
+
CompilerDefinitionWriter(PSDLCompiler)
getCom pilerProperties() : Map<String, Object>
getFileHeaderT mpl() : URL
write(T, File) : void
interface
Generator
instantiate
+
+
addTo(TypeDefinitionAppender) : void
w riteYouSelfInto(FileBuilderColaborator) : void
instantiate
T:extends FullTypeDefinition
TextAppender
realize
interface
FileBuilder
FileBuilderColaborator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
attributeEnd() : void
attributeStart() : void
bodyEnd() : void
bodyStart() : void
getFileProperties(Generator) : Map<String, Object>
getStringRepresentation(TypeDefinition) : String
methodEnd(boolean) : void
methodStart(boolean) : void
writeAccesibility(AccessibilityDefinition) : void
writeBlock(String, Generator, Map<String, Object>, boolean) : void
writeExceptions(List<TypeDefinition>) : void
writeInstance(InstanceDefinition) : void
writeKeyw ord(Keyw ord) : void
writeLiteral(String) : void
writeOperationWithParameters(String, List<InstanceDefinition>, boolean) : void
writeSuperClass(TypeDefinition) : void
writeSuperInterfaces(Keyw ord, List<TypeDefinition>) : void
writeTemplateText(URL, Map<String, Object>, boolean) : void
writeTypeDefinition(TypeDefinition) : void
FullTypeDefinition
+
+
+
+
#types
instantiate
realize
FileBuilder::
LocalFilebuilderColaborator
El grfico anterior define como a partir del modelo, se procede a generar los archivos fuentes.
Cada parte del modelo implementa la interfase Generator. Esta interfase define que el objeto que la
implementa sabe como agregarse a s mismo a un objeto encargado de construir un archivo, mediante el
mtodo writeYourSelfTo. Este mtodo recibe como parmetro un objeto que implementa la interfase
FileBuilderColaborator. Una instancia de FileBuilder, ser la encargada de tomar cada una de las
definiciones construidas en el CompileProcess y mediante una llamada al mtodo writeYourSelfTo,
construir el archivo fuente para cada tipo definido.
71
Pablo M. Ilardi
una entrada con el nombre registered, cuyo valor debe contener la lista de targets registrados en el
compilador. Por ejemplo: registered=transient, persistent. Por cada una de los targets registrados, tiene
que haber otra entrada en dicho archivo que contenga el nombre completo de la clase que implementa la
interfase TargetCompiler, para dicho target.
class compileGenerationLite
i nterface
TargetCompiler
AbstractGenerator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
generateConstraintVali dations(process, homeBui lder, defi ni ti on, keyIdentifi er, stateNames) : voi d
generateCreateFour(process, homeBuil der, definition, methodDefi ni ti on) : voi d
generateCreateOne(process, homeBui lder, defi ni ti on, methodDefinition) : void
generateCreateThree(process, homeBuil der, defi niti on, methodDefi ni ti on) : voi d
generateCreateTwo(process, homeBui lder, defi ni ti on, methodDefinition) : void
generateFactoryMethod(process, homeBuil der, factoryMethodBuil der, definition, methodDefi ni ti on) : voi d
generateFinderMethod(process, homeBuil der, definition, methodDefi niti on, keyBui l der) : void
generateLifeCycl eListener(process, storageHome, definition, stateBuil der) : voi d
generateRead(process, buil der, defi nition, attribute) : void
generateReadRef(process, bui lder, defi ni ti on, attri bute) : voi d
generateReadWri te(process, storageTypeBuil der, bui lder, defi ni ti on, attri bute) : voi d
generateRefFi nderMethod(process, homeBui lder, defi ni ti on, methodDefini tion, keyBuil der) : voi d
generateStorageHome(process, storageHome, definition, isAbstract) : voi d
generateStorageObject(process, storageType, defi ni ti on, i sAbstract, properStates) : void
generateWrite(process, storageTypeBui l der, bui lder, defi niti on, attri bute) : void
generateWriteRef(process, storageTypeBuil der, bui l der, defini ti on, attri bute) : voi d
getCompi leInstance() : TargetCompi l er
getDescri pti on() : Stri ng
getName() : String
getTempl ates() : Compi lerTempl ates
i ni t(name, regi stry) : voi d
reali ze
HelperGenerator
Generati onTemplates
AbstractTargetCompiler
HolderGenerator
-tem plates
CompilerTemplates
{l eaf}
-i nstance
TargetCompilerRegistry
+
+
+
+
+
defaultOne() : T argetCom pi l er
forName(nam e) : TargetCom pil er
getInstance() : TargetCom pil erRegistry
getProperty(key) : String
getRegi stered() : Set<Stri ng>
configures
flow
pss_pmi _com pil er.properties
memory::
TransientTargetCompiler
persistent::
PersistentTargetCompiler
72
Pablo M. Ilardi
funcin del tipo y cantidad de atributos persistentes que tengan los objetos almacenados. Esto requiere
que los mtodos sean construidos dinmicamente en funcin de lo que se este compilando.
PASOS
1- Para cada uno de los builders registrados en el CompileProcess de llama al mtodo generate. En
este caso slo existe un builder registrado que representa al objeto almacenado abstracto. Y se
trata de un AbstractStorageTypeBuilder.
2- AbstractStorageTypeBuilder construir una instancia de InterfaceDefinition.
a. Para cada tipo heredado, se agregar una extensin a la definicin de la interfase construida.
Como en este caso, no se hereda de ninguna otra definicin, se agregar automticamente la
extensin de la interfase StorageObject.
b. Para cada estado definido en el tipo, se llamar al mtodo addTo, pasando como parmetro la
definicin de la interfase construida. Slo existe una definicin de estado nombre, que est
representada por un objeto StateMemberBuilder.
i. StateMemberBuilder en el mtodo addTo, como primer medida, determinar si se trata de
una definicin concreta o abstracta (como en este caso) para saber que tipo de mtodos se
deben generar. Construye una definicin de atributo (AttributeDefinition) con el nombre
del estado, luego llamar al mtodo addReadAccessorFor con el atributo construido.
ii. El mtodo addReadAccessor construye una instancia de MethodDefinition, en base al tipo
de objeto del atributo construido anteriormente. Adems le indica al TargetCompiler del
proceso que se est ejecutando, que le agregue un encabezado al mtodo construido. Este
encabezado ser a modo de comentario en sintaxis Java Doc. Si el mtodo debiera ser
implementado por tratarse de un tipo concreto, se llamara al mtodo generateRead del
TargetCompiler. De esta forma, TargetCompiler es el nico objeto que puede referenciar
partes dependientes del servicio de persistencia para el cual se est compilando.
Finalmente, StateMemberBuilder agrega el mtodo a la definicin.
iii. StateMemberBuilder llama al mtodo addWriteAccessorFor. De manera anloga a
addReadAccessor, se construye una definicin de mtodo. TargetCompiler le agrega un
encabezado y finalmente se agrega el mtodo a la definicin que se est construyendo.
c. Para cada operacin definida en el tipo almacenado se llama al mtodo addTo del builder
(OperationBuilder). En este caso no se han definido operaciones.
d. Finalmente, AbstractStorageTypeBuilder agrega al proceso la definicin de la interfase
construida, con el mtodo addGenerated, indicndole que se deben generar la clase Holder para
la interfase.
73
Pablo M. Ilardi
74
Pablo M. Ilardi
75
Pablo M. Ilardi
class ORBInitialization
ConnectorRegistryOperations
org.omg.CORBA.LocalInterface
org.omg.CORBA.portable.IDLEntity
Object
interface
PortableInterceptor::ORBInitializer
interface
configures
orb.properties
flow
CosPersistentState::ConnectorRegistry
LocalInterface
realize
interface
org.omg.CORBA.LocalObject
pss::ConnectorRegistryInitializer
CosPersistentState::
_ConnectorRegistryLocalBase
+
+
_ids() : String[]
pss_pmi_regi stry.properties
pss::ConnectorRegistryImpl
realize
configures
flow
+
+
+
+
+
+
+
ConnectorRegistryImpl()
find_connector(String) : Connector
is_registered(String) : bool ean
post_init(ORBInitInfo) : voi d
pre_init(ORBInitInfo) : void
register_connector(Connector) : Connector
unregister_connector(String) : void
_ConnectorLocalBase
connector::ConnectorBase
En el grfico anterior se muestran las partes que interactan para que el servicio de persistencia
de CORBA est disponible en la ORB. El proceso que permite al servicio de persistencia estar disponible
en la ORB es el siguiente:
76
Pablo M. Ilardi
, en este caso se identifica el conector Transient. Cada vez que se le pida al registro, un conector
identificado por la cadena de caracteres Transient, se har referencia al conector provisto por la clase
ar.uba.fi.pmi.corba.pss.connector.TransientConnector. La nica condicin para estas clases es que
implementen la interfase:
ar.uba.fi.pmi.corba.pss.ConnectorRegistryInitializer:
public void pre_init(ConnectorRegistry registry, Properties initialzationProperties,
String creationProperty);
public void post_init(ConnectorRegistry registry, Properties initialzationProperties);
, como se aprecia, al igual que ORBInitializer expone dos mtodos que representan la fase de
inicializacin, en este caso, del registro de conectores. De forma anloga, el objeto que hace las veces de
inicializador del registro, no tiene por que ser el mismo que representa al conector. Sin embargo, para
simplificar opt por utilizar el mismo. Se espera que en la implementacin del mtodo post_init, se
registre un conector, mientras que el mtodo pre_init se utilice para recolectar y configurar toda la
informacin requerida por el conector a registrar. Existe una implementacin parcial de
ConnectorRegistryInitializer que puede ser utilizada como clase base para la implementacin de
cualquier conector.
De esta forma mi servicio de persistencia propone un mecanismo de configuracin que permite a
cualquier implementacin de conector, incorporarse al registro por medio de una configuracin.
77
Pablo M. Ilardi
class connector
interface
CosPersistentState::ConnectorOperations
~
~
~
~
~
~
~
Local Interface
interface
UnregistrableConnector
+
org.omg.CORBA.Local Interface
org.omg.CORBA.portabl e.IDLEnti ty
reali ze
_ConnectorLocalBase
ConnectorBase
+
+
+
+
+
+
+
+
+
+
+
+
+
i nterface
CosPersistentState::Connector
TransientConnector
+
T ransi entConnector()
PersistentConnector
+
+
El grfico anterior muestra las principales clases que estn relacionadas con el conector. Mi
modelo de registro dinmico de conectores extiende la interfase Connector de CORBA mediante la
interfase: ar.uba.fi.pmi.corba.pss.connector.UnregistrableConnector. La cual permite que los conectores
registrados tengan un callback (llamada) representado por el mtodo onUnregistered, que les permite a
los conectores liberar los recursos que tengan utilizados, cuando la ORB donde se registr el conector,
finalice.
El hecho de que en Java las clases estn representadas por objetos de tipo java.lang.Class
simplifica enormemente el desarrollo. En Java solo se necesita de un objeto de tipo Class para poder
construir un objeto de dicha clase, mientras que en C++, la nica forma de construir una clase es
mediante una llamada explicita a un constructor de la misma mediante cdigo escrito por el
programador. Por esto, las definiciones IDL nativas que hacen referencias a Factory se traducen a objetos
Class en Java, mientras que en C++, se traducen a una clase concreta para cada factory.
La simplicidad del modelo de Java, me permiti crear una implementacin bsica de la interfase
Connector, que es la clase ar.uba.fi.pmi.corba.pss.connector.ConnectorBase y que es funcionalmente
completa. Sin embargo, esta clase est declarada como abstracta, dado que para poder funcionar
correctamente se requiere que el conector conozca el tipo de sesiones que debe crear. Aunque no es
obligatorio heredar de ella para implementar un conector, si es conveniente.
En el diagrama se muestran dos implementaciones del conector TransientConnector y
PersistentConnector, las cuales explico en detalle ms adelante. Bsicamente se trata de las dos
implementaciones que provee mi servicio de persistencia. La primera con soporte de persistencia en
memoria y la segunda en un repositorio persistente ante el reinicio del servidor.
78
Pablo M. Ilardi
Estos mtodos permiten registrar clases para diferentes propsitos en el conector. El primer
mtodo registra la clase que lo representa para un nombre de objeto almacenado. Para estos nombres se
adopta una nomenclatura similar que los nombres de IDL, o sea, la cadena de caracteres comienza con
PSDL:, es seguida por el nombre completo de la clase y finalmente por la versin de la misma. Por
ejemplo, para registrar la clase ar.fi.uba.pmi.corba.pss.test.Persona se deber utilizar un nombre:
PSDL:AR.FI.UBA.PMI.CORBA.PSS.TEST.PERSONA:1.0
, en este caso se registrar la versin 1.0 de la clase Persona.
Para simplificar la generacin de estos nombres proveo la clase ar.uba.fi.pmi.corba.pss.psdl
.PSDLUtils:
class connector
psdl::PSDLUtils
{l eaf}
+
+
+
+
~
+
, que permite generar los nombres en base a la clase que se quiera registrar.
El segundo mtodo register_ del conector es anlogo al primero, permitiendo registrar la clase
que representa un almacn para un nombre dado.
Y finalmente, el tercero de ellos permite registrar la clase que representa una sesin en el
conector. En general, se puede suponer que el conector conoce el tipo de sesiones que puede manejar,
sin tener que indicrselo programticamente. Sin embargo, no es cierto para las clases que representan
almacenes y objetos almacenados. En mi esquema, donde cada tipo de conector tiene su clase que lo
representa, este mtodo no sera necesario. Probablemente sera necesario, si se tiene una nica clase
Connector para todo conector. Al tratarse de un detalle de implementacin del mismo, no debera ser un
79
Pablo M. Ilardi
mtodo pblico del conector dado que el usuario final del servicio no tiene por que conocer cual es la
clase que representa la sesin.
El conector tiene, adems, las siguientes cuatro operaciones:
java.lang.String implementation_id();
byte[] get_pid(Object obj);
byte[] get_short_pid(Object obj);
org.omg.CosPersistentState.Session create_basic_session(
short access_mode, org.omg.CosPersistentState.Parameter[] additional_parameters);
+
+
Param eter()
Param eter(java.l ang.Stri ng, org.om g.CORBA.Any)
pss::SessionParameterBuilder
#
+
#
+
+
+
+
+
+
connector::SessionParametersExtractor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
80
Pablo M. Ilardi
La clase Parameter est definida por dos atributos, el primero es el nombre del parmetro, y el
segundo es su valor, que est representado por un objeto de tipo org.omg.CORBA.Any. La clase Any se
define en CORBA como un contenedor de cualquier tipo de dato u objeto. Esta clase provee operaciones
para transportar el objeto que contenga como valor [CORBA01]. Para trabajar con los objetos de tipo Any
se requiere utilizar algn servicio de CORBA, como por ejemplo, el servicio DynAnyFactory [CORBA01]
(que es una referencia inicial a la ORB). Para mantener encapsulada la creacin y lectura de estos
parmetros proveo dos clases, la primera ar.uba.fi.pmi.corba.pss.SessionParameterBuilder, que
representa la realizacin del patrn de diseo builder de Gamma [Gamma01]. Esta clase captura los
parmetros necesarios para la creacin de la sesin y finalmente con el mtodo build construye un array
de objetos Parameter que podr ser pasado como parmetro, al mtodo create_session del conector.
La otra clase es ar.uba.fi.pmi.corba.pss.connector.SessionParametersExtractor, que permite
recuperar los valores de un array de objetos Parameter. Esta clase es usada internamente por el conector
para extraer los parmetros necesarios para la creacin de la sesin.
Es el tipo de conector quien define cuales nombres de parmetros aceptar (el atributo name de
la clase Any). Este tipo de pasaje de parmetros no restringe cuales son los parmetros vlidos y
requeridos por cada conector. Cada conector deber validar en tiempo de ejecucin, si los parmetros
recibidos son correctos o no, en caso de que no lo sean, lanzar una excepcin de tipo
org.omg.CORBA.PERSIST_STORE.
Tanto la clase que construye la lista de parmetros (SessionParameterBuilder), como la que la
procesa (SessionParametersExtractor), restringen los nombres y tipos de parmetros a los dos
conectores que conocen. Otro conector deber, o bien extender estas dos clases, o proveer otra forma de
generar los parmetros para s mismo.
C REACIN DE OBJETOS
El primer objeto que se necesita crear es la sesin de trabajo y el conector es el encargado de
crearla. En mi implementacin base del conector, la sesin se crea utilizando la clase registrada para tal
efecto. Se requiere solamente que dicha clase tenga un constructor sin parmetros. La clase registrada
debe heredar de la clase ar.uba.fi.pmi.corba.pss.catalog.SessionBase, tambin provista por m. Dicha
clase provee un mtodo initialize, que es llamado inmediatamente luego de la creacin del objeto por el
conector.
Todas las clases base que proveo exponen el comportamiento que deben proveer pero no lo
implementan completamente, es por ello que estn definidas como abstractas. El diseo de estas clases
sigue el patrn de diseo Template Method [Gamma01]. Dicho patrn permite definir un esqueleto de
una clase dejando mtodos que las subclases debern implementar para completar el comportamiento.
Estos mtodos son los llamados template. En el caso concreto de la clase SessionBase, el mtodo
initialize est declarado como final. Internamente initialize llama a otro mtodo protegido de la clase
denominado do_initialize (el template method). Las subclases deben sobrescribirlo, si lo requieren, para
poder realizar alguna inicializacin adicional tal como una conexin a la base de datos. El principal
beneficio del uso de este patrn es que permite un alto grado de reutilizacin de cdigo. En mi caso, me
81
Pablo M. Ilardi
permiti definir varias clases base que pueden ser utilizadas en distintas implementaciones de conectores
del servicio de persistencia.
En el diagrama que se muestra a continuacin se observan todos los template methods que
provee la clase SessionBase. Son todos aquellos que comienzan con el nombre do_xxx.
class ConnectorBases
_ConnectorLocalBase
C:extends ConnectorBase
connector::ConnectorBase
_SessionLocalBase
+
+
+
+
+
+
+
+
+
+
+
+
+
catalog::SessionBase
C:extends ConnectorBase
H:extends AbstractStorageHomeBase
catalog::CommonSessionBase
#
#
#
#
#
#
#
+
after_initialize(H) : H
afterCreateSO(SO) : void
createStorageObjectIdentifier(H, byte[], byte[]) : StorageObjectIdentifier
do_find_storage_home(String) : StorageHom eBase
getHom es() : M ap<String, H>
next_pid() : byte[]
register(SO, StorageObjectSpec, byte[], H) : SO
+
#
+
#
#
#
+
#
#
#
#
#
#
#
+
+
+
+
#
+
+
+
+
+
82
Pablo M. Ilardi
ALMACENES
En este punto cabe plantearse, qu implica crear un almacn? Siendo que los almacenes son
objetos que estn ligados lgicamente al repositorio donde fueron creados originalmente, ya que
almacenan objetos que pertenecen a un nico repositorio. Los almacenes creados en el contexto de una
sesin, son en realidad vistas de los almacenes existentes en el repositorio. Si dos sesiones estn
conectadas con el mismo repositorio debern obtener cada una, una instancia distinta del mismo
almacn. Entonces los almacenes creados son vistas que estn conectadas en tiempo de ejecucin a la
sesin donde fueron creados y mediante ella al repositorio que conecta la sesin.
Existe otra caracterstica de los almacenes que hacen complicada su creacin. Los almacenes
tiene una estructura jerrquica, o sea, dentro de una familia de almacenes, el primer almacn (la raz) en
la jerarqua es capaz de manejar cualquier objeto almacenado dentro de la misma jerarqua.
class storagehome hierarchy
StorageHomeBaseOperati ons
org.omg.CORBA.Local Interface
org.omg.CORBA.portabl e.IDLEnti ty
S:extends SessionBase
DH:extends ExtendedStorageHome
storageHome::AbstractChildStorageHome
i nterface
CosPersistentState::StorageHomeBase
#
#
#
+
#
+
+
+
#
#
+
#
#
#
#
AbstractChil dStorageHome()
afterDestroy(StorageObject) : voi d
beforeDestroy(StorageObject) : voi d
destroy(StorageObj ect) : voi d
destroyReference(StorageObj ect, String, byte[]) : voi d
exist(StorageObject) : bool ean
fi nd_by_short_pid(byte[]) : Object
fi nd_by_short_pid(ExtendedStorageHome, byte[]) : Object
fi nd_ref_by_spec(StorageObjectSpec) : byte[]
getDel egatee() : DH
home_fami ly_id() : Stri ng
i niti al izeChil dHome(S, String, String, String) : AbstractChi ldStorageHome
i niti al izeMe(S, Stri ng, DH, String) : AbstractChi ldStorageHome
i niti al izeRootHome(S, String, Stri ng) : AbstractChil dStorageHome
newSpec() : StorageObjectSpec
i nterface
storageHome::ExtendedStorageHome
+
+
+
+
+
+
+
+
storageHome::
AbstractStorageHomeBase
Lo anteriormente dicho y el hecho de que los almacenes son clases totalmente definidas y
construidas por el compilador PSDL, me llev a definir el siguiente modelo base para todo almacn que
pueda existir dentro de mi servicio de persistencia.
org.omg.CosPersistentState.StorageHomeBase es la interfase definida por CORBA como
almacn, la cual he extendido agregando operaciones adicionales mediante la interfase
ar.uba.fi.pmi.corba.pss.storageHome.ExtendedStorageHome. Estas operaciones me permitieron definir
el comportamiento requerido para cualquier almacn que exista dentro de mi servicio de persistencia. Se
trata de una interfase y no de una clase, ya que cualquier conector es libre de implementarla como
83
Pablo M. Ilardi
corresponda. De todas formas, yo he implementado algunas clases base de esta interfase para maximizar
la reutilizacin de cdigo entre mis dos implementaciones de conector. La clase
AbstractStorageHomeBase, es una implementacin base de dicha interfase. Adems, proveo otras dos
clases, que resuelven el problema de la jerarqua de almacenes y que son:
ar.uba.fi.pmi.corba.pss.storageHome.AbstractChildStorageHome
ar.uba.fi.pmi.corba.pss.storageHome.AbstractRootStorageHome
M ODELO DE D ELEGACIN
Estas dos clases resuelven el problema de la herencia de almacenes mediante la delegacin. La
jerarqua de los almacenes est parcialmente definida por el compilador. Si es el usuario quien define
algn almacn con operaciones, es l mismo quien es responsable de crear una clase que herede de la
clase provista por el compilador, quedando as fuera del control del compilador. Por otro lado, dentro de
una jerarqua pueden existir
mltiples nodos hijos, tal como
class Home Incomplete Hierarchy
muestra el grfico a la izquierda.
CompilerDefinedClasses
PersonStorageHome
VendorStorageHome
ClientStorageHome
UserDefinedClasses
ACMEPersonStorageHome
XXXVendorStorageHome
YYYClientStorageHome
Este modelo de delegacin simplifica el proceso de compilacin, ya que gran parte de las
operaciones que deben implementar los almacenes son delegadas y el compilador slo debe preocuparse
de generar las llamadas al almacn donde se delega. La diferencia entre un almacn que sea raz y otro
que no lo es, est dada por como es inicializado cuando es construido y por el almacn donde se delega.
En el caso que el almacn sea raz de la jerarqua, el almacn donde se delega es una instancia de
AbstractRootStorageHome. Por consiguiente, lo nico que debe considerar el compilador a la hora de
generar el mecanismo de inicializacin de cada almacn, es el mtodo de la superclase que debe llamar
para inicializar dicho almacn.
Este modelo contribuye a la simplicidad del compilador, ya que las clases que deben conocer los
conectores, estn limitadas a las provistas por ellos mismos y no a las clases definidas por los usuarios
mediante el lenguaje PSDL. La delegacin es una tcnica de POO, distinta de la herencia, que permite
tambin un alto grado de reutilizacin [BM0].
OBJETOS ALMACENADOS
84
Pablo M. Ilardi
Los almacenes permiten acceder a los objetos almacenados, ya sea crendolos o recuperando
aquellos que fueron creados anteriormente. Dentro del servicio, los almacenes son los nicos objetos que
permiten crear objetos almacenados que puedan ser persistidos en un repositorio.
El mecanismo de delegacin es necesario tambin para la creacin de objetos, dado que el
compilador no sabe cuales clases sern las registradas por el usuario del servicio, como la que represente
al objeto almacenado para un determinado almacn. Se evita que el compilador genere cdigo para
construir objetos, generando solamente los mtodos que recolectarn los atributos necesarios para la
construccin del objeto almacenado.
Cuando se construye un objeto almacenado tambin existe el problema de su identidad. CORBA
provee dos formas de identificar un objeto almacenado. La primera es un identificador global dentro del
repositorio (Pid) y la segunda es un identificador dentro de la familia de almacenes a la que pertenece
(ShortPid). Los objetos almacenados pueden ser creados como entidades primarias, pero tambin existen
aquellos objetos almacenados que son parte de otros objetos almacenados que los contienen (Embedded
Storage Objects) como atributos (estado) de los mismos. En este ltimo caso, segn la especificacin de
CORBA, estos objetos almacenados no tendrn identidad propia, es decir que no tienen Pid ni ShortPid.
Dichos objetos se denominan Embedded o encastrados. Estos objetos embedded sern objetos creados
manualmente por el usuario y no por medio de un almacn.
class Extended Storage Obj ect
i nterface
Seriali zable
storageObject::StorageObjectSpec
i nterface
storageObject::StorageObjectIdentifier
+
+
+
+
+
+
-parent +
+
+
+
+
+
reali ze
interface
CosPersistentState::StorageObject
+
+
+
+
+
destroy_object() : voi d
get_pi d() : byte[]
get_short_pi d() : byte[]
get_storage_home() : StorageHomeBase
object_exists() : bool ean
real i ze
i nterface
storageObject::ExtendedStorageObject
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
real ize
storageObj ect::StorageObj ectSpecImpl
Entonces los objetos almacenados presentan dos problemas, el primero es la creacin mediante
almacenes o como objetos embedded y el segundo es su identidad. Para tratar con estos problemas
propongo el esquema expuesto en el diagrama anterior.
En el centro del diagrama se muestra la interfase StorageObject provista por CORBA, la cual
debe ser implementada por todo objeto almacenado abstracto definido en PSDL. Yo he extendido dicha
interfase mediante: ar.uba.fi.pmi.corba.pss.storageObject.ExtendedStorageObject. Cualquier objeto
almacenado, ya sea embbeded o no, debe implementar StorageObject y en el caso de los embedded
prcticamente todos los mtodos de la interfase carecen de sentido. Mi interfase extendida agrega tres
85
Pablo M. Ilardi
operaciones que permiten trabajar con objetos almacenados que puedan ser utilizados tanto como
embedded o no. La nica restriccin que agrega mi servicio de persistencia para poder persistir objetos
almacenados, es que implementen esta interfase extendida, quedando a criterio de cada conector del
servicio, como hacerlo. Las operaciones extendidas que agrega mi interfase son:
boolean is_initialized();
void initialize(StorageObjectIdentifier identifier, StorageObjectSpec specification);
StorageObjectIdentifier get_identifier();
Estas operaciones presuponen que la creacin de un objeto en el contexto del servicio de
persistencia tiene dos etapas. La primera es la construccin fsica del objeto y la segunda una fase de
inicializacin del mismo. Cualquier objeto almacenado de mi servicio de persistencia, as sea embedded o
no, debe pasar por estas dos etapas. La diferencia radica en cmo y quin es el que inicializa el objeto.
El segundo mtodo (initialize) tiene dos parmetros. El primero parmetro es un identificador de
objeto y el segundo, una especificacin del objeto a inicializar. A continuacin voy explicar estos dos
conceptos fundamentales de mi servicio.
S TORAGE O BJECT S PEC
Esta interfase representa una especificacin de un objeto almacenado y se utiliza tanto para la
creacin como para la bsqueda de dichos objetos. La bsqueda ser explicada ms adelante. Es una
interfase de uso interno al servicio y los usuarios nunca deben lidiar con ella. Esta interfase provee la
informacin necesaria para construir o buscar un objeto almacenado, lo cul incluye tanto al tipo de
objeto (la clase) como los valores de los atributos que lo definen (estados). La clase
AbstractStorageHomeBase provee un mtodo newSpec, que permite crear un objeto que implementa
esta interfase. Este objeto puede ser
utilizado por los mtodos internos
public Two createNamed(String nameTwo, One one) {
generados por el compilador.
El
StorageObjectSpec spec = this.newSpec();
spec.set_string("nameTwo", nameTwo);
segmento de cdigo a la izquierda
spec.set_storageObject("one", one);
representa
un
factory
method
return (Two)this.create(spec);
[Gamma01] llamado createNamed de un
}
almacn generado por el compilador. Este
objeto almacenado tiene dos atributos
nameTwo y one que son pasados como parmetro al mtodo. La primer lnea crea una nueva
especificacin que en las siguientes lneas es cargada con los parmetros de entrada del mtodo.
Finalmente la creacin del objeto es delegada en el mtodo create que recibe tan solo la especificacin
de que debe crear. Esta forma de comunicacin simplifica y generaliza la lgica del compilador, ya que
toda la complejidad de la creacin del objeto est resuelta en la superclase y no en la clase generada por
el compilador.
S TORAGE O BJECT I DENTIFIER
La idea de un identificador de objetos es un concepto que agrega el servicio de persistencia de
CORBA. En el modelo de objetos de Java, los objetos no tienen identificadores. La identidad de los
objetos slo est garantizada a nivel de instancia. Para el operador == de Java, un objeto es igual a otro, si
y solo si, se trata de la misma instancia. Aunque Java tambin provee un mtodo equals (iguales en
ingls), que permite comparar dos objetos por algn criterio distinto de la instancia misma. De todas
formas para la clase Object de Java, el mtodo equals, solo devuelve verdadero cuando se trata de la
misma instancia. Si se quiere utilizar otro criterio de comparacin, las clases deben redefinir dicho
mtodo.
86
Pablo M. Ilardi
Los primeros cinco mtodos son importados de la interfase StorageObject. Esto permite que el
compilador delegue la implementacin de la interfase StorageObject en el atributo que represente al
identificador del objeto almacenado. Los siguientes dos mtodos, permiten tratar a un objeto
almacenado como embedded. El primero indica si el objeto identificado por este objeto es un objeto
almacenado embedded. El segundo le permite a un objeto almacenado inicializar a otro objeto
almacenado que representa un atributo embedded en l. Luego de llamar a este mtodo, el objeto
storageObject, quedar marcado como embedded dentro del objeto identificado.
Los ltimos tres mtodos son tiles para tratar con copias/instancias de los objetos que fueron
persistidos en el repositorio. Los dos primeros mtodos comparan objetos almacenados por sus
identificadores y el ltimo permite conectar una instancia de objeto almacenada con el catalogo o sesin
donde existe o ser utilizado. Esta ltima operacin es necesaria, ya que cuando una instancia es
recuperada de un repositorio persitente es cuando se puede determinar a que catlogo pertenece. Esta
informacin solo es til para una instancia de objeto activa dentro de un catlogo, por lo que no debe ser
persistida en el repositorio.
87
Pablo M. Ilardi
El otro problema que tienen que resolver los conectores y tambin el servicio en s mismo, es la
bsqueda de objetos. La bsqueda implica encontrar los objetos almacenados y los almacenes que ya
fueron creados previamente en el servicio. La especificacin de CORBA define algunas operaciones de
bsqueda estndar, tales como las expuestas en el cuadro anterior. Estas operaciones son relativamente
simples de resolver. La bsqueda de almacenes se limita a buscar en un ndice de almacenes creados
dentro de una sesin y si no existe, crearlo acorde al registro de almacenes. Esta funcionalidad est
implementada en la clase CommonSessionBase vista anteriormente. Las dos operaciones siguientes
dependen del conector.
Existe un tipo de operaciones de bsquedas ms complejas. Son aquellas que se definen
automticamente al definir claves dentro de un almacn. Cada definicin de clave define implcitamente
dos operaciones de bsqueda por los atributos que conforman la clave. La primera busca el objeto
almacenado y la segunda una referencia al objeto que est identificado por la clave.
S find_by_key_name(<parameter_list>) raises (CosPersistentState::NotFound);
ref<S> find_ref_by_key_name(<parameter_list>);
Estas operaciones requieren que los conectores provean una forma eficiente de realizar
bsquedas genricas por atributos de los objetos almacenados dentro de un almacn particular. Deben
ser genricas, ya que los conectores no conocen las claves que pueden definir los almacenes en tiempo
de diseo. Ms adelante explicar como cada conector en particular, resuelve estas operaciones.
Estas operaciones de bsqueda son necesarias en el momento de creacin de los objetos
almacenados para poder garantizar la unicidad de las claves.
V ALIDACIN DE C LAVES
La especificacin de CORBA define el concepto de clave, su significado y el cdigo que se genera
en cada lenguaje. No especifica el comportamiento esperado. Por ejemplo, las claves definen la unicidad
de los objetos dentro de un almacn o familia de ellos, pero no se especifica que sucede cuando no se
cumple la restriccin que impone alguna de las claves, ni tampoco, cuando deben verificarse estas
restricciones.
Dado que la especificacin es particularmente amplia en este sentido, he optado por definir un
mecanismo de validacin de las claves que puede ser disparado en diferentes momentos. Los conectores
pueden optar por redefinir o extender este comportamiento segn sus necesidades, definiendo cuando
ser utilizado. El modelo base obliga a que se verifiquen las claves cada vez que se construya un objeto,
generalmente, sern necesarias verificaciones adicionales.
Las cuatro clases representadas en el diagrama siguiente, modelan el comportamiento necesario
para la validacin de las claves definidas por una familia de almacenes. StorageHomeKeySet es una clase
abstracta cuyo objeto es el de recolectar el conjunto de claves, cada una representada por la interfase
StorageHomeKey, definidas por una familia de almacenes. Para ello cuentan con el soporte de la clase
StorageHomeKeyBuilder (patrn de diseo Builder [Gamma01]), que permite construir las claves definida
en los almacenes.
La clase AbstractStorageHomeBase define el mtodo:
protected void collectKeys(StorageHomeKeySet keySet)
, que se deber ser sobrescrito en cada uno de los almacenes que defina al menos una clave.
88
Pablo M. Ilardi
class storageHome
StorageObjectSpec
H:extends ExtendedStorageHome
interface
StorageHomeKey
StorageHomeKeySet
+
+
+
+
getName() : String
-set
real ize
StorageObjectSpecImpl
StorageHomeKeyImpl
StorageHomeKeyBuilder
+
+
+
+
+
+
89
Pablo M. Ilardi
DIFERENTES CONECTORES
Ya mencion anteriormente que he construido dos conectores del servicio de persistencia. La
razn principal para ello es la forma que he desarrollado el servicio. El primer conector que provee
persistencia temporal, es la implementacin ms simple que cumple con todos los requerimientos del
servicio. Este conector se us para construir el servicio y el compilador a la par.
interface
memory::
TransientTargetCompiler
memory::TransientStoragetHome
+
+
StorageHomeKeySet
memory::TransientStorageHomeKeySet
realize
reali ze
AbstractRootStorageHome
memory::
TransientRootStorageHome
{leaf}
AbstractChildStorageHome
memory::TransientStorageHomeBase
+
+
+
CommonSessionBase
+
+
dettach(StorageObject) : void
T ransientSession()
ConnectorBase
ExtendedStorageObject
catalog::TransientSession
connector::
TransientConnector
interface
memory::TransientStorageObject
+
T ransientConnector()
El diagrama anterior muestra el esquema general de las clases que componen al conector. Todo
conector debe proveer una contribucin al compilador para que este pueda generar cdigo para l. La
90
Pablo M. Ilardi
contribucin consiste en la clase TransientTargetCompiler, junto con las plantillas de cdigo que utilizar
el compilador para generar el cdigo fuente.
El compilador requiere, adems, que la contribucin sea registrada en su archivo de configuracin
(pss_pmi_compiler.properties):
registered=transient
transient=ar.uba.fi.pmi.corba.pss.psdl.compiler.memory.TransientTargetCompiler
transient.templateProperties=psdl_transient_templates.properties
El conector debe tener su registro en el servicio de persitencia, con una clase que implemente la
interfase ConnectorRegistryInitializer. La interfase est implementada por el conector mismo, y es:
ar.uba.fi.pmi.corba.pss.connector.TransientConnector
El conector se registra en el archivo pss_pmi_registry.properties, mediante la siguiente lnea:
PSSPMIConnector.ar.uba.fi.pmi.corba.pss.connector.TransientConnector=Transient
Habiendo agregado esta ltima lnea, el conector ya est listo para ser utilizado en tiempo de
ejecucin.
F UNCIONAMIENTO
La funcionalidad del conector est provista mayormente por la sesin de trabajo que provee. La
clase que representa una sesin en el conector temporal es TransientSession. Esta clase hereda de la
implementacin base de la sesin mencionada anteriormente: CommonSessionBase, que resuelve la
administracin de almacenes de una manera simple, por lo que lo nico que le queda resolver es la
construccin y manejo de objetos almacenados.
MANEJO DE IDENTIFICADORES
El primer problema que se necesita resolver, para la creacin de objetos almacenados, es la
asignacin de identificadores de objeto, tanto para el Pid como para el ShortPid. La especificacin indica
que para Java los identificadores se traducen en un byte[], lo cual hace complicada su manipulacin
directa. Para la generacin de identificadores que estn representados por un byte[], proveo la interfase
ByteArraySequencer, que permite obtener secuencias de identificadores en dicho formato.
class utils
interface
ByteArraySequencer
~
next() : byte[]
realize
SimpleByteArraySequencer
+
+
+
BinaryUtils
next() : byte[]
use
Sim pleByteArraySequencer()
Sim pleByteArraySequencer(initialValue)
+
+
91
Pablo M. Ilardi
BinaryUtils. La sesin del conector tiene una instancia de esta clase para generar los identificadores
globales (Pid) de los objetos almacenados y a su vez cada familia de almacenes que se use en la sesin,
tendr otra instancia de este tipo de secuenciador.
ALMACENES TEMPORALES
El conector temporal extiende la interfase de almacn de CORBA mediante
TransientStoragetHome. Esto implica que todo almacn generado por este conector deber implementar
dicha interfase. Existen dos clases base la implementan que son: TransientRootStorageHome y
TransientStorageHomeBase. La primera representa la raz de una familia de almacenes y la segunda la
clase base para todo almacn generado por el compilador de este conector. El modelo de almacenes
temporales sigue el modelo de delegacin propuesto inicialmente por mi servicio.
Cada almacn raz de una familia de almacenes tiene un atributo SimpleByteArraySequencer,
que es utilizado para generar los identificadores objeto (ShortPid).
Para mantener los objetos almacenados dentro de la sesin cada almacn raz tiene un mapa
donde almacena los objetos que fueron creados durante la sesin. Dicho mapa est indexado por el
identificador ShortPid.
OPERACIONES DE BSQUEDA
La clase AbstractChildStorageHome define el mtodo:
protected abstract byte[] find_ref_by_spec(StorageObjectSpec spec);
, que permite buscar una referencia a un objeto almacenado que cumpla con la especificacin dada. Los
conectores deben implementar dicha operacin. En el caso de este conector, la implementacin ms
simple es iterar sobre todos los objetos almacenados dentro de la familia del almacn, representados por
los valores del mapa de la raiz y verificando si alguno de ellos cumple con la especificacin dada. Para ello,
la interfase TransientStorageObject, define el mtodo matches, que permite determinar si el objeto
almacenado cumple con la especificacin dada.
Cualquier operacin de bsqueda en este conector se traduce en construir una especificacin
con los atributos que se estn buscando, para luego llamar al mtodo find_ref_by_spec del almacn
donde se realizar el proceso anteriormente descrito.
La clase TransientStorageHomeKeySet es la encargada de realizar las validaciones de claves. Esta
clase utiliza el mismo mecanismo de bsqueda para buscar referencias a objetos que cumplan con la
definicin de la clave.
92
Pablo M. Ilardi
existiendo en la nueva sesin. Todas las operaciones de consulta definidas por el servicio de persistencia
deben tambin estar soportadas. Y las claves definidas en el modelo debern ser igualmente respetadas.
El repositorio deber permitir ms de una conexin o sesin concurrente.
Es importante recalcar que el servicio de persistencia de CORBA no tiene el objeto de reemplazar
una base de datos, por lo general los repositorios no contendrn una gran cantidad de objetos.
El acceso remoto al repositorio es un adicional, ya que el servicio de persistencia no lo impone
como requerimiento, aunque si constituye una cualidad muy til.
Antes de entrar en los detalles de mi conector persistente, voy a realizar un anlisis de las
distintas alternativas que consider para lograr persistencia durable.
93
Pablo M. Ilardi
almacenar en este caso, no son datos relacionales, sino un modelo de objetos. Se requiere una
transformacin bidireccional entre los objetos y el modelo relacional de tablas y registros.
Las bases de datos relacionales utilizan el lenguaje de consulta SQL. Las consultas deben
realizarse sobre un modelo que las soporte. Dicho modelo deber ser generado por el compilador y ms
especficamente, por la contribucin del conector persistente relacional al compilador. Si bien el lenguaje
de consultas es generalmente estndar, para todas las bases de datos, el lenguaje de definicin del
modelo (DDL o Data Definition Language) no lo es. Esto implica que no slo se deber construir un
conector para bases de datos relacionales, sino que el conector deber considerar cual es la base de
datos que se quiere utilizar.
Dado que el compilador ser quien defina el modelo relacional a utilizar, se requiere entonces
que dicho modelo sea creado en la base de datos propiamente dicha. Hasta que no est creado el
modelo, no se podr utilizar el servicio de persistencia con el conector. Se agrega entonces un paso
posterior a la compilacin, para poder utilizar el servicio de persistencia.
Existen herramientas o bibliotecas que simplifican el uso de bases de datos relacionales para la
persistencia de objetos. Tal es el caso de: Hibernate [KingG01], Castor[Castor01], Toplink[Toplink01],
JDO [RoodsR01], entre otras. Son denominadas genricamente ORM (Object-relation Mapping) o mapeo
de objeto-relacin.
En estos modelos, por lo general, una instancia de una clase particular representa un registro en
una o ms tablas, dependiendo de la jerarqua de la clase. Cada atributo persistente de la clase est
representado por una o ms columnas en una tabla. Todas ofrecen un mecanismo de consulta de alto
nivel, que termina generando consultas SQL con las que se interacta con la base de datos. De esta
forma, el usuario no est obligado a tratar en forma directa con SQL. Algunas de estas herramientas
resuelven las diferencias de sintaxis particular de DDL para cada base de datos mediante mecanismos de
extensin por el usuario y otras slo funcionan con algunas bases de datos fijas. La relacin entre el
modelo de objetos y el modelo relacional, el mapeo de objetos, est definida, por lo general, en una
configuracin en forma de archivo XML, aunque algunas de ellas soportan este mapeo a travs de
anotaciones en las clases Java [Annotations01].
Algunas herramientas como Hibernate o Toplink, soportan persistencia transparente, de forma
tal que no imponen restricciones o requerimientos sobre las clases que se pueden persistir. A este tipo de
persistencia se lo llama genricamente POJO (Plain Old Java Objects o Viejos y simples objetos Java)
dado que cualquier objeto comn Java puede ser persistido. JDO, en cambio, requiere de un poscompilador, que modifica las clases generadas por el compilador para que puedan ser persistidas.
O bien mediante el uso de alguna herramienta como las mencionadas, o mediante la
construccin de otra herramienta, un conector para una base de datos relacional es perfectamente
viable.
El principal problema del uso de una base de datos relacional, es tener que coexistir con dos
modelos distintos, pero que representan lo mismo [NewardT01]. Es necesario crear otro modelo
(relacional) anlogo al modelo de objetos. Si se cambia el modelo de objetos, se debe cambiar el modelo
relacional, cada vez que se guarda un objeto se debe traducir al modelo relacional y cuando se lee del
modelo relacional se debe volver a transformar en objetos.
Otro punto a considerar es que el modelo en la base de datos relacional es visible al usuario, esto
expone los detalles de la implementacin del conector. Lo que tambin podra fomentar que el usuario
interactu con el modelo relacional directamente, creando as una dependencia con la implementacin
94
Pablo M. Ilardi
del conector. Esta dependecia de la implementacin viola las polticas de CORBA y de la especifcacin del
servicio de estado persistence.
95
Pablo M. Ilardi
class db4o
Db4o
+
+
+
+
+
+
+
configure() : Configuration
licensedTo(String) : void
main(String[]) : void
openClient(String, int, String, String) : ObjectContainer
openFile(String) : ObjectContainer
openServer(String, int) : ObjectServer
version() : String
interface
ObjectContainer
opens
starts
opens
interface
ObjectServer
+
+
+
+
close() : boolean
ext() : ExtObjectServer
grantAccess(String, String) : void
openClient() : ObjectContainer
+
+
+
+
+
+
+
+
+
+
+
+
+
El mtodo openFile abre una conexin directa a un archivo que representa la base de datos. Esta
forma de conexin no admite interaccin remota con la base datos. Para permitir que clientes remotos
accedan a la base de datos, se debe iniciar un proceso servidor, representado por la interfase:
com.db4o.ObjectServer.
El mtodo openServer de la clase Db4o crea una instancia de servidor, que escuchar en el
puerto indicado, permitiendo conexiones a la base de datos que represente el archivo indicado, tanto
locales como remotas. Para obtener acceso local a la base de datos, la interfase ObjectServer, provee el
mtodo openClient.
La nica diferencia entre el acceso local y remoto, es cmo se establece la conexin. Una vez
establecida la conexin, no existe diferencia alguna para el usuario. La conexin est representada por la
interfase: com.db4o.ObjectContainer. Esta interfase provee mtodos para almacenar, buscar y eliminar
objetos.
GUARDANDO OBJETOS
Para indicarle a la base de datos que un objeto debe ser almacenado, ObjectContainer provee el
mtodo set, que recibe como parmetro el objeto a almacenar. Cada vez que se llame a este mtodo con
un nuevo objeto, o sea que no fue obtenido de la base de datos mediante una consulta, se estar
almacenando un nuevo objeto.
Durante la vida de la conexin, la identidad del objeto est garantizada nicamente por la
instancia del objeto. Si se llama a set, con el mismo objeto dos veces, la segunda vez, se le indicar a la
base de datos que actualice el estado del objeto previamente almacenado.
RECUPERANDO OBJETOS
Se proveen diferentes mecanismos para recuperar objetos de la base de datos en funcin de la
complejidad de la consulta.
La forma ms simple, se la denomina Consulta por Ejemplo o QBE (Query By Example). La idea
es crear un objeto prototipo, con los atributos de aquellos objetos que se quieren recuperar, llamando
al mtodo get de ObjectContainer. Dicha operacin devolver una instancia de la interfase ResultSet, que
es un conjunto de resultados. Para todo objeto dentro del conjunto resultado, se cumple que los
96
Pablo M. Ilardi
atributos del objeto prototipo son iguales a los del objeto del conjunto. La condicin evala aquellos
atributos del objeto prototipo que tienen un valor distinto del valor por defecto del tipo de atributo. Se
entiende por valor por defecto, al valor que asigna la mquina virtual de Java al inicializar un atributo de
dicho tipo. Por ejemplo, para un atributo de tipo int, el valor por defecto es 0, mientras que para un
atributo de tipo java.lang.Integer, el valor es null. Este tipo de consultas slo permiten concatenar
condiciones por positivo, donde todos los atributos del objeto prototipo deben coincidir con los
resultados.
Para realizar consultas mas avanzadas, se provee otro mecanismo llamado Consultas Nativas o
NQ (Native Query). Se las denomina nativas, porque permite realizar consultas a la base de datos
mediante condiciones escritas en el lenguaje de programacin, en este caso Java [CookWR01]. El
principal beneficio de este tipo de consultas, es que estn escritas en el mismo lenguaje. Lo que implica
que son compiladas, haciendo que los cambios en el modelo produzcan un error de compilacin cuando
la consulta no los refleja. A su vez, evitan introducir un nuevo lenguaje para expresar la consulta, tal como
en el caso de realizarse consultas SQL sobre una base de datos relacional, para obtener resultados que
luego sern traducidos a objetos. Las consultas nativas estn representadas por la clase
com.db4o.query.Predicate (predicado).
Para realizar una consulta, tan slo se requiere sobrescribir el mtodo match de la clase
Predicate, que recibe como parmetro un objeto, el cual ser comparado mediante las condiciones que
determine el predicado. En el ejemplo siguiente, se muestra un predicado en el que la condicin evala
que las personas tengan un nombre igual a Pablo o PABLO.
Predicate personasConNombrePablo = new Predicate<Persona>() {
public boolean match(Persona persona) {
return persona.getName().equals("Pablo") || persona.getName().equals("PABLO");
}
};
Esta forma de realizar consultas es muy atractiva en aquellos casos en los que la consulta est
completamente definida, pero qu pasa en aquellos casos en los que la consulta se define en tiempo de
ejecucin, en funcin de diferentes parmetros?, donde se deben realizar consultas dinmicas. En estos
casos, se provee una interfaz ms avanzada para la construccin de consultas dinmicas, basada en otro
proyecto de cdigo abierto llamado S.O.D.A (Simple Object Database Access o acceso simple de objetos
en base de datos) [SODA01].
SODA trata de proveer una interfase orientada a objetos, que permite construir consultas
dinmicas. Tratando as de minimizar el uso de cadenas de caracteres para realizar consultas, y maximizar
las ventajas que el paradigma de objetos provee, como reutilizacin y encapsulamiento.
Las consultas estn representadas por la interfase com.db4o.query.Query y son creadas por el
ObjectContainer. El mtodo descend de Query, permite navegar los atributos de los objetos, de forma tal
de estableces restricciones (Constraint) sobre ellos. La interfase Constraint representa una restriccin
que se aplica sobre un atributo de los objetos. El mtodo constraint de Query recibe el valor del atributo
y alguna de las operaciones de Constraint determina el tipo de restriccin que se aplica sobre el par
atributo-valor. Por ejemplo, el mtodo greater (mayor) representa que el atributo navegado deber ser
mayor que el valor utilizado como parmetro en la llamada a constraint (la cual cre originalmente el
objeto Constraint).
97
Pablo M. Ilardi
Serializable
interface
Constraint
QueryComparator
+
+
+
+
+
+
+
+
+
+
+
+
+
sorts by
creates
interface
Query
+
+
+
+
+
+
+
interface
Constraints
+
toArray() : Constraint[]
98
Pablo M. Ilardi
activationDepth(int) : void
objectClass(Object) : ObjectClass
setOut(PrintStream) : void
singleThreadedClient(boolean) : void
testConstructors(boolean) : void
timeoutClientSocket(int) : void
timeoutPingClients(int) : void
timeoutServerSocket(int) : void
unicode(boolean) : void
updateDepth(int) : void
weakReferenceCollectionInterval(int) : void
weakReferences(boolean) : void
access
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
callConstructor(boolean) : void
cascadeOnActivate(boolean) : void
cascadeOnDelete(boolean) : void
cascadeOnUpdate(boolean) : void
compare(ObjectAttribute) : void
enableReplication(boolean) : void
generateUUIDs(boolean) : void
generateVersionNumbers(boolean) : void
maximumActivationDepth(int) : void
minimumActivationDepth(int) : void
objectField(String) : ObjectField
persistStaticFieldValues() : void
readAs(Object) : void
rename(String) : void
storeTransientFields(boolean) : void
translate(ObjectTranslator) : void
updateDepth(int) : void
interface
ObjectField
access
+
+
+
+
+
+
cascadeOnActivate(boolean) : void
cascadeOnDelete(boolean) : void
cascadeOnUpdate(boolean) : void
indexed(boolean) : void
queryEvaluation(boolean) : void
rename(String) : void
El servicio de persistencia necesita adems, de una configuracin para soportar este conector.
Por esto, este conector agrega al archivo de configuracin del servicio, la lnea que indica la clase que ser
responsable de procesar el registro del conector, que en este caso es: PersistentConnector.
PSSPMIConnector.ar.uba.fi.pmi.corba.pss.connector.PersistentConnector=Persistent
FUNCIONAMIENTO
Las sesiones que crea el conector estarn representadas por la clase PersistenSession. Una
sesin se conecta a un DataStore por medio de la interfase DataStoreConnection. Existen dos clases
99
Pablo M. Ilardi
ObjectContainerFactory
+
create() : ObjectContainer
realize
DataStoreConnection
close() : void
createQuery() : Query
doAttomicOperation(operation) : void
flush(object, introspectionLevel) : void
getContainer() : ObjectContainer
interface
AttomicDataStoreOperation
+ doOperation(container) : void
-factory
-connection
realize
DataStore
+
+
+
+
+
+
AbstractDataStoreConnection
connectionClosed(connection) : void
create() : ObjectContainer
DataStore(fileName)
DataStore(fileName, user, password, port)
openConnection() : DataStoreConnection
shoutDown() : void
+
+
+
+
+
+
AbstractDataStoreConnection(factory)
close() : void
createQuery() : Query
doAttomicOperation(operation) : void
flush(object, introspectionLevel) : void
getContainer() : ObjectContainer
CommonSessionBase
PersistentSession
+
+
+
+
createQuery(operation) : Query
destroy(storageObject) : void
doAttomicOperation(purpose, operation) : void
exist(storageObject) : boolean
-server
LocalDataStoreConnection
+
+
RemoteDataStoreConnection
close() : void
LocalDataStoreConnection(server)
Cuando se crea una sesin, sta recibe como parmetro un objeto que implementa
DataStoreConnection, que ser provisto por el conector. El conector se vale de las clases
SessionParameterBuilder y SessionParametersExtractor, para recibir e identificar los parmetros
(representados por la clase Parameter), que definen el tipo de conexin que debe crear.
La interfase DataStoreConnection permite que la sesin sea completamente independiente del
tipo de conexin que se utilice, dado que todas las operaciones contra el DataStore se realizan a travs
de dicha interfase.
R ELACIN CON DB4O
La conexin que tiene asociada una sesin, permite acceder al ObjectContainer de DB4O, que
ser utilizado internamente para almacenar y recuperar los objetos. El hecho de que el conector utilice
DB4O para mantener el estado est oculto a los ojos del usuario final del servicio. Esto se debe a que un
usuario final siempre interactuar con las interfases provistas por el servicio de CORBA, sin tener que
lidiar nunca con mis implementaciones de ellas, ni con sus detalles.
O BJETOS CON ES TADO COMPAR TIDO
Para acceder a un almacn registrado en el conector, ser necesario considerar algunos
problemas que no se presentaban en el conector de memoria. Existe una diferencia fundamental entre el
conector de memoria y el persistente, si bien todo objeto tiene estado (definido por sus atributos), en el
conector persistente, los objetos pueden ser compartidos por mltiples sesiones. Esta caracterstica hace
que se deba tener particular cuidado en como se accede a estos objetos en forma concurrente.
El repositorio en s mismo, tiene atributos que definen un estado que est compartido por todas
las sesiones que lo acceden. El estado est definido fundamentalmente por tres atributos: cuales
100
Pablo M. Ilardi
almacenes fueron creados en el repositorio, cuales objetos almacenados fueron creados en los
almacenes del repositorio y una secuencia. La secuencia permite obtener un identificador global dentro
del repositorio, que es asignado a los objetos almacenados al momento de su creacin.
I DENTIFICADORES
El conector persistente se basa en el mecanismo general propuesto por el servicio para identificar
los objetos, mediante la clase: PersistentStorageObjectIdentifier, que implementa la interfase
StorageObjectIdentifier.
Como mencion anteriormente, el modelo de objetos de Java no provee el concepto de
identificador, por esto DB4O no recomienda el uso de identificadores y no provee mecanismos para su
generacin automtica. Las bases de datos relacionales proveen mecanismos eficientes para la
generacin de secuencias de nmeros, como pueden ser tipos de datos autoincrementados. Estos
mecanismos soportan acceso concurrente y transaccional a las secuencias de forma tal que dos o ms
operaciones concurrentes obtengan identificadores distintos.
El modelo general del servicio de persistencia provee una clase que permite generar secuencias
de bytes, ByteArraySequencer. El conector persistente debe garantizar el acceso concurrente y
transaccional a dicha clase para proveer identificadores vlidos.
La forma ms simple de garantizar el acceso concurrente, es serializar el acceso a la operacin
next del objeto secuencia. Esto se logra comnmente mediante el uso de un semforo [Conc01]. Un
semforo es una construccin que garantiza el acceso nico a un recurso o segmento de cdigo, en este
caso a la secuencia. Cuando uno o ms usuarios quieren acceder en forma simultnea a un recurso, el
semforo slo permitir el paso de uno de ellos, bloqueando a los siguientes, hasta que el usuario actual
del recurso lo libere. En Java, los semforos estn encapsulados dentro del lenguaje, cada objeto tiene un
atributo (no visible al usuario) que representa un semforo. Este semforo se utiliza mediante la palabra
clave synchronized, que indica que slo un Thread podr ejecutar el cdigo dentro del bloque
sincronizado.
La clase ByteArraySequencer garantiza el acceso concurrente a ella sincronizando el acceso al
mtodo next. Pero slo sern sincronizados los Threads que se ejecuten dentro de la misma mquina
virtual y sobre la misma instancia de objeto.
Para crear un objeto, se requieren dos identificadores provistos por dos secuencias distintas, el
primero es la secuencia global de identificadores del repositorio y el segundo la secuencia para la familia
de objetos almacenados a la que pertenezca el objeto. Esto ltimo implica que las secuencias sern
compartidas por distintas conexiones a un mismo repositorio y dichas conexiones pueden ser incluso
realizadas desde otras mquinas. Por esto el mecanismo original de sincronizacin de las secuencia es
insuficiente en este escenario.
O PERACIONES ATMICAS
Para garantizar la atomicidad de este tipo de operaciones (generacin de identificadores y otras),
proveo una interfase llamada AtomicDataStoreOperation. Esta interfase representa una operacin que
podr ser realizada en forma atmica en un DataStore. Una operacin atmica es aquella que slo tiene
dos posibles resultados. Exitoso en cuyo caso el contexto queda modificado y fallido, en donde el
contexto queda en el mismo estado que antes de realizar la operacin. El objetivo de esta interfase es
permitir operaciones que no alteren el contexto actual, sino que hagan uso de informacin obtenida
como resultado de la operacin.
101
Pablo M. Ilardi
class content
interface
ContentLocator
persistent::AtomicDataStoreOperation
+
locate(container, template) : I
C:extends Obj ect
#locator
IdentifiedContent
real ize
I:extends IdentifiedContent
AtomicDataStoreOverContentOperation
+
#
+
#
#
#
AtomicDataStoreOverContentOperation(initi al)
commitBeforeUnlocking() : boolean
doOperation(container) : void
getInitial Content() : I
getWaiteTimeOut() : int
operate(container, restored, blocked) : boolean
#
#
+
+
+
+
+
+
+
+
assertInitialized() : void
assertNotInitialzed() : void
getContent() : C
getId() : String
IdentifiedContent()
IdentifiedContent(id, content)
isInitialized() : boolean
setContent(content) : void
setId(id) : void
toString() : Stri ng
ByteArraySequencerContent
ByteArraySequencerOperation
+
+
#
ByteArraySequencerOperation(id)
getValue() : byte[]
operate(container, restored, blocked) : boolean
+
+
+
+
ByteArraySequencerContent()
ByteArraySequencerContent(id)
ByteArraySequencerContent(id, content)
next() : byte[]
102
Pablo M. Ilardi
ubicar el contenido con el ContentLocator, si el contenido no existe, se crear para ser almacenado en el
contendor. Sobre el contenido se realiza la operacin necesaria, mediante el mtodo operate de la
operacin. Se almacena el resultado como atributo del objeto, luego se finaliza la operacin liberando el
semforo y se cierra la conexin.
Esta forma de ejecucin garantiza que una nica operacin pueda ser realizada sobre el mismo
repositorio y sobre el mismo contenido en forma concurrente. Las operaciones son genricas y pueden
ser aplicadas a cualquier proceso que requiera acceso exclusivo sobre un contenido del repositorio.
Esta forma de garantizar acceso concurrente, se denomina genericamente bloqueo pesimista
[RoySeif01] dado que se realiza el bloqueo del semforo cada vez que se quiere acceder al recurso
compartido. En un esquema optimista se tiene la premisa que la mayora de las operaciones no
interferirn entre ellas, por lo que no es necesario realizar un bloqueo inicialmente. De todas formas, se
tiene que garantizar que en el caso de que las operaciones interfieran, los resultados sern correctos. En
este caso no se deberan tener dos identificadores iguales en distintas operaciones. En el esquema del
identificador global, es altamente probable que las operaciones interfieran entre s, dado que existe un
nico identificador global por repositorio. Y por otro lado, se entiende que el servicio de estado
persistence no tendr una cantidad masiva de conexiones remotas concurrentes, por lo que no es tan
crtico que el tiempo consumido por la operacin de creacin sea mnimo. Adems el bloqueo optimista
es ms complicado de implementar, es por esto y lo anteriormente dicho que consider al bloqueo
pesimista como la mejor opcin para este caso.
A LMACENES
Este conector tambin sigue el esquema de delegacin propuesto inicialmente
Todo almacn de objetos que utilice este conector debe implementar
PersistentStorageHome. Esta interfase permite que el conector implemente el mismo
delegacin que el conector de memoria, extendiendo a la interfase base
ExtendedStorageHome.
por el servicio.
la interfase:
mecanismo de
del servicio:
AbstractTargetCompiler
interface
persistent::PersistentTargetCompiler
persistent::PersistentStorageHome
+
+
create(PersistentStorageHome, PersistentStorageHomeKeySet) : SO
find_by_spec(PersistentStorageHome, StorageObjectSpec) : SO
StorageHomeKeySet
persistent::PersistentStorageHomeKeySet
+
realize
ConnectorBase
realize
connector::PersistentConnector
AbstractRootStorageHome
persistent::
PersistentRootStorageHome
{leaf}
+
+
AbstractChildStorageHome
persitent::PersistentStorageObj ectIdentifier
persistent::PersistentStorageHomeBase
+
+
+
create(PersistentStorageHome, PersistentStorageHomeKeySet) : SO
find_by_spec(PersistentStorageHome, StorageObjectSpec) : SO
PersistentStorageHomeBase()
CommonSessionBase
+
+
+
+
+
+
createConstraint(Query) : Constraint
getLong_pid() : Long
getLong_short_pid() : Long
PersistentStorageObjectIdentifier(PersistentStorageHome)
PersistentStorageObjectIdentifier(byte[], byte[], PersistentStorageHome)
PersistentStorageObjectIdentifier(byte[], byte[], String, String)
persistent::PersistentSession
+
+
+
+
persistent::SpecToConstraintTransformer
createQuery(String) : Query
destroy(StorageObject) : void
doAtomicOperation(String, AtomicDataStoreOperation) : void
exist(StorageObject) : boolean
transform(StorageObjectSpec) : Constraint
103
Pablo M. Ilardi
Existen
dos
implementaciones
base
de
dicha
interfase,
la
primera
es
PersistentStorageHomeBase que es utilizada como clase base por el generador de cdigo del conector.
Todo almacn generado por el compilador heredar directa o indirectamente de esta clase. La otra
implementacin es PersistentRootStorageHome, que representa a la familia de almacenes para un tipo
de objeto almacenado que no tenga un supertipo.
El nico estado de los almacenes que se mantiene en los repositorios es la secuencia que
permite generar identificadores para la familia. Cada conexin a un repositorio tendr sus propias
instancias de los almacenes, pero todas ellas compartirn los mismos juegos de secuencias mediante
objetos de tipo ByteArraySequencerOperation, que utilizarn secuencias identificadas por los
identificadores de las familias de almacenes. De manera anloga, cada sesin que se conecte a un
repositorio tendr como atributo una operacin atmica que permitir generar identificadores globales
para el repositorio. Esta operacin utilizar un identificador especial reservado para la secuencia global.
O PERACIONES DE CONSULTA
Las operaciones de consultas se realizan utilizando una de las interfases que provee DB4O para tal
efecto. Dado que el usuario final no conoce esta interfase, ser necesario que el compilador genere el
cdigo necesario para construir las consultas para el servicio.
Las consultas que debe generar el compilador estn definidas principalmente por las operaciones
de bsqueda que se deriven de la definicin PSDL compilada. Estas consultas son dinmicas en el sentido
de que varan en funcin de la jerarqua de objetos que presenten los almacenes. Por esto, no pueden ser
generadas en su totalidad por el compilador, ya que ste slo tiene una vista parcial del esquema, que
est dada por el archivo PSDL que est procesando.
En consecuencia, es solamente en tiempo de ejecucin donde se pueden conocer todos los
parmetros necesarios para construir las consultas requeridas. Esto implica que el conector deber
proveer al compilador un mecanismo lo suficientemente amplio como para generar las consultas en
tiempo de ejecucin.
Las consultas requeridas, siguiendo el esquema general propuesto en el servicio, son las basadas
en las especificaciones de los objetos (StorageObjectSpec). Con relativamente poco trabajo, se puede
traducir una especificacin de objeto en una consulta de DB4O, representada por la clase Constraint. La
clase SpecToConstraintTransformer est encargada de esta tarea. Toma una especificacin de objeto,
itera sobre todos los atributos de la especificacin agregando una clusula (Constraint) por cada atributo
que defina la especificacin.
Este mecanismo es lo suficientemente genrico como para que el compilador se encargue de
agregar las entradas necesarias en las clases generadas, como para construir especificaciones vlidas y en
base a ellas construir las consultas necesarias por el servicio.
C REACIN DE OBJETOS ALMACENADOS
Los mecanismos de construccin de objetos almacenados son los mismos, tanto para este
conector como para el conector de memoria, ya que ambos siguen el esquema de delegacin propuesto
por el servicio. La diferencia radica en los mecanismos que se utilizan para la generacin de
identificadores (antes descripta) y para la validacin de las claves.
El mecanismo general para la validacin se dispara cuando se construye un objeto y se basa en la
clase StorageHomeKeySet. Dicha clase es extendida por el conector persistente, mediante
PersistentStorageHomeKeySet, en donde se delega la validacin en una consulta generada a partir de
todas las claves que se definan en la especificacin. La consulta se genera utilizando la clase
104
Pablo M. Ilardi
mquina3
use
CPU1
PMIPSS1
Repositorio3 - DB4O
local
use
PMIPSS3
CPU3
use
Cliente1
Cliente3
105
Pablo M. Ilardi
106
Pablo M. Ilardi
solucin acotada para mantener el estado de un servant, que generalmente tendr pocos objetos para
persistir e interactuar.
El compilador usa un sistema generador de cdigo fuente que constru para este trabajo. Utiliza
un modelo de clases y plantillas de cdigo. Adems constru un intrprete de clases que permite generar
esqueletos de clases e interfases en base a un objeto real dado. Estas dos construcciones pueden ser
utilizadas en cualquier otro trabajo que pueda o no estar relacionado con ste. Las plantillas se traducen a
cdigo fuente utilizando la biblioteca Jexl que permite incrustar secciones dinmicas en las plantillas que
se evalan en base a un contexto provisto por mi generador de cdigo fuente.
Se construyeron dos implementaciones de conectores para mi servicio de estado persistente de
CORBA:
o
o
Todas las construcciones realizadas, incluyendo el compilador, cuentan con pruebas unitarias,
para garantizar el funcionamiento de cada una de las partes. Estas pruebas permiten que las
construcciones puedan ser mejoradas y completadas, asegurando que lo construido siga funcionando de
la forma esperada. Las pruebas unitarias se realizaron utilizando la biblioteca JUnit.
Algunas de estas pruebas unitarias requieren compilar y validar su resultado en tiempo de
ejecucin, lo que equivale a compilar cdigo fuente Java en tiempo de ejecucin. Para realizar esta tarea
he utilizado un framework llamado Janino, que permite utilizar clases compiladas en tiempo de ejecucin
a partir de su cdigo fuente (generado en este caso por el compilador).
Tanto el compilador como los conectores, utilizan internamente algunas bibliotecas de Jakarta
Commons como Loggings y Collections. Jakarta Commons es un proyecto de Apache que tiene el
propsito de construir componentes de software reutilizables en todo tipo de aplicaciones Java.
El cdigo fuente fue desarrollado utilizando el IDE Eclipse y la versin 5 de Java. El cdigo fuente
contiene ms de 300 clases que corresponden al generador de cdigo fuente, al compilador, al servicio de
estado persistente y a los dos conectores. Adems se elaboraron ms de 100 pruebas unitarias para todas
las funcionalidades construidas.
Al final de esta seccin se encuentra una lista con las referencias utilizadas en el trabajo.
107
Pablo M. Ilardi
UN EJEMPLO CONCRETO
A continuacin voy a presentar un ejemplo simple, mostrando el cdigo generado por el
compilador para el conector persistente, y demostrando cmo este cdigo es utilizado en el contexto de
una aplicacin CORBA.
C DIGO PSDL
El cdigo PSDL representa una definicin de un objeto almacenado abstracto, un almacn
abstracto para este objeto, junto con sus respectivas implementaciones.
abstract storagetype Persona {
state string nombre;
state string apellido;
state long nroDocumento;
string nombreCompleto();
};
abstract storagehome PersonaHome of Persona {
key nroDocumento;
factory crear(nombre, apellido, nroDocumento);
};
storagetype PersonaBase implements Persona { };
storagehome PersonaHomeBase of PersonaBase implements PersonaHome {
};
En este ejemplo el objeto almacenado es Persona, su almacn es PersonaHome, y PersonaBase es
su implementacin, mientras que PersonaHomeBase es la implementacin del almacn. Persona tiene
tres atributos: nombre, apellido y nmero de documento, junto con una operacin de usuario llamada
nombreCompleto. El almacn de la persona define una clave nica en base al nmero de documento de
la persona. Y expone una operacin de fbrica llamada crear, que permite construir personas con
nombre, apellido y nmero de documento en una sola operacin.
108
Pablo M. Ilardi
Para el caso de este ejemplo me voy a focalizar slo en los cuatro primeros archivos, que son los
ms importantes a los efectos prcticos del servicio de persistencia.
P ERSONA
El cuadro de texto siguiente representa una versin simplificada del cdigo fuente de la interfase
generada por el compilador: Persona. Se han eliminado parte de los comentarios para reducir el tamao.
En el cdigo fuente, se muestra que la interfase hereda de la interfase StorageObject de PSS, adems,
cada uno de los estados tiene sus mtodos para lectura y escritura, y la operacin de usuario
nombreCompleto.
Tanto los comentarios de inicio del archivo como los comentarios de la interfase y cada uno de los
mtodos son generados en base a las plantillas de cdigo configuradas en el compilador.
/**
* .
* <b>F.I.U.B.A.</b>
* ..
* <a href='mailto:pilardi@fi.uba.ar'>Pablo Maximiliano Ilardi</a>
*
* Persona.java: was generated by PMI-PSDL Compiler Version 1.0
* .
*/
package ar.uba.fi.pmi.corba.pss.psdl.test.persistent.simple;
import org.omg.CosPersistentState.StorageObject;
/**
* ..
* @author PMI-PSDL Compiler Version 1.0 - persistent
*/
public interface Persona extends StorageObject {
public abstract String nombre();
public abstract void nombre(String s);
public abstract String apellido();
public abstract void apellido(String s);
public abstract long nroDocumento();
public abstract void nroDocumento(long l);
public String nombreCompleto();
}
P ERSONA HOME
Las primeras operaciones permiten ubicar a una Persona por la clave definida por el nmero de
documento. El ltimo mtodo representa la operacin de fbrica, que permite crear Personas por sus
atributos.
109
Pablo M. Ilardi
package ar.uba.fi.pmi.corba.pss.psdl.test.persistent.simple;
.
/**
* ....
* @author PMI-PSDL Compiler Version 1.0 - persistent
*/
public interface PersonaHome extends PersonaHomeOperations, LocalInterface, IDLEntity,
StorageHomeBase {
}
package ar.uba.fi.pmi.corba.pss.psdl.test.persistent.simple;
P ERSONA B ASE
.
package ar.uba.fi.pmi.corba.pss.psdl.test.persistent.simple;
.
public abstract class PersonaBase implements Persona, StorageObject, ExtendedStorageObject {
private static final long serialVersionUID = -1737034293L;
private StorageObjectIdentifier identifier;
private long nroDocumento;
private String apellido;
private String nombre;
public PersonaBase() { }
public final long nroDocumento() { return this.nroDocumento; }
public final void nroDocumento(long l) { this.nroDocumento = l; }
public final String apellido() { return this.apellido; }
public final void apellido(String s) { this.apellido = s; }
public final String nombre() { return this.nombre; }
public final void nombre(String s) { this.nombre = s; }
public final byte[] get_pid() { return this.get_identifier().get_pid(); }
public final byte[] get_short_pid() { return this.get_identifier().get_short_pid(); }
public final StorageHomeBase get_storage_home() {
return this.get_identifier().get_storage_home();
}
public final void destroy_object() {
((ExtendedStorageHome) this.get_storage_home()).destroy(this);
}
110
Pablo M. Ilardi
111
Pablo M. Ilardi
public PersonaHomeBase() {}
public Persona crear(String nombre, String apellido, long nroDocumento) {
StorageObjectSpec spec = this.newSpec();
spec.set_string("nombre", nombre);
spec.set_string("apellido", apellido);
spec.set_long("nroDocumento", nroDocumento);
return (Persona)this.create(spec);
}
public Persona find_by_nroDocumento(long nroDocumento) throws NotFound {
StorageObjectSpec spec = this.newSpec();
spec.set_long("nroDocumento", nroDocumento);
return (Persona)this.find_by_spec(spec);
}
public byte[] find_ref_by_nroDocumento(long nroDocumento) {}
protected void collectKeys(StorageHomeKeySet keys) {
super.collectKeys(keys);
StorageHomeKeyBuilder keynroDocumento = keys.keyBuilder("nroDocumento");
keynroDocumento.with("nroDocumento");
keynroDocumento.build();
}
112
Pablo M. Ilardi
113
Pablo M. Ilardi
El cliente est representado por la clase ConsultaPersonas. Esta clase accede al registro
mediante una referencia obtenida de la ORB. El acceso a la ORB, tanto para el cliente como para el
servidor, est centralizado en la clase ORBAccessor. Esta clase es simplemente una utilidad provista por
m, que permite centralizar todas las operaciones que requieran interaccin con la ORB, como acceso a
las referencias iniciales, al servicio de persistencia o a la creacin de la ORB.
Este modelo de aplicacin deja muy clara la separacin entre el dominio de la aplicacin CORBA
y el del servicio de persistencia. Todas las operaciones del registro de personas no estn ligadas a los
objetos utilizados por el servicio de persistencia, esto se debe a que dichos objetos son privados, o sea
locales al servant y no pueden ser exportados por la ORB a otra mquina. Los objetos que define el
servicio de persistencia pasan a ser detalles de implementacin del servant y desde el punto de vista de
un cliente del servant no existen.
Servant
cerrarRegistro() : void
crearPersona(String, String, int) : void
eliminarPersona(int) : void
nombreCompleto(i nt) : String
RegistroPersonaPOA
IDLEntity
Object
RegistroPersonaImpl
utils::ORBAccessor
i nterface
+
+
+
#
+
+
RegistroPersona
-registro
cliente
ConsultaPersonas
#
+
+
+
+
atenderConsultas() : voi d
ConsultaPersonas(String[])
l eerEntrada() : Stri ng
main(String[]) : void
presentarMenu() : i nt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
activateRootPOAManager() : void
getDynAnyFactory() : DynAnyFactory
getNameService() : NamingContextExt
getOrb() : ORB
getPersistentStateServi ce() : ConnectorRegistry
getRootPOA() : POA
isIni tialized() : boolean
object_to_string(org.omg.CORBA.Object) : String
ORBAccessor()
ORBAccessor(String[])
ORBAccessor(String[], Properties)
readObject(String) : org.omg.CORBA.Object
shoutDown(bool ean) : void
string_to_object(String) : org.omg.CORBA.Obj ect
writeObject(org.omg.CORBA.Object, String) : voi d
servidor
Serv idorPersonas
+
+
cerrarRegistro() : voi d
crearPersona(String, String, int) : void
eliminarPersona(i nt) : void
getPersona(i nt) : Persona
nombreCompleto(i nt) : String
RegistroPersonaImpl(ORBAccessor, PersonaHome)
-home
IDLEntity
PersonaHomeOperati ons
StorageHomeBase
LocalInterface
interface
PersonaHome
accede
creacin
StorageObject
interface
Persona
+
+
+
+
+
+
+
114
Pablo M. Ilardi
115
Pablo M. Ilardi
Otra instancia del servicio de persistencia que quiera acceder al mismo repositorio creado
anteriormente, deber utilizar parmetros como los mostrados en el cuadro anterior. Se asume que la
direccin de Internet, donde se cre el repositorio inicialmente es 192.168.133.100.
116
Pablo M. Ilardi
REFERENCIAS
PSS01 Persistence State Service V2.0 OMG 2002. http://www.omg.org/cgi-bin/doc?formal/0209-06
TS01 - Transaction Service Specification, OMG
2003.http://www.omg.org/technology/documents/corbaservices_spec_catalog.htm
CORBA01 Common Object Request Broker Architecture, Core Specification OMG.
http://www.omg.org/technology/documents/corba_spec_catalog.htm
JVMTI01 Java Virtual Machine Tool
http://java.sun.com/j2se/1.5.0/docs/guide/jvmti
2004.
2004.
IDL2Java
IDL
to
Java Language
Mapping
interface
Specification.
SUN
Java
http://www.omg.org/cgi-
bin/doc?formal/02-08-05
CorbaJava00 CORBA Technology and the Java (TM) 2 Platform Standard Edition.
http://java.sun.com/j2se/1.5.0/docs/guide/idl/corba.html
Garshol00 BNF and EBNF: What are they and how do they work?, Lars Marius Garshol.
http://www.garshol.priv.no/download/text/bnf.html
CooperRice00 Engineering A Compiler, Keith Cooper - Rice University, Houston, Texas; Linda
Torczon - Rice University, Houston, Texas http://www.cs.rice.edu/~keith/
Javacc00 Java Compiler Compiler [tm] (JavaCC [tm]) - The Java Parser Generator.
https://javacc.dev.java.net/
JavaccTu00 The JavaCC Tutorial, Theodore S. Norvell http://www.engr.mun.ca/~theo/JavaCCTutorial/
Crenshaw00 Let's Build a Compiler, by Jack Crenshaw http://compilers.iecc.com/crenshaw/
Dasgupta00 Algorithms, S. Dasgupta, C. H. Papadimitriou, and U. V. Vazirani. July 18, 2006.
Gamma01 Design Patterns: Elements of Reusable Object-Oriented Software - Addison-Wesley
Professional Computing Series - by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides,
January 15, 1995.
BM0 Meyer, Bertrand. Object-Oriented Software Construction. Prentice Hall, 1997. ISBN 013-629155-4.
GrandM01 Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML, 2nd
Edition, Volume 1, by Mark Grand. Wiley; September 17, 2002. ISBN-10: 0471227293.
KingG01 Hibernate in Action, Christian Bauer, Gavin King; Manning, 2005. ISBN: 1932394-15-X.
http://www.hibernate.org
RoodsR01 Java Data Objects, Robin M. Roods; Addison-Wesley, 2003. ISBN 0-321-12380-8.
http://java.sun.com/javaee/technologies/jdo
117
Pablo M. Ilardi
family
of
products.
CKA01 - Surviving Object-Oriented Projects, By Alistair Cockburn, Dec 22, 1997, Addison Wesley
Professional. Part of The Agile Software Development Series.
DBO401 Database for Objects. http://www.db4o.com/about/productinformation
SODA01 Simple Object Database Access. http://sodaquery.sourceforge.net
Cache01 InterSystems Cach high-performance object database.
http://www.intersystems.com/cache/index.html
Annotations01 Java 5.0 Annotations.
http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
Conc01 The origin of concurrent programming: from semaphores to remote procedure calls
book contents. ISBN:0-387-95401-5, Center for Science and Technology, Syracuse University,
Syracuse, NY. Edsger W. Dijkstra, Per Brinch Hansen, C. A. R. Hoare
RoySeif01 Concepts, Techniques, and Models of Computer Programming, by Peter Van Roy and
Seif Haridi. The MIT Press Cambridge, Massachusetts London, England. ISBN 0-262-22069-5
GrayReuter01 - Transaction Processing: Concepts and Techniques by Jim Gray, Andreas Reuter ,
1993 Morgan Kaufmann. ISBN 1558601902
DEVQTC01 Developing Quality Technical Information. A handbook for Writers and Editors.
Second Edition. G. Hargis, M. Carey, A. Hernandez, P. Hughes, D. Longo, S. Rouiller, E. Wide. ISBN
0-13-1477490.
118
Pablo M. Ilardi
REFERENCIAS A BIBLIOTECAS
Jakarta Commons http://commons.apache.org/
Jakarta Commons Logging http://commons.apache.org/logging/
Jakarta Commons Collections http://commons.apache.org/collections/
Jakarta Commons Jexl http://commons.apache.org/jexl/
Hibernate http://www.hibernate.org/
JDO http://java.sun.com/jdo/
Db4o Database For Objects , http://www.db4o.com/
Javacc Java Compiler Compiler, https://javacc.dev.java.net/
JJTree https://javacc.dev.java.net/doc/JJTree.html
Junit http://www.junit.org/
Janino An Embedded Java Compiler, http://www.janino.net/
Eclipse http://www.eclipse.org/
119
120
Pablo M. Ilardi
121
122
Pablo M. Ilardi
ado que PSS no es uno de los servicios CORBA ms difundidos, existen pocas implementaciones,
y especialmente en Java. Cuando se habla de una implementacin de CORBA, generalmente se
est hablando de implementaciones de la ORB. Todas las implementaciones proveen adems de
la ORB, implementaciones de los servicios bsicos, como puede ser el NameService y algunas en
particular ofrecen implementaciones del PSS.
Mi proyecto no contempla la creacin de una ORB, ya que hay muchas implementaciones de
ella, sino se propone integrar el servicio con, idealmente, cualquier implementacin de la ORB en Java.
He probado mi servicio, con dos implementaciones de ORB: la de SUN para Java que trae la mquina
virtual y la ORB de JacORB [JACORB01]. JacORB es una implementacin en cdigo abierto del
Departamento de Ciencias de la Computacin de la Universidad de Freie en Berln, Alemania.
Ninguna de las dos ORBs con las que he probado mi servicio, tienen implementaciones de PSS, y
por ende, constituyeron un buen escenario para integrar mi servicio con ellas.
SERVICIOS A COMPARAR
De las pocas implementaciones existentes, para realizar la comparacin he elegido las dos ms
representativas: OpenORB [OPENORB01] y OpenCCM [OPENCCM01].
OPENORB
OpenORB (u ORB abierta) es una implementacin de la ORB de CORBA, basada en una ORB
anterior, escrita totalmente en Java, y llamada JavaORB (que actualmente se encuentra discontinuada).
Esta ORB fue construida por el grupo de personas llamado Distributed Object Group (Grupo de Objetos
Distribuidos) [DOG01], que se dedica a proveer tecnologa CORBA de cdigo abierto. Uno de los servicios
que provee OpenORB es el servicio de estado persistente que utilizar para la comparacin. Segn la
documentacin de este servicio, provee una implementacin totalmente compatible con la especificacin
PSS de CORBA.
OpenORB provee tres conectores para el servicio: conector de memoria sin soporte
transaccional, otro conector con soporte de archivos donde se almacena el estado persistente con
soporte transaccional y un tercer conector que utiliza una base de datos relacional para almacenar el
estado persistente del repositorio. Este ltimo conector requiere un proveedor de base de datos
relacional, que se encuentra fuera del control del servicio. Al tratarse de una dependencia no controlada
por el servicio, la aplicacin CORBA requiere tener configurada una base de datos relacional para poder
utilizar esta implementacin del servicio.
Segn la documentacin, este servicio requiere utilizar su propia implementacin de ORB y su
servicio de Transacciones OTS, tambin provisto por este grupo.
El servicio provee un compilador PSDL, que se invoca mediante un script por lnea de comandos.
El servicio no soporta persistencia transparente, slo se puede utilizar el servicio mediante una definicin
PSDL compilada por su propio compilador.
La configuracin se realiza a travs del mecanismo de configuracin de la ORB provista por
OpenORB, lo que lo hace completamente dependiente de ella. Esta configuracin tambin incluye los
parmetros de uso de los conectores de base de datos relacional y de archivos, dejando sin uso a los
parmetros de construccin de la sesin.
En cuando a las posibilidades de extensin, la documentacin slo trata la interaccin con el
servicio por un usuario del mismo. De todas formas, el cdigo fuente es libre y se lo puede analizar. El
compilador de PSDL que utiliza, est basado en el compilador de OpenORB para el que est definido el
123
Pablo M. Ilardi
servicio. Para agregar un nuevo conector es necesario modificar el cdigo del servicio, ya que ste no
provee configuracin alguna que permita un comportamiento dinmico del compilador. El compilador
slo genera cdigo para sus tres conectores. De manera anloga, el servicio tampoco soporta registro
dinmico de conectores, lo que obliga a modificar el cdigo para agregar un nuevo conector.
OPENCCM
OpenCCM tambin surge de JavaORB, pero no se trata de una implementacin de ORB, sino de
una implementacin del modelo de componentes de CORBA [CCM01]. Una parte de CCM es la ORB que
se utiliza internamente y en este caso se trata de JacORB. Al tratarse de un contenedor de componentes,
de acuerdo a la especificacin de CORBA, es posible tambin combinarlo con el servicio de estado
persistente PSS. OpenCCM provee su propia implementacin de PSS.
Este servicio provee dos conectores de funcionalidades similares. El primero es un conector que
utiliza al framework Hibernate [KingG01] para almacenar el estado en una base de datos relacional.
Hibernate es una herramienta de mapeo de objetos a bases de datos relacionales. El otro conector utiliza
a la API de SUN, para persistencia de objetos llamada JDO (Java Database Object) [RoodsR01]. Si bien el
servicio provee dos conectores, se debe definir en tiempo de compilacin del servicio cual conector se
utilizar, lo que deja en la prctica un nico conector posible en tiempo de ejecucin. El servicio est muy
acoplado a la implementacin de la ORB y al contenedor de componentes. No me fue posible configurar
el conector de Hibernate en mis pruebas, slo logr hacerlo funcionar con JDO.
Tanto JDO como Hibernate requieren del uso de una base de datos relacional. De todas formas
Hibernate provee herramientas para utilizar una base de datos incrustada en el proceso donde se lo
utilice, como por ejemplo HypersonicSQL [HSQLDB01] que est realizada completamente en Java.
La posibilidad de extensin est dada en el momento de compilacin del servicio, pero est muy
acoplada al modelo de construccin de componentes y servicios que provee OpenCCM.
PUNTOS DE COMPARACIN
Las caractersticas que he comparado con estas dos implementaciones del servicio son:
1. Compatibilidad con el estndar
Se evala el grado en que se respetan los requerimientos impuestos por el estndar con respecto
a los requerimientos del mismo, tales como claves mltiples, construcciones de PSDL, generacin de
cdigo Java, funcionalidades del compilador, etc.
2. Nivel de dependencia con la ORB
Se evala la dependencia de la implementacin del servicio con respecto a la ORB para la que se
promueve su utilizacin.
3. Conectores disponibles y caractersticas de los mismos
Este punto es quizs, el ms importante desde la perspectiva de un usuario del servicio. Se
evalan los conectores que provee el servicio, sus requerimientos y funcionalidades que proveen.
4. Requerimientos y facilidad de uso
Otro punto importante para un usuario final son los requerimientos que impone el uso de un
determinado servicio o conector, y los conocimientos y recursos de los cuales debe disponer un nuevo
usuario.
5. Extensibilidad para la creacin de nuevos conectores
Finalmente este punto trata de evaluar las posibilidades y limitaciones para la extensin del
servicio, ya sea mediante un nuevo conector o modificando el servicio.
124
Pablo M. Ilardi
OpenCCM, tampoco respeta las interfases. De acuerdo a la especificacin, las interfases que
representen objetos almacenados debern heredar de la interfase StorageObject de CORBA. Sin embargo
en
OpenCCM,
heredan
de
una
interfase
definida
por
ellos:
org.objectweb.openccm.pss.runtime.common.api.StorageObject, que a su vez hereda de
StorageObject. Dicha interfase agrega un mtodo inicialize, que es utilizado para indicarle al objeto el
almacn al que pertenece.
// En OpenCCM
public interface Person extends
org.objectweb.openccm.pss.runtime.common.api.StorageObject
// En mi compilador
import org.omg.CosPersistentState.StorageObject;
public interface Person extends StorageObject
LocalInterface,
IDLEntity,
OpenCCM no genera interfases para las operaciones del almacn. Todas las operaciones estn
declaradas dentro de la misma interfase del almacn. Tampoco genera las clases de utilidad como Holder
y Helper que requiere CORBA para una interfase. OpenCCM no genera interfases CORBA vlidas.
Considero que es un problema importante que no se respete el estndar a nivel de interfase,
dado que expone la implementacin de un servicio CORBA al usuario del mismo, sin permitir un
intercambio directo de implementaciones entre distintos proveedores del servicio. La independencia de
la implementacin es una de las caractersticas ms importantes de las especificaciones CORBA.
125
Pablo M. Ilardi
126
Pablo M. Ilardi
127
Pablo M. Ilardi
como para el de Hibernate, es necesario crear y administrar la base datos con la cual se utilizar el
servicio, antes de poder utilizar el servicio mismo.
Tanto OpenORB como OpenCCM requieren de la intervencin explcita del usuario para poder
utilizar el conector de base de datos relacional. El usuario debe agregar tambin el driver de conexin
para la base datos que decida utilizar.
En el caso de mi servicio, no se requiere ninguna configuracin adicional para que funcione el
servicio o los conectores. Solamente requiere los parmetros necesarios para la creacin de la sesin de
trabajo. A diferencia de los otros dos servicios, mis conectores no exponen los detalles de
implementacion de los mismos para su configuracin. Cuando se utiliza el conector para DB4O, el usuario
no sabe realmente cmo y con qu se estn persistiendo los objetos.
CONCLUSIONES
Un punto que est fuera de la comparacin es la cantidad de personas involucradas en el
proyecto. Tanto en OpenORB como OpenCCM, los proyectos estn constituidos por mltiples personas y
adems, al contar con el soporte de una ORB, tienen muchas utilidades que se puede reutilizar en el
servicio. En mi caso se trat de un proyecto de una nica persona.
Desde el punto de vista de la extensibilidad creo que mi servcio es el ms apto de los tres, dado
que es el que permite mayor grado de configuracin sin recompilar y tambin es el nico que no expone
detalles de implementacin de los conectores. Mi compilador de PSDL est en desventaja al no generar
cdigo fuente para las construcciones IDL, esta debe ser la primer tarea a encarar en un trabajo futuro
sobre el servicio. Implementar la integracin con algn servicio de transacciones de CORBA (TTS) tambin
es una caracterstica que sera importante agregar. Desde el punto de vista funcional los tres servicios
proveen funcionalidades similares (salvo por la integracion con TTS). En relacin a la correctitud de los
requerimientos de la especificacin, creo que mi servicio es el ms apto, ya que es el nico que segn mi
interpretacin del estndar, lo respeta. La independencia de la ORB es un objetivo propio de mi trabajo y
no tiene porque estar soportado por otros servicios.
Ninguna de las implementaciones del servicio que he analizado, tanto en Java como en C++,
incluyendo la ma, proveen soporte para persistencia transparente. Esto creo que se debe principalmente
a que no est bien resuelto por la especificacin, y en el modelo de trabajo de CORBA es comn requerir
de un compilador de un lenguaje genrico a un lenguaje concreto.
128
Pablo M. Ilardi
Finalmente, el acceso remoto al repositorio es tambin una caracteristica que est fuera del
alcance de la especificacin y que en las otras implementaciones del servicio est solo resuelta
parcialmente por el uso de una base de datos relacional.
La forma de accesso remoto propuesta tiene como desventaja que no permite independecia de
la ubicacin, ya que depende directamente de la ubicacin donde se cre el repositorio. De todas
formas, la ubicacin del repositorio es slo necesaria al momento de crear la sesin de trabajo y es ste el
nico punto donde est expuesta. Este grado de desacoplamiento de la ubicacin permite migrar el
repositorio en forma manual y relativamente sencilla, poniendo la ubicacin fsica del repositorio en una
configuracin externa a la aplicacin.
A continuacin expongo una tabla comparativa entre las distintas caractersticas analizadas y los
tres servicios de estado persistente comparados.
Caracterstica \ Servicio
OpenORB
Respeta el estandar
No
Depende de una ORB
Si
Candidad de Conectores
3
Complejidad de Uso
Media
Requiere adicionales
BDR + Driver
Extensibilidad
Baja
Soporte de transacciones
Corba TSS
Compilador
IDL + PSDL
Persistencia Transparente
No
Acceso Remoto
No
Expone implementacin Si, x BD Relacional
Candidad de Personas
+3
OpenCCM
PMI-PSS
No
Si
2(uno x vez)
Alta
BDR + Driver
Media
Corba TSS
IDL + PSDL
No
x BD Relacional
Si, x BD Relacional y JDO
Consorcio de Software
Si
No
2
Baja
No
Alta
Solo x DB4O
PSDL
No
x Conector Persistente
No
1(Yo)
129
Pablo M. Ilardi
REFERENCIAS
JACORB01 JacORB: Software Engineering and Systems Software Group, at the CS department of
Freie Universitt Berlin, Germany. www.jacorb.org
OPENORB01 The Community OpenORB, www.openorb.org
DOG01 Distributed Object Group. dog.team.free.fr
OPENCCM01 OpenCCM
openccm.objectweb.org
The
Open
CORBA
Component
Model
Platform.
130
Trabajos Adicionales
Pablo M. Ilardi
TRABAJOS ADICIONALES
PSS tiene algunas limitaciones en su modelo que podran ser incorporadas en un futuro. La
principal es la posibilidad de hacer consultas complejas. La nica alternativa de consultas que se plantea
en PSS es mediante consultas por las claves de los objetos en los almacenes. Existen situaciones reales en
las que se quieren realizar consultas ms avanzadas sobre los objetos, por atributos que no son parte de
la clave necesariamente o por condiciones complejas. Este tipo de consultas estn bien resueltas en la API
de SODA en la que se basa uno de los modos de consulta de DB40.
Existe otra limitacin importante de PSS, que es el manejo de colecciones. En PSS la nica forma
de manejar una coleccin como atributo / estado de un objeto almacenado, es mediante un array de
objetos almacenados, lo que se logra mediante una definicin IDL de un arreglo de objetos almacenados.
Si bien es suficiente para almacenar ms de un objeto como estado, el lenguaje Java provee posibilidades
mucho ms avanzadas para el manejo de colecciones, tales como colecciones con semntica de conjuntos
o colecciones indexadas. El tratar con un array plano de objetos hace que se requiera la construccin de
operaciones que ya estn definidas en el lenguaje en forma nativa para poder utilizarlas con el modelo de
PSS. Esta limitacin concretamente se debe a que PSS es una especificacin multilenguaje,
particularmente para Java y C++. Esto requiere que las funcionalidades provistas deban ser soportadas
por todos los lenguajes de forma relativamente simple y en el caso de C++, los arrays son las nicas
construcciones nativas que se soportan para el manejo de colecciones.
Mi implementacin en particular requiere agregar al compilador de PSS la posibilidad de generar
construcciones IDL para permitir interactuar a los objetos almacenados con ellas, por ejemplo, mediante
atributos / estados que sean tipos definidos en IDL directamente.
De acuerdo a la especificacin PSS, existen dos caractersticas opcionales, que son persistencia
transparente y soporte transaccional. Si se provee persistencia transparente, se dice que el servicio es: "a
compliant Persistent State Service implementation with transparent persistence support", o una
implementacin del servicio de estado persistente compatible con soporte de persistencia transparente.
Y si provee soporte transaccional es: a compliant Persistent State Service implementation with
transaction support o una implementacin del servicio de estado persistente compatible con soporte de
transacciones. Mi servicio no provee ninguna de estas dos caractersticas adicionales, por lo que son
buenos candidatos de futuros trabajos.
131
132
ndice de Grficos
Pablo M. Ilardi
NDICE DE GRFICOS
FUNCIONAMIENTO DEL SERVICIO DE ESTADO P ERSISTENTE
Grfico 1 - Interaccin con la ORB _______________________________________________________
Grfico 2 - MODELO LGICO ___________________________________________________________
Grfico 3 - Sesin para acceder al DataStore _______________________________________________
Grfico 4 - Herencia Diamante de interfases en CORBA ______________________________________
Grfico 5 - Tipos y Modelo de Herencia en PSS _____________________________________________
Grfico 6 - Acceso al servicio ___________________________________________________________
33
34
34
35
36
37
COMPILADOR
Compilador 1 - Proceso de Compilacin ___________________________________________________
Compilador 2 - Primer Paso ____________________________________________________________
Compilador 3 - Javacc ________________________________________________________________
Compilador 4 - Diagrama general del Compilador___________________________________________
Compilador 5 - Fases del compilador _____________________________________________________
Compilador 6 - Nodos de rbol__________________________________________________________
Compilador 7 - Primera Fase ___________________________________________________________
Compilador 8 - Exepciones de Validacin __________________________________________________
Compilador 9 - Tres Partes _____________________________________________________________
Compilador 10 - Qu generar ___________________________________________________________
Compilador 11 - Generacin de archivos __________________________________________________
Compilador 12 - Cmo generarlo ________________________________________________________
53
54
56
58
60
63
64
68
69
70
71
72
133
134
Glosario
Pablo M. Ilardi
GLOSARIO
POO Programacin Orientada a Objetos u OOP Object Oriented Programming.
API Application programming interface o interfase de programacin de aplicaciones
IDE Integrated Development Environment o entorno de desarrollo integrado.
CORBA Common Object Request Broker Arquitecture o Arquitectura Comn para el Agente de Pedidos a
Objetos.
OMG Object Management Group o Grupo de Administracin de Objetos
OMA Object Management Architecture o Arquitectura para la Administracin de Objetos
ORB Object Request Broker o Agente de Pedidos a Objetos
Servant entidad programada en un lenguaje, que implementa uno o ms objetos CORBA. Se dice que
los servants, encarnan los objetos, porque proveen los cuerpos o implementaciones de los mismos. Los
servants, existen dentro del contexto de una aplicacin servidora. Dentro de un lenguaje de
programacin orientado a objetos, se trata de una instancia de un tipo de objeto.
IDL Interface Definition Language o Lenguaje de Definicin de Interfases. Lenguaje genrico de
definiciones utilizado por CORBA para permitir interconectar objetos implementados en diferentes
interfases.
PSS Persistent State Service o Servicio de Estado Persistente, servicio de CORBA para permitir almacenar
objetos en forma persistente para los servants.
RDBMS Relational Dabase Management System o Sistema de Administracin de Base de Datos
Relacional.
SQL Structured Query Language o Lenguaje Estructurado de Consultas utilizado para realizar consultas
en bases de datos Relacionales.
SQL3 Extensin al ANSI-SQL tambin llamado SQL 1999 que introdujo conceptos de los lenguajes
orientados a objetos.
OODBMS Object Oriented Dabase Management System o Sistemas de Administracin de Bases de
Datos Orientadas a Objetos
TS Transaction Service o Servicio de Transacciones de CORBA para realizar operaciones en contextos
trasaccionales.
PSDL Persistent State Definition Language o Lenguaje de Definiciones de Estado Persistente
Bytecode Cdigo de bytes utilizado internamente por la mquina virtual de Java.
Sistema Distribuido conjunto de computadoras independientes que se presentan al usuario del sistema
cmo una nica computadora. Desde la perspectiva de hardware, las mquinas o computadoras son
autnomas, y pero desde el punto de vista del software, el sistema se ve por el usuario como un todo.
BOA Basic Object Adapter o Adaptador Bsico de Objetos, especificacin descontinuada de CORBA que
permita invocar operaciones remotas definidas en lenguaje C ubicadas en diferentes ORBs.
135
Glosario
Pablo M. Ilardi
POA Portable Object Adapter o Adaptador Portable de Objetos, especificacin de CORBA que sucedi a
BOA y permiti ejecutar operaciones remotas ubicadas en diferentes ORBs e implementadas en cualquier
lenguaje.
OR - Object Reference o Referencia a Objeto, identifica un objeto CORBA, en forma unvoca. Le permite a
CORBA, identificar, ubicar y direccionar al objeto. Para los clientes, son entidades opacas que no pueden
ser modificadas ni creadas por ellos, las utilizan para dirigir los pedidos a los objetos. Identifican un nico
objeto CORBA.
GIOP General Inter ORB Protocol o Protocolo General Inter ORB, definicin abstracta de un protocolo
que permiti interconectar diferentes implementaciones de la ORB.
TCP/IP Transmission Control Protocol / Internet Protocolo, conjunto de protocolos, el primero sobre la
capa de transporte y el segundo sobre la capa de red, utilizados para comunicarse en Internet y la
mayora de las redes comerciales.
IIOP Internet Inter ORB Protocol o Protocolo Inter ORB sobre Internet, implementacin de GIOP
mapeada sobre TCP.
IOR Interoperable Object Reference o Referencia Interoperable a Objeto, referencia a objeto que es
entendible por todas las implementaciones de GIOP.
CCM CORBA Component Model o Modelo de Componentes de CORBA, nueva especificacin de CORBA
que promueve la construccin de sistemas mediante un modelo de componentes que extiende a las
interfases de CORBA.
RFP Request For Proposal o Pedido de Propuesta, consiste en el llamado a entidades a participar en la
creacin de una nueva especificacin.
POS Persistent Object Service o Servicio de Objetos Persistentes, especificacin descontinuada de
CORBA que fue reemplazada por PSS, utilizada para permitir persistir objetos en el entorno de una ORB.
StorageObject (PSS) Objeto almacenado, todo objeto que est definido en PSDL se define como "objeto
almacenado".
StorageHome (PSS) Almacn de PSDL donde se "almacenan" objetos de una familia definida por un tipo
base.
Singleton Patrn de diseo que define a un objeto del que slo puede existir una nica instancia en
forma simultnea.
Connector (PSS) Interfase que representa la implementacin del servicio de persistencia, mediante ella
se realizan las operaciones inciales sobre el servicio. Se obtiene una instancia invocando a un mtodo del
registro que devuelva la implementacin segn el tipo de conector solicitado.
ConnectorRegistry (PSS) "interfase/clase" que representa el registro de conectores de PSS, permite
obtener referencias a las implementaciones del servicio de persistencia (Conectores). El registro se
obtiene llamando al mtodo resolve_initial_references(PSS) de la ORB.
CatalogBase (PSS) Es un repositorio donde se encuentran los almacenes y objetos persistidos,
tcnicamente representa lo mismo que una sesin. Esta clase es abstracta, existen dos extensiones a la
misma, que son una sesin y un pool de sesiones. Toda instancia de home, sabe a qu catalogo
pertenece.
136
Glosario
Pablo M. Ilardi
137
Glosario
Pablo M. Ilardi
DDL Data Definition Language o Lenguaje de Definicin de Datos utilizado en las bases de datos
Relacionales.
DB4O Dabase For Objects o Base de Datos para Objetos
SODA Simple Object Data Base Access o Acceso Simple a Bases de Datos de Objetos.
JacORB Implementacin en Java de la ORB del Departamento de Ciencias de la Computacin de la
Universidad de Freie en Berln, Alemania.
138