(08) Apache Felix 入門 - 08

1、輸入檢測服務 Bundle

在下面的例子中,我們定義了一個名稱爲 SpellChecker 的服務,該服務將使用我們註冊的所有字典服務來檢測用戶輸入的單詞是否正確,而且 SpellChecker 只有在至少有一個字典服務是有效的時候才能被使用,下面是 SpellChecker 接口的定義:

    /*
    * Apache Felix OSGi tutorial.
    **/

    package tutorial.example6.service;

    /**
     * 檢測用戶輸入的一串字符串是否正確。
    **/
    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);
    }

在下面 bundle 的源代碼中,我們需要創建一個字典服務集合目前可用的所有字典服務,並且當發現新的可用的字典服務的時候將其添加到此集合,當舊的某個服務不可用了需要將其移除集合。除此之外,我們還需要在字典服務從有到無的時候使 SpellChecker 失效,也就是取消註冊,當字典服務集合從無變有的時候重新註冊 SpellChecker 服務。最後,爲了監控字典服務的註冊與註銷,我們需要將將此 Bundle 自身作爲服務監聽者註冊到系統,具體實現代碼如下:

/*
 * 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;

/**
 * 提供了 SpellChecker 的實現,在 SpellChecker 的實現中,我們使用系統所有的字典服務檢測用戶輸入的單詞是否正確。
 * Acticator 中除監測字典服務之外,還實現了動態將新發現的字典服務添加到此 bundle 維護的字典服務集合中,將失效的
 * 字典服務移除此 bundle 維護的字典服務集合,當字典服務集合中字典服務從有到無的時候,此 bundle 需要取消 SpellChecker 
 * 字典服務的註冊,當字典服務集合中字典服務從無到有的時候,此 bundle 需要重新將 SpellChecker 註冊到 OSGI 框架中。
**/
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()]);
        }
    }
}

構建 manifest.mf:

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

編譯、打包:

D:\devInstall\apache\felix-framework-6.0.0\examples\demo06\src> javac -cp ../../demo02/target/example2.jar;../../../bin/felix.jar -encoding UTF-8 -d ../target tutorial\example6\Activator.java tutorial\example6\service\SpellChecker.java
D:\devInstall\apache\felix-framework-6.0.0\examples\demo06\src> cd ../target
D:\devInstall\apache\felix-framework-6.0.0\examples\demo06\src> cp ../src/manifest.mf ./
D:\devInstall\apache\felix-framework-6.0.0\examples\demo06\src> jar cvfm example6.jar .\manifest.mf -C . .
已添加清單
正在添加: manifest.mf(輸入 = 320) (輸出 = 178)(壓縮了 44%)
正在添加: tutorial/(輸入 = 0) (輸出 = 0)(存儲了 0%)
正在添加: tutorial/example6/(輸入 = 0) (輸出 = 0)(存儲了 0%)
正在添加: tutorial/example6/Activator$1.class(輸入 = 211) (輸出 = 163)(壓縮了 22%)
正在添加: tutorial/example6/Activator$SpellCheckerImpl.class(輸入 = 1845) (輸出 = 995)(壓縮了 46%)
正在添加: tutorial/example6/Activator.class(輸入 = 3429) (輸出 = 1603)(壓縮了 53%)
正在添加: tutorial/example6/service/(輸入 = 0) (輸出 = 0)(存儲了 0%)
正在添加: tutorial/example6/service/SpellChecker.class(輸入 = 189) (輸出 = 147)(壓縮了 22%)

安裝、運行:

g! install file:./examples/demo06/target/example6.jar                                                           00:57:20
Bundle ID: 20
g! start 20                                                                                                     00:57:33
org.osgi.framework.BundleException: Unable to resolve [20](R 20.0): missing requirement [[20](R 20.0)] osgi.wiring.package; (osgi.wiring.package=tutorial.example2.service) Unresolved requirements: [[[20](R 20.0)] osgi.wiring.package; (osgi.wiring.package=tutorial.example2.service)]
g! lb                                                                                                           00:57:38
START LEVEL 1
   ID|State      |Level|Name
    0|Active     |    0|System Bundle (6.0.0)|6.0.0
    1|Active     |    1|jansi (1.17.1)|1.17.1
    2|Active     |    1|JLine Bundle (3.7.0)|3.7.0
    3|Active     |    1|Apache Felix Bundle Repository (2.0.10)|2.0.10
    4|Active     |    1|Apache Felix Gogo Command (1.0.2)|1.0.2
    5|Active     |    1|Apache Felix Gogo JLine Shell (1.1.0)|1.1.0
    6|Active     |    1|Apache Felix Gogo Runtime (1.1.0)|1.1.0
    7|Active     |    1|Service listener example (1.0.0)|1.0.0
   20|Installed  |    1|Spell checker service (1.0.0)|1.0.0
g! install file:./examples/demo02/target/example2.jar                                                           00:57:43
Bundle ID: 21
g! start 21                                                                                                     00:58:11
Ex1: Service of type tutorial.example2.service.DictionaryService registered.
g! start 20                                                                                                     00:58:13
Ex1: Service of type tutorial.example6.service.SpellChecker registered.
g! lb                                                                                                           00:58:19
START LEVEL 1
   ID|State      |Level|Name
    0|Active     |    0|System Bundle (6.0.0)|6.0.0
    1|Active     |    1|jansi (1.17.1)|1.17.1
    2|Active     |    1|JLine Bundle (3.7.0)|3.7.0
    3|Active     |    1|Apache Felix Bundle Repository (2.0.10)|2.0.10
    4|Active     |    1|Apache Felix Gogo Command (1.0.2)|1.0.2
    5|Active     |    1|Apache Felix Gogo JLine Shell (1.1.0)|1.1.0
    6|Active     |    1|Apache Felix Gogo Runtime (1.1.0)|1.1.0
    7|Active     |    1|Service listener example (1.0.0)|1.0.0
   20|Active     |    1|Spell checker service (1.0.0)|1.0.0
   21|Active     |    1|English dictionary (1.0.0)|1.0.0
g!                                                                                                              

上面的例子中,我們首先將原來安裝的所有 DictionaryService 卸載,然後安裝了 SpellChecker,啓動 SpellChecer Bundle 提示缺少可用的 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章