2009-07-21 5 views
7

Pracuję nad aplikacją przy użyciu OSGi (platforma Equinox), a jeden z pakietów wymaga sparsowania plików XML. Do tej pory zaimplementowałem to z SAX (javax.xml.parsers.SAXParserFactory) i chciałbym pobrać SAXParserFactory z platformy.Używanie implementacji parsera XML jako usługi OSGi

Widziałem standard OSGi dla XMLParserActivator, aby umożliwić implementacjom JAXP rejestrację się (http://www.osgi.org/javadoc/r4v41/org/osgi/util/xml/XMLParserActivator.html), więc domyślam się, że powinny istnieć pakiety, które oferują SAXParserFactory jako usługę.

Jednak nie mogłem dowiedzieć się, który pakiet dodać jako zależność, aby znaleźć usługę oferującą SAXParserFactory. Staram się odzyskać odniesienie usług przy użyciu

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

Zważywszy, że analizowania XML jest dość często coś zrobić, przypuszczam, istnieją implementacje dostępne, lub inne środki do uzyskania usługi parsera XML z platformy.

Każda pomoc będzie bardzo mile widziane!

+0

Cześć, nie jestem przekonana o OSGi, ale dlaczego nie użyć stosu XML w pakiecie z JRE? – ATorras

+0

Cześć, tak, ale mechanizm ładujący klasy OSGi różni się - i stąd wywołanie SAXParserFactory.newInstance() może przysporzyć problemów, ponieważ mechanizm ładujący JAXP spodziewa się znaleźć parser w bieżącym programie ładującym klasy wątków i niekoniecznie musi to być przypadek . –

Odpowiedz

3

Generalnie nie jest dobrym pomysłem, aby używać JAXP w OSGi (ze względu na mechanizm ładowania klas) i znacznie lepszy pomysł, aby uzyskać fabrykę jak usługę.

Jeśli używasz równonocy The SaxParserFactory (za pomocą jednego JRE/JDK jest uruchomiony na) jest faktycznie świadczona przez system Bundle, co oznacza, że ​​nie potrzebne są dodatkowe pakiety:

{javax.xml .parsers.SAXParserFactory} = {service.id = 6} Zarejestrowany przez pakiet: Zestaw systemowy [0]

Jeśli chcesz napisać kod, który zajmuje się warstwą cyklu życia platformy OSGi, sugerowałbym śledzenie odniesienie, zamiast bezpośrednio go szukać. Istnieje wiele podejść do tego; Napisałem o jednym, który nazywam ServiceMediator here.

np. w Twoim przypadku (kod jest pod Apache 2 Licencji Coalevo Projektu):

 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

Proponuję również, aby spojrzeć na "Usługi dynamiczne OSGI" lub "Spring DM" oba mają podobne środki do zadeklarowania/rozwiązania zależności deklaracji pakietu. Dzięki tym mechanizmom powyższy kod znacznie uprościłby proces. –

+0

Powyższy kod nie jest zbyt skomplikowany i można go łatwo wygenerować maszynowo (zatrzask można pobrać z różnych miejsc, jeśli jest to wymagane w środowisku wykonawczym). Nie wątpię, że DS (zakładam, że odwołujesz się do usług deklaratywnych) jest alternatywą, jednak równie dobrze możesz czasem znaleźć dość skomplikowane pliki konfiguracyjne. W każdym razie zawsze dobrze jest mieć alternatywy do wyboru :) – Dieter

-1

Możesz użyć Apache Xerces do parsowania Saxa. Odpowiedni pakiet jest dostępny pod numerem Eclipse Orbit project. Nie wiem, że pakiet Xerces rejestruje usługę SAXParserFactory, ale można dodać zależność od pakietu i bezpośrednio użyć parsera Sax.

+0

Unikaj zależności, jeśli to możliwe. – brindy