felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fmesc...@apache.org
Subject svn commit: r1421893 [20/24] - in /felix/site/trunk/content: ./ documentation/ documentation/community/ documentation/development/ documentation/faqs/ documentation/subprojects/ documentation/subprojects/apache-felix-commons/ documentation/subprojects/...
Date Fri, 14 Dec 2012 14:30:22 GMT
Added: felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-2b.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-2b.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-2b.mdtext (added)
+++ felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-2b.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,129 @@
+Title: Apache Felix Tutorial Example 2b
+
+## Example 2b - Alternate Dictionary Service Bundle
+
+This example creates an alternative implementation of the dictionary service defined in Example 2. The source code for the bundle is identical except that instead of using English words, French words are used. The only other difference is that in this bundle we do not need to define the dictionary service interface again, since we can just import the definition from the bundle in Example 2. The main point of this example is to illustrate that multiple implementations of the same service may exist; this example will also be of use to us in Example 5.
+
+In the following source code, the bundle uses its bundle context to register the dictionary service. We implement the dictionary service as an inner class of the bundle activator class, but we could have also put it in a separate file. The source code for our bundle is as follows in a file called `Activator.java`:
+
+
+    /*
+     * Apache Felix OSGi tutorial.
+    **/
+    
+    package tutorial.example2b;
+    
+    import java.util.Hashtable;
+    
+    import org.osgi.framework.BundleActivator;
+    import org.osgi.framework.BundleContext;
+    import org.osgi.framework.ServiceListener;
+    import org.osgi.framework.ServiceEvent;
+    
+    import tutorial.example2.service.DictionaryService;
+    
+    /**
+     * This class implements a simple bundle that uses the bundle
+     * context to register an French language dictionary service
+     * with the OSGi framework. The dictionary service interface is
+     * defined in a separate class file and is implemented by an
+     * inner class. This class is identical to the class in
+     * Example 2, except that the dictionary contains French words.
+    **/
+    public class Activator implements BundleActivator
+    {
+        /**
+         * Implements BundleActivator.start(). Registers an
+         * instance of a dictionary service using the bundle context;
+         * attaches properties to the service that can be queried
+         * when performing a service look-up.
+         * @param context the framework context for the bundle.
+        **/
+        public void start(BundleContext context)
+        {
+            Hashtable<String, String> props = new Hashtable<String, String>();
+            props.put("Language", "French");
+            context.registerService(
+                DictionaryService.class.getName(), new DictionaryImpl(), props);
+        }
+    
+        /**
+         * Implements BundleActivator.stop(). Does nothing since
+         * the framework will automatically unregister any registered services.
+         * @param context the framework context for the bundle.
+        **/
+        public void stop(BundleContext context)
+        {
+            // NOTE: The service is automatically unregistered.
+        }
+    
+        /**
+         * A private inner class that implements a dictionary service;
+         * see DictionaryService for details of the service.
+        **/
+        private static class DictionaryImpl implements DictionaryService
+        {
+            // The set of words contained in the dictionary.
+            String[] m_dictionary =
+                { "bienvenue", "au", "tutoriel", "osgi" };
+    
+            /**
+             * Implements DictionaryService.checkWord(). Determines
+             * if the passed in word is contained in the dictionary.
+             * @param word the word to be checked.
+             * @return true if the word is in the dictionary,
+             *         false otherwise.
+            **/
+            public boolean checkWord(String word)
+            {
+                word = word.toLowerCase();
+    
+                // This is very inefficient
+                for (int i = 0; i < m_dictionary.length; i++)
+                {
+                    if (m_dictionary[i].equals(word))
+                    {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        }
+    }
+
+
+We must create a manifest.mf file that contains the metadata for our bundle; the manifest file contains the following:
+
+
+    Bundle-Name: French dictionary
+    Bundle-Description: A bundle that registers a French dictionary service
+    Bundle-Vendor: Apache Felix
+    Bundle-Version: 1.0.0
+    Bundle-Activator: tutorial.example2b.Activator
+    Import-Package: org.osgi.framework,
+     tutorial.example2.service
+
+
+We specify which class implements the `Bundle-Activator` interface and also specify that our bundle imports the OSGi core package and the dictionary service interface package using the `Import-Package` attribute. Th dictionary service package will be fulfilled by the bundle in Example 2, which exports this package. (Note: Make sure your manifest file ends in a trailing carriage return or else the last line will be ignored.)
+
+To compile our source code, we need the `felix.jar` file (found in Felix' `bin` directory) and the `example2.jar` file in our class path. We compile the source file using a command like:
+
+
+    javac -d c:\classes *.java
+
+
+This command compiles all source files and outputs the generated classes into a subdirectory of the `c:\classes` directory; this subdirectory is `tutorial\example2b`, named after the package we specified in the source file. For the above command to work, the `c:\classes` directory must exist. After compiling, we need to create a JAR file containing the generated package directories. We will also add our manifest file that contains the bundle's meta-data to the JAR file. To create the JAR file, we issue the command:
+
+
+    jar cfm example2b.jar manifest.mf -C c:\classes tutorial\example2b
+
+
+This command creates a JAR file using the manifest file we created and includes all of the classes in the `tutorial\example2b` directory inside of the c:\classes directory. Once the JAR file is created, we are ready to install and start the bundle.
+
+To run Felix, we follow the instructions described in usage.html. When we start Felix, it asks for a profile name, we will put all of our bundles in a profile named `tutorial`. After running Felix, we should make sure that the bundle from Example 1 is active. We can use the Felix `lb` shell command to get a list of all bundles, their state, and their bundle identifier number. If the Example 1 bundle is not active, we should start the bundle using the `start` command and the bundle's identifier number that is displayed by the `lb` command. Now we can install and start our dictionary service bundle. Assuming that we created our bundle in the directory c:\tutorial, we can install and start it in Felix' shell using the following command:
+
+
+    start file:/c:/tutorial/example2b.jar
+
+
+The above command installs and starts the bundle in a single step; it is also possible to install and start the bundle in two steps by using the Felix `install` and `start` shell commands. To stop the bundle, use the Felix `stop` shell command. If the bundle from Example 1 is still active, then we should see it print out the details of the service event it receives when our new bundle registers its dictionary service. Using the Felix shell `lb` command to get the bundle identifier number for our dictionary service bundle and we can stop and restart it at will using the `stop` and `start` commands, respectively. Each time we start and stop our dictionary service bundle, we should see the details of the associated service event printed from the bundle from Example 1. In Example 3, we will create a client for our dictionary service. To exit Felix, we use the `shutdown` command.
\ No newline at end of file

Added: felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-3.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-3.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-3.mdtext (added)
+++ felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-3.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,149 @@
+Title: Apache Felix Tutorial Example 3
+
+Example 3 - Dictionary Client Bundle
+
+This example creates a bundle that is a client of the dictionary service implemented in Example 2. In the following source code, our bundle uses its bundle context to query for a dictionary service. Our client bundle uses the first dictionary service it finds and if none are found it simply prints a message saying so and stops. Using an OSGi service is the same as using any Java interface, we simply need to cast it to the known dictionary service interface. The source code for our bundle is as follows in a file called `Activator.java`:
+
+
+    /*
+     * Apache Felix OSGi tutorial.
+    **/
+    
+    package tutorial.example3;
+    
+    import java.io.BufferedReader;
+    import java.io.InputStreamReader;
+    import java.io.IOException;
+    
+    import org.osgi.framework.BundleActivator;
+    import org.osgi.framework.BundleContext;
+    import org.osgi.framework.ServiceReference;
+    
+    import tutorial.example2.service.DictionaryService;
+    
+    /**
+     * This class implements a bundle that uses a dictionary
+     * service to check for the proper spelling of a word by
+     * check for its existence in the dictionary. This bundle
+     * uses the first service that it finds and does not monitor
+     * the dynamic availability of the service (i.e., it does not
+     * listen for the arrival or departure of dictionary services).
+     * When starting this bundle, the thread calling the start()
+     * method is used to read words from standard input. You can
+     * stop checking words by entering an empty line, but to start
+     * checking words again you must stop and then restart the bundle.
+    **/
+    public class Activator implements BundleActivator
+    {
+        /**
+         * Implements BundleActivator.start(). Queries for
+         * all available dictionary services. If none are found it
+         * simply prints a message and returns, otherwise it reads
+         * words from standard input and checks for their existence
+         * from the first dictionary that it finds.
+         * (NOTE: It is very bad practice to use the calling thread
+         * to perform a lengthy process like this; this is only done
+         * for the purpose of the tutorial.)
+         * @param context the framework context for the bundle.
+        **/
+        public void start(BundleContext context) throws Exception
+        {
+            // Query for all service references matching any language.
+            ServiceReference[] refs = context.getServiceReferences(
+                DictionaryService.class.getName(), "(Language=*)");
+    
+            if (refs != null)
+            {
+                try
+                {
+                    System.out.println("Enter a blank line to exit.");
+                    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+                    String word = "";
+    
+                    // Loop endlessly.
+                    while (true)
+                    {
+                        // Ask the user to enter a word.
+                        System.out.print("Enter word: ");
+                        word = in.readLine();
+    
+                        // If the user entered a blank line, then
+                        // exit the loop.
+                        if (word.length() == 0)
+                        {
+                            break;
+                        }
+    
+                        // First, get a dictionary service and then check
+                        // if the word is correct.
+                        DictionaryService dictionary =
+                            (DictionaryService) context.getService(refs[0]);
+                        if (dictionary.checkWord(word))
+                        {
+                            System.out.println("Correct.");
+                        }
+                        else
+                        {
+                            System.out.println("Incorrect.");
+                        }
+    
+                        // Unget the dictionary service.
+                        context.ungetService(refs[0]);
+                    }
+                } catch (IOException ex) { }
+            }
+            else
+            {
+                System.out.println("Couldn't find any dictionary service...");
+            }
+        }
+    
+        /**
+         * Implements BundleActivator.stop(). Does nothing since
+         * the framework will automatically unget any used services.
+         * @param context the framework context for the bundle.
+        **/
+        public void stop(BundleContext context)
+        {
+            // NOTE: The service is automatically released.
+        }
+    }
+
+
+Note that we do not need to unget or release the service in the `stop()` method, because the OSGi framework will automatically do so for us. We must create a `manifest.mf` file that contains the meta-data for our bundle; the manifest file contains the following:
+
+
+    Bundle-Name: Dictionary client
+    Bundle-Description: A bundle that uses the dictionary service if it finds it at startup
+    Bundle-Vendor: Apache Felix
+    Bundle-Version: 1.0.0
+    Bundle-Activator: tutorial.example3.Activator
+    Import-Package: org.osgi.framework,
+     tutorial.example2.service
+
+
+We specify the bundle's activator class via the `Bundle-Activator` attribute and also specify that our class imports the OSGi core framework package and the dictionary service interface package via the `Import-Package` attribute. The dictionary service interface package will be fulfilled by the bundle in Example 2, which exports this package. The OSGi framework will automatically handle the details of resolving import packages. (Note: Make sure your manifest file ends in a trailing carriage return or else the last line will be ignored.)
+
+To compile our source code, we need to have the `felix.jar` file (found in Felix' `bin` directory) and the `example2.jar` file in our class path. We compile the source file using a command like:
+
+
+    javac -d c:\classes *.java
+
+
+This command compiles all source files and outputs the generated classes into a subdirectory of the `c:\classes` directory; this subdirectory is `tutorial\example3`, named after the package we specified in the source file. For the above command to work, the `c:\classes` directory must exist. After compiling, we need to create a JAR file containing the generated package directories. We will also add our manifest file that contains the bundle's meta-data to the JAR file. To create the JAR file, we issue the command:
+
+
+    jar cfm example3.jar manifest.mf -C c:\classes tutorial\example3
+
+
+This command creates a JAR file using the manifest file we created and includes all of the classes in the `tutorial\example3` directory inside of the `c:\classes` directory. Once the JAR file is created, we are ready to install and start the bundle.
+
+To run Felix, we follow the instructions described in usage.html. When we start Felix, it asks for a profile name, we will put all of our bundles in a profile named `tutorial`. After running Felix, we should check that all tutorial bundles are stopped, except for the English dictionary service bundle from Example 2. We can use the Felix `lb` shell command to get a list of all bundles, their state, and their bundle identifier number. If the Example 2 bundle is not active, we should start the bundle using the `start` command along with the bundle's identifier number displayed by the `lb` command and `stop` any other unneeded tutorial bundles using the `stop` command. (Note: Felix uses some bundles to provide its command shell, so do not stop these bundles.) Now we can install and start our dictionary client bundle. Assuming that we created our bundle in the directory `c:\tutorial`, we can install and start it in Felix' shell using the following command:
+
+
+    start file:/c:/tutorial/example3.jar
+
+
+The above command installs and starts the bundle in a single step; it is also possible to install and start the bundle in two steps by using the Felix `install` and start shell commands. When we start the bundle, it will use the shell thread to prompt us for words. Enter one word at a time to check the words and enter a blank line to stop checking words. To restart the bundle, we must use the Felix shell `lb` command to get the bundle identifier number for the bundle and first use the `stop` command to stop the bundle, then the `start` command to restart it. To test the dictionary service, enter any of the words in the dictionary (e.g., "welcome", "to", "the", "OSGi", "tutorial") or any word not in the dictionary.
+
+This example client is simple enough and, in fact, is too simple. What would happen if the dictionary service were to unregister suddenly? Our client would throw a null pointer exception when it tried to access the service object. This dynamic service availability issue is a central tenent of the OSGi service model. As a result, we must make our client more robust in dealing with such situations. In Example 4, we explore a slightly more complicated dictionary client that dynamically monitors service availability.
\ No newline at end of file

Added: felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-4.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-4.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-4.mdtext (added)
+++ felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-4.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,242 @@
+Title: Apache Felix Tutorial Example 4
+
+## Example 4 - Robust Dictionary Client Bundle
+
+In Example 3, we create a simple client bundle for our dictionary service. The problem with that client was that it did not monitor the dynamic availability of the dictionary service, thus an error would occur if the dictionary service disappeared while the client was using it. In this example we create a client for the dictionary service that monitors the dynamic availability of the dictionary service. The result is a more robust client.
+
+The functionality of the new dictionary client is essentially the same as the old client, it reads words from standard input and checks for their existence in the dictionary service. Our bundle uses its bundle context to register itself as a service event listener; monitoring service events allows the bundle to monitor the dynamic availability of the dictionary service. Our client uses the first dictionary service it finds. The source code for our bundle is as follows in a file called `Activator.java`:
+
+
+    /*
+     * Apache Felix OSGi tutorial.
+    **/
+    
+    package tutorial.example4;
+    
+    import java.io.BufferedReader;
+    import java.io.InputStreamReader;
+    import java.io.IOException;
+    
+    import org.osgi.framework.BundleActivator;
+    import org.osgi.framework.BundleContext;
+    import org.osgi.framework.InvalidSyntaxException;
+    import org.osgi.framework.ServiceReference;
+    import org.osgi.framework.ServiceListener;
+    import org.osgi.framework.ServiceEvent;
+    
+    import tutorial.example2.service.DictionaryService;
+    
+    /**
+     * This class implements a bundle that uses a dictionary
+     * service to check for the proper spelling of a word by
+     * checking for its existence in the dictionary. This bundle
+     * is more complex than the bundle in Example 3 because it
+     * monitors the dynamic availability of the dictionary
+     * services. In other words, if the service it is using
+     * departs, then it stops using it gracefully, or if it needs
+     * a service and one arrives, then it starts using it
+     * automatically. As before, the bundle uses the first service
+     * that it finds and uses the calling thread of the
+     * start() method to read words from standard input.
+     * You can stop checking words by entering an empty line, but
+     * to start checking words again you must stop and then restart
+     * the bundle.
+    **/
+    public class Activator implements BundleActivator, ServiceListener
+    {
+        // Bundle's context.
+        private BundleContext m_context = null;
+        // The service reference being used.
+        private ServiceReference m_ref = null;
+        // The service object being used.
+        private DictionaryService m_dictionary = null;
+    
+        /**
+         * Implements BundleActivator.start(). Adds itself
+         * as a listener for service events, then queries for 
+         * available dictionary services. If any dictionaries are
+         * found it gets a reference to the first one available and
+         * then starts its "word checking loop". If no dictionaries
+         * are found, then it just goes directly into its "word checking
+         * loop", but it will not be able to check any words until a
+         * dictionary service arrives; any arriving dictionary service
+         * will be automatically used by the client if a dictionary is
+         * not already in use. Once it has dictionary, it reads words
+         * from standard input and checks for their existence in the
+         * dictionary that it is using.
+         * (NOTE: It is very bad practice to use the calling thread
+         * to perform a lengthy process like this; this is only done
+         * for the purpose of the tutorial.)
+         * @param context the framework context for the bundle.
+        **/
+        public void start(BundleContext context) throws Exception
+        {
+            m_context = context;
+    
+            // We synchronize while registering the service listener and
+            // performing our initial dictionary service lookup since we
+            // don't want to receive service events when looking up the
+            // dictionary service, if one exists.
+            synchronized (this)
+            {
+                // Listen for events pertaining to dictionary services.
+                m_context.addServiceListener(this,
+                    "(&(objectClass=" + DictionaryService.class.getName() + ")" +
+                    "(Language=*))");
+    
+                // Query for any service references matching any language.
+                ServiceReference[] refs = m_context.getServiceReferences(
+                    DictionaryService.class.getName(), "(Language=*)");
+    
+                // If we found any dictionary services, then just get
+                // a reference to the first one so we can use it.
+                if (refs != null)
+                {
+                    m_ref = refs[0];
+                    m_dictionary = (DictionaryService) m_context.getService(m_ref);
+                }
+            }
+    
+            try
+            {
+                System.out.println("Enter a blank line to exit.");
+                String word = "";
+                BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+    
+                // Loop endlessly.
+                while (true)
+                {
+                    // Ask the user to enter a word.
+                    System.out.print("Enter word: ");
+                    word = in.readLine();
+    
+                    // If the user entered a blank line, then
+                    // exit the loop.
+                    if (word.length() == 0)
+                    {
+                        break;
+                    }
+                    // If there is no dictionary, then say so.
+                    else if (m_dictionary == null)
+                    {
+                        System.out.println("No dictionary available.");
+                    }
+                    // Otherwise print whether the word is correct or not.
+                    else if (m_dictionary.checkWord(word))
+                    {
+                        System.out.println("Correct.");
+                    }
+                    else
+                    {
+                        System.out.println("Incorrect.");
+                    }
+                }
+            } catch (Exception ex) { }
+        }
+    
+        /**
+         * Implements BundleActivator.stop(). Does nothing since
+         * the framework will automatically unget any used services.
+         * @param context the framework context for the bundle.
+        **/
+        public void stop(BundleContext context)
+        {
+            // NOTE: The service is automatically released.
+        }
+    
+        /**
+         * Implements ServiceListener.serviceChanged(). Checks
+         * to see if the service we are using is leaving or tries to get
+         * a service if we need one.
+         * @param event the fired service event.
+        **/
+        public synchronized void serviceChanged(ServiceEvent event)
+        {
+            String[] objectClass =
+                (String[]) event.getServiceReference().getProperty("objectClass");
+    
+            // If a dictionary service was registered, see if we
+            // need one. If so, get a reference to it.
+            if (event.getType() == ServiceEvent.REGISTERED)
+            {
+                if (m_ref == null)
+                {
+                    // Get a reference to the service object.
+                    m_ref = event.getServiceReference();
+                    m_dictionary = (DictionaryService) m_context.getService(m_ref);
+                }
+            }
+            // If a dictionary service was unregistered, see if it
+            // was the one we were using. If so, unget the service
+            // and try to query to get another one.
+            else if (event.getType() == ServiceEvent.UNREGISTERING)
+            {
+                if (event.getServiceReference() == m_ref)
+                {
+                    // Unget service object and null references.
+                    m_context.ungetService(m_ref);
+                    m_ref = null;
+                    m_dictionary = null;
+    
+                    // Query to see if we can get another service.
+                    ServiceReference[] refs = null;
+                    try
+                    {
+                        refs = m_context.getServiceReferences(
+                            DictionaryService.class.getName(), "(Language=*)");
+                    }
+                    catch (InvalidSyntaxException ex)
+                    {
+                        // This will never happen.
+                    }
+                    if (refs != null)
+                    {
+                        // Get a reference to the first service object.
+                        m_ref = refs[0];
+                        m_dictionary = (DictionaryService) m_context.getService(m_ref);
+                    }
+                }
+            }
+        }
+    }
+
+
+The client listens for service events indicating the arrival or departure of dictionary services. If a new dictionary service arrives, the bundle will start using that service if and only if it currently does not have a dictionary service. If an existing dictionary service disappears, the bundle will check to see if the disappearing service is the one it is using; if it is it stops using it and tries to query for another dictionary service, otherwise it ignores the event.
+
+Like normal, we must create a `manifest.mf` file that contains the meta-data for our bundle:
+
+
+    Bundle-Name: Dynamic dictionary client
+    Bundle-Description: A bundle that uses the dictionary service whenever it becomes available
+    Bundle-Vendor: Apache Felix
+    Bundle-Version: 1.0.0
+    Bundle-Activator: tutorial.example4.Activator
+    Import-Package: org.osgi.framework,
+     tutorial.example2.service
+
+
+We specify the class to activate our bundle via the `Bundle-Activator` attribute and also specify that our bundle imports the core OSGi framework package and the dictionary service interface package using the `Import-Package` attribute. The OSGi framework will automatically handle the details of resolving import packages. (Note: Make sure your manifest file ends in a trailing carriage return or else the last line will be ignored.)
+
+To compile our source code, we need to have the `felix.jar` file (found in Felix' `bin` directory) and the `example2.jar` file in our class path. We compile the source file using a command like:
+
+
+    javac -d c:\classes *.java
+
+
+This command compiles all source files and outputs the generated classes into a subdirectory of the `c:\classes` directory; this subdirectory is `tutorial\example4`, named after the package we specified in the source file. For the above command to work, the `c:\classes` directory must exist. After compiling, we need to create a JAR file containing the generated package directories. We will also add our manifest file that contains the bundle's meta-data to the JAR file. To create the JAR file, we issue the command:
+
+
+    jar cfm example4.jar manifest.mf -C c:\classes tutorial\example4
+
+
+This command creates a JAR file using the manifest file we created and includes all of the classes in the `tutorial\example4` directory inside of the `c:\classes` directory. Once the JAR file is created, we are ready to install and start the bundle.
+
+To run Felix, we follow the instructions described in usage.html. When we start Felix, it asks for a profile name, we will put all of our bundles in a profile named `tutorial`. After running Felix, we should check that all tutorial bundles are stopped, except for the English dictionary service bundle from Example 2. We can use the Felix `lb` shell command to get a list of all bundles, their state, and their bundle identifier number. If the Example 2 bundle is not active, we should start the bundle using the `start` command along with the bundle's identifier number displayed by the `lb` command and stop any other unneeded tutorial bundles using the stop command. (Note: Felix uses some bundles to provide its command shell, so do not stop these bundles.) Now we can install and start our dictionary client bundle. Assuming that we created our bundle in the directory `c:\tutorial`, we can install and start it in Felix' shell using the following command:
+
+
+    start file:/c:/tutorial/example4.jar
+
+
+The above command installs and starts the bundle in a single step; it is also possible to install and start the bundle in two steps by using the Felix `install` and `start` shell commands. When we start the bundle, it will use the shell thread to prompt us for words. Enter one word at a time to check the words and enter a blank line to stop checking words. To restart the bundle, we must use the Felix shell `lb` command to get the bundle identifier number for the bundle and first use the `stop` command to stop the bundle, then the `start` command to restart it. To test the dictionary service, enter any of the words in the dictionary (e.g., "welcome", "to", "the", "OSGi", "tutorial") or any word not in the dictionary.
+
+Since this client monitors the dynamic availability of the dictionary service, it is robust in the face of sudden departures of the the dictionary service. Further, when a dictionary service arrives, it automatically gets the service if it needs it and continues to function. These capabilities are a little difficult to demonstrate since we are using a simple single-threaded approach, but in a multi-threaded or GUI-oriented application this robustness is very useful.
\ No newline at end of file

Added: felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-5.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-5.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-5.mdtext (added)
+++ felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-5.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,163 @@
+Title: Apache Felix Tutorial Example 5
+
+## Example 5 - Service Tracker Dictionary Client Bundle
+
+In Example 4, we created a more robust client bundle for our dictionary service. Due to the complexity of dealing with dynamic service availability, even that client may not sufficiently address all situations. To deal with this complexity the OSGi Alliance defined the `ServiceTracker` utility class back in 2001. In this example we create a client for the dictionary service that uses the `ServiceTracker` class to monitor the dynamic availability of the dictionary service, resulting in an even more robust client.
+
+The functionality of the new dictionary client is essentially the same as the one from Example 4. Our bundle uses its bundle context to create a `ServiceTracker` instance to track the dynamic availability of the dictionary service on our behalf. Our client uses the dictionary service return by the `ServiceTracker`, which is selected based on a ranking algorithm defined by the OSGi specification. The source code for our bundle is as follows in a file called `Activator.java`:
+
+
+    /*
+     * Apache Felix OSGi tutorial.
+    **/
+    
+    package tutorial.example5;
+    
+    import java.io.BufferedReader;
+    import java.io.InputStreamReader;
+    import java.io.IOException;
+    
+    import org.osgi.framework.BundleActivator;
+    import org.osgi.framework.BundleContext;
+    import org.osgi.util.tracker.ServiceTracker;
+    
+    import tutorial.example2.service.DictionaryService;
+    
+    /**
+     * This class implements a bundle that uses a dictionary
+     * service to check for the proper spelling of a word by
+     * checking for its existence in the dictionary. This bundle
+     * is more complex than the bundle in Example 3 because it
+     * monitors the dynamic availability of the dictionary
+     * services. In other words, if the service it is using
+     * departs, then it stops using it gracefully, or if it needs
+     * a service and one arrives, then it starts using it
+     * automatically. As before, the bundle uses the first service
+     * that it finds and uses the calling thread of the
+     * start() method to read words from standard input.
+     * You can stop checking words by entering an empty line, but
+     * to start checking words again you must stop and then restart
+     * the bundle.
+    **/
+    public class Activator implements BundleActivator
+    {
+        // Bundle's context.
+        private BundleContext m_context = null;
+        // The service tacker object.
+        private ServiceTracker m_tracker = null;
+    
+        /**
+         * Implements BundleActivator.start(). Crates a service
+         * tracker to monitor dictionary services and starts its "word
+         * checking loop". It will not be able to check any words until
+         * the service tracker find a dictionary service; any discovered
+         * dictionary service will be automatically used by the client.
+         * It reads words from standard input and checks for their
+         * existence in the discovered dictionary.
+         * (NOTE: It is very bad practice to use the calling thread
+         * to perform a lengthy process like this; this is only done
+         * for the purpose of the tutorial.)
+         * @param context the framework context for the bundle.
+        **/
+        public void start(BundleContext context) throws Exception
+        {
+            m_context = context;
+    
+            // Create a service tracker to monitor dictionary services.
+            m_tracker = new ServiceTracker(
+                m_context,
+                m_context.createFilter(
+                    "(&(objectClass=" + DictionaryService.class.getName() + ")" +
+                    "(Language=*))"),
+                null);
+            m_tracker.open();
+    
+            try
+            {
+                System.out.println("Enter a blank line to exit.");
+                String word = "";
+                BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+    
+                // Loop endlessly.
+                while (true)
+                {
+                    // Ask the user to enter a word.
+                    System.out.print("Enter word: ");
+                    word = in.readLine();
+    
+                    // Get the selected dictionary service, if available.
+                    DictionaryService dictionary = (DictionaryService) m_tracker.getService();
+    
+                    // If the user entered a blank line, then
+                    // exit the loop.
+                    if (word.length() == 0)
+                    {
+                        break;
+                    }
+                    // If there is no dictionary, then say so.
+                    else if (dictionary == null)
+                    {
+                        System.out.println("No dictionary available.");
+                    }
+                    // Otherwise print whether the word is correct or not.
+                    else if (dictionary.checkWord(word))
+                    {
+                        System.out.println("Correct.");
+                    }
+                    else
+                    {
+                        System.out.println("Incorrect.");
+                    }
+                }
+            } catch (Exception ex) { }
+        }
+    
+        /**
+         * Implements BundleActivator.stop(). Does nothing since
+         * the framework will automatically unget any used services.
+         * @param context the framework context for the bundle.
+        **/
+        public void stop(BundleContext context)
+        {
+        }
+    }
+
+
+Since this client uses the `ServiceTracker` utility class, it will automatically monitor the dynamic availability of the dictionary service. Like normal, we must create a `manifest.mf` file that contains the meta-data for our bundle:
+
+
+    Bundle-Name: Service Tracker-based dictionary client
+    Bundle-Description: A dictionary client using the Service Tracker.
+    Bundle-Vendor: Apache Felix
+    Bundle-Version: 1.0.0
+    Bundle-Activator: tutorial.example5.Activator
+    Import-Package: org.osgi.framework,
+     org.osgi.util.tracker,
+     tutorial.example2.service
+
+
+We specify the class to activate our bundle via the `Bundle-Activator` attribute and also specify that our bundle imports the core OSGi framework package, the Service Tracker package, and the dictionary service interface package using the `Import-Package` attribute. The OSGi framework will automatically handle the details of resolving the bundle's imported packages. (Note: Make sure your manifest file ends in a trailing carriage return or else the last line will be ignored.)
+
+To compile our source code, we need to have the `felix.jar` file (found in Felix' `bin` directory) and the `example2.jar` file in our class path. We compile the source file using a command like:
+
+
+    javac -d c:\classes *.java
+
+
+This command compiles all source files and outputs the generated classes into a subdirectory of the `c:\classes` directory; this subdirectory is `tutorial\example5`, named after the package we specified in the source file. For the above command to work, the `c:\classes` directory must exist. After compiling, we need to create a JAR file containing the generated package directories. We will also add our manifest file that contains the bundle's meta-data to the JAR file. To create the JAR file, we issue the command:
+
+
+    jar cfm example5.jar manifest.mf -C c:\classes tutorial\example5
+
+
+This command creates a JAR file using the manifest file we created and includes all of the classes in the `tutorial\example5` directory inside of the `c:\classes` directory. Once the JAR file is created, we are ready to install and start the bundle.
+
+To run Felix, we follow the instructions described in usage.html. When we start Felix, it asks for a profile name, we will put all of our bundles in a profile named `tutorial`. After running Felix, we should check that all tutorial bundles are stopped, except for the English dictionary service bundle from Example 2. We can use the Felix `lb` shell command to get a list of all bundles, their state, and their bundle identifier number. If the Example 2 bundle is not active, we should start the bundle using the `start` command along with the bundle's identifier number displayed by the `lb` command and stop any other unneeded tutorial bundles using the stop command. (Note: Felix uses some bundles to provide its command shell, so do not stop these bundles.) Now we can install and start our dictionary client bundle. Assuming that we created our bundle in the directory `c:\tutorial`, we can install and start it in Felix' shell using the following command:
+
+
+    start file:/c:/tutorial/example5.jar
+
+
+The above command installs and starts the bundle in a single step; it is also possible to install and start the bundle in two steps by using the Felix `install` and `start` shell commands. When we start the bundle, it will use the shell thread to prompt us for words. Enter one word at a time to check the words and enter a blank line to stop checking words. To restart the bundle, we must use the Felix shell `lb` command to get the bundle identifier number for the bundle and first use the `stop` command to stop the bundle, then the `start` command to restart it. To test the dictionary service, enter any of the words in the dictionary (e.g., "welcome", "to", "the", "OSGi", "tutorial") or any word not in the dictionary.
+
+Since this client uses the `ServiceTracker` class, it is robust in the face of sudden departures of the the dictionary service. Further, when a dictionary service arrives, it automatically gets the service if it needs it and continues to function. These capabilities are a little difficult to demonstrate since we are using a simple single-threaded approach, but in a multi-threaded or GUI-oriented application this robustness is very useful.
\ No newline at end of file

Added: felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-6.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-6.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-6.mdtext (added)
+++ felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-6.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,327 @@
+Title: Apache Felix Tutorial Example 6
+
+# Example 6 - Spell Checker Service Bundle
+
+*(This example should be rewritten to use the Service Tracker.)*
+
+In this example, we complicate things further by defining a new service that uses an arbitrary number of dictionary services to perform its function. More precisely, we define a spell checker service will aggregate all dictionary services and provide another service that allows us to spell check passages using our underlying dictionary services to verify the spelling of words. Our bundle will only provide the spell checker service if there is at least one dictionary service available. First, we will start by defining the spell checker service interface in a file called `SpellChecker.java`:
+
+
+    /*
+     * Apache Felix OSGi tutorial.
+    **/
+    
+    package tutorial.example6.service;
+    
+    /**
+     * A simple service interface that defines a spell checker service.
+     * A spell checker 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 SpellChecker
+    {
+        /**
+         * 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);
+    }
+
+
+The service interface is quite simple, with only one method that needs to be implemented. Notice that we put the service interface in the package `tutorial.example6.service`, instead of just putting it in `tutorial.example6`. We did this because we need to share the interface definition with other bundles, therefore it is better to separate service interfaces that need to be shared from code that does not need to be shared. Such an approach ensures a strong separation between interface and implementation.
+
+In the following bundle source code, the bundle needs to create a complete list of all dictionary services; this is somewhat tricky and must be done carefully. First, the bundle uses its bundle context to register itself as a service event listener, then it queries for all currently available dictionary services. After creating the list of dictionary services, the bundle then registers its spell checker service if and only if there is at least one dictionary service available. These actions must be performed in a synchronized block to avoid interference from service events. Additionally, since the bundle is monitoring the dynamic availability of the dictionary services, when the number of dictionary services falls to zero or increases from zero, the bundle must unregister and register its spell checker service, respectively. We implement our bundle in a file called `Activator.java`:
+
+
+    /*
+     * Apache Felix OSGi tutorial.
+    **/
+    
+    package tutorial.example6;
+    
+    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.example6.service.SpellChecker;
+    
+    /**
+     * This class implements a bundle that implements a spell
+     * checker service. The spell checker 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 checker service is only registered
+     * if there are dictionary services available, thus the spell
+     * checker 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 checker 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 checker
+         * service is registered.
+         * @param context the framework context for the bundle.
+        **/
+        public void start(BundleContext context) throws Exception
+        {
+            m_context = context;
+    
+            synchronized (m_refList)
+            {
+                // 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)
+                {
+                    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 checker service if there are any
+                    // dictionary services.
+                    if (m_refList.size() > 0)
+                    {
+                        m_reg = m_context.registerService(
+                            SpellChecker.class.getName(),
+                            new SpellCheckerImpl(), 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 checker service is unregistered. As soon as any dictionary
+         * service becomes available, the spell checker service is
+         * reregistered.
+         * @param event the fired service event.
+        **/
+        public void serviceChanged(ServiceEvent event)
+        {
+            synchronized (m_refList)
+            {
+                // Add the new dictionary service to the service list.
+                if (event.getType() == ServiceEvent.REGISTERED)
+                {
+                    // 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 checker service if necessary.
+                        if (m_reg == null)
+                        {
+                            m_reg = m_context.registerService(
+                                SpellChecker.class.getName(),
+                                new SpellCheckerImpl(), null);
+                        }
+                    }
+                    else if (service != null)
+                    {
+                        m_context.ungetService(event.getServiceReference());
+                    }
+                }
+                // Remove the departing service from the service list.
+                else if (event.getType() == ServiceEvent.UNREGISTERING)
+                {
+                    // 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 checker service.
+                        if (m_refList.size() == 0)
+                        {
+                            m_reg.unregister();
+                            m_reg = null;
+                        }
+                    }
+                }
+            }
+        }
+    
+        /**
+         * A private inner class that implements a spell checker service;
+         * see SpellChecker for details of the service.
+        **/
+        private class SpellCheckerImpl implements SpellChecker
+        {
+            /**
+             * Implements SpellChecker.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()]);
+            }
+        }
+    }
+
+
+Note that we do not need to unregister the service in stop() method, because the OSGi framework will automatically do so for us. The spell checker service that we have implemented is very simple; it simply parses a given passage into words and then loops through all available dictionary services for each word until it determines that the word is correct. Any incorrect words are added to an error list that will be returned to the caller. This solution is not optimal and is only intended for educational purposes. Next, we create a `manifest.mf` file that contains the meta-data for our bundle:
+
+
+    Bundle-Name: Spell checker service
+    Bundle-Description: A bundle that implements a simple spell checker service
+    Bundle-Vendor: Richard Hall
+    Bundle-Version: 1.0.0
+    Bundle-Activator: tutorial.example6.Activator
+    Export-Package: tutorial.example6.service
+    Import-Package: org.osgi.framework,
+     tutorial.example2.service
+
+
+We specify which class used to activate the bundle via the `Bundle-Activator` attribute. Our bundle exports the spell checker service interface using the `Export-Package` attribute and imports the OSGi core framework and dictionary service interface packages using the `Import-Package` attribute. (Note: Make sure your manifest file ends in a trailing carriage return or else the last line will be ignored.)
+
+To compile our source, we need to have the `felix.jar` file (found in Felix' `bin` directory) and the example2.jar file in our class path. We compile the source file using a command like:
+
+
+    javac -d c:\classes *.java
+
+
+This command compiles all source files and outputs the generated classes into a subdirectory of the `c:\classes` directory; this subdirectory is `tutorial\example6`, named after the package we specified in the source file. For the above command to work, the `c:\classes` directory must exist. After compiling, we need to create a JAR file containing the generated package directories. We will also add our manifest file that contains the bundle's meta-data to the JAR file. To create the JAR file, we issue the command:
+
+
+    jar cfm example6.jar manifest.mf -C c:\classes tutorial\example6
+
+
+This command creates a JAR file using the manifest file we created and includes all of the classes in the `tutorial\example6` directory inside of the `c:\classes` directory. Once the JAR file is created, we are ready to install and start the bundle.
+
+To run Felix, we follow the instructions described in usage.html. When we start Felix, it asks for a profile name, we will put all of our bundles in a profile named `tutorial`. After running Felix, we should stop all tutorial bundles except for the service bundles. Use the `lb` command to make sure that only the bundles from Example 2 and Example 2b are active; use the `start` and `stop` commands as appropriate to start and stop the various tutorial bundles, respectively. (Note: Felix uses some bundles to provide its command shell, so do not stop these bundles.) Now we can install and start our spell checker service bundle. Assuming that we created our bundle in the directory `c:\tutorial`, we can install and start it in Felix' shell using the following command:
+
+
+    start file:/c:/tutorial/example6.jar
+
+
+The above command installs and starts the bundle in a single step; it is also possible to install and start the bundle in two steps by using the Felix `install` and `start` shell commands. To stop the bundle, use the Felix `stop` shell command. Using the Felix shell `lb` command to get the bundle identifier number for our spell checker service bundle and we can stop and restart it at will using the `stop` and `start` commands, respectively. Using the `services` command, we can see which services are currently available in the OSGi framework, including our dictionary and spell checker services. We can experiment with our spell checker service's dynamic availability by stopping the dictionary service bundles; when both dictionary services are stopped, the `services` command will reveal that our bundle is no longer offering its spell checker service. Likewise, when the dictionary services comeback, so will our spell checker service. We create a client for our spell checker serv
 ice in Example 7. To exit Felix, we use the `shutdown` command.

Added: felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-7.mdtext
URL: http://svn.apache.org/viewvc/felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-7.mdtext?rev=1421893&view=auto
==============================================================================
--- felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-7.mdtext (added)
+++ felix/site/trunk/content/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial/apache-felix-tutorial-example-7.mdtext Fri Dec 14 14:29:22 2012
@@ -0,0 +1,161 @@
+Title: Apache Felix Tutorial Example 7
+
+# Example 7 - Spell Checker Client Bundle
+
+In this example we create a client for the spell checker service we implemented in Example 6. This client monitors the dynamic availability of the spell checker service using the Service Tracker and is very similar in structure to the dictionary client we implemented in Example 5. The functionality of the spell checker client reads passages from standard input and spell checks them using the spell checker service. Our bundle uses its bundle context to create a `ServiceTracker` object to monitor spell checker services. The source code for our bundle is as follows in a file called `Activator.java`:
+
+
+    /*
+     * Apache Felix OSGi tutorial.
+    **/
+    
+    package tutorial.example7;
+    
+    import java.io.BufferedReader;
+    import java.io.InputStreamReader;
+    import java.io.IOException;
+    
+    import org.osgi.framework.BundleActivator;
+    import org.osgi.framework.BundleContext;
+    import org.osgi.util.tracker.ServiceTracker;
+    
+    import tutorial.example6.service.SpellChecker;
+    
+    /**
+     * This class implements a bundle that uses a spell checker
+     * service to check the spelling of a passage. This bundle
+     * is essentially identical to Example 5, in that it uses the
+     * Service Tracker to monitor the dynamic availability of the
+     * spell checker service. When starting this bundle, the thread
+     * calling the start() method is used to read passages from
+     * standard input. You can stop spell checking passages by
+     * entering an empty line, but to start spell checking again
+     * you must stop and then restart the bundle.
+    **/
+    public class Activator implements BundleActivator
+    {
+        // Bundle's context.
+        private BundleContext m_context = null;
+        // The service tacker object.
+        private ServiceTracker m_tracker = null;
+    
+        /**
+         * Implements BundleActivator.start(). Creates a Service
+         * Tracker object to monitor spell checker services. Enters
+         * a spell check loop where it reads passages from standard
+         * input and checks their spelling using the spell checker service.
+         * (NOTE: It is very bad practice to use the calling thread
+         * to perform a lengthy process like this; this is only done
+         * for the purpose of the tutorial.)
+         * @param context the framework context for the bundle.
+        **/
+        public void start(BundleContext context) throws Exception
+        {
+            m_context = context;
+    
+            // Create a service tracker to monitor dictionary services.
+            m_tracker = new ServiceTracker(
+                m_context,
+                m_context.createFilter(
+                    "(objectClass=" + SpellChecker.class.getName() + ")"),
+                null);
+            m_tracker.open();
+    
+            try
+            {
+                System.out.println("Enter a blank line to exit.");
+                String passage = "";
+                BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+    
+                // Loop endlessly.
+                while (true)
+                {
+                    // Ask the user to enter a passage.
+                    System.out.print("Enter passage: ");
+                    passage = in.readLine();
+    
+                    // Get the selected dictionary service, if available.
+                    SpellChecker checker = (SpellChecker) m_tracker.getService();
+    
+                    // If the user entered a blank line, then
+                    // exit the loop.
+                    if (passage.length() == 0)
+                    {
+                        break;
+                    }
+                    // If there is no spell checker, then say so.
+                    else if (checker == null)
+                    {
+                        System.out.println("No spell checker available.");
+                    }
+                    // Otherwise check passage and print misspelled words.
+                    else
+                    {
+                        String[] errors = checker.check(passage);
+    
+                        if (errors == null)
+                        {
+                            System.out.println("Passage is correct.");
+                        }
+                        else
+                        {
+                            System.out.println("Incorrect word(s):");
+                            for (int i = 0; i < errors.length; i++)
+                            {
+                                System.out.println("    " + errors[i]);
+                            }
+                        }
+                    }
+                }
+            } catch (Exception ex) { }
+        }
+    
+        /**
+         * Implements BundleActivator.stop(). Does nothing since
+         * the framework will automatically unget any used services.
+         * @param context the framework context for the bundle.
+        **/
+        public void stop(BundleContext context)
+        {
+        }
+    }
+
+
+The client uses the Service Tracker to listen for spell checker services. Like normal, we must create a `manifest.mf` file that contains the meta-data for our bundle; the manifest file contains the following:
+
+
+    Bundle-Name: Spell checker client
+    Bundle-Description: A bundle that uses the spell checker service
+    Bundle-Vendor: Richard Hall
+    Bundle-Version: 1.0.0
+    Bundle-Activator: tutorial.example7.Activator
+    Import-Package: org.osgi.framework,
+     org.osgi.util.tracker,
+     tutorial.example6.service
+
+
+We specify which class is used to activate the bundle via the `Bundle-Activator` attribute and also specify that our bundle imports the OSGi core, OSGi Service Tracker, and spell checker service interface packages with the `Import-Package` attribute. The OSGi framework will automatically handle the details of resolving import packages. (Note: Make sure your manifest file ends in a trailing carriage return or else the last line will be ignored.)
+
+To compile our source code, we need to have the `felix.jar` file (found in Felix' `bin` directory) and the `example6.jar` file in our class path. We compile the source file using a command like:
+
+
+    javac -d c:\classes *.java
+
+
+This command compiles all source files and outputs the generated classes into a subdirectory of the `c:\classes` directory; this subdirectory is `tutorial\example7`, named after the package we specified in the source file. For the above command to work, the `c:\classes` directory must exist. After compiling, we need to create a JAR file containing the generated package directories. We will also add our manifest file that contains the bundle's meta-data to the JAR file. To create the JAR file, we issue the command:
+
+
+    jar cfm example7.jar manifest.mf -C c:\classes tutorial\example7
+
+
+This command creates a JAR file using the manifest file we created and includes all of the classes in the tutorial\example6 directory inside of the `c:\classes` directory. Once the JAR file is created, we are ready to install and start the bundle.
+
+To run Felix, we follow the instructions described in usage.html. When we start Felix, it asks for a profile name, we will put all of our bundles in a profile named `tutorial`. After running Felix, we should stop all tutorial bundles except for the service bundles. Use the `lb` command to make sure that only the bundles from Example 2, Example 2b, and Example 6 are active; use the `start` and `stop` commands as appropriate to start and stop the various tutorial bundles, respectively. (Note: Felix uses some bundles to provide its command shell, so do not stop these bundles.) Now we can install and start our spell checker client bundle. Assuming that we created our bundle in the directory `c:\tutorial`, we can install and start it in Felix' shell using the following command:
+
+
+    start file:/c:/tutorial/example7.jar
+
+
+The above command installs and starts the bundle in a single step; it is also possible to install and start the bundle in two steps by using the Felix `install` and `start` shell commands. When we start the bundle, it will use the shell thread to prompt us for passages; a passage is a collection or words separate by spaces, commas, periods, exclamation points, question marks, colons, or semi-colons. Enter a passage and press the enter key to spell check the passage or enter a blank line to stop spell checking passages. To restart the bundle, we must use the Felix shell `lb` command to get the bundle identifier number for the bundle and first use the `stop` command to stop the bundle, then the `start` command to restart it.
+
+Since this client uses the Service Tracker to monitor the dynamic availability of the spell checker service, it is robust in the scenario where the spell checker service suddenly departs. Further, when a spell checker service arrives, it automatically gets the service if it needs it and continues to function. These capabilities are a little difficult to demonstrate since we are using a simple single-threaded approach, but in a multi-threaded or GUI-oriented application this robustness is very useful. 
\ No newline at end of file



Mime
View raw message