Professional Documents
Culture Documents
Gateway Interface”
Contenido
1. Introducción
a. ¿Qué proporciona?
b. ¿Dónde se aplica?
c. Especificaciones y Herramientas OSGi 2.
2. Arquitectura OSGi
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
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/142
1
Contenido
6. Conclusión
3/142
4/142
2
OSGi (Open Services Gateway Initiative)
¿Qué aporta?
OSGi aporta modularidad dinámica a Java y permite estandarizar la
integración del software
5/142
6/142
3
OSGi Alliance
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/142
4
¿Qué proporciona OSGi?
9/142
Structured
Programming
Assembly
10/142
5
¿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/142
Access
from any Web Terminal Aggregation &
Management Platform
Notification
HomeControl Server
Security Internet
Different
Networks Secure Tunnel
Access Family
Webpad OSGi Gateway Portal
Entertainment/ Service Gateway Firewall
Gaming
Service
Offering
Internet
Services Services
Provider
12/142
6
Ejemplo de Despliegue OSGi en el Hogar (2)
13/142
14/142
7
Implementaciones OSGi R4 Libres
15/142
16/142
8
Características Esenciales de OSGi
17/142
OS
CPU IO
18/142
9
Configuración Remota de Componentes
19/142
20/142
10
Cooperación entre Aplicaciones (2)
Arquitectura Orientada a
Servicios (SOA):
Separa el contrato de la
implementación
Permite implementaciones Service Contract
alternativas provides
Component
Descubre y asocia dinámicamente
las aplicaciones uses
21/142
22/142
11
Arquitectura OSGi (1)
23/142
24/142
12
Arquitectura OSGi (3)
25/142
Services
Security
Applications
Life Cycle
Module
Execution Environment
26/142
13
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/142
OSGi
Min.
J2SE
CDC/FP 28/142
14
Capas de la Framework OSGi: Modularidad (1)
29/142
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/142
15
Capas de la Framework OSGi: Modularidad (3)
31/142
Manages
Instalarlos
Resolverlos
Arrancar
Parar System
bundle
Bundle
M
Refrescar
Actualizar
Desinstalar Bundle
X-v2
X
Bundle
Bundle B
A
32/142
16
Capas de la Framework OSGi: Ciclo de Vida (2)
El BundleActivator recibe un
stop
BundleContext que provee
acceso a las funciones de la
framework OSGi UNINSTALLED STOPPING
33/142
34/142
17
Capas de la Framework OSGi: Servicios(2)
35/142
36/142
18
Beneficios de la Plataforma OSGi
37/142
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 Bundel Repository: http://oscar-osgi.sourceforge.net/
38/142
19
Bundles: Contenido interno
39/142
40/142
20
Modelo de Colaboración en OSGi: Servicios
= service, defined by
OSGi Framework java interface
= bundle
Bundle A
{…}
Bundle B
{…}
Bundle C
{…}
41/142
42/142
21
Modelo de Colaboración en OSGi: Servicios
44/142
22
Modelo de Colaboración en OSGi: Servicios
45/142
No management bundles
Service
Midlet, registry Midlet, No collaboration
Xlet, Xlet,
or or
Applet packages Applet
packages No package management
(versions!)
JAVA
Hardware
46/142
23
Ciclo de Vida de un Bundle en Detalle (1)
47/142
48/142
24
Registro de Servicios en Detalle (1)
49/142
50/142
25
Detalles sobre Servicios
listen
51/142
Manipulación de Servicios
La interfaz BundleContext
facilita los métodos para manipular
el registro de servicios
ServiceRegistration registerService(
Los registros de servicio son String clss,
gestionados por objetos de tipo Object srvc,
ServiceRegistration Dictionary prprts)
52/142
26
Seguridad en Detalle
53/142
54/142
27
Servicios Estándar en OSGi (2)
55/142
56/142
28
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/142
Knopflerfish
58/142
29
Instalación de Knoplerfish
59/142
60/142
30
Instalación Plug-in Eclipse OSGi
61/142
62/142
31
Usando Ant para Compilar Bundles
63/142
64/142
32
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">
name="compile">
<javac destdir = "./classes
"./classes"
classes" debug = "on
"on">
on">
<src path=
path= "./src
"./src"/><
src"/><classpath
"/><classpath refid="
refid="lib.class.path
="lib.class.path"/>
lib.class.path"/>
</javac
</javac>
javac>
</target
</target>
target>
65/142
<target name="
name="jar
="jar">
jar">
<jar basedir = "./classes"
jarfile = "./build/${app.name}.jar"
compress = "true" includes = "**/*"
manifest = "./meta-inf/MANIFEST.MF"/>
</target>
<target name="
name="clean
="clean">
clean">
<delete dir = "./classes"/><delete dir = "./build"/>
</target>
<target name="
name="deploy
="deploy"
deploy" depends="
depends="jar
="jar">
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/142
33
Creando nuestro primer bundle
67/142
68/142
34
Pasos en detalle para crear nuestro primer
bundle
manifest.mf
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 página 3.2.1 Bundle Manifest Headers
(página 36) de la Especificación de OSGi
Propiedad Bundle-
Bundle-Activator indica a la framework qué clase es la
Activator clase principal a invocar por la framework cuando cargue
el bundle
Import-Package indica al framework que nuestro bundle requiere
Import-
acceso a todas las clases en el paquete org.osgi.framework
69/142
package es.deusto.simplebundle.impl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
public static BundleContext bc = null;
private HelloWorldThread thread = null;
70/142
35
Pasos en detalle para crear nuestro primer
bundle
71/142
4. Create
simplebundle/src/es/deusto/simplebundle/impl/HelloWorldThread.j
ava
package es.deusto.simplebundle.impl;
public 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/142
36
Pasos en detalle para crear nuestro primer
bundle
73/142
74/142
37
Ciclo de Desarrollo de un Bundle en OSGi
75/142
76/142
38
Creando tu primer bundle ofreciendo un
servicio
77/142
78/142
39
Registro de Servicios en OSGi
79/142
40
Consumiendo un Servicio en OSGi
81/142
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;
82/142
41
Consumiendo Servicios en OSGi
proporcionados por ServiceFactory
83/142
84/142
42
Usando un Servicio OSGi que Implementa
ServiceFactory
85/142
86/142
43
Consumiendo Servicios en OSGi
87/142
44
Consumiendo Servicios en OSGi
Mejora 3 Usar ServiceTracker (BestActivator.java)
public class BestActivator implements BundleActivator {
public static BundleContext bc = null;
private ServiceTracker tracker = null;
45
Comentarios Mejoras Activators
91/142
92/142
46
Resumen Desarrollo de Servicios en OSGi
93/142
94/142
47
El Servicio Estándar HttpService
95/142
96/142
48
Dateservicewebuser –
Activator.java
import org.osgi.service.http.HttpService
org.osgi.service.http.HttpService;
;
import org.osgi.service.log.LogService;
org.osgi.service.log.LogService;
Activator.bc = context;
//get a reference to the http service
ServiceReference ref =
context.getServiceReference(HttpService.class.getName());
context.getServiceReference(HttpService.class.getName ());
HttpService http = (HttpService
(HttpService)
HttpService) context.getService(ref);
context.getService(ref);
//register
//register the capabilities servlet
http.registerServlet("/
http.registerServlet("/example
("/example",
example", new DateServlet(context),
DateServlet(context),new
),new
Properties(),
Properties(),null
(),null);
null);
}
Dateservicewebuser –
DateServlet.java
public class DateServlet extends HttpServlet {
BundleContext context;
public DateServlet(BundleContext context) {
this.context = context;
}
protected void doGet(HttpServletRequest request,
request, HttpServletResponse response) throws
ServletException, IOException {
//strip the service id from the url
String req = request.getRequestURI();
String serviceId = req.substring(req.lastIndexOf('/')+1);
//find a service that matches up
ServiceReference[] 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 match
Activator.log.log(LogService.LOG_INFO, "Comparando con clase " + DateService.class.getName());
if (serviceId.equals(DateService.class.getName())) {
//do it
response.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/142
49
Desarrollo de un Servicio Avanzado en OSGi:
BundleDiscoverer
99/142
BundleDiscoverer
100/142
50
BundleDiscoverer
101/142
102/142
51
BundleDiscoverer: Parte Cliente
103/142
package es.deusto.bundlediscoverer;
104/142
52
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();
}
BundleDiscoverImpl
106/142
53
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 servicePort
StringTokenizer 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,
RetrieveRegisterBundleThread(this, uuid,
uuid, ipAddress,
ipAddress, Integer.parseInt(port)).start();
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/142
org.osgi.framework.Bundle
108/142
54
Eliminación Selectiva de Bundles
109/142
110/142
55
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/142
112/142
56
BundleDiscoverer
113/142
BundleDiscoverer
114/142
57
Patrón de Diseño Whiteboard
115/142
Declarative Services
116/142
58
Declarative Services
117/142
Service-
Service-Component:
Component: OSGI-
OSGI-
INF/es.deusto.tecnologico.osgi.declarative.impl.Display.xml
INF/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
Import-
Import-Package:
Package: org.osgi.service.component,
org.osgi.service.component,
org.osgi.service.log
118/142
59
Fichero XML de definición de un bundle
119/142
60
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:
Event situación que un bundle quiere notificar, compuesto de:
Event):
Evento (Event
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.
Handler interfaz bajo el cual debe registrarse un servicio que quiera
Event Handler,
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 Publisher – publicadores de eventos que no tienen ninguna
característica especial. Simplemente necesitan una referencia al servicio
EventAdmin donde publicar eventos.
EventAdmin – servicio que implementa el canal de eventos, ofreciendo dos tipos
de envío: síncrono y asíncrono
121/142
Manifest-Version: 1.0
Bundle-Version: 1.0.0
Bundle-Name: event_admin_example
Bundle-ManifestVersion: 2
Bundle-SymbolicName: event_admin_example
Import-
Import-Package:
Package: org.osgi.service.component,
org.osgi.service.component,
org.osgi.service.event,
org.osgi.service.event, org.osgi.service.log
Service-Component: OSGI-INF/Display.xml,OSGI-
INF/Clock.xml
122/142
61
Ficheros de configuración de los componentes
productor y consumidor de eventos
Productor: Clock.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='
name='eventAdmin
='eventAdmin'
eventAdmin' interface='
interface='org.osgi.service.event.EventAdmin
='org.osgi.service.event.EventAdmin'
org.osgi.service.event.EventAdmin'
bind='
bind='setEventAdmin
='setEventAdmin'
setEventAdmin' unbind='
unbind='unsetEventAdmin
='unsetEventAdmin'/>
unsetEventAdmin'/>
</component>
Consumidor: Display.xml
<?xml version="1.0" encoding="utf-8"?>
<component name="es.deusto.tecnologico.osgi.eventadmin.impl.Display"
immediate="
immediate="true
="true"
true">
<implementation
class="es.deusto.tecnologico.osgi.eventadmin.impl.Display"/>
<property
name="
name="event.topics
="event.topics">es/
event.topics">es/deusto
">es/deusto/
deusto/tecnologico/
tecnologico/osgi/
osgi/eventadmin/
eventadmin/Clock/
Clock/NEW_DATE</
NEW_DATE</p
</p
roperty>
roperty>
<service>
service>
<provide interface="
interface="org.osgi.service.event.EventHandler
="org.osgi.service.event.EventHandler"
org.osgi.service.event.EventHandler" />
<provide interface="
interface="es.deusto.tecnologico.osgi.eventadmin.IDisplay
="es.deusto.tecnologico.osgi.eventadmin.IDisplay"
es.deusto.tecnologico.osgi.eventadmin.IDisplay" />
</service
</service>
service>
<reference name="log" interface="org.osgi.service.log.LogService"
bind="setLog" unbind="unsetLog"/>
</component>
123/142
124/142
62
Productor de Eventos: Clock
125/142
package es.deusto.tecnologico.osgi.eventadmin;
126/142
63
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,
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) {
log.log(LogService.LOG_INFO, "Display component activated");
}
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)
newEvent) {
message = (String)newEvent.getProperty("currentTime");
}
public String getLastMessage() {
return message;
}
}
127/142
Configuration Admin
128/142
64
Obteniendo, creando o actualizando un
objeto de Configuración
//Search the reference to the ConfigurationAdmin
ServiceReference configAdminReference =
context.getServiceReference(ConfigurationAdmin.class.getName());
context.getServiceReference(ConfigurationAdmin.class.getName());
ConfigurationAdmin configAdmin =
(ConfigurationAdmin)context.getService(configAdminReference);
ConfigurationAdmin)context.getService(configAdminReference);
if (configAdmin == null) System.out.println("Configuration Admin Service not
found.");
//As this is the first time the properties must be created first
Hashtable properties = new Hashtable();
Hashtable();
properties.put("port",
properties.put("port", new Integer(6023));
properties.put("motto",
properties.put("motto", "Message set with the configuration admin");
129/142
130/142
65
Wire Admin Service
131/142
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/142
66
Definiendo un Productor
import org.osgi.service.wireadmin.Producer;
org.osgi.service.wireadmin.Producer;
…
public 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.put(org.osgi.service.wireadmin.WireConstants.WIREADMIN_PRODUCER_FLAVORS
p.put(org.osgi.service.wireadmin.WireConstants.WIREADMIN_PRODUCER_FLAVORS,
R_FLAVORS, new
Class[] { Date.class,
Date.class, String.class });
p.put(org.osgi.framework.Constants.SERVICE_PID,
p.put(org.osgi.framework.Constants.SERVICE_PID, "es.deusto.Clock
"es.deusto.Clock");
es.deusto.Clock");
context.registerService(Producer.class.getName(),
context.registerService(Producer.class.getName(), this, p);
}
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.toString());
wires[i].update(now.toString());
}
wait(3000);
} catch (InterruptedException ie) {}
}
133/142
Definiendo un Productor
134/142
67
Artículos de Investigación Usando OSGi
135/142
136/142
68
R-OSGi
137/142
Conclusion
138/142
69
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
139/142
Apéndices
70
OSGi vs. UPnP
141/142
OSGi UPnP
Java XML DTD
Executing code Communications
Behaviour (Code) Declarative
Program-Program oriented User oriented
Standardizing Java interfaces Standardizing XML templates
Service is local and fast Service is remote and slow to
execute
142/142
71