2009-07-21 9 views
7

Estoy desarrollando una aplicación utilizando OSGi (plataforma Equinox), y uno de los paquetes necesita analizar archivos XML. Hasta ahora he implementado esto con SAX (javax.xml.parsers.SAXParserFactory) y me gustaría recuperar el SAXParserFactory de la plataforma.Uso de la implementación del analizador XML como servicio OSGi

vi el estándar OSGi prevé un XMLParserActivator para permitir implementaciones JAXP a registrarse (http://www.osgi.org/javadoc/r4v41/org/osgi/util/xml/XMLParserActivator.html), así que yo creo que debe haber algunos paquetes que ofrecen la SAXParserFactory como un servicio.

Sin embargo, no pude determinar qué paquete agregar como dependencia para encontrar un servicio que ofrezca SAXParserFactory. Trato de recuperar una referencia de servicio utilizando

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

Teniendo en cuenta que el análisis de XML es una cosa bastante común de hacerlo, supongo que hay implementaciones disponibles, u otros medios para conseguir un servicio de intérprete XML desde la plataforma.

¡Cualquier ayuda sería bienvenida!

+0

Hola, No estoy seguro con OSGi pero ¿por qué no utilizar la pila XML incluido con el JRE? – ATorras

+0

Hola, sí, pero el mecanismo del cargador de clases OSGi es diferente, por lo que llamar a SAXParserFactory.newInstance() puede generar problemas, ya que el mecanismo cargador JAXP espera encontrar el analizador en el cargador de clases de hilo de la corriente y puede no ser necesariamente el caso . –

Respuesta

3

En general, no es una buena idea usar JAXP en OSGi (debido principalmente al mecanismo de carga de clases) y una idea mucho mejor para obtener la fábrica como un servicio.

Si está utilizando el equinoccio, el SAXParserFactory (usando el JRE/JDK está ejecutando sucesivamente) es en realidad proporcionada por el paquete del sistema, lo que significa que no necesita paquetes adicionales:

{javax.xml .parsers.SAXParserFactory} = {} = 6 service.id registrado por paquete: Sistema Bundle [0]

Si desea escribir código que se ocupa de la capa del ciclo de vida de la plataforma OSGi, sugeriría para seguir el referencia, en lugar de buscarlo directamente. Hay muchos enfoques para esto; He escrito sobre uno que llamo ServiceMediator here.

p. Ej. para su caso (código está bajo licencia Apache 2, Proyecto 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 
+0

Sugiero también consultar "Servicios dinámicos OSGI" o "Spring DM" ambos tienen medios similares para declarar/resolver dependencias de un paquete declarativamente. Y con estos mecanismos, el código anterior se simplificaría considerablemente. –

+0

El código anterior no es realmente complicado y se puede generar fácilmente en máquina (el Latch se puede tomar desde diferentes lugares si es necesario para el entorno de ejecución). No dudo que DS (supongo que se refiere a los Servicios Declarativos) es una alternativa, sin embargo, a veces también puede terminar con algunos archivos de configuración bastante complejos. De todos modos, siempre es bueno tener alternativas para elegir :) – Dieter

-1

Puede utilizar Apache Xerces para el análisis de Sax. Un paquete adecuado está disponible en el Eclipse Orbit project. No sé si el paquete Xerces registra un servicio SAXParserFactory, pero puede agregar una dependencia al paquete y usar el analizador de Sax directamente.

+0

Evite las dependencias de Bundle siempre que sea posible. – brindy

Cuestiones relacionadas