apéndice a: osgi: open services gateway...

70
1 Apéndice A: OSGi: Open Services Gateway Interface Dr. Diego Lz. de Ipiña Gz. de Artaza http://paginaspesonales.deusto.es/dipina http://www.morelab.deusto.es http://www.ctmd.deusto.es [email protected] Contenido 1. Introducción (30’) a. ¿Qué proporciona? b. ¿Dónde se aplica? c. Especificaciones y Herramientas OSGi 2. 2. Arquitectura OSGi (30’) a. JVM, modularidad, gestión de ciclo de vida, seguridad b. Registro de Servicios c. Concepto de Bundle d. Servicios Estándar OSGi 3. Programando OSGi con Knopplerfish (75’) + Descanso (15’) a. Instalación y configuración de plug-in para Eclipse b. Usando Ant para compilar código OSGi c. Desarrollando un primer bundle d. Fichero de manifesto e. Creación de la clase Activator f. Compilando e instalando un bundle g. Creando interfaces de servicio h. Usando el registro de servicios i. Usando los servicios avanzados de servicios: ServiceListener y ServiceTracker 2/140

Upload: others

Post on 17-Jul-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

1

Apéndice A: OSGi: Open Services Gateway Interface

Dr. Diego Lz. de Ipiña Gz. de Artazahttp://paginaspesonales.deusto.es/dipina

http://www.morelab.deusto.eshttp://[email protected]

Contenido

1. Introducción (30’)a. ¿Qué proporciona?b. ¿Dónde se aplica?c. Especificaciones y Herramientas OSGi 2.

2. Arquitectura OSGi (30’)a. JVM, modularidad, gestión de ciclo de vida, seguridadb. Registro de Serviciosc. Concepto de Bundled. Servicios Estándar OSGi

3. Programando OSGi con Knopplerfish (75’) + Descanso (15’)a. Instalación y configuración de plug-in para Eclipseb. Usando Ant para compilar código OSGic. Desarrollando un primer bundled. Fichero de manifestoe. Creación de la clase Activatorf. Compilando e instalando un bundleg. Creando interfaces de servicioh. Usando el registro de serviciosi. Usando los servicios avanzados de servicios: ServiceListener y ServiceTracker

2/140

Page 2: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

2

Contenido

4. Servicios Avanzados en OSGi (45’)a. Log Serviceb. Http Servicec. Declarative Serviced. Configuration Servicee. Event Admin Servicef. Wire Admin Serviceg. R-OSGi

5. Desarrollo de un ejemplo complejo en OSGi (60’)a. Diseño de un Servicio de Descubrimiento de Servicios distribuidosb. Usando el LogServicec. Implementando el servicio, bundle y activatord. Creación de Servicios Distribuidos descubribles mediante el Distributed Bundle

Discoverere. Aplicación Bundle ilustrando Declarative, Configuration, Event Admin y Wire

Admin services

6. Conclusión y preguntas (15’)

3/140

OSGi en Pocas Palabras

� Una framework Java para el desarrollo de aplicaciones desplegables remotamente, que requieren:� Robustez� Elevada distribución� Heterogeneidad (diferentes dispositivos)� Colaboraciones

� Resuelve el problema de desplegar muchos programas independientes en grandes sistemas distribuidos, proveyendo:� Un sistema operativo para programas� Un formato para la descarga de código ejecutable� Un mecanismo para descubrir otros programas� Estandarización de APIs para promocionar la reutilización� Gestión eficiente del ciclo de vida de las aplicaciones descargadas

4/140

Page 3: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

3

OSGi (Open Services Gateway Initiative)

� Define una Arquitectura Centralizada Orientada a Servicios (SOA) dentro de una máquina virtual (JVM)

� ¿Por qué se creo?

� Necesidad de crear herramientas que estandaricen los aspectos de integración del software de tal manera que la reutilización de componentes software sea más sencilla, fiable, robusta y de bajo coste.

� ¿Qué aporta?

� OSGi aporta modularidad dinámica a Java y permite estandarizar la integración del software

5/140

OSGi (Open Services Gateway Initiative)

� OSGi define un entorno de ejecución estandarizado orientado a componentes que es la base de una arquitectura SOA.� Proporciona una pequeña capa de software que permite la cooperación

entre componentes Java en una única JVM.� Gestiona dinámica del ciclo de vida de los componentes gestionados

(instalación, actualización o eliminación) sin reinicio del dispositivo� Múltiples dominios de aplicación:

� Pasarelas residenciales� Dispositivos móviles de última generación� Industria del automóvil� Aplicaciones de sobremesa o � Dispositivos electrónicos (Philips iPronto, Nokia N800 y E70 o NSLU2)

� Realmente una especificación, no un producto, en R4:� r4.core.pdf (2.01 MB) -- R4 Core Specification� r4.cmpn.pdf (4.55 MB) -- R4 Service Compendium

6/140

Page 4: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

4

OSGi Alliance

� OSGi es gestionado por la OSGi Alliance: http://www.osgi.org/, actualmente más de 30 empresas:

Alpine Electronics Europe Gmbh , Aplix Corporation , BMW Group , Computer Associates ,

Deutsche Telekom AG , Echelon Corporation , Electricité de France (EDF) , Ericsson Mobile

Platforms AB , Esmertec , Espial Group, Inc. , ETRI Electronics and Telecommunications

Research Institute , France Telecom , Gatespace Telematics AB , Gemplus , Harman/Becker

Automotive Systems GmbH , Hitachi, Ltd. , IBM Corporation , Industrial Technology

Research Institute , Insignia Solutions , Intel Corporation , KDDI R&D Laboratories, Inc. , KT

Corporation , Mitsubishi Electric Corporation , Motorola, Inc. , NEC Corporation , Nokia

Corporation , NTT , Oracle Corporation , Panasonic Technologies, Inc. , ProSyst Software

GmbH , Robert Bosch Gmbh , Samsung Electronics Co., Ltd. , SavaJe Technologies, Inc. ,

Sharp Corporation , Siemens AG , Sun Microsystems, Inc. , Telcordia Technologies, Inc. ,

Telefonica I+D , TeliaSonera , Vodafone Group Services Limited

7/140

Características Principales de OSGi

1. Gestión de componentes software� Formato de empaquetamiento para aplicaciones (bundle)� Instalar/Arrancar/Parar/Actualizar/Desinstalar un bundle� Capacidad de recibir actualizaciones futuras de productos

2. Gestión de Componentes Remota� Provee una API de gestión a utilizar por un bundle de gestión que mapea un

protocolo a un conjunto de llamadas� Hace frente a aspectos de heterogeneidad

3. Cooperación entre Aplicaciones� Los bundles pueden contribuir tanto con código como servicios al entorno� Contenedor abierto donde las aplicaciones no se ejecutan aisladas, comparten

librerías� El Registro de Servicios de OSGi ofrece modelo ligero para publicar, encontrar

y asociar servicios dentro de una JVM� Incluye un servicio de notificación para generar eventos de ciclo de vida

4. Naturaleza Dinámica� La actualización de componentes no requiere el reinicio

5. Otras propiedades� Despliegue simplificado� Separación estricta de interfaz e implementación (enfoque SOA)� Entorno de Ejecución Seguro� Componentes Comerciales pueden Desplegarse Fácilmente

8/140

Page 5: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

5

¿Qué proporciona OSGi?

� Framework de componentes software estándar y abierto para productores de dispositivos, proveedores de servicios y desarrolladores

� Modelo de coexistencia para permitir diferentes componentes dentro de una JVM

� Modelo cooperativo donde las aplicaciones pueden descubrir y usar servicios provistos por otras aplicaciones en la misma instancia de OSGi

� Arquitectura flexible de gestión remota: API de despliegue que controla ciclo de vida de aplicaciones: bundle + ciclo de vida de bundle

� Conjunto de servicios opcionales como HTTP, Wiring, IO o eventos

� Entorno de ejecución seguro

9/140

Complejidad del Software

Structured Programming

Pro

duct

ivity

Complexity and Size

Assembly

Service Oriented Programming

10/140

Page 6: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

6

¿Dónde se aplica?

� Pasarelas residenciales:� Empresas como Siemens producen dispositivos para la automatización

del hogar y sus componentes conectados por PLC o UPnP. Hace controlables remotamente a esos dispositivos.

� Aplicaciones de dektop:� El popular entorno de desarrollo Eclipse está basado en OSGi

(http://www.eclipse.org/osgi/)� Dispositivos móviles de nueva generación:

� Los fabricantes de dispositivos móviles requieren una plataforma para el despliegue continuo de servicios escalable, flexible y de pequeño tamaño basada en OSGi y Java (JSR 232 – http://jcp.org/en/jsr/detail?id=232 y http://gceclub.sun.com.cn/java_one_online/2006/TS-3757/TS-3757.pdf)

� Automoción:� Series 5 y 7 BMW incorporan OSGi para su plataforma de información y

entretenimiento (AMI-C – http://www.ami-c.org/)� Próximamente en Servidores de Aplicaciones Empresariales

� Interface21, creadores de Spring, definiendo la nueva generación de servidor EE en OSGi (http://www.springframework.org/osgi/specification)

� Ultima versión de IBM WebSphere basada en OSGi

11/140

Ejemplo de Despliegue OSGi en el Hogar (1)

Home Office

HomeControl

DifferentNetworks

Security

ServicesProvider

Firewall

Aggregation & Management Platform

Subscriber, Service andDevice Management

Notification Server

FamilyPortal

Secure Tunnel

Entertainment/Gaming

InternetServices

Webpad

Internet

AccessGateway

ServiceOffering

Accessfrom any Web Terminal

e.g. access from office or via PDA/WAP phone

OSGi Service Gateway

12/140

Page 7: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

7

Ejemplo de Despliegue OSGi en el Hogar (2)

13/140

Implementaciones OSGi R4 Comerciales

� Existen varias implementaciones de OSGi comerciales certificadas para la versión 4:� Makewave Knopflerfish Pro 2.0 (www.makewave.com) �

comercial/libre� ProSyst Software mBedded Server 6.0 (www.prosyst.com) � Samsung OSGi R4 Solution (www.samsung.com) � KT OSGi Service Platform (KOSP) 1.0 (http://www.kt.co.kr/) � HitachiSoft SuperJ Engine Framework (http://hitachisoft.jp/)

14/140

Page 8: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

8

Implementaciones OSGi R4 Libres

� Además, las siguientes implementaciones libres de R4 OSGi también existen:� Eclipse Equinox (http://www.eclipse.org/equinox/) – framework

OSGi usada en Eclipse

� Makewave Knopflerfish (http://www.knopflerfish.org/) – más usada y mejor documentada (elegida para este curso)

� Apache Felix (http://felix.apache.org/site/index.html) � OSCAR

15/140

Aplicaciones Reales usando OSGi

� X-ray measurement Systems� BMW 7 series� Eclipse� Siemens Medical� Nokia E70� Siemens Gigaset SX765� Espial Set-top box� VDO on-board computer� Prosyst mBedded Server, Remote

Manager and Builder� Bosch and Siemens Home

Appliances� Philips iPronto� Telefónica ehogar� Websphere application server

16/140

Page 9: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

9

Características Esenciales de OSGi

� Gestión de componentes software

� Gestión remota de componentes

� Cooperación entre componentes/aplicaciones

� Provisión de entorno de ejecución seguro

17/140

Gestión de Componentes Software

� OSGi provee las siguientes funciones para la gestión del ciclo de vida de aplicaciones:� Bundles: formato de empaquetamiento para aplicaciones. Es un

simple JAR compatible con mecanismos de compresión ZIP.� Gestión de ciclo de vida de bundles:

� Instalar un bundle� Arrancar/parar un bundle� Actualizar un bundle� Desinstalar un bundle

IOCPU

OS

Java VM

18/140

Page 10: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

10

Configuración Remota de Componentes

� OSGi está concebido para dispositivos que operan desatendidos o controlados por un operador de plataforma que requiera gestión remota

� El ciclo de vida del software no para cuando un dispositivo abandona la fábrica

� Es conveniente poder actualizar el software instalado una vez desplegado

� Para permitir gestión remota, OSGi proporciona una API de gestión de bundles, donde algunos bundles autorizados actúan de puente entre cualquier protocolo y las llamadas de la API.

19/140

Cooperación entre Aplicaciones (1)

� OSGi es el único modelo de servidor de aplicaciones Java donde éstas pueden compartir código entre ellas y no se ejecutan aisladas unas de otras:� A diferencia de MIDP, Java EE (librerías pero mucha replicación)

� OSGi aporta un modelo de servicios ligero que permite publicar, encontrar y asociar servicios dentro de una JVM a través del Registro de Servicios

� Servicio OSGi = objeto de un bundle disponible para su uso por otros bundles

20/140

Page 11: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

11

Cooperación entre Aplicaciones (2)

� Arquitectura Orientada a Servicios (SOA):

� Separa el contrato de la implementación

� Permite implementaciones alternativas

� Descubre y asocia dinámicamente las aplicaciones

� Asociación basada en contratos (definiciones de interfaz)

� Reutilización de componentes� Componentes desligados a los

detalles de implementación de otros componentes, solamente sus interfaces tienen que conocerse

Service Contract

Componentprovides

uses

21/140

Entorno de Ejecución Seguro

� OSGi ofrece un modelo de seguridad dividido en 4 niveles:� Mecanismo de seguridad de la JVM: previene operaciones

peligrosas como manipulación de punteros o acceso no restringido a arrays

� Seguridad del lenguaje Java: modificadores de acceso (“public”, “private”, “protected”)

� Seguridad proporcionada por la plataforma Java SE (http://java.sun.com/javase/technologies/security/ y java.security.permission.*)

� OSGi separa unos bundles de otros y comprueba que un bundle tiene permisos para interactuar con otro

22/140

Page 12: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

12

Arquitectura OSGi (1)

� OSGi proporciona un entorno de computación para bundles que se ejecutan conjuntamente en una JVM.

23/140

Arquitectura OSGi (2)

24/140

Page 13: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

13

Arquitectura OSGi (3)

� Permite a las aplicaciones compartir una única JVM. � Gestiona la carga de clases en una manera mejor

definida y eficiente que el estándar Java� Soporta incluso versiones

� Provee aislamiento/seguridad entre aplicaciones

� Media permitiendo comunicación y colaboraciónentre aplicaciones

� Provee gestión del ciclo de vida (instalar, empezar, parar, actualizar)

� Libre de políticas� Éstas son impuestas por los bundles

25/140

Capas de la Framework OSGi (1)

Module

Life Cycle

Services

Sec

urity

Execution Environment

App

licat

ions

26/140

Page 14: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

14

Capas de la Framework OSGi (2)

� Entorno de ejecución� Provee un contexto de ejecución bien definido a las aplicaciones, tal como J2SE, CDC, CLDC,

MIDP

� Módulos� Provee capacidades de carga y empaquetamiento de clases� Facilita el lincado entre módulos

� Ciclo de Vida:� Instalación, comienzo, parada, actualización y desinstalación dinámica de Bundles� Mecanismos de dependencia para asegurar operación correcta del entorno

� Servicios:� Modelo de cooperación entre bundles que tiene en cuenta el dinamismo � Completo modelo para compartir objetos entre bundles. � Provisión de un mecanismo de eventos para gestionar el dinamismo

� Seguridad� Imbuida en todas las capas basada en Java y en el modelo de seguridad de Java 2� Añade gestión dinámica de permisos

27/140

Capas de la Framework OSGi: Entorno de Ejecución

� OSGi requiere un entorno de computación seguro, abierto, robusto, bien documentado, maduro, rico y portable

� Inspirado en Java porque en 1999 cuando se creó OSGi, Java ya contaba con uno

� Podrían realizarse implementaciones alternativas de OSGi en .NET

� Las APIs de OSGi utilizan un subconjunto de las clases definidas por Java SE o Java ME CDC/CLDC

CLDC/MIDP

J2SE

CDC/FP

OSGiMin.

28/140

Page 15: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

15

Capas de la Framework OSGi: Modularidad (1)

� Un bundle es la unidad de ejecución en OSGi

� Compuesto principalmente de clases Java, librerías, recursos y manifest.mf

� Mejora la modularidad de las aplicaciones Java:� Elimina dependencias en Classpath

� Protege quién accede a qué� Soporta versiones

29/140

Capas de la Framework OSGi: Modularidad (2)

� Características:� Compartición: OSGi promueve compartir las clases entre bundles

� Un bundle puede proveer librerías utilizadas por otros bundles � reducción en necesidades de memoria

� Cada bundle puede exportar e importar paquetes (conjuntos de clases):� Si múltiples bundles exportan el mismo paquete (con una versión diferente), la

framework ha de seleccionar una versión apropiada por cada bundle

� Tras desinstalar un bundle los importadores son reiniciados para que se asocien a otro nuevo exportador de paquetes

� Gestión de interdependencias: los bundles pueden depender de funcionalidad ya alojada en un entorno

� Lazy loading: un bundle puede tener dependencias en bundles todavía no instalados

� Versionamiento: Diferentes bundles pueden utilizar diferentes versiones de la misma clase

30/140

Page 16: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

16

Capas de la Framework OSGi: Modularidad (3)

31/140

Capas de la Framework OSGi: Ciclo de Vida (1)

� El bundle del sistema representa a la framework OSGi.� Ofrece una API para gestionar bundles:

� Instalarlos� Resolverlos� Arrancar� Parar� Refrescar� Actualizar� Desinstalar Bundle

XBundle

X-v2

BundleB

BundleM

BundleA

Systembundle

State (active or not)

Manages

32/140

Page 17: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

17

Capas de la Framework OSGi: Ciclo de Vida (2)

� Un bundle es iniciado por la clase BundleActivatorBundleActivatorBundleActivatorBundleActivator

� Una cabecera en el fichero JAR que define un bundle hace referencia a esta clase

� La interfaz BundleActivatortiene dos métodos:� Start()Start()Start()Start(): inicializa y retorna

inmediatamente� Stop()Stop()Stop()Stop(): limpia el bundle

� El BundleActivator recibe un BundleContextBundleContextBundleContextBundleContext que provee acceso a las funciones de la framework OSGi

� La Framework provee el servicio Start Level que controla el inicio/parada de grupos de aplicaciones

INSTALLED

RESOLVED

UNINSTALLED

ACTIVE

STOPPING

STARTING

start

stop

33/140

Capas de la Framework OSGi: Servicios(1)

� Provee un modelo de servicios dentro de una JVM

� Descubrimiento (y notificación) de servicios basada en interfaces y propiedades, no requiere ningún protocolo

� Asociación a uno o varios servicios mediante:� Control de programa� Siguiendo ciertas reglas de la framework� Configuración de despliegue

� Aclaración sobre Service Oriented Architectures (SOA)

� Los Servicios Web se asocian y descubren en la red� En la plataforma OSGi lo hacen dentro de una Java VM

� La OSGi Alliance define un gran conjunto de servicios

34/140

Page 18: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

18

Capas de la Framework OSGi: Servicios(2)

35/140

36363636/142/142/142/142

Capas de la Framework OSGi: Seguridad

� Basado en Seguridad de Java 2� Permisos� Firma de bundles

36/140

Page 19: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

19

Beneficios de la Plataforma OSGi

� Los componentes son pequeños

� Fáciles de hacer

� Los componentes están totalmente desacoplados unos de otros

� Aporta reusabilidad

� Modelo colaborativo

� Permite la reutilización de componentes para diferentes aplicaciones

� Gran aceptación

� Mercado grande, muchos componentes existentes

� Modelo dinámico para las personalización y variación continua de aplicaciones en los dispositivos actuales

37/140

Bundles: Infraestructura de Despliegue en OSGi

� Un bundle es una aplicación autocontenida ejecutable en diferentes implementaciones de OSGi� Como si fuera un fichero EXE en Windows� Contiene programas y recursos� Registra cero o más servicios

� Un servicio se especifica como una interfaz Java y puede ser implementado por varios bundles

� Un mecanismo de búsqueda puede ser utilizado para encontrar servicios registrados por otros bundles

� Lenguaje de consultas (filtros)

� Recordemos que:� La propia framework es un bundle (System Bundle)� La especificación de OSGi define un conjunto de servicios estándar

que las aplicaciones pueden cargar y utilizar� Bundle Repository – http://www2.osgi.org/Repository/HomePage

� Oscar Bundle Repository: http://oscar-osgi.sourceforge.net/

38/140

Page 20: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

20

Bundles: Contenido interno

� Un bundle es un fichero JAR que contiene:� El fichero manifest.mfmanifest.mfmanifest.mfmanifest.mf con los metadatos del bundle:

� Algunas cabeceras predefinidas por el formato JAR� Otras definidas por la OSGi Alliance

� Código (las clases en paquetes)� Recursos (otros ficheros dentro del .JAR)

� Durante la instalación, la framework:� Lee el manifesto del fichero� Instala el código y los recursos� Resuelve las dependencias� Inicia el control del ciclo de vida del bundle

� Durante la ejecución, la framework:� Invoca BundleActivatorBundleActivatorBundleActivatorBundleActivator para iniciar gestión del ciclo de vida� Gestiona el CLASSPATH del bundle como una red de classloaders� Gestiona las dependencias entre servicios� Invoca a BundleActivator para parar el bundle� Elimina los recursos utilizados por el bundle cuando acaba

Bundle A

{…}

39/140

Modelo de Colaboración en OSGi

� OSGi es más que un entorno de ejecución de Applet, MIDlet o Xlet� Los bundles, unidades de ejecución en OSGi, colaboran

mediante:

� Objetos de servicios

� Compartiendo paquetes

� Un Registro de Servicios dinámico permite a un bundle encontrar y seguir el rastro de otros objetos de servicio

� La framework efectúa una gestión eficiente de esta colaboración� Dependencias, seguridad

40/140

Page 21: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

21

Modelo de Colaboración en OSGi: Servicios

OSGi Framework

Bundle A

{…}

= service, defined by

java interface

Bundle B

{…}

Bundle C

{…}

= bundle

41/140

Modelo de Colaboración en OSGi: Dependencias

� La especificacion OSGi soporta la declaración de dependencias mediante las cabeceras: RequireRequireRequireRequire----BundleBundleBundleBundle e ImportImportImportImport----PackagePackagePackagePackage

� Require-Bundle crea una dependencia en un bundle completo� Muy fácil de usar� Importa paquetes que no son utilizados

� Import-Package crea una dependencia en un único paquete� Los bundles solamente importan lo que

necesitan

� Se recomienda usar Import-Package porque facilita el despliegue y la gestión de versiones

r

r

s

r

q

p

Require-Bundle

Import-Package

42/140

Page 22: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

22

Modelo de Colaboración en OSGi: Servicios

� OSGi define una plataforma orientada a servicios con tres actores:� Proveedores de Servicios, publican descripciones de servicios� Consumidores de Servicios, descubren los servicios y se

asocian a sus proveedores� Pueden recibir notificaciones sobre cambios en el estado de servicios

� Registro de Servicios, permite a los consumidores de servicios descubrir otros servicios mediante consultas en sintaxis LDAP:

� "(&(" + Constants.OBJECTCLASS + "=Person)(|(sn=Jensen)(cn=Babs J*)))"

� En OSGi, un servicio está formado por:� Interfaz de Servicio, una clase o interfaz Java� Propiedades del servicio, pares nombre-valor

� Los servicios se implementan como objetos dentro del bundle

43/140

Modelo de Colaboración en OSGi: Servicios

44/140

Page 23: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

23

Modelo de Colaboración en OSGi: Servicios

45/140

Modelo de Colaboración en OSGi: Servicios

JAVA

Operating System

Hardware

Java Application Manager

Serviceregistry

packagespackages

Midlet,Xlet,

orApplet

Midlet,Xlet,or

Applet

No native code

No package management(versions!)

No collaboration

No management bundles

46/140

Page 24: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

24

Ciclo de Vida de un Bundle en Detalle (1)

� Antes de poder arrancar un bundle instalado es necesario resolver sus dependencias� Todo bundle arrancable debe implementar la interfaz BundleActivatorBundleActivatorBundleActivatorBundleActivator

con los métodos: a) start(BundleContext)start(BundleContext)start(BundleContext)start(BundleContext) y b) stop(BundleContext)stop(BundleContext)stop(BundleContext)stop(BundleContext)

� La cabecera del manifesto Bundle-Activator indica la clase que habrá que instanciar para arrancar o parar un bundle

� Durante la vida de un bundle varios eventos pueden ocurrir en la framework:� Otros bundles son parados, actualizados, desinstalados, instalados,

empezados, etc.� Si se desinstala un bundle en el que otro tiene dependencias, el

último accederá a los paquetes exportados anteriormente mientras no haya alternativas a esos paquetes exportados adoptados mediante un refresco del bundle

� El comienzo y fin de un bundle es grabado permanentemente, además existen start-levels que indican el orden de arranque de los bundles en la framework

47/140

Ciclo de Vida de un Bundle en Detalle (2)

� El objeto BundleContext provee una API para la instalación de bundles y su registro

48/140

Page 25: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

25

Registro de Servicios en Detalle (1)

� La característica diferencial de OSGi frente a otros entornos Java es su naturaleza dinámica:� Teléfono móvil es asociado a un nuevo dispositivo� Pasarela residencial detecta nueva electrodoméstico conectado� Coche detecta la presencia de un teléfono móvil a su alrededor

� El Registro de Servicios permite a los desarrolladores de aplicaciones construir componentes pequeños y desacoplados que pueden adaptarse al entorno cambiante en tiempo real� Estos componentes pueden ser combinados para crear

aplicaciones complejas

49/140

Registro de Servicios en Detalle (2)

� Un servicio se registra bajo un nombre de interfaz y un conjunto de propiedades

� Un lenguaje de filtrado sencillo basado en LDAP es utilizado para seleccionar los servicios necesarios.� (&(sn=Ipiña)(cn=Diego))

� La interfaz ServiceListenerServiceListenerServiceListenerServiceListener y la clase ServiceTrackerServiceTrackerServiceTrackerServiceTrackerpermiten recibir notificaciones de eventos de ciclo de vida de servicios de interés

� La interfaz BundleContextBundleContextBundleContextBundleContext permite la interacción con el Registro de Servicios:� Registrar objetos (BundleContext.registerService())

� Buscar otros objetos en el registro (BundleContext.getServiceReference())

� Recibir notificaciones cuando servicios de interés son registrados o eliminados (BundleContext.addServiceListener())

50/140

Page 26: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

26

Detalles sobre Servicios

� Un servicio es un objeto registrado con el Framework por un bundle para su uso por otros bundles

� La semántica de un servicio es dada por su interfaz Java

� Un bundle puede registrar uno o varios servicios

� Un bundle puede usar un servicio (bind) con cierta cardinalidad� 1..1, 0..1, 0..n

� Un servicio puede ser descubierto dinámicamente� Búsqueda activa con filtro de

consulta� Interfaz listener

� ¡Los servicios pueden acabar en cualquier momento! ¡Todo es muy dinámico!

service

bind register

listen

package org.osgi.service.log;

import org.osgi.framework.ServiceReference;

public interface LogService {

static final intLOG_ERROR= 1;

static final intLOG_WARNING= 2;

static final intLOG_INFO= 3;

static final intLOG_DEBUG= 4;

void log(int level, String message);

void log(int level, String message,

Throwable exception);

void log(ServiceReference sr,int level,

String message);

void log(ServiceReference sr, int level,

String message, Throwable exception);

}

51/140

Manipulación de Servicios

� La interfaz BundleContextBundleContextBundleContextBundleContextfacilita los métodos para manipular el registro de servicios

� Los registros de servicio son gestionados por objetos de tipo ServiceRegistrationServiceRegistrationServiceRegistrationServiceRegistration

� Pueden utilizarse para desregistrar un servicio o modificar sus propiedades

� Los objetos ServiceReferenceServiceReferenceServiceReferenceServiceReferencedan acceso al servicio así como a sus propiedades

� El acceso a un servicio es mediante el método getServicegetServicegetServicegetService

� Los servicios se devuelven con el método ungetServiceungetServiceungetServiceungetService.

ServiceRegistration registerService(

String clss,

Object srvc,

Dictionary prprts)

ServiceReference[]

getServiceReferences(

String clss,

String fltr)

Object getService(

ServiceReference reference)

boolean ungetService(

ServiceReference rfrnc);

52/140

Page 27: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

27

Seguridad en Detalle

� OSGi ejecuta aplicaciones de una variedad de fuentes bajo control estricto de un sistema de gestión:� Seguridad de Código de Java 2: java.security.Permission

y sus subclases (FilePermission, SocketPermission) protegen el acceso a recursos del sistema

� Exposición de contenido de bundles mínima mediante modificadores de acceso de las clases Java o haciendo que los paquetes sean visibles sólo dentro de un bundle

� Permisos de paquete OSGi limitan quién puede importar o exportar paquetes o mediante org.osgi.framework.ServicePermission

53/140

Servicios Estándar en OSGi (1)

� Servicios del Framework:

� Permission Admin: los permisos de bundles actuales o futuros pueden ser manipulados a través de este servicio

� Conditional Permission Admin: extiende el Permission Admincon permisos que son aplicados cuando ciertas condiciones son cumplidas

� Package Admin: provee información sobre el estado compartido por un paquete y permite refrescarlos

� Start Level: conjunto de bundles que deben ejecutarse conjuntamente precediendo o siguiendo a otros niveles de comienzo

� URL Handlers: permite a los bundles contribuir dinámicamente con nuevos gestores de contenidos a la clase URL

54/140

Page 28: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

28

Servicios Estándar en OSGi (2)

� Servicios del Sistema:� Log Service: trazado de información, advertencias, información

de debug o errores es redireccionado a bundles subscritos con él� Configuration Admin: modelo flexible y dinámico para obtener

información de configuración� Event Admin: mecanismo general y flexible de publicar y

subscribirse a eventos� Device Access: mecanismo para asociar un driver a un nuevo

dispositivo y descargar automáticamente un bundle� User Admin: BBDD con información de usuario con propósito de

autenticación y autorización� IO Conector: permite a los bundles proveer nuevos y alternativos

protocolos para javax.microedition.io� Preferences Service: provee acceso a base de datos jerárquica

de propiedades. Similar al registro de Windows.

55/140

Servicios Estándar en OSGi (3)

� Servicios del Sistema:

� Servicio HTTP: este servicio ejecuta un contenedor de servlets, los bundles pueden proveer servlets que son accesibles mediante HTTP.

� Servicio UPnP: mapea dispositivos en una red UPnP al Registro de Servicios.

� Wire Admin: permite la composición de diferentes servicios de acuerdo a una conexión.

56/140

Page 29: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

29

Servicios Estándar en OSGi (4)

� Soporte a la Programación:� Service Tracker: simplifica la gestión de servicios proveyendo

una clase que sigue la pista de los servicios de una aplicación� Declarative Services: permite leer una configuración XML de un

bundle con registro de servicios y dependencias. Será iniciado solamente cuando los servicios declarados sean realmente necesarios por otros bundles.

57/140

Knopflerfish

� Varias opciones de implementaciones open source� Makewave Knopflerfish – http://www.knopflerfish.org/� Equinox – implementación de OSGi usada por Eclipse

(http://www.eclipse.org/equinox/)� Apache Felix (http://felix.apache.org)

� Knopflerfish ofrece la mejor documentación y acabado� Muy sencilla de utilizar

� Provee herramienta de gestión de bundles fantástica

� Producida por Makewave (antes Gatespace Telematics)� Una de las implementaciones de pago más utilizadas

� Para una comparativa entre las ventajas y desventajas de las diferentes implementaciones open source de OSGi visitar: � http://www.pierocampanelli.info/articles/2007/01/22/status-of-opensource-

osgi-containers

58/140

Page 30: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

30

Instalación de Knoplerfish

� Prerrequisito: tener una versión de Java 1.2.2 o superior en tu máquina

� Descargar knopflerfish_osgi_2.0.3.jar (8,6 MB)� Framework completa, incluyendo código fuente, documentación,

ejecutable autoextraíble:� http://www.knopflerfish.org/download.html#2.0.3

� Instalar Knoplerfish con el siguiente comando:� java -jar knopflerfish_osgi_<version>.jar

� Ejecutar Knoplerfish mediante: � cd %KNOPFLERFISH_INTALL_DIR%/knopflerfish.org/osgi

� java –jar framework.jar

� Abrirá el Knopplerfish OSGi Desktop

59/140

Knoplerfish OSGi Desktop

60/140

Page 31: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

31

Instalación Plug-in Eclipse OSGi

� Download Eclipse Europa de: http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/20071103/eclipse-java-europa-fall2-win32.zip

� Pasos necesarios para su instalación:1. Seleccionar la opción de menú en Eclipse Help�Software

Updates�Find and Install....2. Seleccionar Search for new features to install e introducir los

detalles de un nuevo site remoto: Knopflerfish update site, y la URL http://www.knopflerfish.org/eclipse-update/.

3. Hacer clic sobre la caja Knopflerfish update site y pulsar Finish. � Documentado en: http://www.knopflerfish.org/eclipse_install.html

� Pasos necesarios para su configuración:� Seleccionar opción de menú Window�Preferences y en Framework

añadir el directorio de instalación de Knopflerfish.� Seleccionar Default JRE como el entorno de ejecución de bundles.

� Podrían seleccionarse otras opciones como CLDC u OSGi Minimum� Asociar un Bunde repository donde Eclipse pueda resolver

dependencias durante la compilación y ejecución de los bundles. � Documentado en: http://www.knopflerfish.org/eclipse_preferences.html

61/140

Configuración de un Proyecto Knopflerfish en Eclipse

1. Seleccionar la opción de menú File�New�Project...

2. Seleccionar la opción Bundle Project e introducir la información del proyecto.

3. Editar y compilar el proyecto creado. � La primera vez que se vaya a compilar y ejecutar el proyecto

habrá que introducir una nueva configuración de lanzamiento, yendo a la opción del menú Run: OSGi�Knopflerfish.

� Documentación adicional en: http://www.knopflerfish.org/eclipse_plugin.html

62/140

Page 32: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

32

Usando Ant para Compilar Bundles

� Knopflerfish viene con un fichero build.xml preconfigurado que permite la generación y compilación de bundles en OSGi

� Pasos para configurar el proyecto:1. Crear un nuevo directorio donde colocar el código del nuevo bundle. Por

ejemplo, holamundobundle.2. Copiar el fichero

knopflerfish_osgi_2.0.1\knopflerfish.org\ant\build_example.xml a holamundobundle\build.xml.

3. Configurar la plantilla de fichero build.xml a tu proyecto. Entre otras cosas deberás configurar las propiedades impl.pattern y api.pattern.

4. Invocar ant.5. Instalar el bundle, bien usando la interfaz gráfica o bien los comandos de

línea de comando provistos por Knopflerfish. � Prerrequisitos:

� Instalar ant y modificar variable PATH a directorio %ANT_HOME%\bin

63/140

Nuestro Propio Fichero Ant

� Nosotros vamos a utilizar una versión simplificada del build.xml, no autogenera manifest.mf, pero sí compila (compile), crea el .jar (jar) correspondiente al bundle y lo despliega en Knopflerfish (deploy)� IMPORTANTE: hay que crear la variable de entorno OSGI_HOMEOSGI_HOMEOSGI_HOMEOSGI_HOME

para que apunte al directorio de instalación de Knopflerfish, por ejemplo: C:\%INTALL_OSGI_DIR%\knopflerfish.org\osgi

64/140

Page 33: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

33

Nuestro Propio Fichero Ant

<?xml version="1.0"?><project name="nombre-bundle" default="all">

<property name="app.name" value="nombre-bundle"/><property name="output.home" value="./build"/><property environment="env"/><property name="osgi.deploy" value="${env.OSGI_HOME}/jars"/><path id="lib.class.path">

<fileset dir="${env.OSGI_HOME}"><include name="**/*.jar"/>

</fileset></path><target name="all" depends="init,compile,jar,deploy"/><target name="init">

<mkdir dir="./classes"/><mkdir dir="./build"/></target><target name="compile"><target name="compile"><target name="compile"><target name="compile">

<javac destdir = "./classes" debug = "on"><javac destdir = "./classes" debug = "on"><javac destdir = "./classes" debug = "on"><javac destdir = "./classes" debug = "on"><src path= "./src"/><classpath refid="lib.class.path"/><src path= "./src"/><classpath refid="lib.class.path"/><src path= "./src"/><classpath refid="lib.class.path"/><src path= "./src"/><classpath refid="lib.class.path"/>

</javac></javac></javac></javac></target></target></target></target>

65/140

Nuestro Propio Fichero Ant

<target name="jar"><target name="jar"><target name="jar"><target name="jar"><jar basedir = "./classes"

jarfile = "./build/${app.name}.jar"compress = "true" includes = "**/*"manifest = "./meta-inf/MANIFEST.MF"/>

</target><target name="clean"><target name="clean"><target name="clean"><target name="clean">

<delete dir = "./classes"/><delete dir = "./build"/></target><target name="deploy" depends="jar"><target name="deploy" depends="jar"><target name="deploy" depends="jar"><target name="deploy" depends="jar">

<delete><fileset dir="${osgi.deploy}">

<include name="${app.name}.jar"/></fileset>

</delete><copy todir="${osgi.deploy}">

<fileset dir="${output.home}" includes="${app.name}.jar"/></copy>

</target></project>

66/140

Page 34: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

34

Creando nuestro primer bundle

� Nuestro primer bundle contendrá un hilo que imprime el mensaje “¡Hola Mundo!” cada cinco segundos.

� Pasos para implementar un bundle autónomo que no exporta servicios a otros, pero sí puede consumirlos:� Creación del fichero manifest.mf.

� Edición de una clase que implemente la interfaz BundleActivator.

� Edición de la clase del bundle, compilación y despliegue del bundle.

� Repetiremos el mismo proceso desde Eclipse

67/140

Pasos en detalle para crear nuestro primer bundle

1. Creación de un directorio para el bundle1. cd %KNOPFLERFISH_INSTALL%/knopflerfish.org/osgi

2. mkdir bundles

3. mkdir simplebundle

4. mkdir simplebundle/src

5. mkdir simplebundle/META-INF

2. Creación del fichero simplebundle/META-INF/manifest.mfManifest-Version: 1.0

Bundle-Name: simplebundle

Bundle-SymbolicName: simplebundle

Bundle-Version: 1.0.0

Bundle-Description: Demo Bundle

Bundle-Vendor: Universidad de Deusto-ko Unibertsitatea

BundleBundleBundleBundle----Activator: es.deusto.simplebundle.impl.ActivatorActivator: es.deusto.simplebundle.impl.ActivatorActivator: es.deusto.simplebundle.impl.ActivatorActivator: es.deusto.simplebundle.impl.Activator

Bundle-Category: example

ImportImportImportImport----Package: org.osgi.frameworkPackage: org.osgi.frameworkPackage: org.osgi.frameworkPackage: org.osgi.framework

68/140

Page 35: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

35

Pasos en detalle para crear nuestro primer bundle

� manifestmanifestmanifestmanifest....mfmfmfmf

� Fichero existente en todo archivo .jar� Extendido por la especificación de OSGi para añadir información adicional

sobre un bundle.� Indica los servicios ofrecidos por un bundle a otros bundles.

� Expresa las interdependencias existentes entre el bundle configurado y otros

- Un bundle no arranca hasta que todas sus dependencias han sido resueltas.

� En OSGi al fin y al cabo todo es un bundle, incluso la propia framework� Su contenido documentado en la sección 3.2.1 Bundle Manifest Headers

(página 36) de la Especificación de OSGi

� Propiedad BundleBundleBundleBundle----ActivatorActivatorActivatorActivator indica a la framework qué clase es laActivatorActivatorActivatorActivator � clase principal a invocar por la framework cuando cargueel bundle

� ImportImportImportImport----PackagePackagePackagePackage indica al framework que nuestro bundle requiereacceso a todas las clases en el paquete org.osgi.framework

69/140

Pasos en detalle para crear nuestro primer bundle

3. Create simplebundle/src/es/deusto/simplebundle/impl/Activator.java

package es.deusto.simplebundle.impl;import org.osgi.framework.BundleActivator;import org.osgi.framework.BundleContext;public class Activator implementsActivator implementsActivator implementsActivator implements BundleActivatorBundleActivatorBundleActivatorBundleActivator {

public static BundleContext bc = null;private HelloWorldThread thread = null;

public void start(BundleContext bc) throws Exceptionpublic void start(BundleContext bc) throws Exceptionpublic void start(BundleContext bc) throws Exceptionpublic void start(BundleContext bc) throws Exception {System.out.println("SimpleBundle starting...");Activator.bc = bc;this.thread = new HelloWorldThreadHelloWorldThreadHelloWorldThreadHelloWorldThread();this.thread.start();

}public void stop(BundleContext bc) throws Exceptionpublic void stop(BundleContext bc) throws Exceptionpublic void stop(BundleContext bc) throws Exceptionpublic void stop(BundleContext bc) throws Exception {

System.out.println("SimpleBundle stopping...");this.thread.stopThread();this.thread.join(); Activator.bc = null;

}}

70/140

Page 36: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

36

Pasos en detalle para crear nuestro primer bundle

� Casi todos los bundles tienen una clase Activator� Los Bundles que exportan funcionalidad pero no son ejecutados carecen de esta

clase� Clase que implementa la interfaz org.osgi.framework.BundleActivatororg.osgi.framework.BundleActivatororg.osgi.framework.BundleActivatororg.osgi.framework.BundleActivator

� Los métodos start() y stop() permiten gestionar el ciclo de vida de un bundle

� La clase BundleContextBundleContextBundleContextBundleContext permite a un bundle interactuar con la framework OSGi:� Subscribirse a eventos publicados por el framework (addXXXListeneraddXXXListeneraddXXXListeneraddXXXListener)� Registrar servicios con el Registro de Servicios de la framework OSGi

(registerServiceregisterServiceregisterServiceregisterService)� Recuperar ServiceReferences del Registro de Servicios

(getServiceReferencesgetServiceReferencesgetServiceReferencesgetServiceReferences)� Obtener y liberar objetos de servicios (getServicegetServicegetServicegetService y ungetServiceungetServiceungetServiceungetService)� Instalar nuevos bundles (installBundleinstallBundleinstallBundleinstallBundle)� Obtener la lista de bundles disponibles (getBundles()getBundles()getBundles()getBundles())� Obtener el objeto Bundle asociado a una implementación de un bundle

(getBundlegetBundlegetBundlegetBundle)� Crear ficheros permanentes para el uso del bundle (getDataFilegetDataFilegetDataFilegetDataFile)

71/140

Pasos en detalle para crear nuestro primer bundle

4. Create simplebundle/src/es/deusto/simplebundle/impl/HelloWorldThread.java

package es.deusto.simplebundle.impl;public class HelloWorldThread extends Threadpublic class HelloWorldThread extends Threadpublic class HelloWorldThread extends Threadpublic class HelloWorldThread extends Thread {

private boolean running = true;public HelloWorldThread() {}public void run() {

while (running) {System.out.println("Hello World!");try {

Thread.sleep(5000);} catch (InterruptedException e) {

System.out.println("HelloWorldThread ERROR: " + e);}

}}public void stopThread() {

this.running = false;}

}

72/140

Page 37: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

37

Pasos en detalle para crear nuestro primer bundle

5. Compilarlo con fichero Ant provisto: ant

6. Importarlo usando el Knopplerfish OSGi Desktop

73/140

Ejecución del Bundle

74/140

Page 38: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

38

Ciclo de Desarrollo de un Bundle en OSGi

� Los pasos a seguir son:1. Creación del fichero manifest.mf

2. Definición de una interfaz Java con los métodos provistos por el servicio a ofrecer.

3. Implementación de tal interfaz en una clase Java.4. Activación de la clase creada mediante un BundleActivator

5. Compilación y despliegue del bundle

� Los ponemos en práctica mediante el desarrollo de la aplicación datebundledatebundledatebundledatebundle

� Ofrece como servicio formatear una fecha como un string

� Principal novedad del fichero manifest.mf es la cabecera ExportExportExportExport----Package: es.deusto.dateservicePackage: es.deusto.dateservicePackage: es.deusto.dateservicePackage: es.deusto.dateservice

75/140

Creando tu primer bundle ofreciendo un servicio

1. Definimos el fichero manifest.mf

Manifest-Version: 1.0

Bundle-Name: dateservice

Bundle-SymbolicName: dateservice

Bundle-Version: 1.0.0

Bundle-Description: Demo Bundle

Bundle-Vendor: Universidad de Duesto

BundleBundleBundleBundle----Activator: Activator: Activator: Activator: es.deusto.dateservice.impl.Activatores.deusto.dateservice.impl.Activatores.deusto.dateservice.impl.Activatores.deusto.dateservice.impl.Activator

Bundle-Category: example

ImportImportImportImport----Package: org.osgi.frameworkPackage: org.osgi.frameworkPackage: org.osgi.frameworkPackage: org.osgi.framework

ExportExportExportExport----Package: es.deusto.dateservicePackage: es.deusto.dateservicePackage: es.deusto.dateservicePackage: es.deusto.dateservice

76/140

Page 39: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

39

Creando tu primer bundle ofreciendo un servicio

2. Creamos la interfaz que define el servicio src/es/deusto/dateservice/DateService.javapackage es.deusto.dateservice;import java.util.Date;

public interface DateServicepublic interface DateServicepublic interface DateServicepublic interface DateService {public String getFormattedDate(Date date);

}

3. Creamos la implementación del servicio en src/es/deusto/dateservice/impl/DateServiceImpl.javapackage es.deusto.dateservice.impl;import java.text.DateFormat;import java.util.Date;import es.deusto.dateservice.DateService;public class DateServiceImpl implements DateServiceDateServiceImpl implements DateServiceDateServiceImpl implements DateServiceDateServiceImpl implements DateService {

public String getFormattedDate(Date date)String getFormattedDate(Date date)String getFormattedDate(Date date)String getFormattedDate(Date date) {return DateFormat.getDateInstance(DateFormat.SHORT).format(date);}

}

77/140

Creando tu primer bundle ofreciendo un servicio

4. Creación de la clase que activa (Activator) el bundle en OSGi y exporta el servicio: src/es/deusto/dateservice/impl/Activator.java:package es.deusto.dateservice.impl;import java.util.Hashtable;import org.osgi.framework.BundleActivator;import org.osgi.framework.BundleContext;import org.osgi.framework.Constants;import org.osgi.framework.ServiceRegistration;import es.deusto.dateservice.DateService;

public class Activator implements BundleActivatorActivator implements BundleActivatorActivator implements BundleActivatorActivator implements BundleActivator {public static BundleContextBundleContextBundleContextBundleContext bc = null;public void start(BundleContext bc)start(BundleContext bc)start(BundleContext bc)start(BundleContext bc) throws Exception {System.out.println("Empezando " + bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME)bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME)bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME)bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME) + " ...");Activator.bc = bc;DateService service = new DateServiceImpl();ServiceRegistration registration = ServiceRegistration registration = ServiceRegistration registration = ServiceRegistration registration = bc.registerService(DateService.class.getName(), service, new Hashtable());bc.registerService(DateService.class.getName(), service, new Hashtable());bc.registerService(DateService.class.getName(), service, new Hashtable());bc.registerService(DateService.class.getName(), service, new Hashtable());System.out.println("Servicio registrado: dateservice");}

public void stop(BundleContext bc)stop(BundleContext bc)stop(BundleContext bc)stop(BundleContext bc) throws Exception {System.out.println("Parando " + bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME) + " ...");Activator.bc = null;}

}

5. Compilar y ejecutar la aplicación

78/140

Page 40: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

40

Registro de Servicios en OSGi

� El método registerService de BundleContextpermite el registro de un servicio con el Registro de Servicios de OSGI. Recibe tres parámetros:� Nombre de la interfaz del servicio� Implementación del servicio� Información adicional (opcional) sobre el servicio en formato de

pares clave/value.

� Ejemplo de registro de servicio:Long I = new Long(20);Long I = new Long(20);Long I = new Long(20);Long I = new Long(20);

Hashtable props = new Hashtable();Hashtable props = new Hashtable();Hashtable props = new Hashtable();Hashtable props = new Hashtable();

props.put("description", "This an long value");props.put("description", "This an long value");props.put("description", "This an long value");props.put("description", "This an long value");

bc.registerService(Long.class.getName(), i, props);bc.registerService(Long.class.getName(), i, props);bc.registerService(Long.class.getName(), i, props);bc.registerService(Long.class.getName(), i, props);

79/140

Más detalles sobre el Activator

� El método getBundle() de BundleContext devuelve un objeto de tipo org.osgi.framework.Bundleasociado con tal contexto.

� El objeto BundleBundleBundleBundle permite recuperar todo tipo de metadatos:� Su identificador (getBundleId()getBundleId()getBundleId()getBundleId())� Cabeceras de su fichero manifest.mf asociado

(getHeaders()getHeaders()getHeaders()getHeaders()) � Recursos asociados al bundle (getResources()getResources()getResources()getResources()).

� La interfaz ConstantsConstantsConstantsConstants define nombres estándar para propiedades del entorno OSGi, sus servicios y las cabeceras del fichero Manifest (e.g. BUNDLE_NAME, BUNDLE_ACTIVATOR).

80/140

Page 41: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

41

Consumiendo un Servicio en OSGi

� Creamos un nuevo proyecto denominado DateBundleUser con los ficheros manifest.mf y Activator.java

� Manifest.mf:Manifest-Version: 1.0

Bundle-Name: dateserviceuser

Bundle-SymbolicName: dateserviceuser

Bundle-Version: 1.0.0

Bundle-Description: Bundle that consumes dateservice exported by another bundle

Bundle-Vendor: Revista Sólo Programadores

BundleBundleBundleBundle----Activator: es.deusto.dateserviceuser.impl. Activator: es.deusto.dateserviceuser.impl. Activator: es.deusto.dateserviceuser.impl. Activator: es.deusto.dateserviceuser.impl. ActivatorWithoutCheckingReferenceActivatorWithoutCheckingReferenceActivatorWithoutCheckingReferenceActivatorWithoutCheckingReference

ImportImportImportImport----Package: org.osgi.framework,es.deusto.dateservicePackage: org.osgi.framework,es.deusto.dateservicePackage: org.osgi.framework,es.deusto.dateservicePackage: org.osgi.framework,es.deusto.dateservice

81/140

Consuming a Service in OSGi

� Creamos la clase datebundleuser/src/es/deusto/dateserviceuser/impl/ActivatorWithoutCheckingReference.java, que obtiene una referencia al servicio DateService de manera incorrecta:� Para dateservice y luego ejecuta dateserviceuser, ¿por qué falla?

package es.deusto.dateserviceuser.impl;

import java.util.Date;import org.osgi.framework.BundleActivator;import org.osgi.framework.BundleContext;import org.osgi.framework.Constants;import org.osgi.framework.ServiceReference;import es.deusto.dateservice.DateService;

public class ActivatorWithoutCheckingReference implements BundleActivatorActivatorWithoutCheckingReference implements BundleActivatorActivatorWithoutCheckingReference implements BundleActivatorActivatorWithoutCheckingReference implements BundleActivator {public static BundleContext bc = null;public void start(BundleContext bc) throws Exception {

System.out.println("Empezando" + bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME)+ " ...");ActivatorWithoutCheckingReference.bc = bc;ServiceReference reference = bc.getServiceReference(DateService.class.getName());ServiceReference reference = bc.getServiceReference(DateService.class.getName());ServiceReference reference = bc.getServiceReference(DateService.class.getName());ServiceReference reference = bc.getServiceReference(DateService.class.getName());DateService service = (DateService)bc.getService(reference);DateService service = (DateService)bc.getService(reference);DateService service = (DateService)bc.getService(reference);DateService service = (DateService)bc.getService(reference);System.out.println("Usando DateService: formatting date: " + service.getFormattedDate(new

Date()));bc.ungetService(reference);bc.ungetService(reference);bc.ungetService(reference);bc.ungetService(reference);

}

public void stop(BundleContext bc) throws Exception {System.out.println("Parando " + bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME) + "

...");ActivatorWithoutCheckingReference.bc = null;

}}

82/140

Page 42: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

42

Consumiendo Servicios en OSGi proporcionados por ServiceFactory

� Una factoría de servicios permite la personalización del objeto de servicio que es devuelto cuando un bundle invoca a BundleContext.getService(ServiceReference)BundleContext.getService(ServiceReference)BundleContext.getService(ServiceReference)BundleContext.getService(ServiceReference).� Normalmente, el objeto de servicio registrado por el bundle es

devuelto� Si el objeto de servicio implementa la interfaz org.osgi.framework.ServiceFactory, la Framework invoca el método ServiceFactory.getService para crear un instancia única no compartida del objeto de servicio por cada bundle que quiere obtener el servicio.

� La framework cachea el objeto devuelto hasta que el bundle lo libere.

83/140

Declarando, Instanciando y Registrando un Service Factory

� Definición del ServiceFactory:import org.osgi.framework.ServiceFactory;public class DisplayServiceFactory implements ServiceFactorypublic class DisplayServiceFactory implements ServiceFactorypublic class DisplayServiceFactory implements ServiceFactorypublic class DisplayServiceFactory implements ServiceFactory {

public Object getService(Bundle bundle, ServiceRegistration registration)public Object getService(Bundle bundle, ServiceRegistration registration)public Object getService(Bundle bundle, ServiceRegistration registration)public Object getService(Bundle bundle, ServiceRegistration registration){

Display newDisplay = new Display(Long.toString(bundle.getBundleId()));return newDisplay;

}public void ungetService(Bundle bundle, ServiceRegistration public void ungetService(Bundle bundle, ServiceRegistration public void ungetService(Bundle bundle, ServiceRegistration public void ungetService(Bundle bundle, ServiceRegistration registration,Object service)registration,Object service)registration,Object service)registration,Object service) {

//Nothing needed here in this case}

}

� Creando y registrando el ServiceFactory://Create the ServiceFactoryDisplayServiceFactory factory = new DisplayServiceFactory();DisplayServiceFactory factory = new DisplayServiceFactory();DisplayServiceFactory factory = new DisplayServiceFactory();DisplayServiceFactory factory = new DisplayServiceFactory();//Create the properties of the service. Not mandatory, but used to show //how properties workHashtable properties = new Hashtable();Hashtable properties = new Hashtable();Hashtable properties = new Hashtable();Hashtable properties = new Hashtable();properties.put("service.description", "Factory of Display Services");properties.put("service.description", "Factory of Display Services");properties.put("service.description", "Factory of Display Services");properties.put("service.description", "Factory of Display Services");properties.put("service.type", "Factory");properties.put("service.type", "Factory");properties.put("service.type", "Factory");properties.put("service.type", "Factory");

//Register the ServiceFactory for the type IDisplayServiceRegistration registration = ServiceRegistration registration = ServiceRegistration registration = ServiceRegistration registration =

context.registerService(IDisplay.class.getName(), context.registerService(IDisplay.class.getName(), context.registerService(IDisplay.class.getName(), context.registerService(IDisplay.class.getName(), factory, properties);factory, properties);factory, properties);factory, properties);

84/140

Page 43: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

43

Usando un Servicio OSGi que Implementa ServiceFactory

//Get and Use one Factory of DisplayService using a filter

String filter = "(service.type=Factory)";String filter = "(service.type=Factory)";String filter = "(service.type=Factory)";String filter = "(service.type=Factory)";

ServiceReference[] serviceRef = ServiceReference[] serviceRef = ServiceReference[] serviceRef = ServiceReference[] serviceRef = context.getServiceReferences(IDisplay.class.getName(),filter);context.getServiceReferences(IDisplay.class.getName(),filter);context.getServiceReferences(IDisplay.class.getName(),filter);context.getServiceReferences(IDisplay.class.getName(),filter);

//Here we now there should be only one

IDisplay display = (IDisplay)context.getService(serviceRef[0]);IDisplay display = (IDisplay)context.getService(serviceRef[0]);IDisplay display = (IDisplay)context.getService(serviceRef[0]);IDisplay display = (IDisplay)context.getService(serviceRef[0]);

display.showMessage("Using Display service from Display Consumer -Search with a filter");

//Release the service reference. This MUST be done when the

// service is no longer going to be used by the consumer bundle

context.ungetService(serviceRef[0]);context.ungetService(serviceRef[0]);context.ungetService(serviceRef[0]);context.ungetService(serviceRef[0]);

85/140

Consumiendo Servicios en OSGi

� OSGi es un lugar muy dinámico donde los servicios aparecerán y desaparecerán continuamente � Necesidad de comprobar que lo que se recupera del Registro

de Servicios de OSGi es realmente una implementación de servicio válida y no nullnullnullnull

� Después de haber utilizado el servicio es recomendable realizar un unget

� Recuperación de una instancia de un servicio es un doble paso: 1. Recuperación de una referencia al servicio mediante el método

getServiceReference de BundleContext y

2. Recuperación de un una instancia del servicio mediante el método getService de BundleContext

86/140

Page 44: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

44

Consumiendo Servicios en OSGi

� Mejora 1 � Comprobar que el servicio es disponible antes de utilizarlo:ServiceReference reference = ServiceReference reference = ServiceReference reference = ServiceReference reference = bc.getServiceReference(DateService.class.getName(bc.getServiceReference(DateService.class.getName(bc.getServiceReference(DateService.class.getName(bc.getServiceReference(DateService.class.getName());));));));

if (reference != null) {if (reference != null) {if (reference != null) {if (reference != null) {

DateService service = (DateService)bc.getService(reference);

System.out.println("Usando DateService: formateando fecha: " +service.getFormattedDate(new Date()));

bc.ungetService(reference);

} else {

System.out.println("¡Servicio no disponible!");

}

87/140

Consumiendo Servicios en OSGi

� Mejora 2 � Usar ServiceListenerpublic class ActivatorWithServiceListener implements ActivatorWithServiceListener implements ActivatorWithServiceListener implements ActivatorWithServiceListener implements

BundleActivator, ServiceListenerBundleActivator, ServiceListenerBundleActivator, ServiceListenerBundleActivator, ServiceListener {public static BundleContext bc = null;private ServiceUserThread thread = null;private DateService service = null;public void start(BundleContext bc)void start(BundleContext bc)void start(BundleContext bc)void start(BundleContext bc) throws Exception {System.out.println("Empezando " + getClass().getName());ActivatorWithServiceListener.bc = bc;String filter = "(objectclass=" + String filter = "(objectclass=" + String filter = "(objectclass=" + String filter = "(objectclass=" +

DateService.class.getName() + ")";DateService.class.getName() + ")";DateService.class.getName() + ")";DateService.class.getName() + ")";bc.addServiceListener(this, filter);bc.addServiceListener(this, filter);bc.addServiceListener(this, filter);bc.addServiceListener(this, filter);ServiceReference references[] =

bc.getServiceReferences(null, filter);for (int i = 0; references != null && i <

references.length; i++) {this.serviceChanged(new

ServiceEvent(ServiceEvent.REGISTERED, references[i]));}

}public void serviceChanged(ServiceEvent event)public void serviceChanged(ServiceEvent event)public void serviceChanged(ServiceEvent event)public void serviceChanged(ServiceEvent event) {

…}

88/140

Page 45: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

45

Consumiendo Servicios en OSGi

� Mejora 3 � Usar ServiceTracker (BestActivator.java)public class BestActivator implements BundleActivatorpublic class BestActivator implements BundleActivatorpublic class BestActivator implements BundleActivatorpublic class BestActivator implements BundleActivator {

public static BundleContext bc = null;private ServiceTracker tracker = null;

public void start(BundleContext bc)void start(BundleContext bc)void start(BundleContext bc)void start(BundleContext bc) throws Exception {System.out.println("Arrancando " +

bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME) + " ...");

BestActivator.bc = bc;MyServiceTrackerCustomizer customizer = new MyServiceTrackerCustomizer customizer = new MyServiceTrackerCustomizer customizer = new MyServiceTrackerCustomizer customizer = new

MyServiceTrackerCustomizer(bc);MyServiceTrackerCustomizer(bc);MyServiceTrackerCustomizer(bc);MyServiceTrackerCustomizer(bc);tracker = new ServiceTracker(bc, tracker = new ServiceTracker(bc, tracker = new ServiceTracker(bc, tracker = new ServiceTracker(bc,

DateService.class.getName(), customizer);DateService.class.getName(), customizer);DateService.class.getName(), customizer);DateService.class.getName(), customizer);tracker.open();tracker.open();tracker.open();tracker.open();

}

public void stop(BundleContext bc) throws Exception {System.out.println("Parando " +

bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME) + " ...");

tracker.close();tracker.close();tracker.close();tracker.close();BestActivator.bc = null;

}} 89/140

Consumiendo Servicios en OSGi

� Mejora 3 � Usando ServiceTracker (MyServiceTrackerCustomizer.java)import org.osgi.util.tracker.ServiceTrackerCustomizer;import es.deusto.dateservice.DateService;public class MyServiceTrackerCustomizer implements ServiceTrackerCustomizerMyServiceTrackerCustomizer implements ServiceTrackerCustomizerMyServiceTrackerCustomizer implements ServiceTrackerCustomizerMyServiceTrackerCustomizer implements ServiceTrackerCustomizer {

private ServiceUserThread thread = null;private BundleContext bc;public MyServiceTrackerCustomizer(BundleContext bc) { this.bc = bc; }public Object addingService(ServiceReference reference)Object addingService(ServiceReference reference)Object addingService(ServiceReference reference)Object addingService(ServiceReference reference) {DateService service = (DateService) bc.getService(reference);if (this.thread == null) {this.thread = new ServiceUserThread(service);this.thread.start();return service;

} else return service;}public void modifiedService(ServiceReference reference, Object serviceObject)void modifiedService(ServiceReference reference, Object serviceObject)void modifiedService(ServiceReference reference, Object serviceObject)void modifiedService(ServiceReference reference, Object serviceObject) {this.thread.stopThread();try {this.thread.join();

} catch (InterruptedException e) {e.printStackTrace();

}DateService service = (DateService) bc.getService(reference);this.thread = new ServiceUserThread(service);this.thread.start();

public void removedService(ServiceReference reference, Object serviceObject)void removedService(ServiceReference reference, Object serviceObject)void removedService(ServiceReference reference, Object serviceObject)void removedService(ServiceReference reference, Object serviceObject) {this.thread.stopThread();try {this.thread.join();

} catch (InterruptedException e) {e.printStackTrace();

}this.thread = null;

}}

90/140

Page 46: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

46

Comentarios Mejoras Activators

� Comparar si la referencia a un servicio no es null resuelve el problema del NullPointerException� PROBLEMA: si datebundle no es disponible cuando datebundleuser es arrancado ya no puede usarlo

� BundleContextBundleContextBundleContextBundleContext permite registrar un ServiceListenerServiceListenerServiceListenerServiceListenercon la framework indicándose un objeto de filtrado adicional sobre los eventos de servicios (registro, desregistro) de interés. � String en formato LDAP especifica filtro:

"(&(" + Constants.OBJECTCLASS + "=Person)(|(sn=Ipiña)(cn=Diego I*)))“

� Ahora no obtenemos una referencia directamente a DateServiceen el método start().

� De manera indirecta con la ayuda del método serviceChanged que debe implementar el Activator

91/140

Comentarios Mejoras Activators

� La clase de utilidad ServiceTracker automáticamente monitoriza los ServiceEvents asociados a un servicio dando al usuario la posibilidad de personalizar qué realizar cada vez que un servicio aparezca o desaparezca. � Requiere implementar la interfaz ServiceTrackerCustomizer y

proveer una clase instanciando tal interfaz como parámetro al objeto ServiceTracker.

� Los métodos addingService, modifiedService y removedService serán invocados por la clase ServiceTracker, cada vez que un nuevo servicio sea añadido, modificado o borrado.

� Solventa el problema de la interfaz ServiceListener que sólo es capaz de darse cuenta de la aparición de nuevos servicios o de la desaparición de antiguos.

� Truco: generar en start() eventos ServiceEvent.REGISTERED a partir de una búsqueda Registro Servicios

92/140

Page 47: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

47

Resumen Desarrollo de Servicios en OSGi

� 5 pasos requeridos por un bundle exportador de servicios: 1. Implementación del fichero manifest.mfmanifest.mfmanifest.mfmanifest.mf

2. Definición de una interfaz con el servicio a exportar por el bundle

3. Implementación de tal servicio

4. Implementación de la clase principal del bundle (BundleActivatorBundleActivatorBundleActivatorBundleActivator) y

5. Compilación y despliegue del bundle en el servidor OSGi

� RECUERDA!!! OSGi es un entorno muy dinámico donde aparecen y desaparecen servicios continuamente, donde la interfaz ServiceListenerServiceListenerServiceListenerServiceListener y la clase ServiceTrackerServiceTrackerServiceTrackerServiceTracker nos pueden ofrecer ayuda.

93/140

El Servicio Estándar LogService

� OSGi LogService permite la creación de trazas de depuración o información durante la ejecución de un bundle � La interfaz org.osgi.service.log.LogServiceorg.osgi.service.log.LogServiceorg.osgi.service.log.LogServiceorg.osgi.service.log.LogService define su

funcionalidad� Tipos de logeo: LOG_ERROR, LOG_WARNING, LOG_INFO y LOG_DEBUG � Método log() para logearlos

� La interfaz org.osgi.service.log.LogReaderService permite recuperar objetos de tipo org.osgi.service.log.LogEntry del log registrando un org.osgi.service.log.LogListener

� Normalmente, en la clase Activator crearemos una variable estática donde guardaremos la referencia a LogService

� Para cambiar el nivel de traceo en Knopflerfish hay que cambiar el fichero props.xargs modificando sus propiedades:� Dorg.knopflerfish.log.out a true y � -Dorg.knopflerfish.log.level a (debug, info, warning o

error)

94/140

Page 48: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

48

El Servicio Estándar HttpService

� Puerta de entrada HTTP a la funcionalidad de la plataforma OSGi

� Definido en la interfaz org.osgi.service.http.HttpServiceorg.osgi.service.http.HttpServiceorg.osgi.service.http.HttpServiceorg.osgi.service.http.HttpService

� Permite registrar servlets (registerServlet()) y recursos (registerResources()) en la propia plataforma para que sean accedidos desde el exterior, para:

� Control remoto� Interfaces remotas

� Ventaja principal:� Permite acceder a OSGi mediante peticiones HTTP-GET y POST

y de ahí redireccionar a servicios internos

95/140

Poniendo en Práctica el LogService y el HttpService

� Objetivo: crear un cliente web del servicio dateservicedateservicedateservicedateservice a través del servicio estándar de OSGi HttpServiceHttpServiceHttpServiceHttpService

� Pasos para su uso:� La cabecera Import-Package del manifest.mf debe incluir los

siguientes elementos javax.servlet, javax.servlet.http, org.osgi.service.http

� La clase Activator en su método start() obtiene una referencia al servicio HttpService de OSGi y registra en él un servlet

� Implementamos una clase que herede de javax.servlet.http.HttpServlet

96/140

Page 49: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

49

Dateservicewebuser –Activator.java

import org.osgi.service.http.HttpService;import org.osgi.service.http.HttpService;import org.osgi.service.http.HttpService;import org.osgi.service.http.HttpService;import org.osgi.service.log.LogService;import org.osgi.service.log.LogService;import org.osgi.service.log.LogService;import org.osgi.service.log.LogService;

public class Activator implements BundleActivatorActivator implements BundleActivatorActivator implements BundleActivatorActivator implements BundleActivator {public static BundleContext bc = null;public static LogService log = null;public void start(BundleContext context) throws Exception {Activator.bc = context;ServiceReference refLog = ServiceReference refLog = ServiceReference refLog = ServiceReference refLog =

Activator.bc.getServiceReference(LogService.class.getName()); Activator.bc.getServiceReference(LogService.class.getName()); Activator.bc.getServiceReference(LogService.class.getName()); Activator.bc.getServiceReference(LogService.class.getName()); Activator.log = (LogService) Activator.bc.getService(refLog);Activator.log = (LogService) Activator.bc.getService(refLog);Activator.log = (LogService) Activator.bc.getService(refLog);Activator.log = (LogService) Activator.bc.getService(refLog);Activator.log.log(LogService.LOG_INFO, "Empezando " + Activator.log.log(LogService.LOG_INFO, "Empezando " + Activator.log.log(LogService.LOG_INFO, "Empezando " + Activator.log.log(LogService.LOG_INFO, "Empezando " +

Activator.bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME) + " Activator.bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME) + " Activator.bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME) + " Activator.bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME) + " ...");...");...");...");

Activator.bc = context;//get a reference to the http serviceServiceReference ref = ServiceReference ref = ServiceReference ref = ServiceReference ref =

context.getServiceReference(HttpService.class.getName()); context.getServiceReference(HttpService.class.getName()); context.getServiceReference(HttpService.class.getName()); context.getServiceReference(HttpService.class.getName()); HttpService http = (HttpService) context.getService(ref);HttpService http = (HttpService) context.getService(ref);HttpService http = (HttpService) context.getService(ref);HttpService http = (HttpService) context.getService(ref);//register the capabilities servlet//register the capabilities servlet//register the capabilities servlet//register the capabilities servlethttp.registerServlet("/example", new DateServlet(context),new http.registerServlet("/example", new DateServlet(context),new http.registerServlet("/example", new DateServlet(context),new http.registerServlet("/example", new DateServlet(context),new Properties(),null);Properties(),null);Properties(),null);Properties(),null);

}

public void stop(BundleContext context) throws Exception {}}

97/140

Dateservicewebuser –DateServlet.java

public class DateServlet extends HttpServletDateServlet extends HttpServletDateServlet extends HttpServletDateServlet extends HttpServlet {BundleContext context;public DateServlet(BundleContext context) {this.context = context;

}protected void doGet(HttpServletRequest request, HttpServletResponse response)doGet(HttpServletRequest request, HttpServletResponse response)doGet(HttpServletRequest request, HttpServletResponse response)doGet(HttpServletRequest request, HttpServletResponse response) throws

ServletException, IOException {//strip the service id from the urlString req = request.getRequestURI();String serviceId = req.substring(req.lastIndexOf('/')+1);//find a service that matches upServiceReference[] refs = null;try {refs = context.getServiceReferences(DateService.class.getName(),null);

} catch (InvalidSyntaxException e) {new IOException().initCause(e);

}for (int i = 0; i < refs.length; i++) {DateService service = (DateService) context.getService(refs[i]);//perform the id matchActivator.log.log(LogService.LOG_INFO, "Comparando con clase " + DateService.class.getName());if (serviceId.equals(DateService.class.getName())) {//do itresponse.getOutputStream().write(("Usando DateService: formateando fecha: " +

service.getFormattedDate(new Date())).getBytes());context.ungetService(refs[i]);return;

}}response.getOutputStream().write(("No pudo encontrar servicio con id:"+ serviceId).getBytes());

}}

98/140

Page 50: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

50

Desarrollo de un Servicio Avanzado en OSGi: BundleDiscoverer

� Tradicionalmente, los entornos OSGi básicos requieren que el administrador del entorno instale los bundles o drivers que hablan con los nuevos dispositivos desplegados o con aquellos que potencialmente vayan a desplegarse. � Queremos añadir extensibilidad dinámica a nuestro entorno

mediante un servicio de descubrimiento y despliegue automático de bundles disponibles en un entorno LAN dentro de un hogar, oficina o empresa

� Es un bundle que descubre, descarga e instala bundles anunciados por dispositivos conectados a un canal multicast bien conocido

� Su sencillo protocolo consta de 5 mensajes:� BUNDLE_SEARCHBUNDLE_SEARCHBUNDLE_SEARCHBUNDLE_SEARCH

� BUNDLE_RESPONSE uuid ipAddress portBUNDLE_RESPONSE uuid ipAddress portBUNDLE_RESPONSE uuid ipAddress portBUNDLE_RESPONSE uuid ipAddress port

� BUNDLE_ANNOUNCE uuid ipAddress portBUNDLE_ANNOUNCE uuid ipAddress portBUNDLE_ANNOUNCE uuid ipAddress portBUNDLE_ANNOUNCE uuid ipAddress port

� BUNDLE_GET_METADATA uuidBUNDLE_GET_METADATA uuidBUNDLE_GET_METADATA uuidBUNDLE_GET_METADATA uuid

� BUNDLE_GET_JAR uuidBUNDLE_GET_JAR uuidBUNDLE_GET_JAR uuidBUNDLE_GET_JAR uuid

99/140

BundleDiscoverer

100/140

Page 51: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

51

BundleDiscoverer

101/140

BundleDiscoverer: Parte Servidora

102/140

Page 52: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

52

BundleDiscoverer: Parte Cliente

103/140

Constantes del Protocolo

package es.deusto.bundlediscoverer;

public class BundleDiscoveryConstantsBundleDiscoveryConstantsBundleDiscoveryConstantsBundleDiscoveryConstants {public final static int DISCOVERY_PORT = 4445;public final static String DISCOVERY_IP = "230.0.0.1";public final static int MAX_BLOCK_SIZE = 1024; public final static int BUNDLE_SEARCH_PERIOD = 5000; public final static int BUNDLE_HEARTBEAT_PERIOD = BUNDLE_SEARCH_PERIOD * 4;

public final static String BUNDLE_SEARCH = "BUNDLE_SEARCH";public final static String BUNDLE_ANNOUNCE = "BUNDLE_ANNOUNCE";public final static String BUNDLE_RESPONSE = "BUNDLE_RESPONSE";public final static String BUNDLE_GET_METADATA = "BUNDLE_GET_METADATA";public final static String BUNDLE_GET_BUNDLE_JAR = "BUNDLE_GET_BUNDLE_JAR";

}

104/140

Page 53: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

53

Parte Servidora BundleDiscoverer

� El servicio que exporta define un único método que devuelve un listado con los bundles descubiertos:package es.deusto.bundlediscoverer;public interface BundleDiscoverer {

public BundleMetadata[] getAvailableBundles();}

� Fichero con metadatos del bundle:package es.deusto.bundlediscoverer;import java.io.Serializable;import org.osgi.framework.Bundle;public class BundleMetadata implements SerializableBundleMetadata implements SerializableBundleMetadata implements SerializableBundleMetadata implements Serializable {

public String uuid;public String ipAddress;public int port;public long timestamp;public Bundle bundle;public BundleMetadata(String uuid, String ipAddress, int port, Bundle public BundleMetadata(String uuid, String ipAddress, int port, Bundle public BundleMetadata(String uuid, String ipAddress, int port, Bundle public BundleMetadata(String uuid, String ipAddress, int port, Bundle bundle)bundle)bundle)bundle) {this.uuid = uuid;this.ipAddress = ipAddress;this.port = port;this.timestamp = System.currentTimeMillis();this.bundle = bundle;

}}

105/140

BundleDiscoverImpl

� La clase BundleDiscovererImpl aparte de implementar la interfaz BundleDiscoverer, también hereda de la clase Thread� Implementa 2 timers:

1. Responsable de enviar regularmente el mensaje BUNDLE_SEARCH a través de un canal multicast con el objeto de descubrir los servicios provistos por dispositivos en el entorno controlado

2. Comprueba que los proveedores de servicios (dispositivos) antes descubiertos siguen todavía activos, para en caso contrario proceder a la eliminación de los metadatos de los servicios descubiertos y desinstalar los bundles que actúan como proxies controladores de los dispositivos remotos

� Subscripción y recepción de datos en canal multicast:this.socket = new

MulticastSocket(BundleDiscoveryConstants.DISCOVERY_PORT);

this.addressGroup = InetAddress.getByName(BundleDiscoveryConstants.DISCOVERY_IP);

this.socket.joinGroup(addressGroup);

byte[] buf = new byte[BundleDiscoveryConstants.MAX_BLOCK_SIZE];

DatagramPacket packet = new DatagramPacket(buf, buf.length);

socket.receive(packet);

106/140

Page 54: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

54

BundleDiscovererImpl.run()

public void run() {this.initPeriodicSearchMessageDelivery();this.initPeriodicRegistryCleanUp();while (continueDiscovering) {

try {String msgReceived = "";do {

msgReceived = this.receiveMulticastMessage();} while (msgReceived.startsWith(BundleDiscoveryConstants.BUNDLE_SEARCH));if ((msgReceived.startsWith(BundleDiscoveryConstants.BUNDLE_ANNOUNCE)) ||

(msgReceived.startsWith(BundleDiscoveryConstants.BUNDLE_RESPONSE))) {// Process BUNDLE_RESPONSE uuid serviceIP servicePortStringTokenizer st = new StringTokenizer(msgReceived);if (st.countTokens() == 4) {

String cmdMsg = st.nextToken();String uuid = st.nextToken();String ipAddress = st.nextToken();String port = st.nextToken();if (!this.bundlesAvailableMap.containsKey(uuid) ) {

new RetrieveRegisterBundleThread(this, uuid, ipAddress, Integer.parseInt(port)).start();new RetrieveRegisterBundleThread(this, uuid, ipAddress, Integer.parseInt(port)).start();new RetrieveRegisterBundleThread(this, uuid, ipAddress, Integer.parseInt(port)).start();new RetrieveRegisterBundleThread(this, uuid, ipAddress, Integer.parseInt(port)).start();} else {

synchronized (this.bundlesAvailableMap) {Bundle oldBundle = this.bundlesAvailableMap.get(uuid).bundle;int bundleState = oldBundle.getState();if (bundleState == Bundle.UNINSTALLED) {

this.bundlesAvailableMap.remove(uuid);} else if (bundleState == Bundle.ACTIVE) {

this.bundlesAvailableMap.get(uuid).timestamp = System.currentTimeMillis();}

}}}

} else {Activator.log.log(LogService.LOG_DEBUG, "BundleDiscovererImpl.run(): Ignored message: " + msgReceived);

}} catch (IOException ioe) {

Activator.log.log(LogService.LOG_ERROR, "BundleDiscovererImpl.run(): " + ioe.getMessage());}

}}

107/140

org.osgi.framework.Bundle

� Esta clase es el punto de acceso para controlar el ciclo de vida de un bundle ya instalado en la framework. � getBundleId() – para obtener el identificador único de un

bundle� start() para arrancarlo� stop() para pararlo� update() para actualizarlo� uninstall() para desinstalarlo� getState() para obtener su estado actual (UNINSTALLED,

INSTALLED, RESOLVED, STARTING, STOPPING o ACTIVE) o � getHeaders() para obtener un Dictionary con las cabeceras

y valores declaradas en el manifiesto del bundle.

108/140

Page 55: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

55

Eliminación Selectiva de Bundles

private void initPeriodicRegistryCleanUpinitPeriodicRegistryCleanUpinitPeriodicRegistryCleanUpinitPeriodicRegistryCleanUp() {int delay = 0; // delay for 0 sec.this.bundleGarbageCollectionTimer = new Timer();this.bundleGarbageCollectionTimer.scheduleAtFixedRate(new TimerTask() {public void run() {

long currentTime = System.currentTimeMillis();synchronized (bundlesAvailableMap) {for (BundleMetadata service: bundlesAvailableMap.values()BundleMetadata service: bundlesAvailableMap.values()BundleMetadata service: bundlesAvailableMap.values()BundleMetadata service: bundlesAvailableMap.values()) {

if (service.timestamp+BundleDiscoveryConstants.BUNDLE_HEARTBEAT_PERIOD < currentTime) {

try {service.bundle.stop();service.bundle.stop();service.bundle.stop();service.bundle.stop();service.bundle.uninstall();service.bundle.uninstall();service.bundle.uninstall();service.bundle.uninstall();bundlesAvailableMap.remove(service.uuid);

} catch (org.osgi.framework.BundleException be) {Activator.log.log(LogService.LOG_ERROR,

"BundleDiscovererImpl.initPeriodicRegistryCleanUp(): " + be.getMessage());}

}}

}}}, delay, BundleDiscoveryConstants.BUNDLE_HEARTBEAT_PERIOD);}

109/140

Recuperando e Instalando los .jar de los bundles

ByteArrayOutputStream jarFile = new ByteArrayOutputStream();do {

bytesRead = in.read(buf, 0, 1024);jarFile.write(buf, 0, bytesRead);

} while (bytesRead == 1024);String uploadedBundleDirectoryPath = System.getProperty("user.dir") +

System.getProperty("file.separator") + "uploadedBundles";String jarFileName = uploadedBundleDirectoryPath +

System.getProperty("file.separator") + this.uuid+".jar";FileOutputStream fos = new FileOutputStream(new File(jarFileName));jarFile.writeTo(fos);fos.close();jarFile.close();String bundleUrl = "file:///" + jarFileName;try {

Bundle bundleInstalado = Activator.bc.installBundle(bundleUrl);Bundle bundleInstalado = Activator.bc.installBundle(bundleUrl);Bundle bundleInstalado = Activator.bc.installBundle(bundleUrl);Bundle bundleInstalado = Activator.bc.installBundle(bundleUrl);bundleInstalado.start();bundleInstalado.start();bundleInstalado.start();bundleInstalado.start();this.parent.updateBundlesAvailable(this.uuid, new BundleMetadata(this.uuid, this.ipAddress, this.port, bundleInstalado));

} catch (BundleException be) {Activator.log.log(LogService.LOG_ERROR, " RetrieveRegisterBundleThread.run(): " + be.getMessage());

}

110/140

Page 56: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

56

Servidor de Sockets para Proporcionar .jar en Cliente

package es.solop.bundlediscoverer.impl.client;public class UnicastListener extends Thread {

private ServerSocket server;...public UnicastListener(BundleDiscovererClient parent) throws IOException {

this.server = new ServerSocket (0);this.parent = parent;

}public void run() {

try {while (continueProcessingRequests) {

Socket socket = server.accept();BundleDiscoveryHandler handler = new

BundleDiscoveryHandler(socket, this.parent);handler.start();

}} catch (IOException ioe) {

ioe.printStackTrace();}

}...

}

111/140

Aplicación de Ejemplo Usando BundleDiscoverer

� La clase WeatherForecastServer exporta dos bundles que ofrecen el pronóstico del tiempo en un conjunto de ciudades españolas:� WeatherForecastBunde – se comunica con la estación

metereológica remota (WeatherForecastServer) para obtener el pronóstico del tiempo en formato HTML.

� WeatherForecastWebBundle – requiere la previa instalación de WeatherForecastBundle en el entorno en que se despliegue y ofrece una interfaz web para seleccionar la ciudad de la que se quiere obtener el pronóstico del tiempo y así obtenerlo con la ayuda de WeatherForecastBundle

112/140

Page 57: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

57

BundleDiscoverer

113/140

BundleDiscoverer

114/140

Page 58: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

58

Patrón de Diseño Whiteboard

� El modelo tradicional de subscribir los consumidores a los proveedores (patrón observer) requiere demasiadas clases y por tanto carga en el entorno que lo implementa para gestionar la notificación de eventos y no se ajusta al entorno dinámico de OSGi (establece demasiadas dependencias entre productores y consumidores)

� En el patrón de diseño Whiteboard:� Cuando un consumidor quiere consumir se registra con el registro

de servicios� El productor escucha al registro de servicios de manera que cuando

tenga que realizar una notificación contiene la lista actual activa de consumidores

� Delega la responsabilidad de la gestión de consumidores al Service Registry

� Se utiliza en la mayoría de servicios, excepto el LogService y el HttpService que vienen de la versión R1. � Para más info:

http://www.osgi.org/documents/osgi_technology/whiteboard.pdf

115/140

Declarative Services

� El modelo programático de activación bundles en OSGi se basa en la publicación, búsqueda y enlazado de servicios

� Problemático cuando el tamaño del sistema empieza a crecer:� Tiempo de arranque: cada bundle tiene que registrar de forma

activa sus servicios, requiriendo que todas sus referencias estén presentes de antemano. En sistemas grandes esto puede provocar retrasos de inicialización demasiado elevados.

� Tamaño en memoria: Cuando se registra un servicio, éste es cargado en memoria. Si no se utiliza es un espacio que se está malgastando, aparte de la sobrecarga que supone tener que crear el class loader correspondiente.

� Complejidad: en un entorno donde los servicios se consideran dinámicos (pueden aparecer y desaparecer en cualquier momento) el modelo de programación en sistemas complejos puede resultar difícil de mantener.

116/140

Page 59: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

59

Declarative Services

� Para resolver esta situación OSGi propone un modelo declarativo, basado en el concepto de componente:� Un componente es una clase Java con ciertas características especiales:

� Descripción XML que indica cómo debe gestionarse en OSGi� Registro de servicios, comprobación de dependencias, registro de eventos se hace por nosotros

� Principales diferencias con el modelo tradicional:� Se elimina el concepto de BundleActivator, el framework leerá el XML con los

componentes que estén definidos y los creará en función de la política definida:� Immediate, se crea el componente nada más resolver todas sus dependencias� Delayed, el servicio es registrado, pero no se crea la instancia hasta que alguien lo solicita � Factory, se registra una factoría para crear las diferentes instancias.

� Cada componente debe implementar dos métodos, uno de activación (activate()activate()activate()activate()) y otro de desactivación (deactivate()deactivate()deactivate()deactivate()), que se invocarán durante su ciclo de vida.

� Las referencias a otros servicios se declaran en el XML con ciertas propiedades (si son obligatorias, opcionales o la cardinalidad permitida) y es el framework el que se asegura de que estén correctamente enlazadas antes de activar el componente.

� La gestión de las referencias a servicios que desaparecen mientras el componente está activo también se pueden gestionar automáticamente sin necesidad de registrarse al framework para escuchar los eventos.

� Excelente alternativa para el desarrollo de componentes complejos en OSGi, muchas de las tareas a realizar se automatizan en el XML

117/140

Formato bundle.manifest en un Bundle definido con el Declarative Services

ServiceServiceServiceService----Component: OSGIComponent: OSGIComponent: OSGIComponent: OSGI----INF/es.deusto.tecnologico.osgi.declarative.impl.Display.xmlINF/es.deusto.tecnologico.osgi.declarative.impl.Display.xmlINF/es.deusto.tecnologico.osgi.declarative.impl.Display.xmlINF/es.deusto.tecnologico.osgi.declarative.impl.Display.xml

Private-Package: es.deusto.tecnologico.osgi.declarative.impl

Bundle-Version: 1.0.0

Bundle-Name: declarative_example

Bundle-ManifestVersion: 2

Bundle-SymbolicName: declarative_example

ImportImportImportImport----Package: org.osgi.service.component, Package: org.osgi.service.component, Package: org.osgi.service.component, Package: org.osgi.service.component, org.osgi.service.logorg.osgi.service.logorg.osgi.service.logorg.osgi.service.log

118/140

Page 60: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

60

Fichero XML de definición de un bundle

<?xml version='1.0' encoding='utf-8'?>

<component <component <component <component name='es.deusto.tecnologico.osgi.declarative.impl.Display'>name='es.deusto.tecnologico.osgi.declarative.impl.Display'>name='es.deusto.tecnologico.osgi.declarative.impl.Display'>name='es.deusto.tecnologico.osgi.declarative.impl.Display'>

<implementationimplementationimplementationimplementationclassclassclassclass='es.deusto.tecnologico.osgi.declarative.impl.Display'/>

<referencereferencereferencereference name='log' interfaceinterfaceinterfaceinterface='org.osgi.service.log.LogService' bindbindbindbind='setLog' unbindunbindunbindunbind='unsetLog'/>

</component></component></component></component>

119/140

Implementación del Bundle

import org.osgi.service.component.ComponentContext;...public class Display extends Thread {public class Display extends Thread {public class Display extends Thread {public class Display extends Thread {

LogService log;private boolean quit = false;protected void activate(ComponentContext context)protected void activate(ComponentContext context)protected void activate(ComponentContext context)protected void activate(ComponentContext context) {

log.log(LogService.LOG_INFO, "Display component activated");this.start();

}protected void deactivate(ComponentContext context)protected void deactivate(ComponentContext context)protected void deactivate(ComponentContext context)protected void deactivate(ComponentContext context) {

log.log(LogService.LOG_INFO, "Display component deactivated");quit = true;

}public synchronized void run()public synchronized void run()public synchronized void run()public synchronized void run() {

while (!quit)try {

Date now = new Date();log.log(LogService.LOG_INFO, now.toString());wait(5000);

} catch (InterruptedException ie) { /*will recheck quit*/ }}public void setLog(LogService log)public void setLog(LogService log)public void setLog(LogService log)public void setLog(LogService log) {

this.log = log;log.log(LogService.LOG_INFO, "LogService bounded to Display");

}public void unsetLog(LogService log)public void unsetLog(LogService log)public void unsetLog(LogService log)public void unsetLog(LogService log) {

log.log(LogService.LOG_INFO, "LogService unbounded to Display");this.log = null;

} }

120/140

Page 61: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

61

Event Admin Service

� Canal de eventos con opciones de filtrado y clasificado de eventos sencillo y homogéneo dentro de la plataforma OSGi, ofreciendo un mecanismo de comunicación entre bundles basado en paradigma publish/subscribe

� Los elementos que intervienen en el esquema del Event Admin son:� Evento (EventEventEventEvent): situación que un bundle quiere notificar, compuesto de:

� Un tipo se utilizada para categorizar los eventos, su nombre es un espacio de nombres jerárquico que se utiliza como un primer mecanismo de filtrado para saber cómo despacharlos a los diferentes consumidores.

� Sintáxis: fully/qualified/package/ClassName/ACTION� Un conjunto de propiedades, o pares atributo valor que proporcionan más información

sobre el evento. El atributo debe ser de tipo String, pero el valor puede ser cualquier objeto Java primitivo o String.

� Event HandlerEvent HandlerEvent HandlerEvent Handler, interfaz bajo el cual debe registrarse un servicio que quiera escuchar eventos del EventAdmin. Se configura con dos propiedades:

� topic-scope: eventos a los que se suscribe � event-filter: filtro en sintaxis LDAP que hay que aplicar� Ejemplo: “Recibir evento LOG_WARNING de cualquier bundle cuyo nombre simbólico

empieza por com.acne”� topic-scope � org/osgi/service/log/LogEntry/LOG_WARNING� event-filter � (bundle.symbolicName=com.acme.*)

� Event PublisherEvent PublisherEvent PublisherEvent Publisher – publicadores de eventos que no tienen ninguna característica especial. Simplemente necesitan una referencia al servicio EventAdmin donde publicar eventos.

� EventAdminEventAdminEventAdminEventAdmin – servicio que implementa el canal de eventos, ofreciendo dos tipos de envío: síncrono y asíncrono

121/140

bundle.manifest de bundle utilizando servicio EventAdmin

Manifest-Version: 1.0

Bundle-Version: 1.0.0

Bundle-Name: event_admin_example

Bundle-ManifestVersion: 2

Bundle-SymbolicName: event_admin_example

ImportImportImportImport----Package: org.osgi.service.component, Package: org.osgi.service.component, Package: org.osgi.service.component, Package: org.osgi.service.component, org.osgi.service.event, org.osgi.service.logorg.osgi.service.event, org.osgi.service.logorg.osgi.service.event, org.osgi.service.logorg.osgi.service.event, org.osgi.service.log

Service-Component: OSGI-INF/Display.xml,OSGI-INF/Clock.xml

122/140

Page 62: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

62

Ficheros de configuración de los componentes productor y consumidor de eventos

� Productor: Clock.xmlClock.xmlClock.xmlClock.xml<?xml version='1.0' encoding='utf-8'?><component name='es.deusto.tecnologico.osgi.eventadmin.impl.Clock'><implementation class='es.deusto.tecnologico.osgi.eventadmin.impl.Clock'/><reference name='log' interface='org.osgi.service.log.LogService' bind='setLog' unbind='unsetLog'/><reference name='eventAdmin' interface='org.osgi.service.event.EventAdmin' <reference name='eventAdmin' interface='org.osgi.service.event.EventAdmin' <reference name='eventAdmin' interface='org.osgi.service.event.EventAdmin' <reference name='eventAdmin' interface='org.osgi.service.event.EventAdmin' bind='setEventAdmin' unbind='unsetEventAdmin'/>bind='setEventAdmin' unbind='unsetEventAdmin'/>bind='setEventAdmin' unbind='unsetEventAdmin'/>bind='setEventAdmin' unbind='unsetEventAdmin'/>

</component>

� Consumidor: Display.xmlDisplay.xmlDisplay.xmlDisplay.xml<?xml version="1.0" encoding="utf-8"?><component name="es.deusto.tecnologico.osgi.eventadmin.impl.Display"

immediate="true"immediate="true"immediate="true"immediate="true"><implementation class="es.deusto.tecnologico.osgi.eventadmin.impl.Display"/><property <property <property <property name="event.topics">es/deusto/tecnologico/osgi/eventadmin/Clock/NEW_DATE</pname="event.topics">es/deusto/tecnologico/osgi/eventadmin/Clock/NEW_DATE</pname="event.topics">es/deusto/tecnologico/osgi/eventadmin/Clock/NEW_DATE</pname="event.topics">es/deusto/tecnologico/osgi/eventadmin/Clock/NEW_DATE</property>roperty>roperty>roperty><service><service><service><service><provide interface="org.osgi.service.event.EventHandler" /><provide interface="org.osgi.service.event.EventHandler" /><provide interface="org.osgi.service.event.EventHandler" /><provide interface="org.osgi.service.event.EventHandler" /><provide interface="es.deusto.tecnologico.osgi.eventadmin.IDisplay" /><provide interface="es.deusto.tecnologico.osgi.eventadmin.IDisplay" /><provide interface="es.deusto.tecnologico.osgi.eventadmin.IDisplay" /><provide interface="es.deusto.tecnologico.osgi.eventadmin.IDisplay" /></service> </service> </service> </service> <reference name="log" interface="org.osgi.service.log.LogService" bind="setLog" unbind="unsetLog"/>

</component>

123/140

Productor de Eventos: Clock

import org.osgi.service.component.ComponentContext;import org.osgi.service.event.Event;import org.osgi.service.event.EventAdmin;public class Clock extends ThreadClock extends ThreadClock extends ThreadClock extends Thread {

LogService log = null;EventAdmin eventAdmin = null;boolean quit = false;protected void activate(ComponentContext context)protected void activate(ComponentContext context)protected void activate(ComponentContext context)protected void activate(ComponentContext context) {

log.log(LogService.LOG_INFO, "Clock component activated");this.start();

}protected void deactivate(ComponentContext context)protected void deactivate(ComponentContext context)protected void deactivate(ComponentContext context)protected void deactivate(ComponentContext context) {

log.log(LogService.LOG_INFO, "Clock component deactivated");quit = true;

}public synchronized void run() {

while (!quit) {try {

Date now = new Date();String topic = "es/deusto/tecnologico/osgi/eventadmin/Clock/NEW_DATE";String topic = "es/deusto/tecnologico/osgi/eventadmin/Clock/NEW_DATE";String topic = "es/deusto/tecnologico/osgi/eventadmin/Clock/NEW_DATE";String topic = "es/deusto/tecnologico/osgi/eventadmin/Clock/NEW_DATE";Hashtable properties = new Hashtable();Hashtable properties = new Hashtable();Hashtable properties = new Hashtable();Hashtable properties = new Hashtable();properties.put("currentTime", now.toString() );properties.put("currentTime", now.toString() );properties.put("currentTime", now.toString() );properties.put("currentTime", now.toString() );Event newEvent = new Event(topic,properties);Event newEvent = new Event(topic,properties);Event newEvent = new Event(topic,properties);Event newEvent = new Event(topic,properties);eventAdmin.sendEvent(newEvent); // send it synchronouslyeventAdmin.sendEvent(newEvent); // send it synchronouslyeventAdmin.sendEvent(newEvent); // send it synchronouslyeventAdmin.sendEvent(newEvent); // send it synchronouslywait(3000);

} catch (InterruptedException ie) {}}

}

124/140

Page 63: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

63

Productor de Eventos: Clock

public void setLog(LogService log)public void setLog(LogService log)public void setLog(LogService log)public void setLog(LogService log) {

this.log = log;

log.log(LogService.LOG_INFO, "LogService bounded to Display");

}

public void unsetLog(LogService log)public void unsetLog(LogService log)public void unsetLog(LogService log)public void unsetLog(LogService log) {

log.log(LogService.LOG_INFO, "LogService unbounded to Display");

this.log = null;

}

public void setEventAdmin(EventAdmin eventAdmin)public void setEventAdmin(EventAdmin eventAdmin)public void setEventAdmin(EventAdmin eventAdmin)public void setEventAdmin(EventAdmin eventAdmin) {

this.eventAdmin = eventAdmin;

}

public void unsetEventAdmin(EventAdmin eventAdmin)public void unsetEventAdmin(EventAdmin eventAdmin)public void unsetEventAdmin(EventAdmin eventAdmin)public void unsetEventAdmin(EventAdmin eventAdmin) {

this.eventAdmin = null;

}

}

125/140

Consumidor de Eventos: IDisplay

package es.deusto.tecnologico.osgi.eventadmin;

public interface IDisplay {public interface IDisplay {public interface IDisplay {public interface IDisplay {public String getLastMessage();public String getLastMessage();public String getLastMessage();public String getLastMessage();

}}}}

126/140

Page 64: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

64

Consumidor de Eventos: Display

import org.osgi.service.component.ComponentContext;import org.osgi.service.event.Event;import org.osgi.service.event.EventHandler;...public class Display implements IDisplay, EventHandlerDisplay implements IDisplay, EventHandlerDisplay implements IDisplay, EventHandlerDisplay implements IDisplay, EventHandler {

LogService log;private String message;final static String [] topics = new String[] {"es/deusto/tecnologico/osgi/eventadmin/Clock/NEW_DATE" };protected void activate(ComponentContext context)protected void activate(ComponentContext context)protected void activate(ComponentContext context)protected void activate(ComponentContext context) {

log.log(LogService.LOG_INFO, "Display component activated");}protected void deactivate(ComponentContext context)protected void deactivate(ComponentContext context)protected void deactivate(ComponentContext context)protected void deactivate(ComponentContext context) {

log.log(LogService.LOG_INFO, "Display component deactivated");}public void setLog(LogService log) {

this.log = log;log.log(LogService.LOG_INFO, "LogService bounded to Display");

}public void unsetLog(LogService log) {

log.log(LogService.LOG_INFO, "LogService unbounded to Display");this.log = null;

} public synchronized void handleEvent(Event newEvent)public synchronized void handleEvent(Event newEvent)public synchronized void handleEvent(Event newEvent)public synchronized void handleEvent(Event newEvent) {

message = (String)newEvent.getProperty("currentTime");}public String getLastMessage() {

return message;}

}

127/140

Configuration Admin

� Facilita las labores de configuración de las propiedades de los diferentes bundles del sistema� Consiste de un conjunto de interfaces que los servicios han de

implementar para ser avisados cuando sus configuraciones cambian� Dos alternativas:

� ManagedService – para servicios con un único conjunto de propiedades

� ManagedServiceFactory – para cuando se generan varias instancias de un servicio y cada una necesitas sus propiedades

� El índice a las propiedades de un servicio es su PID� Cuando un bundle necesita información de configuración debe

registrar uno o más objetos ManagedService� El ConfigurationAdmin es capaz de enviar eventos cuando la

configuración cambia (CM_UPDATED) o es eliminada (CM_DELETED)� Hay que registrarse previamente bajo el interfaz

ConfigurationListener

� En la cabecera Import-Package hay que usarorg.osgi.framework, org.osgi.service.cm

128/140

Page 65: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

65

Obteniendo, creando o actualizando un objeto de Configuración

//Search the reference to the ConfigurationAdminServiceReference configAdminReference = ServiceReference configAdminReference = ServiceReference configAdminReference = ServiceReference configAdminReference =

context.getServiceReference(ConfigurationAdmin.class.getName());context.getServiceReference(ConfigurationAdmin.class.getName());context.getServiceReference(ConfigurationAdmin.class.getName());context.getServiceReference(ConfigurationAdmin.class.getName());ConfigurationAdmin configAdmin = ConfigurationAdmin configAdmin = ConfigurationAdmin configAdmin = ConfigurationAdmin configAdmin =

(ConfigurationAdmin)context.getService(configAdminReference);(ConfigurationAdmin)context.getService(configAdminReference);(ConfigurationAdmin)context.getService(configAdminReference);(ConfigurationAdmin)context.getService(configAdminReference);if (configAdmin == null) System.out.println("Configuration Admin Service not

found.");

//Create configuration for bundle configuration_admin_example//This returns a new Configuration object. //This new object is bound to the location and the properties set to null. //If the location parameter is null, it will be set when a Managed Service// with the corresponding PID is registered for the first time.Configuration config = Configuration config = Configuration config = Configuration config =

configAdmin.getConfiguration("es.deusto.tecnologico.osgi.GetConfigurationconfigAdmin.getConfiguration("es.deusto.tecnologico.osgi.GetConfigurationconfigAdmin.getConfiguration("es.deusto.tecnologico.osgi.GetConfigurationconfigAdmin.getConfiguration("es.deusto.tecnologico.osgi.GetConfiguration", null );", null );", null );", null );

//As this is the first time the properties must be created firstHashtable properties = new Hashtable();Hashtable properties = new Hashtable();Hashtable properties = new Hashtable();Hashtable properties = new Hashtable();properties.put("port", new Integer(6023));properties.put("port", new Integer(6023));properties.put("port", new Integer(6023));properties.put("port", new Integer(6023));properties.put("motto", "Message set with the configuration admin");properties.put("motto", "Message set with the configuration admin");properties.put("motto", "Message set with the configuration admin");properties.put("motto", "Message set with the configuration admin");

//Update the propertiesconfig.update(properties);config.update(properties);config.update(properties);config.update(properties);

129/140

Usando un Objeto de Configuración

package es.deusto.tecnologico.osgi.configurationadmin;public class GetConfiguration implements ManagedService {

…public synchronized void init(BundleContext context) {

//Set default properties, SERVICE_PID is mandatoryproperties = new Hashtable();properties.put(Constants.SERVICE_PID , "es.deusto.tecnologico.osgi.GetConfiguration");properties.put("port", new Integer(6123));properties.put("motto", "First message of the day");//Register the service as a ManagedService interfaceregistration = context.registerService(ManagedService.class.getName(), this, properties);

}public synchronized void updated(Dictionary properties) throws ConfigurationException {

if (properties != null) {try {

message = (String) properties.get("motto");port = Integer.parseInt((String) properties.get("port"));//It is advisable but not mandatory to update the properties of the serviceregistration.setProperties(properties);

} catch (Exception e) {// Ignore, use defaults}}if (motd != null) motd.kill(); //Restart the Motto of the Day server with the new configuration

motd = new MottoOfTheDay();motd.setPort(port == 0 ? port = 6123 : port);motd.setMotto(message == null ? "No motto" : message);motd.start();

}}

}

130/140

Page 66: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

66

Wire Admin Service

� Objetivo: productor y el consumidor de datos o eventos conozcan lo mínimo posible el uno del otro para que los cambios en cada uno no perjudiquen al otro.

� En los entornos orientados a servicios existen varias alternativas a la hora de enlazar unos servicios con otros:� Permitir al consumidor que elija al productor, siguiendo el tradicional patrón Observer � Productor localiza a sus consumidores mediante el llamado patrón whiteboard� Wire Admin Service – desligar completamente el productor y el consumidor

� Modelo de funcionamiento: productores (interfaz Producer) y consumidores (interfaz Consumer) se asocian mediante la creación de objetos Wire � Un Wire asocia a dos servicios identificados por su PID

� Son gestionados por el WireAdmin que notifica a producers y consumers cuando los enlaces son activados

� Cuando un Producer tenga datos que notificar, actualizará el correspondiente Wire� Se permite la definición de filtros

� Los datos que se envían entre el Consumer y el Producer deben ser compatibles: concepto de flavors

� Soporta el mecanismo Push y el Pull� Proporciona un conjunto de eventos para gestionar el ciclo de vida de los Wires� La cabecera Import-Package: org.osgi.framework,

org.osgi.service.wireadmin

131/140

Definiendo un Consumidor

import org.osgi.service.wireadmin.Consumer;…public class Tv implements Consumer {

Wire[] producers;public Tv (BundleContext context) {

Hashtable ht = new Hashtable();ht.put( Constants.SERVICE_PID, "es.deusto.Tv" );ht.put( WireConstants.WIREADMIN_CONSUMER_FLAVORS, new Class[] { String.class, Date.class } );

context.registerService( Consumer.class.getName(), this, ht );}public void producersConnected(Wire[] producers) {

this.producers = producers;}public void updated(Wire arg0, Object in) {

if ( in instanceof Date ) {System.out.println("[Tv] - New time shown as Date: " + in.toString());

} else if ( in instanceof String ) {System.out.println("[Tv] - New time shown as String: " + in);

} else {System.out.println("[Tv] Error: object type not supported.");

}}…

}

132/140

Page 67: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

67

Definiendo un Productor

import org.osgi.service.wireadmin.Producer;import org.osgi.service.wireadmin.Producer;import org.osgi.service.wireadmin.Producer;import org.osgi.service.wireadmin.Producer;…public class Clock extends Thread implements Producerpublic class Clock extends Thread implements Producerpublic class Clock extends Thread implements Producerpublic class Clock extends Thread implements Producer {

Wire wires[];BundleContext context;boolean quit = false;Clock(BundleContext context) {

this.context = context;registerProducer();

}private void registerProducer() {

Hashtable p = new Hashtable();Hashtable p = new Hashtable();Hashtable p = new Hashtable();Hashtable p = new Hashtable();p.put(org.osgi.service.wireadmin.WireConstants.WIREADMIN_PRODUCER_FLAVORS, new p.put(org.osgi.service.wireadmin.WireConstants.WIREADMIN_PRODUCER_FLAVORS, new p.put(org.osgi.service.wireadmin.WireConstants.WIREADMIN_PRODUCER_FLAVORS, new p.put(org.osgi.service.wireadmin.WireConstants.WIREADMIN_PRODUCER_FLAVORS, new

Class[] { Date.class, String.class });Class[] { Date.class, String.class });Class[] { Date.class, String.class });Class[] { Date.class, String.class });p.put(org.osgi.framework.Constants.SERVICE_PID, "es.deusto.Clock");p.put(org.osgi.framework.Constants.SERVICE_PID, "es.deusto.Clock");p.put(org.osgi.framework.Constants.SERVICE_PID, "es.deusto.Clock");p.put(org.osgi.framework.Constants.SERVICE_PID, "es.deusto.Clock");

context.registerService(Producer.class.getName(), this, p);context.registerService(Producer.class.getName(), this, p);context.registerService(Producer.class.getName(), this, p);context.registerService(Producer.class.getName(), this, p);}public synchronized void run()public synchronized void run()public synchronized void run()public synchronized void run() {

while (!quit)try {

Date now = new Date();for (int i = 0; wires != null && i < wires.length; i++) {

wires[i].update(now);wires[i].update(now);wires[i].update(now);wires[i].update(now);wires[i].update(now.toString());wires[i].update(now.toString());wires[i].update(now.toString());wires[i].update(now.toString());

}wait(3000);

} catch (InterruptedException ie) {}}

133/140

Definiendo un Productor

public synchronized void consumersConnected(Wire[] wires)public synchronized void consumersConnected(Wire[] wires)public synchronized void consumersConnected(Wire[] wires)public synchronized void consumersConnected(Wire[] wires) {

this.wires = wires;

}

public synchronized Object polled(Wire wire) public synchronized Object polled(Wire wire) public synchronized Object polled(Wire wire) public synchronized Object polled(Wire wire) {

Class clazzes[] = wire.getFlavors();

for ( int i=0; i<clazzes.length; i++ ) {

Class clazz = clazzes[i];

if ( clazz.isAssignableFrom( Date.class ) )

return new Date();

else if (clazz.isAssignableFrom(String.class))

return new Date().toString();

}

return null;

}

}

134/140

Page 68: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

68

Artículos de Investigación Usando OSGi

� Challenges in building service-oriented applications for OSGi, � Hall, R.S. Cervantes, H. Lab. LSR IMAG, Domaine Univ., Grenoble, France, IEEE

Communications Magazine, May 2004� Device and service discovery in home networks with OSGi,

� Dobrev, P. Famolari, D. Kurzke, C. Miller, B.A; IEEE Communications Magazine, Aug 2002

� Enabling smart spaces with OSGi, � Choonhwa Lee Nordstedt, D. Helal, S. University of Florida, Jul-Sept 2003

� The Gator Tech Smart House: a programmable pervasive space� Helal, S. Mann, W. El-Zabadani, H. King, J. Kaddoura, Y. Jansen, E. Dept.

of Comput. & Inf. Sci. & Eng., Florida Univ., FL, USA, IEEE Computer, March 2005� Toward an OSGi-based infrastructure for context-aware applications

� Gu, T. Pung, H.K. Zhang, D.Q. Sch. of Comput., Nat. Univ. of Singapore, Singapore, Pervasive Computing, IEEE, Oct-Dec 2004

� Research and implementation of the context-aware middleware for controlling home appliances, � Jonghwa Choi Dongkyoo Shin Dongil Shin, Dept. of Comput. Sci. & Eng.,

Sejong Univ., Seoul, South Korea;IEEE Transactions on Consumer Electronics, Feb 2005

135/140

Características Avanzadas de OSGi

� Integración con Servicios Web� The Knopflerfish Axis port

� Provee acceso SOAP/Web service a cualquier bundle OSGi bien sea para exportar un servicio OSGi como Servicio Web o para importar los servicios web en una framework OSGi

� https://www.knopflerfish.org/svn/knopflerfish.org/trunk/osgi/bundles_opt/soap/axis.html

� Service Binder� Simplifica el desarrollo de bundles OSGi automatizando la gestión de

dependencias de servicios.� Elimina la lógica de gestión de dependencias de servicios de los bundles

� http://gravity.sourceforge.net/servicebinder/

� Bnd plugin de aqute que genera el manifest.mf por ti� Wire Admin Service

� Permite enlazar dinámicamente servicios que producen datos con servicios que los consumen.

� ¿Podríamos enlazar los servicios automáticamente si tuviéramos descripciones de servicios mejoradas con semántica? � tema de investigación

� Eclipse Rich Ajax Platform (RAP) permite crear Rich Internet Applications (RIA) usando el modelo de componentes OSGi� Podemos compartir el mismo código para aplicaciones RCP y RIA

136/140

Page 69: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

69

R-OSGi

� R--OSGi permite el descubrimiento e invocación de servicios provistos en otras implementaciones OSGi� Utiliza SLP para el descubrimiento de servicios

� Los proveedores de servicios tienen que registrar un servicio para acceso remoto.

� Los consumidores en otras instancias de OSGi lo pueden descubrir con la infraestructura R-OSGi y recuperar el servicio (sus propiedades y su interfaz)� La framework cliente construirá un proxy bundle sobre la marcha y lo

registrará en la framework local� Los servicios locales podrán ahora acceder el servcio remoto de manera

transparente

� Desde la versión 0.5 es posible transferir el bundle completo al cliente

� Url: http://r-osgi.sourceforge.net/

137/140

OSGi en la Empresa

� Existen varios proyectos que quieren integrar la capacidades de gestión dinámica de módulos de OSGi en servidores de aplicaciones:� Spring Dynamic Modules for OSGi Services Plataform:

http://www.springframework.org/osgi� JOnAS – Java Open Application Server:

http://wiki.jonas.objectweb.org/xwiki/bin/view/Main/� Equinox Serverside Quickstart:

http://eclipse.org/equinox/documents/http_quickstart.php

138/140

Page 70: Apéndice A: OSGi: Open Services Gateway Interfacepaginaspersonales.deusto.es/dipina/doctorado/ApéndiceA... · 2008-04-21 · Fichero de manifesto e. Creación de la clase Activator

70

Conclusion

� La plataforma OSGi es algo así como un sistema operativo Java para componentes desplegados a través de la red, ofreciendo:� Modelo de ejecución y programación orientada a servicios simple� Despliegue dinámico� Capa de módulos� Capa de servicios� Seguridad integral

� Su misión es simplificar y hacer más eficiente incluso para entornos empotrados:� Problemas de despliegue

� La composición de servicios

� La gestión vitalicia de los componentes

� Implementado por varios fabricantes y comunidades open source �gran apoyo de la industria

139/140

References

� OSGi Tutorials� OSGi Tutorial -- A Step by Step Introduction to OSGi Programming

Based on the Open Source Knopflerfish OSGi Framework� http://www.knopflerfish.org/tutorials/osgi_tutorial.pdf

� Develop OSGi bundles� http://www.knopflerfish.org/programming.html

� OSGi Service tutorial� http://www.knopflerfish.org/osgi_service_tutorial.html

� OSGi and Gravity Service Binder Tutorial� http://oscar-osgi.sourceforge.net/tutorial/

� Bundle Repository� http://www.knopflerfish.org/repo/index.html

� Mi página personal: http://paginaspersonales.deusto.es/dipina

140/140