FileDocCategorySizeDatePackage
DOMValidatorHelper.javaAPI DocJava SE 6 API23972Tue Jun 10 00:22:48 BST 2008com.sun.org.apache.xerces.internal.jaxp.validation

DOMValidatorHelper

public final class DOMValidatorHelper extends Object implements ValidatorHelper, EntityState

A validator helper for DOMSources.

author
Michael Glavassevich, IBM
version
$Id: DOMValidatorHelper.java,v 1.2.2.1 2007/03/15 16:01:20 spericas Exp $

Fields Summary
private static final int
CHUNK_SIZE
Chunk size (1024).
private static final int
CHUNK_MASK
Chunk mask (CHUNK_SIZE - 1).
private static final String
ERROR_REPORTER
Property identifier: error reporter.
private static final String
NAMESPACE_CONTEXT
Property identifier: namespace context.
private static final String
SCHEMA_VALIDATOR
Property identifier: XML Schema validator.
private static final String
SYMBOL_TABLE
Property identifier: symbol table.
private static final String
VALIDATION_MANAGER
Property identifier: validation manager.
private XMLErrorReporter
fErrorReporter
Error reporter.
private NamespaceSupport
fNamespaceContext
The namespace context of this document: stores namespaces in scope.
private DOMNamespaceContext
fDOMNamespaceContext
The namespace context of the DOMSource, includes context from ancestor nodes.
private XMLSchemaValidator
fSchemaValidator
Schema validator.
private SymbolTable
fSymbolTable
Symbol table
private ValidationManager
fValidationManager
Validation manager.
private XMLSchemaValidatorComponentManager
fComponentManager
Component manager.
private final SimpleLocator
fXMLLocator
Simple Locator.
private DOMDocumentHandler
fDOMValidatorHandler
DOM document handler.
private final DOMResultAugmentor
fDOMResultAugmentor
DOM result augmentor.
private final DOMResultBuilder
fDOMResultBuilder
DOM result builder.
private NamedNodeMap
fEntities
Map for tracking unparsed entities.
private char[]
fCharBuffer
Array for holding character data.
private Node
fRoot
Root node.
private Node
fCurrentElement
Current element.
final QName
fElementQName
Fields for start element, end element and characters.
final QName
fAttributeQName
final XMLAttributesImpl
fAttributes
final XMLString
fTempString
Constructors Summary
public DOMValidatorHelper(XMLSchemaValidatorComponentManager componentManager)

    
       
        fComponentManager = componentManager;
        fErrorReporter = (XMLErrorReporter) fComponentManager.getProperty(ERROR_REPORTER);
        fNamespaceContext = (NamespaceSupport) fComponentManager.getProperty(NAMESPACE_CONTEXT);
        fSchemaValidator = (XMLSchemaValidator) fComponentManager.getProperty(SCHEMA_VALIDATOR);
        fSymbolTable = (SymbolTable) fComponentManager.getProperty(SYMBOL_TABLE);        
        fValidationManager = (ValidationManager) fComponentManager.getProperty(VALIDATION_MANAGER);
    
Methods Summary
private voidbeginNode(org.w3c.dom.Node node)
Do processing for the start of a node.

        switch (node.getNodeType()) {
            case Node.ELEMENT_NODE:
                fCurrentElement = node;
                // push namespace context
                fNamespaceContext.pushContext();
                // start element
                fillQName(fElementQName, node);
                processAttributes(node.getAttributes());
                fSchemaValidator.startElement(fElementQName, fAttributes, null);
                break;
            case Node.TEXT_NODE:
                if (fDOMValidatorHandler != null) {
                    fDOMValidatorHandler.setIgnoringCharacters(true);
                    sendCharactersToValidator(node.getNodeValue());
                    fDOMValidatorHandler.setIgnoringCharacters(false);
                    fDOMValidatorHandler.characters((Text) node);
                }
                else {
                    sendCharactersToValidator(node.getNodeValue());
                }
                break;
            case Node.CDATA_SECTION_NODE:
                if (fDOMValidatorHandler != null) {
                    fDOMValidatorHandler.setIgnoringCharacters(true);
                    fSchemaValidator.startCDATA(null);
                    sendCharactersToValidator(node.getNodeValue());
                    fSchemaValidator.endCDATA(null);
                    fDOMValidatorHandler.setIgnoringCharacters(false);
                    fDOMValidatorHandler.cdata((CDATASection) node);
                }
                else {
                    fSchemaValidator.startCDATA(null);
                    sendCharactersToValidator(node.getNodeValue());
                    fSchemaValidator.endCDATA(null); 
                }
                break;
            case Node.PROCESSING_INSTRUCTION_NODE:
                /** 
                 * The validator does nothing with processing instructions so bypass it.
                 * Send the ProcessingInstruction node directly to the result builder.
                 */
                if (fDOMValidatorHandler != null) {
                    fDOMValidatorHandler.processingInstruction((ProcessingInstruction) node);
                }
                break;
            case Node.COMMENT_NODE:
                /** 
                 * The validator does nothing with comments so bypass it.
                 * Send the Comment node directly to the result builder.
                 */
                if (fDOMValidatorHandler != null) {
                    fDOMValidatorHandler.comment((Comment) node);
                }
                break;
            case Node.DOCUMENT_TYPE_NODE:
                /** 
                 * Send the DocumentType node directly to the result builder.
                 */
                if (fDOMValidatorHandler != null) {
                    fDOMValidatorHandler.doctypeDecl((DocumentType) node);
                }
                break;
            default: // Ignore other node types.
                break;
        }
    
private voidfillQName(com.sun.org.apache.xerces.internal.xni.QName toFill, org.w3c.dom.Node node)

        final String prefix = node.getPrefix();
        final String localName = node.getLocalName();
        final String rawName = node.getNodeName();
        final String namespace = node.getNamespaceURI();
        
        toFill.uri = (namespace != null && namespace.length() > 0) ? fSymbolTable.addSymbol(namespace) : null;
        toFill.rawname = (rawName != null) ? fSymbolTable.addSymbol(rawName) : XMLSymbols.EMPTY_STRING;  
        
        // Is this a DOM level1 document?
        if (localName == null) {
            int k = rawName.indexOf(':");
            if (k > 0) {
                toFill.prefix = fSymbolTable.addSymbol(rawName.substring(0, k));
                toFill.localpart = fSymbolTable.addSymbol(rawName.substring(k + 1));                
            }
            else {
                toFill.prefix = XMLSymbols.EMPTY_STRING;
                toFill.localpart = toFill.rawname;
            }            
        }
        else {
            toFill.prefix = (prefix != null) ? fSymbolTable.addSymbol(prefix) : XMLSymbols.EMPTY_STRING;
            toFill.localpart = (localName != null) ? fSymbolTable.addSymbol(localName) : XMLSymbols.EMPTY_STRING;
        }
    
private voidfinishNode(org.w3c.dom.Node node)
Do processing for the end of a node.

        if (node.getNodeType() == Node.ELEMENT_NODE) {
            fCurrentElement = node;
            // end element
            fillQName(fElementQName, node);
            fSchemaValidator.endElement(fElementQName, null);
            // pop namespace context
            fNamespaceContext.popContext();
        }
    
org.w3c.dom.NodegetCurrentElement()

        return fCurrentElement;
    
public booleanisEntityDeclared(java.lang.String name)

        return false;
    
public booleanisEntityUnparsed(java.lang.String name)

        if (fEntities != null) {
            Entity entity = (Entity) fEntities.getNamedItem(name);
            if (entity != null) {
                return (entity.getNotationName() != null);
            }
        }
        return false;
    
private voidprocessAttributes(org.w3c.dom.NamedNodeMap attrMap)

        final int attrCount = attrMap.getLength();
        fAttributes.removeAllAttributes();
        for (int i = 0; i < attrCount; ++i) {
            Attr attr = (Attr) attrMap.item(i);
            String value = attr.getValue();
            if (value == null) {
                value = XMLSymbols.EMPTY_STRING;
            }
            fillQName(fAttributeQName, attr);
            // REVISIT: Assuming all attributes are of type CDATA. The actual type may not matter. -- mrglavas
            fAttributes.addAttributeNS(fAttributeQName, XMLSymbols.fCDATASymbol, value);
            fAttributes.setSpecified(i, attr.getSpecified());
            // REVISIT: Should we be looking at non-namespace attributes
            // for additional mappings? Should we detect illegal namespace
            // declarations and exclude them from the context? -- mrglavas
            if (fAttributeQName.uri == NamespaceContext.XMLNS_URI) {
                // process namespace attribute
                if (fAttributeQName.prefix == XMLSymbols.PREFIX_XMLNS) {
                    fNamespaceContext.declarePrefix(fAttributeQName.localpart, value.length() != 0 ? fSymbolTable.addSymbol(value) : null);
                }
                else {
                    fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, value.length() != 0 ? fSymbolTable.addSymbol(value) : null);
                }
            }
        }
    
private voidsendCharactersToValidator(java.lang.String str)

        if (str != null) {
            final int length = str.length();
            final int remainder = length & CHUNK_MASK;
            if (remainder > 0) {
                str.getChars(0, remainder, fCharBuffer, 0);
                fTempString.setValues(fCharBuffer, 0, remainder);
                fSchemaValidator.characters(fTempString, null);
            }
            int i = remainder;
            while (i < length) {
                str.getChars(i, i += CHUNK_SIZE, fCharBuffer, 0);
                fTempString.setValues(fCharBuffer, 0, CHUNK_SIZE);
                fSchemaValidator.characters(fTempString, null);
            }
        }
    
private voidsetupDOMResultHandler(javax.xml.transform.dom.DOMSource source, javax.xml.transform.dom.DOMResult result)
Sets up handler for DOMResult.

        // If there's no DOMResult, unset the validator handler
        if (result == null) {
            fDOMValidatorHandler = null;
            fSchemaValidator.setDocumentHandler(null);
            return;
        }
        final Node nodeResult = result.getNode();
        // If the source node and result node are the same use the DOMResultAugmentor.
        // Otherwise use the DOMResultBuilder.
        if (source.getNode() == nodeResult) {
            fDOMValidatorHandler = fDOMResultAugmentor;
            fDOMResultAugmentor.setDOMResult(result);
            fSchemaValidator.setDocumentHandler(fDOMResultAugmentor);
            return;
        }
        if (result.getNode() == null) {
            try {
                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                factory.setNamespaceAware(true);
                DocumentBuilder builder = factory.newDocumentBuilder();
                result.setNode(builder.newDocument());
            }
            catch (ParserConfigurationException e) {
                throw new SAXException(e);
            }
        }
        fDOMValidatorHandler = fDOMResultBuilder;
        fDOMResultBuilder.setDOMResult(result);
        fSchemaValidator.setDocumentHandler(fDOMResultBuilder);
    
private voidsetupEntityMap(org.w3c.dom.Document doc)
Extracts NamedNodeMap of entities. We need this to validate elements and attributes of type xs:ENTITY, xs:ENTITIES or types dervied from them.

        if (doc != null) {
            DocumentType docType = doc.getDoctype();
            if (docType != null) {
                fEntities = docType.getEntities();
                return;
            }
        }
        fEntities = null;
    
public voidvalidate(javax.xml.transform.Source source, javax.xml.transform.Result result)

        if (result instanceof DOMResult || result == null) {
            final DOMSource domSource = (DOMSource) source;
            final DOMResult domResult = (DOMResult) result;
            Node node = domSource.getNode();
            fRoot = node;
            if (node != null) {
                fComponentManager.reset();
                fValidationManager.setEntityState(this);
                fDOMNamespaceContext.reset();
                String systemId = domSource.getSystemId();
                fXMLLocator.setLiteralSystemId(systemId);
                fXMLLocator.setExpandedSystemId(systemId);
                fErrorReporter.setDocumentLocator(fXMLLocator);
                try {
                    // regardless of what type of node this is, fire start and end document events
                    setupEntityMap((node.getNodeType() == Node.DOCUMENT_NODE) ? (Document) node : node.getOwnerDocument());
                    setupDOMResultHandler(domSource, domResult);
                    fSchemaValidator.startDocument(fXMLLocator, null, fDOMNamespaceContext, null);
                    validate(node);
                    fSchemaValidator.endDocument(null);
                }
                catch (XMLParseException e) {
                    throw Util.toSAXParseException(e);
                }
                catch (XNIException e) {
                    throw Util.toSAXException(e);
                }
                finally {
                    // Release references to application objects
                    fRoot = null;
                    fCurrentElement = null;
                    fEntities = null;
                    if (fDOMValidatorHandler != null) {
                        fDOMValidatorHandler.setDOMResult(null);
                    }
                }
            }
            return;
        }
        throw new IllegalArgumentException(JAXPValidationMessageFormatter.formatMessage(Locale.getDefault(), 
                "SourceResultMismatch", 
                new Object [] {source.getClass().getName(), result.getClass().getName()}));
    
private voidvalidate(org.w3c.dom.Node node)
Traverse the DOM and fire events to the schema validator.

        final Node top = node;
        // Performs a non-recursive traversal of the DOM. This
        // will avoid a stack overflow for DOMs with high depth.
        while (node != null) {
            beginNode(node);
            Node next = node.getFirstChild();
            while (next == null) {
                finishNode(node);           
                if (top == node) {
                    break;
                }
                next = node.getNextSibling();
                if (next == null) {
                    node = node.getParentNode();
                    if (node == null || top == node) {
                        if (node != null) {
                            finishNode(node);
                        }
                        next = null;
                        break;
                    }
                }
            }
            node = next;
        }