3.3 Aspectos básicos del ORB y el POA Pseudo-IDL n Problema: especificación del interfaz del ORB en el documento de especificación CORBA n n n n ¿ En qué lenguaje está especificado ? En Pseudo-IDL (PIDL) Similar a IDL Diferencias n n Los interfaces especificados son locales (el API del ORB) El mapping de PIDL al lenguaje de implementación puede desviarse del mapping de IDL (y normalmente se desvía) Interfaz básica del ORB en PIDL (1) module CORBA { // PIDL typedef string ORBid; typedef sequence<string> arg_list; interface ORB; // forward declaration ORB ORB_init(inout arg_list argv, in ORBid orb_identifier); // ... interface ORB { typedef string Objectid; exception InvalidName {}; void run(); void shutdown(in boolean wait_for_completion); void destroy(); Object resolve_initial_references(in Objectid identifier) raises(InvalidName); string object_to_string(in Object obj); Object string_to_object(in string str); // ... } }; Interfaz básica del ORB en PIDL (2) n CORBA::ORB_init n n n CORBA::ORB::run n n n Se queda en un bucle atendiendo peticiones a objetos remotos Se debe llamar desde el thread main CORBA:ORB::destroy n n Método factoría Devuelve una instancia de un ORB en función de los parámetros pasados (iremos viendo algunos valores poco a poco) Destruye el ORB (liberando recursos) CORBA::ORB::resolve_initial_references n n Permite obtener referencias iniciales a determinados objetos Identificadores: RootPOA (POA raíz), NameService (contexto raíz del servicio de nombres), etc. Interfaz básica del ORB en PIDL (y 3) n CORBA::ORB::object_to_string n n n Permite obtener una referencia a un objeto CORBA como una cadena de caracteres Es legal aplicar esta operación sobre una referencia nil CORBA::ORB::string_to_object n Permite obtener una referencia a un objeto CORBA a partir de su correspondiente representación como cadena de caracteres Interfaz básica del ORB en Java package org.omg.CORBA; public abstract class ORB { public static ORB init(String[] args, java.util.Properties properties) { ... } public static ORB init() { ... } public void run() { ... } public void shutdown(boolean wait_for_completion) { ... } public void destroy() { ... } public abstract org.omg.CORBA.Object resolve_initial_references(String object_name) throws org.omg.CORBA.ORBPackage.InvalidName { ... } public abstract String object_to_string( org.omg.CORBA.Object obj); public abstract org.omg.CORBA.Object string_to_object( String str); public abstract Any create_any(); // .. } Inicialización del ORB (1) n n n init(String[], Properties) es un método estático factoría para crear una instancia de la clase concreta que deriva de la clase abstracta org.omg.CORBA.ORB, en función de parámetros y propiedades Existe una variante de este método para applets J2SE incorpora el API del ORB de CORBA y una implementación por defecto n El mecanismo anterior permite “enchufar” cualquier ORB de CORBA en J2SE Aplicación CORBA org::omg::CORBA::ORB com::acme::CORBA::ORB Inicialización del ORB (2) n Los parámetros y propiedades se localizan en el siguiente orden n n n n Parámetro argumentos (puede pasarse null) Parámetro propiedades (puede pasarse null) Propiedades del sistema Fichero orb.properties n n n n Ubicado en <user-home>, donde <user-home> es el valor de la propiedad del sistema user.home ubicado en <java-home>/lib, donde <java-home> es el valor de la propiedad del sistema java.home En otro caso, se devuelve la implementación por defecto de J2SE La variante init() devuelve una instancia singleton n Sólo se usa en casos muy concretos (ej.: factoría de Typecodes) Inicialización del ORB (y 3) n Propiedades estandarizadas Nombre n Significado omg.ORB.CORBA.ORBClass Nombre de la clase concreta que utiliza init(String[], Properties) omg.ORB.CORBA.ORBSingletonClass Nombre de la clase concreta que utiliza init() Ejemplo de invocación (con propiedades del sistema) java –Dorg.omg.CORBA.ORBClass=com.acme.CORBA.ORB \ -Dorg.omg.CORBA.ORBSingletonClass=\ com.acme.CORBA.ORBSingleton \ es.udc.fbellas.corbaws.clock.server.Server n Ejemplo de inicialización org.omg.CORBA.ORB orb = ORB.init(args, null); Terminación limpia de servidores n Tanto cliente como servidor deberían llamar a CORBA::ORB::destroy antes de terminar n n Permite liberar recursos CORBA::ORB::shutdown permite terminar el bucle CORBA::ORB::run n n n n wait_for_completion==false => retorna inmediatamente e inicia el proceso de terminación wait_for_completion==true => espera a que todas las peticiones actuales terminen Permite que el servidor ejecute código de finalizacion y llame a CORBA::ORB::destroy ¿ Cómo llamarlo ? n n n Desde una opción del entorno de usuario Una operación especial de un interfaz remoto (con parámetro a false) => gestión de aplicaciones CORBA::ORB::destroy no retorna hasta que todas las peticiones pendientes terminen ConsoleServerORBLoopTerminator (1) package es.udc.fbellas.corbaws.util.server; import import import import java.io.IOException; java.io.InputStreamReader; java.io.BufferedReader; org.omg.CORBA.ORB; public class ConsoleServerORBLoopTerminator extends Thread { private final static String END_STRING = "stop"; private ORB orb; public ConsoleServerORBLoopTerminator(ORB orb) { this.orb = orb; /* * Mark this thread as daemon. It needs to be daemon because * when the main thread finishes (maybe finished by the * Implementation Repository Console), the Java Virtual Machine * should finish. */ setDaemon(true); } ConsoleServerORBLoopTerminator (y 2) public void run() { System.out.println("Type '" + END_STRING + "' and then <intro> to stop server"); try { /* Read until END_STRING be typed. */ String typedString; do { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); typedString = bufferedReader.readLine(); } while (!typedString.equals(END_STRING)); /* Shutdown ORB. */ orb.shutdown(false); } catch (IOException e) { e.printStackTrace(); } } // run } // class En el main del servidor ... try { ... /* Install ORB loop terminator. */ System.out.println("Server running"); ConsoleServerORBLoopTerminator terminator = new ConsoleServerORBLoopTerminator(orb); terminator.start(); /* Allow the ORB to start processing requests. */ orb.run(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (orb != null) { orb.destroy(); } } catch (org.omg.CORBA.SystemException e) { e.printStackTrace(); } } El pseudo interfaz Object en PIDL (1) module CORBA { interface Object { boolean is_nil(); boolean is_a(in string repository_id); boolean is_equivalent(in Object other_object); // .. }; // ... }; El pseudo interfaz Object en PIDL (y 2) n CORBA::Object::is_nil n n CORBA::Object::is_a n n Permite comprobar si la referencia es nil Permite comprobar si la referencia es de un tipo determinado (a partir del correspondiente identificador de repositorio) CORBA::Object::is_equivalent n Se explica en el apartado 3.7 El pseudo interfaz Object en Java (1) package org.omg.CORBA; public interface Object { boolean _is_a(String identifier); boolean _is_equivalent(Object that); // .. } El pseudo interfaz Object en Java (2) n CORBA::Object::is_nil no se traduce en ninguna operación n Dado que las referencias nil se mapean a Java como null, basta if (objectReference == null) { // ... } n CORBA::Object::is_a Thermometer thermometer = controller.findByLocation(“Room01”); if (thermometer._is_a(“IDL:TCS/Thermostat:1.0”)) { Thermostat thermostat = ThermostatHelper.narrow(thermometer); // Aplicar operaciones específicas a los termostatos // .. } El pseudo interfaz Object en Java (y 3) n Otra alternativa más frecuente a _is_a Thermometer thermometer = controller.findByLocation(“Room01”); try { Thermostast thermostat = ThermostatHelper.narrow(thermometer); // Aplicar operaciones específicas a los termostatos // ... } catch (org.omg.CORBA.BAD_PARAM e) { // Era un termómetro. } n _is_a está pensado para aplicaciones que usan el DII y no disponen de las clases Helper necesarias en tiempo de compilación POAs y POAManager (1) Aplicación servidora servants POA Petición ORB POAManager POA POAManager Otros POAManagers ... POAManager ... POA Otros POAs POAs y POAManager (2) n API // PIDL module PortableServer { interface POA { ... } interface POAManager { ... } }; // Java package org.omg.CORBA.PortableServer; public interface POA { ... } public interface POAManager { ... } n Una aplicación servidora puede contener múltiples instancias del POA, de manera que pueda soportar objetos con distintas características o formas de implementación de servants n Cada instancia tiene asociada un conjunto de políticas (ej.: multithreading) POAs y POAManager (3) n Todas las aplicaciones disponen al menos del “Root POA” org.omg.CORBA.Object rootPOAObject = orb.resolve_initial_references("RootPOA"); POA rootPOA = POAHelper.narrow(rootPOAObject); n Cada POA tiene asociado un POAManager (que puede encargarse de varios POAs) n n Actúa como una “válvula” que permite regular el flujo de peticiones que le llegan a los objetos de los POAs que gestiona Puede estar en distintos estados n n n En espera, activo, descartando o inactivo Dispone de operaciones para transitar entre estados Para que pueda entregar peticiones a sus POAs tiene que estar en estado “activo” POAs y POAManager (y 4) n Ejemplo de activación del POAManager POAManager rootPOAManager = rootPOA.the_POAManager(); rootPOAManager.activate(); n La operación _this(ORB) de un servant n n n n n Crea un objeto CORBA (si no estaba creado) Lo registra en el Root POA (si no estaba registrado) Crea una referencia para el objeto (si no estaba creada) Devuelve la referencia Ejemplo de _this(ORB) ClockImpl clockImpl = new ClockImpl(); Clock clock = clockImpl._this(orb); Implementación de interfaces n n Los interfaces remotos se implementan haciendo uso de clases skeleton generadas por el compilador de IDL Una clase skeleton es una implementación del patrón Adapter n n Al igual que en el patrón estándar Adapter, existen dos posibles enfoques n n n Adapta la interfaz de la clase servant a la invocación de mensajes recibidos por el ORB Basado en herencia Basado en delegación Transparente al cliente Enfoque basado en herencia (1) <<interface>> Generada por el org::omg::CORBA::portable::InvokeHandler compilador de IDL + _invoke(method : String, is : InputStream, handler : ResponseHandler) : OutputStream <<interface>> es::udc::fbellas::corbaws::clock::idl:ClockOperations org::omg::PortableServer::Servant + getTimeOfDay() : TimeOfDay es::udc::fbellas::corbaws::clock::idl::ClockPOA Generada por el compilador de IDL + invoke(request : org::omg::CORBA::ServerRequest) + _this(orb : org::omg::CORBA::ORB) : es::udc::fbellas::corbaxml::clock::idl::Clock es::udc::fbellas::corbaws::cloc Proporcionada por k::server::ClockImpl el programador + getTimeOfDay() : TimeOfDay Enfoque basado en herencia (y 2) Resto aplicación cliente getTimeOfDay <<interface>> Clock POA invoke <<interface>> InvokeHandler POAManager ClockPOA getTimeOfDay Clase Proxy Cliente ORB ClockImpl Servidor Herencia simple n IDL <<interface>> Thermometer getTemperature() : Temperature getLocation() : Location <<interface>> Thermostat setTemperature(t : Temperature) : void Implementación de la herencia simple n Asumiendo que todo el código está en el mismo servidor ... <<interface>> ThermometerOperations <<interface>> ThermostatOperations ThermometerPOA ThermometerImpl ThermostatPOA 1 ThermostatImpl t: ThermometerImpl public int getTemperature() { return t.getTemperature(); } Herencia múltiple n IDL <<interface>> LandVehicle <<interface>> WaterVehicle <<interface>> AmphibiousVehicle Implementación de la herencia múltiple n Asumiendo que todo el código está en el mismo servidor ... <<interface>> LandVehicleOperations <<interface>> WaterVehicleOperations <<interface>> AmphibiousVehicleOperations LandVehiclePOA WaterVehiclePOA AmphibiousVehiclePOA LandVehicleImpl 1 AmphibiousVehicleImpl l: LandVehicleImpl w : WaterVehicleImpl 1 WaterVehicleImpl