Tutorial OSGi

Service de correction orthographique

Cet example est similaire au code du client qui sait gérer les modifications dans les services dictionnaire, la différence est qu'au lieu d'être un client interactif, il propose lui même un service de correction qui recoit une phrase.

L'interface du service de correction est la suivante:

/*
* OSGi and Gravity Service Binder tutorial.
* Copyright (c) 2003 Richard S. Hall
* http://oscar-osgi.sourceforge.net
**/


package tutorial.example5.service;

/**
* A simple service interface that defines a spell check service.
* A spell check service checks the spelling of all words in a
* given passage. A passage is any number of words separated by
* a space character and the following punctuation marks: comma,
* period, exclamation mark, question mark, semi-colon, and colon.
**/

public interface SpellCheckService
{

/**
* Checks a given passage for spelling errors. A passage is any
* number of words separated by a space and any of the following
* punctuation marks: comma (,), period (.), exclamation mark (!),
* question mark (?), semi-colon (;), and colon(:).
* @param passage the passage to spell check.
* @return An array of misspelled words or null if no
* words are misspelled.
**/

public String[] check(String passage);
}

L'implémentation du service est la suivante:

/*
* OSGi and Gravity Service Binder tutorial.
* Copyright (c) 2003 Richard S. Hall
* http://oscar-osgi.sourceforge.net
**/


package tutorial.example5;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.StringTokenizer;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceEvent;

import tutorial.example2.service.DictionaryService;
import tutorial.example5.service.SpellCheckService;

/**
* This class implements a bundle that implements a spell
* check service. The spell check service uses all available
* dictionary services to check for the existence of words in
* a given sentence. This bundle not only monitors the dynamic
* availability of dictionary services, but it manages the
* aggregation of all available dictionary services as they
* arrive and depart. The spell check service is only registered
* if there are dictionary services available, thus the spell
* check service will appear and disappear as dictionary
* services appear and disappear, respectively.
**/

public class Activator implements BundleActivator, ServiceListener
{

// Bundle's context.

private BundleContext m_context = null;

// List of available dictionary service references.

private ArrayList m_refList = new ArrayList();

// Maps service references to service objects.

private HashMap m_refToObjMap = new HashMap();

// The spell check service registration.

private ServiceRegistration m_reg = null;

/**
* Implements BundleActivator.start(). Adds itself
* as a service listener and queries for all currently
* available dictionary services. Any available dictionary
* services are added to the service reference list. If
* dictionary services are found, then the spell check
* service is registered.
* @param context the framework context for the bundle.
**/

public void start(BundleContext context) throws Exception
{
m_context = context;

// Listen for events pertaining to dictionary services.

m_context.addServiceListener(this,
"(&(objectClass=" + DictionaryService.class.getName() + ")" +
"(Language=*))");

// Query for all dictionary services.

ServiceReference[] refs = m_context.getServiceReferences(
DictionaryService.class.getName(), "(Language=*)");

// Add any dictionaries to the service reference list.

if (refs != null)
{

// Lock the list.

synchronized (m_refList)
{
for (int i = 0; i < refs.length; i++)
{

// Get the service object.

Object service = m_context.getService(refs[i]);

// Make that the service is not being duplicated.

if ((service != null) &&
(m_refToObjMap.get(refs[i]) == null))
{

// Add to the reference list.

m_refList.add(refs[i]);

// Map reference to service object for easy look up.

m_refToObjMap.put(refs[i], service);
}
}

// Register spell check service if there are any
// dictionary services.

if (m_refList.size() > 0)
{
m_reg = m_context.registerService(
SpellCheckService.class.getName(),
new SpellCheckServiceImpl(), null);
}
}
}
}

/**
* Implements BundleActivator.stop(). Does nothing since
* the framework will automatically unregister any registered services,
* release any used services, and remove any event listeners.
* @param context the framework context for the bundle.
**/

public void stop(BundleContext context)
{

// NOTE: The services automatically released.

}

/**
* Implements ServiceListener.serviceChanged(). Monitors
* the arrival and departure of dictionary services, adding and
* removing them from the service reference list, respectively.
* In the case where no more dictionary services are available,
* the spell check service is registered. As soon as any dictionary
* spell check becomes available, the spell check service is
* reregistered.
* @param event the fired service event.
**/

public void serviceChanged(ServiceEvent event)
{
String[] objectClass =
(String[]) event.getServiceReference().getProperty("objectClass");

// Add the new dictionary service to the service list.

if (event.getType() == ServiceEvent.REGISTERED)
{
synchronized (m_refList)
{

// Get the service object.

Object service = m_context.getService(event.getServiceReference());

// Make that the service is not being duplicated.

if ((service != null) &&
(m_refToObjMap.get(event.getServiceReference()) == null))
{

// Add to the reference list.

m_refList.add(event.getServiceReference());

// Map reference to service object for easy look up.

m_refToObjMap.put(event.getServiceReference(), service);

// Register spell check service if necessary.

if (m_reg == null)
{
m_reg = m_context.registerService(
SpellCheckService.class.getName(),
new SpellCheckServiceImpl(), null);
}
}
else if (service != null)
{
m_context.ungetService(event.getServiceReference());
}
}
}

// Remove the departing service from the service list.

else if (event.getType() == ServiceEvent.UNREGISTERING)
{
synchronized (m_refList)
{

// Make sure the service is in the list.

if (m_refToObjMap.get(event.getServiceReference()) != null)
{

// Unget the service object.

m_context.ungetService(event.getServiceReference());

// Remove service reference.

m_refList.remove(event.getServiceReference());

// Remove service reference from map.

m_refToObjMap.remove(event.getServiceReference());

// If there are no more dictionary services,
// then unregister spell check service.

if (m_refList.size() == 0)
{
m_reg.unregister();
m_reg = null;
}
}
}
}
}

/**
* A private inner class that implements a spell check service;
* see SpellCheckService for details of the service.
**/

private class SpellCheckServiceImpl implements SpellCheckService
{

/**
* Implements SpellCheckService.check(). Checks the
* given passage for misspelled words.
* @param passage the passage to spell check.
* @return An array of misspelled words or null if no
* words are misspelled.
**/

public String[] check(String passage)
{

// No misspelled words for an empty string.

if ((passage == null) || (passage.length() == 0))
{
return null;
}

ArrayList errorList = new ArrayList();

// Tokenize the passage using spaces and punctionation.

StringTokenizer st = new StringTokenizer(passage, " ,.!?;:");

// Lock the service list.

synchronized (m_refList)
{

// Loop through each word in the passage.

while (st.hasMoreTokens())
{
String word = st.nextToken();

boolean correct = false;

// Check each available dictionary for the current word.

for (int i = 0; (!correct) && (i < m_refList.size()); i++)
{
DictionaryService dictionary =
(DictionaryService) m_refToObjMap.get(m_refList.get(i));

if (dictionary.checkWord(word))
{
correct = true;
}
}

// If the word is not correct, then add it
// to the incorrect word list.

if (!correct)
{
errorList.add(word);
}
}
}

// Return null if no words are incorrect.

if (errorList.size() == 0)
{
return null;
}

// Return the array of incorrect words.

return (String[]) errorList.toArray(new String[errorList.size()]);
}
}
}

Le composant qui implémente le service de correction orthographique vérifie lors de son activation qu'il y ait des services dictionnaire présents, si ceci est vrai il peut alors enregistrer son propre service. Si les services dictionnaire sont enlevés il doit lui même desenregistrer son service. Noter qu'il faut introduire des blocks synchronises pour éviter des conditions de concurrence (race condition).

Le manifeste pour ce bundle est le suivant:

Bundle-Activator: tutorial.example5.Activator
Import-Package: tutorial.example2.service
Import-Service: tutorial.example2.service.DictionaryService
Export-Package: tutorial.example5.service
Export-Service: tutorial.example5.service.SpellCheckService
Bundle-Name: Spell check service
Bundle-Description: A bundle that implements a simple spell check service
Bundle-Vendor: Richard Hall
Bundle-Version: 1.0.0

Voici un lien au fichier build_example5.xml. Nous devons maintenant tester notre nouveau service, pour cela un client très similaire à celui qui a été développé antérieurement suffit. Voici le client pour tester ce service: Activator.java,manifest.mf et build_example6.xml.

-> ps

[  0] [Active     ] System Bundle
[  1] [Active     ] Oscar Shell Service
[  2] [Active     ] Shell TUI
[  3] [Active     ] Oscar Bundle Repository
[  5] [Active     ] Service listener example
[  6] [Active     ] English dictionary
[  7] [Active     ] French dictionary
[  8] [Installed  ] Dictionary client
[  9] [Resolved   ] servicebinder.jar
[ 10] [Resolved   ] Table Layout
[ 11] [Installed  ] Gravity
[ 12] [Active     ] Shell Components
[ 13] [Active     ] Shell GUI
[ 14] [Installed  ] Dictionary client
[ 15] [Active     ] Spell check service
[ 16] [Installed  ] Spell check client

-> start 16

Enter a blank line to exit.

Enter passage: hello to the osgi tutorial
Incorrect word(s):
    hello
Enter passage: welcome to the tutorial
Passage is correct.
Enter passage:

->
>

A Faire: Tester avec l'interface graphique des changements au niveau des services.

Cet exemple illustre la complexité de la gestion des dépendances dans OSGi. L'exemple prochain montrera le même service mais implémenté à l'aide du service binder, un outil permetant de gérer les dépendances entre services de façon automatique.

Retour au sommaire


Last update: 22 February 2003
contact: Humberto.Cervantes@imag.fr
Homepage