The Extensible Markup Language (XML) has become a popular method of describing data. As more bundles use XML to describe their data, a common XML Parser becomes necessary in an embedded environment in order to reduce the need for space. Not all XML Parsers are equivalent in function, however, and not all bundles have the same requirements on an XML parser.
This problem was addressed in the Java API for XML Processing, see [4] JAXP for Java 2 Standard Edition and Enterprise Edition. This specification addresses how the classes defined in JAXP can be used in an OSGi framework. It defines how:
- 
                                 Implementations of XML parsers can become available to other bundles 
- 
                                 Bundles can find a suitable parser 
- 
                                 A standard parser in a JAR can be transformed to a bundle 
- 
                                    Standards - Leverage existing standards in Java based XML parsing: JAXP, SAX and DOM 
- 
                                    Unmodified JAXP code - Run unmodified JAXP code 
- 
                                    Simple - It should be easy to provide a SAX or DOM parser as well as easy to find a matching parser 
- 
                                    Multiple - It should be possible to have multiple implementations of parsers available 
- 
                                    Extendable - It is likely that parsers will be extended in the future with more functionality 
- 
                                    XMLParserActivator - A utility class that registers a parser factory from declarative information in the Manifest file. 
- 
                                    SAXParserFactory - A class that can create an instance of a SAXParserclass.
- 
                                    DocumentBuilderFactory - A class that can create an instance of a DocumentBuilderclass.
- 
                                    SAXParser - A parser, instantiated by a SaxParserFactoryobject, that parses according to the SAX specifications.
- 
                                    DocumentBuilder - A parser, instantiated by a DocumentBuilderFactory, that parses according to the DOM specifications.
A bundle containing a SAX or DOM parser is started. This bundle
                                    registers a SAXParserFactory and/or a
                                    DocumentBuilderFactory service object with the Framework.
                                    Service registration properties describe the features of the parsers to
                                    other bundles. A bundle that needs an XML parser will get a
                                    SAXParserFactory or DocumentBuilderFactory
                                    service object from the Framework service registry. This object is then
                                    used to instantiate the requested parsers according to their
                                    specifications.
                           
XML has become very popular in the last few years because it allows the interchange of complex information between different parties. Though only a single XML standard exists, there are multiple APIs to XML parsers, primarily of two types:
- 
                                 The Simple API for XML (SAX1 and SAX2) 
- 
                                 Based on the Document Object Model (DOM 1 and 2) 
Both standards, however, define an abstract API that can be implemented by different vendors.
A given XML Parser implementation may support either or both of
                               these parser types by implementing the org.w3c.dom and/or
                               org.xml.sax packages. In addition, parsers have
                               characteristics such as whether they are validating or non-validating
                               parsers and whether or not they are name-space aware.
                        
An application which uses a specific XML Parser must code to that specific parser and become coupled to that specific implementation. If the parser has implemented [4] JAXP, however, the application developer can code against SAX or DOM and let the runtime environment decide which parser implementation is used.
JAXP uses the concept of a factory. A factory
                               object is an object that abstracts the creation of another object. JAXP
                               defines a DocumentBuilderFactory and a
                               SAXParserFactory class for this purpose.
                        
JAXP is implemented in the javax.xml.parsers package
                               and provides an abstraction layer between an application and a specific
                               XML Parser implementation. Using JAXP, applications can choose to use any
                               JAXP compliant parser without changing any code, simply by changing a
                               System property which specifies the SAX- and DOM factory class
                               names.
                        
In JAXP, the default factory is obtained with a static method in the
                               SAXParserFactory or DocumentBuilderFactory
                               class. This method will inspect the associated System property and create
                               a new instance of that class.
                        
The current specification of JAXP has the limitation that only one
                               of each type of parser factories can be registered. This specification
                               specifies how multiple SAXParserFactory objects and
                               DocumentBuilderFactory objects can be made available to
                               bundles simultaneously.
                        
Providers of parsers should register a JAXP factory object with the OSGi service registry under the factory class name. Service properties are used to describe whether the parser:
- 
                                 Is validating 
- 
                                 Is name-space aware 
- 
                                 Has additional features 
With this functionality, bundles can query the OSGi service registry for parsers supporting the specific functionality that they require.
Parsers must be registered with a number of properties that qualify the service. In this specification, the following properties are specified:
- 
                                 PARSER_NAMESPACEAWARE - The registered parser is aware of name-spaces. Name-spaces allow an XML document to consist of independently developed DTDs. In an XML document, they are recognized by the xmlnsattribute and names prefixed with an abbreviated name-space identifier, like:<xsl:if ...>. The type is aBooleanobject that must betruewhen the parser supports name-spaces. All other values, or the absence of the property, indicate that the parser does not implement name-spaces.
- 
                                 PARSER_VALIDATING - The registered parser can read the DTD and can validate the XML accordingly. The type is a Booleanobject that musttruewhen the parser is validating. All other values, or the absence of the property, indicate that the parser does not validate.
Getting a parser factory requires a bundle to get the appropriate
                               factory from the service registry. In a simple case in which a
                               non-validating, non-name-space aware parser would suffice, it is best to
                               use getServiceReference(String).
                        
DocumentBuilder getParser(BundleContext context) 
    throws Exception {
    ServiceReference ref = context.getServiceReference(
        DocumentBuilderFactory.class.getName() );
    if ( ref == null )
        return null;
    DocumentBuilderFactory factory = 
        (DocumentBuilderFactory) context.getService(ref);
    return factory.newDocumentBuilder();
}In a more demanding case, the filtered version allows the bundle to select a parser that is validating and name-space aware:
SAXParser getParser(BundleContext context) 
    throws Exception {
    ServiceReference refs[] = context.getServiceReferences(
        SAXParserFactory.class.getName(),
            "(&(parser.namespaceAware=true)"
        +   "(parser.validating=true))" );
    if ( refs == null )
        return null;
    SAXParserFactory factory = 
        (SAXParserFactory) context.getService(refs[O]);
    return factory.newSAXParser();
}If an XML Parser supports JAXP, then it can be converted to an OSGi
                               aware bundle by adding a BundleActivator class which
                               registers an XML Parser Service. The utility
                               org.osgi.util.xml.XMLParserActivator class provides this
                               function and can be added (copied, not referenced) to any XML Parser
                               bundle, or it can be extended and customized if desired.
                        
Its functionality is based on the definition of the [5] JAR File specification, services directory. This specification defines a concept for service
                                    providers. A JAR file can contain an implementation of an abstractly
                                    defined service. The class (or classes) implementing the service are
                                    designated from a file in the META-INF/services directory.
                                    The name of this file is the same as the abstract service class.
                           
The content of the UTF-8 encoded file is a list of class names
                                    separated by new lines. White space is ignored and the number sign
                                    ('#' \u0023) is the comment character.
                           
JAXP uses this service provider mechanism. It is therefore likely
                                    that vendors will place these service files in the
                                    META-INF/services directory.
                           
To support this mechanism, the XML Parser service provides a utility class that should be normally delivered with the OSGi framework implementation. This class is a Bundle Activator and must start when the bundle is started. This class is copied into the parser bundle, and not imported.
The start method of the utility
                                    BundleActivator class will look in the
                                    META-INF/services service provider directory for the files
                                    javax.xml.parsers.SAXParserFactory ( SAXFACTORYNAME ) or
                                    javax.xml.parsers.DocumentBuilderFactory ( DOMFACTORYNAME ). The full path name is specified in the
                                    constants SAXCLASSFILE and DOMCLASSFILE respectively.
                           
If either of these files exist, the utility
                                    BundleActivator class will parse the contents according to
                                    the specification. A service provider file can contain multiple class
                                    names. Each name is read and a new instance is created. The following
                                    example shows the possible content of such a file:
                           
# ACME example SAXParserFactory file
com.acme.saxparser.SAXParserFast            # Fast
com.acme.saxparser.SAXParserValidating      # ValidatesBoth the javax.xml.parsers.SAXParserFactory and the
                                    javax.xml.parsers.DocumentBuilderFactory provide methods
                                    that describe the features of the parsers they can create. The
                                    XMLParserActivator activator will use these methods to set
                                    the values of the properties, as defined in Properties,
                                    that describe the instances.
                           
To incorporate this bundle activator into a XML Parser Bundle, do the following:
- 
                                    If SAX parsing is supported, create a /META-INF/services/javax.xml.parsers.SAXParserFactoryresource file containing the class names of theSAXParserFactoryclasses.
- 
                                    If DOM parsing is supported, create a /META-INF/services/javax.xml.parsers.DocumentBuilderFactoryfile containing the fully qualified class names of theDocumentBuilderFactoryclasses.
- 
                                    Create manifest file which imports the packages org.w3c.dom,org.xml.sax, andjavax.xml.parsers.
- 
                                    Add a Bundle-Activator header to the manifest pointing to the XMLParserActivator, the sub-class that was created, or a fully custom one.
- 
                                    If the parsers support attributes, properties, or features that should be registered as properties so they can be searched, extend the XMLParserActivatorclass and override setSAXProperties(javax.xml.parsers.SAXParserFactory,Hashtable) and setDOMProperties(javax.xml.parsers.DocumentBuilderFactory,Hashtable).
- 
                                    Ensure that custom properties are put into the Hashtableobject. JAXP does not provide a way forXMLParserActivatorto query the parser to find out what properties were added.
- 
                                    Bundles that extend the XMLParserActivatorclass must call the original methods via super to correctly initialize the XML Parser Service properties.
- 
                                    Compile this class into the bundle. 
- 
                                    Install the new XML Parser Service bundle. 
- 
                                    Ensure that the org.osgi.util.xml.XMLParserActivatorclass is contained in the bundle.
A single bundle should export the JAXP, SAX, and DOM APIs. The version of contained packages must be appropriately labeled. JAXP 1.1 or later is required which references SAX 2 and DOM 2. See [4] JAXP for the exact version dependencies.
This specification is related to related packages as defined in the JAXP 1.1 document. The following table contains the expected minimum versions.
Table 702.1 JAXP 1.1 minimum package versions
| Package | Minimum Version | 
|---|---|
| javax.xml.parsers | 1.1 | 
| org.xml.sax | 2.0 | 
| org.xml.sax.helpers | 2.0 | 
| org.xsml.sax.ext | 1.0 | 
| org.w3c.dom | 2.0 | 
The Xerces project from the Apache group, [6] Xerces 2 Java Parser, contains a number libraries that implement the necessary APIs. These libraries can be wrapped in a bundle to provide the relevant packages.
A centralized XML parser is likely to see sensitive information from
                               other bundles. Provisioning an XML parser should therefore be limited to
                               trusted bundles. This security can be achieved by providing
                               ServicePermission[javax.xml.parsers.DocumentBuilderFactory |
                               javax.xml.parsers.SAXFactory,REGISTER] to only trusted
                               bundles.
                        
Using an XML parser is a common function, and
                               ServicePermission[javax.xml.parsers.DOMParserFactory |
                               javax.xml.parsers.SAXFactory, GET] should not be
                               restricted.
                        
The XML parser bundle will need FilePermission[<<ALL
                                  FILES>>,READ] for parsing of files because it is not known
                               beforehand where those files will be located. This requirement further
                               implies that the XML parser is a system bundle that must be fully
                               trusted.
                        
XML Parser Package Version 1.0.
Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest.
Example import for consumers using the API in this package:
                                 Import-Package: org.osgi.util.xml; version="[1.0,2.0)"
                              
                        
- 
                                    XMLParserActivator- A BundleActivator class that allows any JAXP compliant XML Parser to register itself as an OSGi parser service.
A BundleActivator class that allows any JAXP compliant XML Parser to register itself as an OSGi parser service. Multiple JAXP compliant parsers can concurrently register by using this BundleActivator class. Bundles who wish to use an XML parser can then use the framework's service registry to locate available XML Parsers with the desired characteristics such as validating and namespace-aware.
The services that this bundle activator enables a bundle to provide are:
- 
                                    javax.xml.parsers.SAXParserFactory(SAXFACTORYNAME)
- 
                                    javax.xml.parsers.DocumentBuilderFactory( DOMFACTORYNAME )
The algorithm to find the implementations of the abstract parsers is derived from the JAR file specifications, specifically the Services API.
An XMLParserActivator assumes that it can find the class file names of the factory classes in the following files:
- 
                                    /META-INF/services/javax.xml.parsers.SAXParserFactoryis a file contained in a jar available to the runtime which contains the implementation class name(s) of the SAXParserFactory.
- 
                                    /META-INF/services/javax.xml.parsers.DocumentBuilderFactoryis a file contained in a jar available to the runtime which contains the implementation class name(s) of theDocumentBuilderFactory
                               If either of the files does not exist, XMLParserActivator assumes
                               that the parser does not support that parser type.
                               
                               
                           
                                       XMLParserActivator attempts to instantiate both the
                               SAXParserFactory and the DocumentBuilderFactory. It registers
                               each factory with the framework along with service properties:
                               
                           
- 
                                    PARSER_VALIDATING- indicates if this factory supports validating parsers. It's value is a Boolean.
- 
                                    PARSER_NAMESPACEAWARE- indicates if this factory supports namespace aware parsers It's value is a Boolean.
                               Individual parser implementations may have additional features, properties,
                               or attributes which could be used to select a parser with a filter. These can
                               be added by extending this class and overriding the setSAXProperties
                               and setDOMProperties methods.
                           
Thread-safe
Fully qualified path name of DOM Parser Factory Class Name file
                                 Filename containing the DOM Parser Factory Class name. Also used as the
                                  basis for the SERVICE_PID registration property.
                                    
                              
                                 Service property specifying if factory is configured to support namespace
                                  aware parsers. The value is of type Boolean.
                                    
                              
                                 Service property specifying if factory is configured to support
                                  validating parsers. The value is of type Boolean.
                                    
                              
Fully qualified path name of SAX Parser Factory Class Name file
                                 Filename containing the SAX Parser Factory Class name. Also used as the
                                  basis for the SERVICE_PID registration property.
                                    
                              
The bundle using the service.
The ServiceRegistration object for the
                                            service.
Creates a new XML Parser Factory object.
A unique XML Parser Factory object is returned for each call to this method.
The returned XML Parser Factory object will be configured for validating and namespace aware support as specified in the service properties of the specified ServiceRegistration object. This method can be overridden to configure additional features in the returned XML Parser Factory object.
A new, configured XML Parser Factory object or null if a configuration error was encountered
- the DocumentBuilderFactory object
- Hashtable of service properties.
Set the customizable DOM Parser Service Properties.
This method attempts to instantiate a validating parser and a namespace aware parser to determine if the parser can support those features. The appropriate properties are then set in the specified props object.
This method can be overridden to add additional DOM2 features and properties. If you want to be able to filter searches of the OSGi service registry, this method must put a key, value pair into the properties object for each feature or property. For example, properties.put("http://www.acme.com/features/foo", Boolean.TRUE);
- the SAXParserFactory object
- the properties object for the service
Set the customizable SAX Parser Service Properties.
This method attempts to instantiate a validating parser and a namespace aware parser to determine if the parser can support those features. The appropriate properties are then set in the specified properties object.
This method can be overridden to add additional SAX2 features and properties. If you want to be able to filter searches of the OSGi service registry, this method must put a key, value pair into the properties object for each feature or property. For example, properties.put("http://www.acme.com/features/foo", Boolean.TRUE);
The execution context of the bundle being started.
Called when this bundle is started so the Framework can perform the bundle-specific activities necessary to start this bundle. This method can be used to register services or to allocate any resources that this bundle needs.
This method must complete and return to its caller in a timely manner.
This method attempts to register a SAX and DOM parser with the Framework's service registry.
                                                   Exception– If this method throws an exception, this
                                             bundle is marked as stopped and the Framework will remove this
                                             bundle's listeners, unregister all services registered by this
                                             bundle, and release all services used by this bundle.
The execution context of the bundle being stopped.
This method has nothing to do as all active service registrations will automatically get unregistered when the bundle stops.
                                                   Exception– If this method throws an exception, the
                                             bundle is still marked as stopped, and the Framework will remove
                                             the bundle's listeners, unregister all services registered by the
                                             bundle, and release all services used by the bundle.
The bundle releasing the service.
The ServiceRegistration object for the
                                            service.
The XML Parser Factory object returned by a previous call
                                            to the getService method.
Releases a XML Parser Factory object.
[1]XMLhttp://www.w3.org/XML
[3]DOM Java Language Bindinghttp://www.w3.org/TR/REC-DOM-Level-1/java-language-binding.html
[4]JAXPhttp://jaxp.java.net/
[5]JAR File specification, services directoryhttp://download.oracle.com/javase/1.4.2/docs/guide/jar/jar.html
[6]Xerces 2 Java Parserhttp://xerces.apache.org/xerces2-j/
