FileDocCategorySizeDatePackage
ParserAdapter.javaAPI DocAndroid 1.5 API29469Wed May 06 22:41:06 BST 2009org.xml.sax.helpers

ParserAdapter

public class ParserAdapter extends Object implements DocumentHandler, XMLReader
Adapt a SAX1 Parser as a SAX2 XMLReader.
This module, both source code and documentation, is in the Public Domain, and comes with NO WARRANTY. See http://www.saxproject.org for further information.

This class wraps a SAX1 {@link org.xml.sax.Parser Parser} and makes it act as a SAX2 {@link org.xml.sax.XMLReader XMLReader}, with feature, property, and Namespace support. Note that it is not possible to report {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity} events, since SAX1 does not make that information available.

This adapter does not test for duplicate Namespace-qualified attribute names.

since
SAX 2.0
author
David Megginson
version
2.0.1 (sax2r2)
see
org.xml.sax.helpers.XMLReaderAdapter
see
org.xml.sax.XMLReader
see
org.xml.sax.Parser

Fields Summary
private static final String
FEATURES
private static final String
NAMESPACES
private static final String
NAMESPACE_PREFIXES
private static final String
XMLNS_URIs
private NamespaceSupport
nsSupport
private AttributeListAdapter
attAdapter
private boolean
parsing
private String[]
nameParts
private Parser
parser
private AttributesImpl
atts
private boolean
namespaces
private boolean
prefixes
private boolean
uris
Locator
locator
EntityResolver
entityResolver
DTDHandler
dtdHandler
ContentHandler
contentHandler
ErrorHandler
errorHandler
Constructors Summary
public ParserAdapter()
Construct a new parser adapter.

Use the "org.xml.sax.parser" property to locate the embedded SAX1 driver.

exception
SAXException If the embedded driver cannot be instantiated or if the org.xml.sax.parser property is not specified.

    super();

    String driver = System.getProperty("org.xml.sax.parser");

    try {
        setup(ParserFactory.makeParser());
    } catch (ClassNotFoundException e1) {
        throw new
        SAXException("Cannot find SAX1 driver class " +
                 driver, e1);
    } catch (IllegalAccessException e2) {
        throw new
        SAXException("SAX1 driver class " +
                 driver +
                 " found but cannot be loaded", e2);
    } catch (InstantiationException e3) {
        throw new
        SAXException("SAX1 driver class " +
                 driver +
                 " loaded but cannot be instantiated", e3);
    } catch (ClassCastException e4) {
        throw new
        SAXException("SAX1 driver class " +
                 driver +
                 " does not implement org.xml.sax.Parser");
    } catch (NullPointerException e5) {
        throw new 
        SAXException("System property org.xml.sax.parser not specified");
    }
    
public ParserAdapter(Parser parser)
Construct a new parser adapter.

Note that the embedded parser cannot be changed once the adapter is created; to embed a different parser, allocate a new ParserAdapter.

param
parser The SAX1 parser to embed.
exception
java.lang.NullPointerException If the parser parameter is null.

    super();
    setup(parser);
    
Methods Summary
public voidcharacters(char[] ch, int start, int length)
Adapter implementation method; do not call. Adapt a SAX1 characters event.

param
ch An array of characters.
param
start The starting position in the array.
param
length The number of characters to use.
exception
SAXException The client may raise a processing exception.
see
org.xml.sax.DocumentHandler#characters

    if (contentHandler != null) {
        contentHandler.characters(ch, start, length);
    }
    
private voidcheckNotParsing(java.lang.String type, java.lang.String name)
Throw an exception if we are parsing.

Use this method to detect illegal feature or property changes.

param
type The type of thing (feature or property).
param
name The feature or property name.
exception
SAXNotSupportedException If a document is currently being parsed.

    if (parsing) {
        throw new SAXNotSupportedException("Cannot change " +
                           type + ' " +
                           name + " while parsing");
                           
    }
    
public voidendDocument()
Adapter implementation method; do not call. Adapt a SAX1 end document event.

exception
SAXException The client may raise a processing exception.
see
org.xml.sax.DocumentHandler#endDocument

    if (contentHandler != null) {
        contentHandler.endDocument();
    }
    
public voidendElement(java.lang.String qName)
Adapter implementation method; do not call. Adapt a SAX1 end element event.

param
qName The qualified (prefixed) name.
exception
SAXException The client may raise a processing exception.
see
org.xml.sax.DocumentHandler#endElement

                // If we're not doing Namespace
                // processing, dispatch this quickly.
    if (!namespaces) {
        if (contentHandler != null) {
        contentHandler.endElement("", "", qName.intern());
        }
        return;
    }

                // Split the name.
    String names[] = processName(qName, false, false);
    if (contentHandler != null) {
        contentHandler.endElement(names[0], names[1], names[2]);
        Enumeration prefixes = nsSupport.getDeclaredPrefixes();
        while (prefixes.hasMoreElements()) {
        String prefix = (String)prefixes.nextElement();
        contentHandler.endPrefixMapping(prefix);
        }
    }
    nsSupport.popContext();
    
public org.xml.sax.ContentHandlergetContentHandler()
Return the current content handler.

return
The current content handler, or null if none was supplied.
see
org.xml.sax.XMLReader#getEntityResolver

    return contentHandler;
    
public org.xml.sax.DTDHandlergetDTDHandler()
Return the current DTD handler.

return
the current DTD handler, or null if none was supplied
see
org.xml.sax.XMLReader#getEntityResolver

    return dtdHandler;
    
public org.xml.sax.EntityResolvergetEntityResolver()
Return the current entity resolver.

return
The current entity resolver, or null if none was supplied.
see
org.xml.sax.XMLReader#getEntityResolver

    return entityResolver;
    
public org.xml.sax.ErrorHandlergetErrorHandler()
Return the current error handler.

return
The current error handler, or null if none was supplied.
see
org.xml.sax.XMLReader#getEntityResolver

    return errorHandler;
    
public booleangetFeature(java.lang.String name)
Check a parser feature flag.

The only features recognized are namespaces and namespace-prefixes.

param
name The feature name, as a complete URI.
return
The current feature value.
exception
SAXNotRecognizedException If the feature value can't be assigned or retrieved.
exception
SAXNotSupportedException If the feature is not currently readable.
see
org.xml.sax.XMLReader#setFeature

    if (name.equals(NAMESPACES)) {
        return namespaces;
    } else if (name.equals(NAMESPACE_PREFIXES)) {
        return prefixes;
    } else if (name.equals(XMLNS_URIs)) {
        return uris;
    } else {
        throw new SAXNotRecognizedException("Feature: " + name);
    }
    
public java.lang.ObjectgetProperty(java.lang.String name)
Get a parser property.

No properties are currently recognized.

param
name The property name.
return
The property value.
exception
SAXNotRecognizedException If the property value can't be assigned or retrieved.
exception
SAXNotSupportedException If the property value is not currently readable.
see
org.xml.sax.XMLReader#getProperty

    throw new SAXNotRecognizedException("Property: " + name);
    
public voidignorableWhitespace(char[] ch, int start, int length)
Adapter implementation method; do not call. Adapt a SAX1 ignorable whitespace event.

param
ch An array of characters.
param
start The starting position in the array.
param
length The number of characters to use.
exception
SAXException The client may raise a processing exception.
see
org.xml.sax.DocumentHandler#ignorableWhitespace

    if (contentHandler != null) {
        contentHandler.ignorableWhitespace(ch, start, length);
    }
    
private org.xml.sax.SAXParseExceptionmakeException(java.lang.String message)
Construct an exception for the current context.

param
message The error message.

    if (locator != null) {
        return new SAXParseException(message, locator);
    } else {
        return new SAXParseException(message, null, null, -1, -1);
    }
    
public voidparse(java.lang.String systemId)
Parse an XML document.

param
systemId The absolute URL of the document.
exception
java.io.IOException If there is a problem reading the raw content of the document.
exception
SAXException If there is a problem processing the document.
see
#parse(org.xml.sax.InputSource)
see
org.xml.sax.Parser#parse(java.lang.String)

    parse(new InputSource(systemId));
    
public voidparse(org.xml.sax.InputSource input)
Parse an XML document.

param
input An input source for the document.
exception
java.io.IOException If there is a problem reading the raw content of the document.
exception
SAXException If there is a problem processing the document.
see
#parse(java.lang.String)
see
org.xml.sax.Parser#parse(org.xml.sax.InputSource)

    if (parsing) {
        throw new SAXException("Parser is already in use");
    }
    setupParser();
    parsing = true;
    try {
        parser.parse(input);
    } finally {
        parsing = false;
    }
    parsing = false;
    
private java.lang.String[]processName(java.lang.String qName, boolean isAttribute, boolean useException)
Process a qualified (prefixed) name.

If the name has an undeclared prefix, use only the qname and make an ErrorHandler.error callback in case the app is interested.

param
qName The qualified (prefixed) name.
param
isAttribute true if this is an attribute name.
return
The name split into three parts.
exception
SAXException The client may throw an exception if there is an error callback.

    String parts[] = nsSupport.processName(qName, nameParts,
                           isAttribute);
    if (parts == null) {
        if (useException)
        throw makeException("Undeclared prefix: " + qName);
        reportError("Undeclared prefix: " + qName);
        parts = new String[3];
        parts[0] = parts[1] = "";
        parts[2] = qName.intern();
    }
    return parts;
    
public voidprocessingInstruction(java.lang.String target, java.lang.String data)
Adapter implementation method; do not call. Adapt a SAX1 processing instruction event.

param
target The processing instruction target.
param
data The remainder of the processing instruction
exception
SAXException The client may raise a processing exception.
see
org.xml.sax.DocumentHandler#processingInstruction

    if (contentHandler != null) {
        contentHandler.processingInstruction(target, data);
    }
    
voidreportError(java.lang.String message)
Report a non-fatal error.

param
message The error message.
exception
SAXException The client may throw an exception.

    if (errorHandler != null)
        errorHandler.error(makeException(message));
    
public voidsetContentHandler(org.xml.sax.ContentHandler handler)
Set the content handler.

param
handler the new content handler
see
org.xml.sax.XMLReader#setEntityResolver

    contentHandler = handler;
    
public voidsetDTDHandler(org.xml.sax.DTDHandler handler)
Set the DTD handler.

param
handler the new DTD handler
see
org.xml.sax.XMLReader#setEntityResolver

    dtdHandler = handler;
    
public voidsetDocumentLocator(org.xml.sax.Locator locator)
Adapter implementation method; do not call. Adapt a SAX1 document locator event.

param
locator A document locator.
see
org.xml.sax.ContentHandler#setDocumentLocator

    this.locator = locator;
    if (contentHandler != null) {
        contentHandler.setDocumentLocator(locator);
    }
    
public voidsetEntityResolver(org.xml.sax.EntityResolver resolver)
Set the entity resolver.

param
resolver The new entity resolver.
see
org.xml.sax.XMLReader#setEntityResolver

    entityResolver = resolver;
    
public voidsetErrorHandler(org.xml.sax.ErrorHandler handler)
Set the error handler.

param
handler The new error handler.
see
org.xml.sax.XMLReader#setEntityResolver

    errorHandler = handler;
    
public voidsetFeature(java.lang.String name, boolean value)
Set a feature flag for the parser.

The only features recognized are namespaces and namespace-prefixes.

param
name The feature name, as a complete URI.
param
value The requested feature value.
exception
SAXNotRecognizedException If the feature can't be assigned or retrieved.
exception
SAXNotSupportedException If the feature can't be assigned that value.
see
org.xml.sax.XMLReader#setFeature



                                                                                    
          
      
    
    if (name.equals(NAMESPACES)) {
        checkNotParsing("feature", name);
        namespaces = value;
        if (!namespaces && !prefixes) {
        prefixes = true;
        }
    } else if (name.equals(NAMESPACE_PREFIXES)) {
        checkNotParsing("feature", name);
        prefixes = value;
        if (!prefixes && !namespaces) {
        namespaces = true;
        }
    } else if (name.equals(XMLNS_URIs)) {
        checkNotParsing("feature", name);
        uris = value;
    } else {
        throw new SAXNotRecognizedException("Feature: " + name);
    }
    
public voidsetProperty(java.lang.String name, java.lang.Object value)
Set a parser property.

No properties are currently recognized.

param
name The property name.
param
value The property value.
exception
SAXNotRecognizedException If the property value can't be assigned or retrieved.
exception
SAXNotSupportedException If the property can't be assigned that value.
see
org.xml.sax.XMLReader#setProperty

    throw new SAXNotRecognizedException("Property: " + name);
    
private voidsetup(org.xml.sax.Parser parser)
Internal setup method.

param
parser The embedded parser.
exception
java.lang.NullPointerException If the parser parameter is null.

    if (parser == null) {
        throw new
        NullPointerException("Parser argument must not be null");
    }
    this.parser = parser;
    atts = new AttributesImpl();
    nsSupport = new NamespaceSupport();
    attAdapter = new AttributeListAdapter();
    
private voidsetupParser()
Initialize the parser before each run.

    // catch an illegal "nonsense" state.
    if (!prefixes && !namespaces)
        throw new IllegalStateException ();

    nsSupport.reset();
    if (uris)
        nsSupport.setNamespaceDeclUris (true);

    if (entityResolver != null) {
        parser.setEntityResolver(entityResolver);
    }
    if (dtdHandler != null) {
        parser.setDTDHandler(dtdHandler);
    }
    if (errorHandler != null) {
        parser.setErrorHandler(errorHandler);
    }
    parser.setDocumentHandler(this);
    locator = null;
    
public voidstartDocument()
Adapter implementation method; do not call. Adapt a SAX1 start document event.

exception
SAXException The client may raise a processing exception.
see
org.xml.sax.DocumentHandler#startDocument

    if (contentHandler != null) {
        contentHandler.startDocument();
    }
    
public voidstartElement(java.lang.String qName, org.xml.sax.AttributeList qAtts)
Adapter implementation method; do not call. Adapt a SAX1 startElement event.

If necessary, perform Namespace processing.

param
qName The qualified (prefixed) name.
param
qAtts The XML attribute list (with qnames).
exception
SAXException The client may raise a processing exception.

                // These are exceptions from the
                // first pass; they should be
                // ignored if there's a second pass,
                // but reported otherwise.
    Vector exceptions = null;

                // If we're not doing Namespace
                // processing, dispatch this quickly.
    if (!namespaces) {
        if (contentHandler != null) {
        attAdapter.setAttributeList(qAtts);
        contentHandler.startElement("", "", qName.intern(),
                        attAdapter);
        }
        return;
    }


                // OK, we're doing Namespace processing.
    nsSupport.pushContext();
    int length = qAtts.getLength();
    
                // First pass:  handle NS decls
    for (int i = 0; i < length; i++) {
        String attQName = qAtts.getName(i);

        if (!attQName.startsWith("xmlns"))
        continue;
                // Could be a declaration...
        String prefix;
        int n = attQName.indexOf(':");

                    // xmlns=...
        if (n == -1 && attQName.length () == 5) {
        prefix = "";
        } else if (n != 5) {
        // XML namespaces spec doesn't discuss "xmlnsf:oo"
        // (and similarly named) attributes ... at most, warn
        continue;
        } else         // xmlns:foo=...
        prefix = attQName.substring(n+1);

        String value = qAtts.getValue(i);
        if (!nsSupport.declarePrefix(prefix, value)) {
        reportError("Illegal Namespace prefix: " + prefix);
        continue;
        }
        if (contentHandler != null)
        contentHandler.startPrefixMapping(prefix, value);
    }
    
                // Second pass: copy all relevant
                // attributes into the SAX2 AttributeList
                // using updated prefix bindings
    atts.clear();
    for (int i = 0; i < length; i++) {
        String attQName = qAtts.getName(i);
        String type = qAtts.getType(i);
        String value = qAtts.getValue(i);

                // Declaration?
        if (attQName.startsWith("xmlns")) {
        String prefix;
        int n = attQName.indexOf(':");

        if (n == -1 && attQName.length () == 5) {
            prefix = "";
        } else if (n != 5) {
            // XML namespaces spec doesn't discuss "xmlnsf:oo"
            // (and similarly named) attributes ... ignore
            prefix = null;
        } else {
            prefix = attQName.substring(6);
        }
                // Yes, decl:  report or prune
        if (prefix != null) {
            if (prefixes) {
            if (uris)
                // note funky case:  localname can be null
                // when declaring the default prefix, and
                // yet the uri isn't null.
                atts.addAttribute (nsSupport.XMLNS, prefix,
                    attQName.intern(), type, value);
            else
                atts.addAttribute ("", "",
                    attQName.intern(), type, value);
            }
            continue;
        }
        } 

                // Not a declaration -- report
        try {
        String attName[] = processName(attQName, true, true);
        atts.addAttribute(attName[0], attName[1], attName[2],
                  type, value);
        } catch (SAXException e) {
        if (exceptions == null)
            exceptions = new Vector();
        exceptions.addElement(e);
        atts.addAttribute("", attQName, attQName, type, value);
        }
    }
    
    // now handle the deferred exception reports
    if (exceptions != null && errorHandler != null) {
        for (int i = 0; i < exceptions.size(); i++)
        errorHandler.error((SAXParseException)
                (exceptions.elementAt(i)));
    }

                // OK, finally report the event.
    if (contentHandler != null) {
        String name[] = processName(qName, false, false);
        contentHandler.startElement(name[0], name[1], name[2], atts);
    }