将XML解析器实现用作OSGi服务

问题描述:

我正在使用OSGi(Equinox平台)开发应用程序,并且其中一个包需要解析XML文件。到目前为止,我用SAX(javax.xml.parsers.SAXParserFactory)实现了这一点,我想从平台中检索SAXParserFactory。将XML解析器实现用作OSGi服务

我看到OSGi标准提供了一个XMLParserActivator来允许JAXP实现自己注册(http://www.osgi.org/javadoc/r4v41/org/osgi/util/xml/XMLParserActivator.html),所以我的猜测是应该有一些bundle提供SAXParserFactory作为服务。

但是,我找不到要添加作为依赖项的包,以便找到提供SAXParserFactory的服务。我试着检索使用

context.getServiceReferences(SAXParserFactory.class.getName(), "(&(parser.namespaceAware=true)(parser.validating=true))") 

由于XML解析是做一个相当常见的事服务的参考,我认为是有实现可用,或其他方式从平台获得一个XML解析器服务。

任何帮助将非常欢迎!

+0

嗨, 我不相信OSGi的,但为什么不使用与JRE捆绑在一起的XML堆栈? – ATorras 2009-07-21 14:42:42

+0

嗨,是的,但是OSGi类加载器机制不同 - 因此调用SAXParserFactory.newInstance()可能会产生问题,因为JAXP加载器机制期望在当前的线程类加载器中查找解析器,并且可能不一定是这种情况。 – 2009-07-22 07:39:10

一般来说,在OSGi中使用JAXP并不是一个好主意(主要是因为类加载机制),而且更好的想法是像工具一样获得工厂。

{javax.xml:

如果您使用春分时,的SAXParserFactory(使用你正在运行的JRE/JDK之一)实际上是由系统捆绑,这意味着你不需要额外提供捆绑.parsers.SAXParserFactory} = {service.id = 6} 注册:Bundle [0]

如果要编写代码来处理OSGi平台的生命周期层,我会建议跟踪参考,而不是直接查找它。 有很多方法,我写了一篇关于我打电话给ServiceMediator here的文章。

例如对于你的情况(代码是在Apache 2许可,Coalevo项目):

 import org.osgi.framework.*; 

    import javax.xml.parsers.SAXParserFactory; 

    import net.wimpi.telnetd.util.Latch; 

    /** 
    * Implements a mediator pattern class for services from the OSGi container. 
    * <p/> 
    * 
    * @author Dieter Wimberger (wimpi) 
    * @version @[email protected] (@[email protected]) 
    */ 
    class ServiceMediator { 

     private BundleContext m_BundleContext; 

     private SAXParserFactory m_SAXParserFactory; 
     private Latch m_SAXParserFactoryLatch; 

     public SAXParserFactory getSAXParserFactory(long wait) { 
     try { 
      if (wait < 0) { 
      m_SAXParserFactoryLatch.acquire(); 
      } else if (wait > 0) { 
      m_SAXParserFactoryLatch.attempt(wait); 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(System.err); 
     } 

     return m_SAXParserFactory; 
     }//getSAXParserFactory 

     public boolean activate(BundleContext bc) { 
     //get the context 
     m_BundleContext = bc; 

     m_SAXParserFactoryLatch = createWaitLatch(); 

     //prepareDefinitions listener 
     ServiceListener serviceListener = new ServiceListenerImpl(); 

     //prepareDefinitions the filter 
     String filter = "(objectclass=" + SAXParserFactory.class.getName() + ")"; 

     try { 
      //add the listener to the bundle context. 
      bc.addServiceListener(serviceListener, filter); 

      //ensure that already registered Service instances are registered with 
      //the manager 
      ServiceReference[] srl = bc.getServiceReferences(null, filter); 
      for (int i = 0; srl != null && i < srl.length; i++) { 
      serviceListener.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, srl[i])); 
      } 
     } catch (InvalidSyntaxException ex) { 
      ex.printStackTrace(System.err); 
      return false; 
     } 
     return true; 
     }//activate 

     public void deactivate() { 
     m_SAXParserFactory = null; 

     m_SAXParserFactoryLatch = null; 

     m_BundleContext = null; 
     }//deactivate 

     private Latch createWaitLatch() { 
     return new Latch(); 
     }//createWaitLatch 

     private class ServiceListenerImpl 
      implements ServiceListener { 

     public void serviceChanged(ServiceEvent ev) { 
      ServiceReference sr = ev.getServiceReference(); 
      Object o = null; 
      switch (ev.getType()) { 
      case ServiceEvent.REGISTERED: 
       o = m_BundleContext.getService(sr); 
       if (o == null) { 
       return; 
       } else if (o instanceof SAXParserFactory) { 
       m_SAXParserFactory = (SAXParserFactory) o; 
       m_SAXParserFactory.setValidating(false); 
       m_SAXParserFactory.setNamespaceAware(true); 
       m_SAXParserFactoryLatch.release(); 
       } else { 
       m_BundleContext.ungetService(sr); 
       } 
       break; 
      case ServiceEvent.UNREGISTERING: 
       o = m_BundleContext.getService(sr); 
       if (o == null) { 
       return; 
       } else if (o instanceof SAXParserFactory) { 
       m_SAXParserFactory = null; 
       m_SAXParserFactoryLatch = createWaitLatch(); 
       } else { 
       m_BundleContext.ungetService(sr); 
       } 
       break; 
      } 
     } 
     }//inner class ServiceListenerImpl 

     public static long WAIT_UNLIMITED = -1; 
     public static long NO_WAIT = 0; 

    }//class ServiceMediator 

您可以使用Apache Xerces进行Sax解析。从Eclipse Orbit project可以找到合适的捆绑包。我不知道Xerces包注册了一个SAXParserFactory服务,但是您可以添加一个对包的依赖并直接使用Sax解析器。

+0

尽可能避免包依赖关系。 – brindy 2010-08-26 09:08:11