OUGF - Nouveautés OSGi Core 4.3

Preview:

Citation preview

Zenika © 2011 1

Nouveautés OSGi Core 4.3

OSGi Users’ Group France Jeudi 24 novembre 2011

François Fornaciari - francois.fornaciari@zenika.com

Zenika © 2011 2

Historique

OSGi Specifications

Core (v4.3): plateforme minimale

Compendium (v4.2) : services additionnels

Enterprise (v4.2) : services orientés « entreprise »

OSGi Core 4.3 : mars 2011

Implémentations open-source

Eclipse Equinox 3.7 (Indigo) Première livraison stable mars 2011

C’est la RI !

Apache Felix 4 Première livraison stable fin septembre 2011

Zenika © 2011 3

<Generics> Introduction

Meilleure lisibilité du code

Meilleur typage des objets

Compatibilité avec le JRE 1.4

Utilisation de l’option de compilation -target jsr14

N’est pas une solution au code contenant des annotations dont la RetentionPolicy est à RUNTIME

Configuration Maven <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>jsr14</target> </configuration> </plugin>

Zenika © 2011 4

<Generics> Enregistrement de service

Avant OSGi 4.3

OSGi 4.3

Comptabilité

PrintService service = new PrintServiceImpl(); Properties props = new Properties(); props.put("color", "true"); bundleContext.registerService(PrintService.class.getName(), service, props);

bundleContext.registerService(PrintService.class, service, props);

Zenika © 2011 5

<Generics> Recherche de service

Avant OSGi 4.3

OSGi 4.3

Comptabilité

ServiceReference reference = bundleContext.getServiceReference(PrintService.class.getName()); PrintService service = (PrintService) bundleContext.getService(reference);

ServiceReference<PrintService> reference = bundleContext.getServiceReference(PrintService.class); PrintService service = bundleContext.getService(reference);

Zenika © 2011 6

<Generics> ServiceTracker (1/2)

Avant OSGi 4.3

ServiceTracker serviceTracker = new ServiceTracker(bundleContext, PrintService.class.getName(), null) { public Object addingService(ServiceReference ref) { // Méthode appelée lors de l'ajout au tracker d'un service satisfaisant le filtre // Avantage : appelée à l'ouverture du tracker pour chaque service déjà enregistré // Retourne un objet associé au service tracké (généralement le service détecté)

return super.addingService(reference); } public void modifiedService(ServiceReference ref, Object service) { // Méthode appelée lors de la modification des propriétés d'un service tracké

} public void removedService(ServiceReference ref, Object service) { // Méthode appelée lors du retrait d'un service tracké // Avantage : appelée à la fermeture du tracker pour chaque service tracké

} }; serviceTracker.open(); PrintService service = (PrintService) serviceTracker.getService();

Zenika © 2011 7

<Generics> ServiceTracker (2/2)

OSGi 4.3

ServiceTracker<PrintService, PrintService> serviceTracker = new ServiceTracker<PrintService, PrintService>(bundleContext, PrintService.class, null) { public PrintService addingService(ServiceReference<PrintService> ref) { return super.addingService(reference); } public void modifiedService(ServiceReference<PrintService> ref, PrintService s) { } public void removedService(ServiceReference<PrintService> reference, PrintService s) { } }; serviceTracker.open(); PrintService service = serviceTracker.getService();

Zenika © 2011 8

<Generics> ServiceFactory

Création d'un nouveau service à chaque lookup

Le service créé est associé au bundle consommateur

Un bundle récupérant deux fois le service reçoit la même instance

public class PrintServiceFactory implements ServiceFactory<PrintService> { public PrintService getService(Bundle b, ServiceRegistration<PrintService> sr) { return new PrintServiceImpl(); } public void ungetService(Bundle b, ServiceRegistration sr, PrintService ps) { } } [...] // Enregistrement du service bundleContext.registerService(PrintService.class, new PrintServiceFactory() , null); [...] // Client PrintService service = bundleContext.getService((bundleContext.getServiceReference(PrintService.class)));

Zenika © 2011 9

<Generics> BundleTracker (1/2)

Avant OSGi 4.3

BundleTracker bundleTracker = new BundleTracker(bundleContext, Bundle.ACTIVE, null) { public Object addingBundle(Bundle bundle, BundleEvent event) { // Méthode appelée lors de l'ajout au tracker d'un bundle satisfaisant l'état spécifié // Avantage : appelée à l'ouverture du tracker pour chaque bundle déjà installé // Retourne un objet associé au bundle tracké

[...] return object; } public void removedBundle(Bundle bundle, BundleEvent event, Object o) { // Méthode appelée lors du retrait d'un des bundles trackés // Possibilité d'effectuer des traitements sur l'objet associé au bundle // Avantage : appelée à la fermeture du tracker pour chaque bundle tracké

} }; bundleTracker.open();

Zenika © 2011 10

<Generics> BundleTracker (2/2)

OSGi 4.3

BundleTracker<String> bundleTracker = new BundleTracker<String> (bundleContext, Bundle.ACTIVE, null) { public String addingBundle(Bundle bundle, BundleEvent event) { // Méthode appelée lors de l'ajout au tracker d'un bundle satisfaisant l'état spécifié // Avantage : appelée à l'ouverture du tracker pour chaque bundle déjà installé // Retourne un objet associé au bundle tracké

[...] return "Objet tracké de type String"; } public void removedBundle(Bundle bundle, BundleEvent event, String o) { // Méthode appelée lors du retrait d'un des bundles trackés // Possibilité d'effectuer des traitements sur l'objet associé au bundle // Avantage : appelée à la fermeture du tracker pour chaque bundle tracké

} }; bundleTracker.open();

Zenika © 2011 11

Capabilities & Requirements Introduction

Jusqu’à présent le framework s’occupait de la résolution des bundles en faisant correspondre des packages importés avec des packages exportés

Depuis OSGi 4.3, généralisation des concepts de dépendances

Un bundle peut offrir un Capability personnalisable

Un bundle peut exprimer une dépendance vers au travers d’un Requirement

Prise en compte lors de la résolution d’un bundle

Permet de définir des dépendances qui ne sont pas des dépendances de code

Ex : nombre minimal de cœurs CPU

Zenika © 2011 12

Capabilities & Requirements Définition (1/2)

Capability

Un set d’attributs (couple clé/valeur) associé à un namespace

Requirement

Un filtre sur des attributs appartenant à un namespace

Namespace réservés

osgi.wiring.package Import-Package, DynamicImport-Package et Export-Package

osgi.wiring.bundle Require-Bundle, Bundle-SymbolicName et Bundle-Version

osgi.wiring.host Fragment-Host, Bundle-SymbolicName et Bundle-Version

Zenika © 2011 13

Capabilities & Requirements Définition (2/2)

Déclaration de le fichier MANIFEST

Capability

Requirement (filtre LDAP)

Déclaration de l’environnement d’exécution requis

Avant OSGi 4.3 (déprécié)

OSGi 4.3

Provide-Capability: com.zenika.formation; year:Long=2011; effective:=resolve

Require-Capability: com.zenika.formation; filter:="(year=2011)"

Bundle-RequiredExecutionEnvironment: JavaSE-1.6

Require-Capability: osgi.ee;filter:="(&(osgi.ee="JavaSE")(version>=1.6))"

Zenika © 2011 14

Core Services

Package Admin Service

Start Level Service

Conditionnal Permission Service

Bundle Wiring API

Start Level API

Service Hook Service

Resolver Hook Service

Weaving Hook Service

URL Handler Services

Remote Services

Zenika © 2011 15

Package Admin Service Rappel

Service permettant d'analyser et d'agir sur les dépendances

Zenika © 2011 16

Start Level Service Rappel

Service permettant de gérer la séquence d'activation des bundles

Zenika © 2011 17

Deprecated services

« Package Admin Service » et « Start Level Service » sont dépréciés

Utilisés par les outils d’administration de plateformes OSGi

Shells OSGi

Console de management web de Felix

Servers d’applications

Etc.

Zenika © 2011 18

Nouveaux services OSGi 4.3

Remplacement de « Package Admin Service » par « Bundle Wiring API » et de « Start Level Service » par « Start Level API »

A l'origine, choix d'une approche orientée service (dynamique) mais ce design n'était pas suffisamment orienté objet (passage de l'objet bundle à chaque méthode)

Nouvelle représentation des « Wiring » entre bundles en se basant sur l’introduction des concepts de « Capability » et « Requirement »

Zenika © 2011 19

Bundle Wiring API (1/4)

A chaque résolution de bundle, un objet de type BundleWiring est créé pour une révision donnée

A noter : chaque mise à jour d'un bundle déclenche la création d'une nouvelle révision. Seule une opération de « refresh » permet de forcer la rafraichissement des liaisons entre les bundles

Permet de récupérer les informations de dépendance

Nom symbolique, version, etc.

Packages requis / fournis, fragments, etc.

Représentation des liaisons au « runtime »

Zenika © 2011 20

Bundle Wiring API (2/4)

Zenika © 2011 21

Bundle Wiring API (3/4)

Exemple de récupération des packages importés

Namespaces osgi.wiring.bundle et osgi.wiring.host

BundleWiring bundleWiring = bundleContext.getBundle().adapt(BundleWiring.class); for (BundleWire wire : bundleWiring.getRequiredWires("osgi.wiring.package")) { String packageName = (String) wire.getCapability().getAttributes().get("osgi.wiring.package"); Bundle bundle = wire.getProviderWiring().getBundle(); [...] }

List<BundleCapability> capabilities = bundleWiring.getCapabilities(null); for (BundleCapability bundleCapability : capabilities) { System.out.println(bundleCapability.toString()); } // En sortie de la console osgi.wiring.bundle; osgi.wiring.bundle="zenika-bundle"; bundle-version:Version="1.0.0" osgi.wiring.host; osgi.wiring.host="zenika-bundle"; bundle-version:Version="1.0.0"

Zenika © 2011 22

Bundle Wiring API (4/4)

Collection<String> resources = bundleWiring.listResources("/", "*.properties", BundleWiring.LISTRESOURCES_RECURSE); Collection<URL> resources = bundleWiring.findEntries("/", "*.class", BundleWiring.FINDENTRIES_RECURSE);

Zenika © 2011 23

Start Level API

Manipulation des informations de « StartLevel »

Opérations à partir du « System Bundle »

BundleStartLevel bundleStartLevel = bundleContext.getBundle().adapt(BundleStartLevel.class); int startLevel = bundleStartLevel.getStartLevel();

FrameworkStartLevel frameworkStartLevel = bundleContext.getBundle(0).adapt(FrameworkStartLevel.class); int initialBundleStartLevel = frameworkStartLevel.getInitialBundleStartLevel();

Zenika © 2011 24

Service Hook Rappel (1/2)

Spécification permettant d'interagir avec le « service engine » : depuis OSGi 4.2

Connaître les services requis par les bundles

Limiter la visibilité de certains services

Mettre facilement en œuvre des proxies de services

Trois types d'interactions

Event Hook : intercepte les évènements liés au cycle de vie des services (enregistrement / désenregistrement / modification) Filtrer tout ou partie des évènements reçus par les bundles

Find Hook : intercepte la recherche de références de services Manipuler les références de services demandées

Listener Hook : intercepte la création et la suppression de ServiceListener Avoir la connaissance des services potentiellement utilisés par les bundles

Zenika © 2011 25

Service Hook Rappel (2/2)

public interface EventHook { // contexts : contextes vers lesquels les évènements sont propagés // (peuvent être modifiés) void event(ServiceEvent event, java.util.Collection contexts); }

public interface FindHook { // allServices : filtre sur getServiceReferences() // ou getAllServiceReferences() void find(BundleContext context, java.lang.String name, java.lang.String filter, boolean allServices, java.util.Collection references); }

public interface ListenerHook { void added(java.util.Collection listeners); void removed(java.util.Collection listeners); }

Zenika © 2011 26

Nouvelles interceptions (1/2)

Ajout de trois nouveaux mécanismes d'interception depuis la version 4.3

Weaving Hook

Permet d'intercepter le chargement de classe des bundles et de manipuler le bytecode avant chargement

Les nouvelles classes générées peuvent dépendre de nouvelles classes, d'où la possibilité de modifier au runtime l'attribut DynamicImport-Package du fichier MANIFEST

Resolver Hook

Permet d'intercepter le mécanisme de résolution de packages et d'influencer le resolver

Exemple : limiter la visibilité de certains packages

Zenika © 2011 27

Nouvelles interceptions (2/2)

Bundle Hook

Permet d'intercepter les évènements du framework à propos du cycle de vie des bundles (Event Hook)

Permet de limiter la visibilité de certains bundles (Find Hook)

Le trio «Service Hook », « Resolver Hook » et « Bundle Hook » offre un mécanisme efficace pour introspecter le framework et agir sur son comportement

Cas d'utilisation : isoler plusieurs applications s'exécutant sur le même framework

Alternative aux mécanismes de sécurité offerts par la plateforme

Zenika © 2011 28

Resolver Hook Service Mise en œuvre

Enregistrement d'un service de type ResolverHookFactory

A chaque tentative de résolution d'un bundle par le framework, création d'une instance de ResolverHook

Possibilité de filtrer la résolution d'un bundle ou la résolution de packages spécifiques

Zenika © 2011 29

Bundle Hook Service Mise en œuvre

Event Hook : intercepte les évènements liés au cycle de vie des bundles (install / start / update / …) avant de les émettre aux différents listeners

Filtrer les évènements reçus par les bundles

Find Hook : intercepte les appels aux méthodes de récupération des bundles présents sur la plateforme

Manipuler la liste de bundles retournées

Zenika © 2011 30

Virgo regions

Eclipse Virgo 3.0 s’appuie sur les mécanismes d’interception pour créer des régions isolées

Précédemment implémentées par les « nested framework » qui ont été abandonnés

Plan de contribution des régions dans Equinox

Zenika © 2011 32

Recommended