Using XML parser implementation as OSGi service
我正在使用 OSGi(Equinox 平台)开发一个应用程序,其中一个包需要解析 XML 文件。到目前为止,我使用 SAX (javax.xml.parsers.SAXParserFactory) 实现了这个,我想从平台检索 SAXParserFactory。
我看到 OSGi 标准提供了 XMLParserActivator 以允许 JAXP 实现注册自己 (http://www.osgi.org/javadoc/r4v41/org/osgi/util/xml/XMLParserActivator.html),所以我猜是应该有一些捆绑提供 SAXParserFactory 作为服务。
但是,我无法确定要添加哪个包作为依赖项才能找到提供 SAXParserFactory 的服务。我尝试使用
检索服务引用
1 | context.getServiceReferences(SAXParserFactory.class.getName(),"(&(parser.namespaceAware=true)(parser.validating=true))") |
鉴于 XML 解析是一件相当常见的事情,我想有可用的实现,或从平台获取 XML 解析器服务的其他方法。
非常欢迎任何帮助!
通常在 OSGi 中使用 JAXP 不是一个好主意(主要是因为类加载机制),而让工厂像服务一样是一个更好的主意。
如果您使用的是Equinox,SaxParserFactory(使用您正在运行的JRE/JDK)实际上是由系统捆绑提供的,这意味着您不需要额外的捆绑:
{javax.xml.parsers.SAXParserFactory}={service.id=6}
由捆绑注册:系统捆绑[0]
如果您想编写处理 OSGi 平台生命周期层的代码,我建议您跟踪参考,而不是直接查找。
有很多方法可以做到这一点;我在这里写了一篇我称之为 ServiceMediator 的文章。
例如对于您的情况(代码在 Apache 2 许可下,Coalevo 项目):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | 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 @version@ (@date@) */ 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 项目提供了一个合适的包。我不知道 Xerces 包注册了 SAXParserFactory 服务,但您可以添加对包的依赖项并直接使用 Sax 解析器。