使用XML解析器实现作为OSGi服务
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 的服务。我尝试使用
检索服务引用
context.getServiceReferences(SAXParserFactory.class.getName(),"(&(parser.namespaceAware=true)(parser.validating=true))")
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
鉴于 XML 解析是一件相当常见的事情,我想有可用的实现,或从平台获取 XML 解析器服务的其他方法。
非常欢迎任何帮助!
通常在 OSGi 中使用 JAXP 不是一个好主意(主要是因为类加载机制),而让工厂像服务一样是一个更好的主意。
如果您使用的是Equinox,SaxParserFactory(使用您正在运行的JRE/JDK)实际上是由系统捆绑提供的,这意味着您不需要额外的捆绑:
{javax.xml.parsers.SAXParserFactory}={service.id=6}
由捆绑注册:系统捆绑[0]
如果您想编写处理 OSGi 平台生命周期层的代码,我建议您跟踪参考,而不是直接查找。
有很多方法可以做到这一点;我在这里写了一篇我称之为 ServiceMediator 的文章。
例如对于您的情况(代码在 Apache 2 许可下,Coalevo 项目):
context.getServiceReferences(SAXParserFactory.class.getName(),"(&(parser.namespaceAware=true)(parser.validating=true))")
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 解析器。