- /*
- * The Apache Software License, Version 1.1
- *
- *
- * Copyright (c) 1999-2003 The Apache Software Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Xerces" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 1999, International
- * Business Machines, Inc., http://www.apache.org. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
- package com.sun.org.apache.xerces.internal.impl.dtd;
-
- import com.sun.org.apache.xerces.internal.impl.Constants;
- import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
- import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
- import com.sun.org.apache.xerces.internal.impl.dtd.models.ContentModelValidator;
- import com.sun.org.apache.xerces.internal.impl.dv.DTDDVFactory;
- import com.sun.org.apache.xerces.internal.impl.dv.DatatypeValidator;
- import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
- import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
- import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
- import com.sun.org.apache.xerces.internal.impl.validation.ValidationState;
- import com.sun.org.apache.xerces.internal.util.SymbolTable;
- import com.sun.org.apache.xerces.internal.util.XMLChar;
- import com.sun.org.apache.xerces.internal.util.XMLSymbols;
- import com.sun.org.apache.xerces.internal.xni.Augmentations;
- import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
- import com.sun.org.apache.xerces.internal.xni.QName;
- import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
- import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
- import com.sun.org.apache.xerces.internal.xni.XMLLocator;
- import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
- import com.sun.org.apache.xerces.internal.xni.XMLString;
- import com.sun.org.apache.xerces.internal.xni.XNIException;
- import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
- import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
- import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
- import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
- import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
- import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
- import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentFilter;
- import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
-
- /**
- * The DTD validator. The validator implements a document
- * filter: receiving document events from the scanner; validating
- * the content and structure; augmenting the InfoSet, if applicable;
- * and notifying the parser of the information resulting from the
- * validation process.
- * <p> Formerly, this component also handled DTD events and grammar construction.
- * To facilitate the development of a meaningful DTD grammar caching/preparsing
- * framework, this functionality has been moved into the XMLDTDLoader
- * class. Therefore, this class no longer implements the DTDFilter
- * or DTDContentModelFilter interfaces.
- * <p>
- * This component requires the following features and properties from the
- * component manager that uses it:
- * <ul>
- * <li>http://xml.org/sax/features/namespaces</li>
- * <li>http://xml.org/sax/features/validation</li>
- * <li>http://apache.org/xml/features/validation/dynamic</li>
- * <li>http://apache.org/xml/properties/internal/symbol-table</li>
- * <li>http://apache.org/xml/properties/internal/error-reporter</li>
- * <li>http://apache.org/xml/properties/internal/grammar-pool</li>
- * <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
- * </ul>
- *
- * @author Eric Ye, IBM
- * @author Andy Clark, IBM
- * @author Jeffrey Rodriguez IBM
- * @author Neil Graham, IBM
- *
- * @version $Id: XMLDTDValidator.java,v 1.59 2004/04/25 05:05:49 mrglavas Exp $
- */
- public class XMLDTDValidator
- implements XMLComponent, XMLDocumentFilter, XMLDTDValidatorFilter {
-
- //
- // Constants
- //
-
- /** Symbol: "<<datatypes>>". */
-
- /** Top level scope (-1). */
- private static final int TOP_LEVEL_SCOPE = -1;
-
- // feature identifiers
-
- /** Feature identifier: namespaces. */
- protected static final String NAMESPACES =
- Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
-
- /** Feature identifier: validation. */
- protected static final String VALIDATION =
- Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
-
- /** Feature identifier: dynamic validation. */
- protected static final String DYNAMIC_VALIDATION =
- Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
-
- /** Feature identifier: warn on duplicate attdef */
- protected static final String WARN_ON_DUPLICATE_ATTDEF =
- Constants.XERCES_FEATURE_PREFIX +Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
-
- protected static final String PARSER_SETTINGS =
- Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
-
-
-
- // property identifiers
-
- /** Property identifier: symbol table. */
- protected static final String SYMBOL_TABLE =
- Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
-
- /** Property identifier: error reporter. */
- protected static final String ERROR_REPORTER =
- Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
-
- /** Property identifier: grammar pool. */
- protected static final String GRAMMAR_POOL =
- Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
-
- /** Property identifier: datatype validator factory. */
- protected static final String DATATYPE_VALIDATOR_FACTORY =
- Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
-
- // property identifier: ValidationManager
- protected static final String VALIDATION_MANAGER =
- Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
-
- // recognized features and properties
-
- /** Recognized features. */
- private static final String[] RECOGNIZED_FEATURES = {
- NAMESPACES,
- VALIDATION,
- DYNAMIC_VALIDATION
- };
-
- /** Feature defaults. */
- private static final Boolean[] FEATURE_DEFAULTS = {
- null,
- null,
- Boolean.FALSE,
- };
-
- /** Recognized properties. */
- private static final String[] RECOGNIZED_PROPERTIES = {
- SYMBOL_TABLE,
- ERROR_REPORTER,
- GRAMMAR_POOL,
- DATATYPE_VALIDATOR_FACTORY,
- VALIDATION_MANAGER
- };
-
- /** Property defaults. */
- private static final Object[] PROPERTY_DEFAULTS = {
- null,
- null,
- null,
- null,
- null,
- };
-
- // debugging
-
- /** Compile to true to debug attributes. */
- private static final boolean DEBUG_ATTRIBUTES = false;
-
- /** Compile to true to debug element children. */
- private static final boolean DEBUG_ELEMENT_CHILDREN = false;
-
- //
- // Data
- //
-
- // updated during reset
- protected ValidationManager fValidationManager = null;
-
- // validation state
- protected ValidationState fValidationState = new ValidationState();
-
- // features
-
- /** Namespaces. */
- protected boolean fNamespaces;
-
- /** Validation. */
- protected boolean fValidation;
-
- /** Validation against only DTD */
- protected boolean fDTDValidation;
-
- /**
- * Dynamic validation. This state of this feature is only useful when
- * the validation feature is set to <code>true</code>.
- */
- protected boolean fDynamicValidation;
-
- /** warn on duplicate attribute definition, this feature works only when validation is true */
- protected boolean fWarnDuplicateAttdef;
-
- // properties
-
- /** Symbol table. */
- protected SymbolTable fSymbolTable;
-
- /** Error reporter. */
- protected XMLErrorReporter fErrorReporter;
-
- // the grammar pool
- protected XMLGrammarPool fGrammarPool;
-
- /** Grammar bucket. */
- protected DTDGrammarBucket fGrammarBucket;
-
- /* location of the document as passed in from startDocument call */
- protected XMLLocator fDocLocation;
-
- /** Namespace support. */
- protected NamespaceContext fNamespaceContext = null;
-
- /** Datatype validator factory. */
- protected DTDDVFactory fDatatypeValidatorFactory;
-
- // handlers
-
- /** Document handler. */
- protected XMLDocumentHandler fDocumentHandler;
-
- protected XMLDocumentSource fDocumentSource;
- // grammars
-
- /** DTD Grammar. */
- protected DTDGrammar fDTDGrammar;
-
- // state
-
- /** True if seen DOCTYPE declaration. */
- protected boolean fSeenDoctypeDecl = false;
-
- /** Perform validation. */
- private boolean fPerformValidation;
-
- /** Schema type: None, DTD, Schema */
- private String fSchemaType;
-
- // information regarding the current element
-
- /** Current element name. */
- private final QName fCurrentElement = new QName();
-
- /** Current element index. */
- private int fCurrentElementIndex = -1;
-
- /** Current content spec type. */
- private int fCurrentContentSpecType = -1;
-
- /** The root element name. */
- private final QName fRootElement = new QName();
-
- private boolean fInCDATASection = false;
- // element stack
-
- /** Element index stack. */
- private int[] fElementIndexStack = new int[8];
-
- /** Content spec type stack. */
- private int[] fContentSpecTypeStack = new int[8];
-
- /** Element name stack. */
- private QName[] fElementQNamePartsStack = new QName[8];
-
- // children list and offset stack
-
- /**
- * Element children. This data structure is a growing stack that
- * holds the children of elements from the root to the current
- * element depth. This structure never gets "deeper" than the
- * deepest element. Space is re-used once each element is closed.
- * <p>
- * <strong>Note:</strong> This is much more efficient use of memory
- * than creating new arrays for each element depth.
- * <p>
- * <strong>Note:</strong> The use of this data structure is for
- * validation "on the way out". If the validation model changes to
- * "on the way in", then this data structure is not needed.
- */
- private QName[] fElementChildren = new QName[32];
-
- /** Element children count. */
- private int fElementChildrenLength = 0;
-
- /**
- * Element children offset stack. This stack refers to offsets
- * into the <code>fElementChildren</code> array.
- * @see #fElementChildren
- */
- private int[] fElementChildrenOffsetStack = new int[32];
-
- /** Element depth. */
- private int fElementDepth = -1;
-
- // validation states
-
- /** True if seen the root element. */
- private boolean fSeenRootElement = false;
-
- /** True if inside of element content. */
- private boolean fInElementContent = false;
-
- // temporary variables
-
- /** Temporary element declaration. */
- private XMLElementDecl fTempElementDecl = new XMLElementDecl();
-
- /** Temporary atribute declaration. */
- private XMLAttributeDecl fTempAttDecl = new XMLAttributeDecl();
-
- /** Temporary entity declaration. */
- private XMLEntityDecl fEntityDecl = new XMLEntityDecl();
-
- /** Temporary qualified name. */
- private QName fTempQName = new QName();
-
- /** Temporary string buffers. */
- private StringBuffer fBuffer = new StringBuffer();
-
- // symbols: general
-
- // attribute validators
-
- /** Datatype validator: ID. */
- protected DatatypeValidator fValID;
-
- /** Datatype validator: IDREF. */
- protected DatatypeValidator fValIDRef;
-
- /** Datatype validator: IDREFS. */
- protected DatatypeValidator fValIDRefs;
-
- /** Datatype validator: ENTITY. */
- protected DatatypeValidator fValENTITY;
-
- /** Datatype validator: ENTITIES. */
- protected DatatypeValidator fValENTITIES;
-
- /** Datatype validator: NMTOKEN. */
- protected DatatypeValidator fValNMTOKEN;
-
- /** Datatype validator: NMTOKENS. */
- protected DatatypeValidator fValNMTOKENS;
-
- /** Datatype validator: NOTATION. */
- protected DatatypeValidator fValNOTATION;
-
- // to check for duplicate ID or ANNOTATION attribute declare in
- // ATTLIST, and misc VCs
-
- //
- // Constructors
- //
-
- /** Default constructor. */
- public XMLDTDValidator() {
-
- // initialize data
- for (int i = 0; i < fElementQNamePartsStack.length; i++) {
- fElementQNamePartsStack[i] = new QName();
- }
- fGrammarBucket = new DTDGrammarBucket();
-
- } // <init>()
-
- DTDGrammarBucket getGrammarBucket() {
- return fGrammarBucket;
- } // getGrammarBucket(): DTDGrammarBucket
-
- //
- // XMLComponent methods
- //
-
- /*
- * Resets the component. The component can query the component manager
- * about any features and properties that affect the operation of the
- * component.
- *
- * @param componentManager The component manager.
- *
- * @throws SAXException Thrown by component on finitialization error.
- * For example, if a feature or property is
- * required for the operation of the component, the
- * component manager may throw a
- * SAXNotRecognizedException or a
- * SAXNotSupportedException.
- */
- public void reset(XMLComponentManager componentManager)
- throws XMLConfigurationException {
-
- // clear grammars
- fDTDGrammar = null;
- fSeenDoctypeDecl = false;
- fInCDATASection = false;
- // initialize state
- fSeenRootElement = false;
- fInElementContent = false;
- fCurrentElementIndex = -1;
- fCurrentContentSpecType = -1;
-
- fRootElement.clear();
-
- fValidationState.resetIDTables();
-
- fGrammarBucket.clear();
- fElementDepth = -1;
- fElementChildrenLength = 0;
-
- boolean parser_settings;
- try {
- parser_settings = componentManager.getFeature(PARSER_SETTINGS);
- }
- catch (XMLConfigurationException e){
- parser_settings = true;
- }
-
- if (!parser_settings){
- // parser settings have not been changed
- fValidationManager.addValidationState(fValidationState);
- return;
- }
-
- // sax features
- try {
- fNamespaces = componentManager.getFeature(NAMESPACES);
- }
- catch (XMLConfigurationException e) {
- fNamespaces = true;
- }
- try {
- fValidation = componentManager.getFeature(VALIDATION);
- }
- catch (XMLConfigurationException e) {
- fValidation = false;
- }
- try {
- fDTDValidation = !(componentManager.getFeature(Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE));
- }
- catch (XMLConfigurationException e) {
- // must be in a schema-less configuration!
- fDTDValidation = true;
- }
-
- // Xerces features
- try {
- fDynamicValidation = componentManager.getFeature(DYNAMIC_VALIDATION);
- }
- catch (XMLConfigurationException e) {
- fDynamicValidation = false;
- }
-
- try {
- fWarnDuplicateAttdef = componentManager.getFeature(WARN_ON_DUPLICATE_ATTDEF);
- }
- catch (XMLConfigurationException e) {
- fWarnDuplicateAttdef = false;
- }
-
- try {
- fSchemaType = (String)componentManager.getProperty (Constants.JAXP_PROPERTY_PREFIX
- + Constants.SCHEMA_LANGUAGE);
- }
- catch (XMLConfigurationException e){
- fSchemaType = null;
- }
-
- fValidationManager= (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER);
- fValidationManager.addValidationState(fValidationState);
- fValidationState.setUsingNamespaces(fNamespaces);
-
- // get needed components
- fErrorReporter = (XMLErrorReporter)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX+Constants.ERROR_REPORTER_PROPERTY);
- fSymbolTable = (SymbolTable)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX+Constants.SYMBOL_TABLE_PROPERTY);
- try {
- fGrammarPool= (XMLGrammarPool)componentManager.getProperty(GRAMMAR_POOL);
- } catch (XMLConfigurationException e) {
- fGrammarPool = null;
- }
-
- fDatatypeValidatorFactory = (DTDDVFactory)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY);
- init();
-
- } // reset(XMLComponentManager)
-
- /**
- * Returns a list of feature identifiers that are recognized by
- * this component. This method may return null if no features
- * are recognized by this component.
- */
- public String[] getRecognizedFeatures() {
- return (String[])(RECOGNIZED_FEATURES.clone());
- } // getRecognizedFeatures():String[]
-
- /**
- * Sets the state of a feature. This method is called by the component
- * manager any time after reset when a feature changes state.
- * <p>
- * <strong>Note:</strong> Components should silently ignore features
- * that do not affect the operation of the component.
- *
- * @param featureId The feature identifier.
- * @param state The state of the feature.
- *
- * @throws SAXNotRecognizedException The component should not throw
- * this exception.
- * @throws SAXNotSupportedException The component should not throw
- * this exception.
- */
- public void setFeature(String featureId, boolean state)
- throws XMLConfigurationException {
- } // setFeature(String,boolean)
-
- /**
- * Returns a list of property identifiers that are recognized by
- * this component. This method may return null if no properties
- * are recognized by this component.
- */
- public String[] getRecognizedProperties() {
- return (String[])(RECOGNIZED_PROPERTIES.clone());
- } // getRecognizedProperties():String[]
-
- /**
- * Sets the value of a property. This method is called by the component
- * manager any time after reset when a property changes value.
- * <p>
- * <strong>Note:</strong> Components should silently ignore properties
- * that do not affect the operation of the component.
- *
- * @param propertyId The property identifier.
- * @param value The value of the property.
- *
- * @throws SAXNotRecognizedException The component should not throw
- * this exception.
- * @throws SAXNotSupportedException The component should not throw
- * this exception.
- */
- public void setProperty(String propertyId, Object value)
- throws XMLConfigurationException {
- } // setProperty(String,Object)
-
- /**
- * Returns the default state for a feature, or null if this
- * component does not want to report a default value for this
- * feature.
- *
- * @param featureId The feature identifier.
- *
- * @since Xerces 2.2.0
- */
- public Boolean getFeatureDefault(String featureId) {
- for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
- if (RECOGNIZED_FEATURES[i].equals(featureId)) {
- return FEATURE_DEFAULTS[i];
- }
- }
- return null;
- } // getFeatureDefault(String):Boolean
-
- /**
- * Returns the default state for a property, or null if this
- * component does not want to report a default value for this
- * property.
- *
- * @param propertyId The property identifier.
- *
- * @since Xerces 2.2.0
- */
- public Object getPropertyDefault(String propertyId) {
- for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
- if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
- return PROPERTY_DEFAULTS[i];
- }
- }
- return null;
- } // getPropertyDefault(String):Object
-
- //
- // XMLDocumentSource methods
- //
-
- /** Sets the document handler to receive information about the document. */
- public void setDocumentHandler(XMLDocumentHandler documentHandler) {
- fDocumentHandler = documentHandler;
- } // setDocumentHandler(XMLDocumentHandler)
-
- /** Returns the document handler */
- public XMLDocumentHandler getDocumentHandler() {
- return fDocumentHandler;
- } // getDocumentHandler(): XMLDocumentHandler
-
-
- //
- // XMLDocumentHandler methods
- //
-
- /** Sets the document source */
- public void setDocumentSource(XMLDocumentSource source){
- fDocumentSource = source;
- } // setDocumentSource
-
- /** Returns the document source */
- public XMLDocumentSource getDocumentSource (){
- return fDocumentSource;
- } // getDocumentSource
-
- /**
- * The start of the document.
- *
- * @param locator The system identifier of the entity if the entity
- * is external, null otherwise.
- * @param encoding The auto-detected IANA encoding name of the entity
- * stream. This value will be null in those situations
- * where the entity encoding is not auto-detected (e.g.
- * internal entities or a document entity that is
- * parsed from a java.io.Reader).
- * @param namespaceContext
- * The namespace context in effect at the
- * start of this document.
- * This object represents the current context.
- * Implementors of this class are responsible
- * for copying the namespace bindings from the
- * the current context (and its parent contexts)
- * if that information is important.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void startDocument(XMLLocator locator, String encoding,
- NamespaceContext namespaceContext, Augmentations augs)
- throws XNIException {
-
- // call handlers
- // get initial grammars
- if(fGrammarPool != null) {
- Grammar [] grammars = fGrammarPool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_DTD);
- for(int i = 0; i<grammars.length; i++) {
- fGrammarBucket.putGrammar((DTDGrammar)grammars[i]);
- }
- }
- fDocLocation = locator;
- fNamespaceContext = namespaceContext;
-
- if (fDocumentHandler != null) {
- fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
- }
-
- } // startDocument(XMLLocator,String)
-
- /**
- * Notifies of the presence of an XMLDecl line in the document. If
- * present, this method will be called immediately following the
- * startDocument call.
- *
- * @param version The XML version.
- * @param encoding The IANA encoding name of the document, or null if
- * not specified.
- * @param standalone The standalone value, or null if not specified.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void xmlDecl(String version, String encoding, String standalone, Augmentations augs)
- throws XNIException {
-
- // save standalone state
- fGrammarBucket.setStandalone(standalone != null && standalone.equals("yes"));
-
- // call handlers
- if (fDocumentHandler != null) {
- fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
- }
-
- } // xmlDecl(String,String,String)
-
- /**
- * Notifies of the presence of the DOCTYPE line in the document.
- *
- * @param rootElement The name of the root element.
- * @param publicId The public identifier if an external DTD or null
- * if the external DTD is specified using SYSTEM.
- * @param systemId The system identifier if an external DTD, null
- * otherwise.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void doctypeDecl(String rootElement, String publicId, String systemId,
- Augmentations augs)
- throws XNIException {
-
- // save root element state
- fSeenDoctypeDecl = true;
- fRootElement.setValues(null, rootElement, rootElement, null);
- // find or create grammar:
- String eid = null;
- try {
- eid = XMLEntityManager.expandSystemId(systemId, fDocLocation.getExpandedSystemId(), false);
- } catch (java.io.IOException e) {
- }
- XMLDTDDescription grammarDesc = new XMLDTDDescription(publicId, systemId, fDocLocation.getExpandedSystemId(), eid, rootElement);
- fDTDGrammar = fGrammarBucket.getGrammar(grammarDesc);
- if(fDTDGrammar == null) {
- // give grammar pool a chance...
- if(fGrammarPool != null) {
- fDTDGrammar = (DTDGrammar)fGrammarPool.retrieveGrammar(grammarDesc);
- }
- }
- if(fDTDGrammar == null) {
- // we'll have to create it...
- fDTDGrammar = new DTDGrammar(fSymbolTable, grammarDesc);
- } else {
- // we've found a cached one;so let's make sure not to read
- // any external subset!
- fValidationManager.setCachedDTD(true);
- }
- fGrammarBucket.setActiveGrammar(fDTDGrammar);
-
- // call handlers
- if (fDocumentHandler != null) {
- fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
- }
-
- } // doctypeDecl(String,String,String, Augmentations)
-
-
- /**
- * The start of an element.
- *
- * @param element The name of the element.
- * @param attributes The element attributes.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
- throws XNIException {
-
- handleStartElement(element, attributes, augs);
- // call handlers
- if (fDocumentHandler != null) {
- fDocumentHandler.startElement(element, attributes, augs);
-
- }
-
- } // startElement(QName,XMLAttributes)
-
- /**
- * An empty element.
- *
- * @param element The name of the element.
- * @param attributes The element attributes.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
- throws XNIException {
-
- boolean removed = handleStartElement(element, attributes, augs);
-
- if (fDocumentHandler !=null) {
- fDocumentHandler.emptyElement(element, attributes, augs);
- }
- if (!removed) {
- handleEndElement(element, augs, true);
- }
-
-
- } // emptyElement(QName,XMLAttributes)
-
- /**
- * Character content.
- *
- * @param text The content.
- *
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void characters(XMLString text, Augmentations augs) throws XNIException {
-
- boolean callNextCharacters = true;
-
- // REVISIT: [Q] Is there a more efficient way of doing this?
- // Perhaps if the scanner told us so we don't have to
- // look at the characters again. -Ac
- boolean allWhiteSpace = true;
- for (int i=text.offset; i< text.offset+text.length; i++) {
- if (!isSpace(text.ch[i])) {
- allWhiteSpace = false;
- break;
- }
- }
- // call the ignoreableWhiteSpace callback
- // never call ignorableWhitespace if we are in cdata section
- if (fInElementContent && allWhiteSpace && !fInCDATASection) {
- if (fDocumentHandler != null) {
- fDocumentHandler.ignorableWhitespace(text, augs);
- callNextCharacters = false;
- }
- }
-
- // validate
- if (fPerformValidation) {
- if (fInElementContent) {
- if (fGrammarBucket.getStandalone() &&
- fDTDGrammar.getElementDeclIsExternal(fCurrentElementIndex)) {
- if (allWhiteSpace) {
- fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
- "MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE",
- null, XMLErrorReporter.SEVERITY_ERROR);
- }
- }
- if (!allWhiteSpace) {
- charDataInContent();
- }
-
- // For E15.2
- if (augs != null && augs.getItem(Constants.CHAR_REF_PROBABLE_WS) == Boolean.TRUE) {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_CONTENT_INVALID_SPECIFIED",
- new Object[]{ fCurrentElement.rawname,
- fDTDGrammar.getContentSpecAsString(fElementDepth),
- "character reference"},
- XMLErrorReporter.SEVERITY_ERROR);
- }
- }
-
- if (fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
- charDataInContent();
- }
- }
-
- // call handlers
- if (callNextCharacters && fDocumentHandler != null) {
- fDocumentHandler.characters(text, augs);
- }
-
- } // characters(XMLString)
-
-
-
- /**
- * Ignorable whitespace. For this method to be called, the document
- * source must have some way of determining that the text containing
- * only whitespace characters should be considered ignorable. For
- * example, the validator can determine if a length of whitespace
- * characters in the document are ignorable based on the element
- * content model.
- *
- * @param text The ignorable whitespace.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
-
- // call handlers
- if (fDocumentHandler != null) {
- fDocumentHandler.ignorableWhitespace(text, augs);
- }
-
- } // ignorableWhitespace(XMLString)
-
- /**
- * The end of an element.
- *
- * @param element The name of the element.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void endElement(QName element, Augmentations augs) throws XNIException {
-
- handleEndElement(element, augs, false);
-
- } // endElement(QName)
-
- /**
- * The start of a CDATA section.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void startCDATA(Augmentations augs) throws XNIException {
-
- if (fPerformValidation && fInElementContent) {
- charDataInContent();
- }
- fInCDATASection = true;
- // call handlers
- if (fDocumentHandler != null) {
- fDocumentHandler.startCDATA(augs);
- }
-
- } // startCDATA()
-
- /**
- * The end of a CDATA section.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void endCDATA(Augmentations augs) throws XNIException {
-
- fInCDATASection = false;
- // call handlers
- if (fDocumentHandler != null) {
- fDocumentHandler.endCDATA(augs);
- }
-
- } // endCDATA()
-
- /**
- * The end of the document.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void endDocument(Augmentations augs) throws XNIException {
-
- // call handlers
- if (fDocumentHandler != null) {
- fDocumentHandler.endDocument(augs);
- }
-
- } // endDocument()
-
- /**
- * A comment.
- *
- * @param text The text in the comment.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by application to signal an error.
- */
- public void comment(XMLString text, Augmentations augs) throws XNIException {
- // fixes E15.1
- if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
- fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
- if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_CONTENT_INVALID_SPECIFIED",
- new Object[]{ fCurrentElement.rawname,
- "EMPTY",
- "comment"},
- XMLErrorReporter.SEVERITY_ERROR);
- }
- }
- // call handlers
- if (fDocumentHandler != null) {
- fDocumentHandler.comment(text, augs);
- }
-
- } // comment(XMLString)
-
-
- /**
- * A processing instruction. Processing instructions consist of a
- * target name and, optionally, text data. The data is only meaningful
- * to the application.
- * <p>
- * Typically, a processing instruction's data will contain a series
- * of pseudo-attributes. These pseudo-attributes follow the form of
- * element attributes but are <strong>not</strong> parsed or presented
- * to the application as anything other than text. The application is
- * responsible for parsing the data.
- *
- * @param target The target.
- * @param data The data or null if none specified.
- * @param augs Additional information that may include infoset augmentations
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void processingInstruction(String target, XMLString data, Augmentations augs)
- throws XNIException {
-
- // fixes E15.1
- if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
- fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
- if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_CONTENT_INVALID_SPECIFIED",
- new Object[]{ fCurrentElement.rawname,
- "EMPTY",
- "processing instruction"},
- XMLErrorReporter.SEVERITY_ERROR);
- }
- }
- // call handlers
- if (fDocumentHandler != null) {
- fDocumentHandler.processingInstruction(target, data, augs);
- }
- } // processingInstruction(String,XMLString)
-
- /**
- * This method notifies the start of a general entity.
- * <p>
- * <strong>Note:</strong> This method is not called for entity references
- * appearing as part of attribute values.
- *
- * @param name The name of the general entity.
- * @param identifier The resource identifier.
- * @param encoding The auto-detected IANA encoding name of the entity
- * stream. This value will be null in those situations
- * where the entity encoding is not auto-detected (e.g.
- * internal entities or a document entity that is
- * parsed from a java.io.Reader).
- * @param augs Additional information that may include infoset augmentations
- *
- * @exception XNIException Thrown by handler to signal an error.
- */
- public void startGeneralEntity(String name,
- XMLResourceIdentifier identifier,
- String encoding,
- Augmentations augs) throws XNIException {
- if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
- fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
- // fixes E15.1
- if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_CONTENT_INVALID_SPECIFIED",
- new Object[]{ fCurrentElement.rawname,
- "EMPTY", "ENTITY"},
- XMLErrorReporter.SEVERITY_ERROR);
- }
- if (fGrammarBucket.getStandalone()) {
- XMLDTDLoader.checkStandaloneEntityRef(name, fDTDGrammar, fEntityDecl, fErrorReporter);
- }
- }
- if (fDocumentHandler != null) {
- fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
- }
- }
-
- /**
- * This method notifies the end of a general entity.
- * <p>
- * <strong>Note:</strong> This method is not called for entity references
- * appearing as part of attribute values.
- *
- * @param name The name of the entity.
- * @param augs Additional information that may include infoset augmentations
- *
- * @exception XNIException
- * Thrown by handler to signal an error.
- */
- public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
- // call handlers
- if (fDocumentHandler != null) {
- fDocumentHandler.endGeneralEntity(name, augs);
- }
- } // endEntity(String)
-
- /**
- * Notifies of the presence of a TextDecl line in an entity. If present,
- * this method will be called immediately following the startParameterEntity call.
- * <p>
- * <strong>Note:</strong> This method is only called for external
- * parameter entities referenced in the DTD.
- *
- * @param version The XML version, or null if not specified.
- * @param encoding The IANA encoding name of the entity.
- * @param augs Additional information that may include infoset
- * augmentations.
- *
- * @throws XNIException Thrown by handler to signal an error.
- */
- public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
-
- // call handlers
- if (fDocumentHandler != null) {
- fDocumentHandler.textDecl(version, encoding, augs);
- }
- }
-
-
- public final boolean hasGrammar(){
-
- return (fDTDGrammar != null);
- }
-
- public final boolean validate(){
- // Do validation if all of the following are true:
- // 1. The JAXP Schema Language property is not XML Schema
- // REVISIT: since only DTD and Schema are supported at this time,
- // such checking is sufficient. but if more schema types
- // are introduced in the future, we'll need to change it
- // to something like
- // (fSchemaType == null || fSchemaType == NS_XML_DTD)
- // 2. One of the following is true (validation features)
- // 2.1 Dynamic validation is off, and validation is on
- // 2.2 Dynamic validation is on, and DOCTYPE was seen
- // 3 Xerces schema validation feature is off, or DOCTYPE was seen.
- return (fSchemaType != Constants.NS_XMLSCHEMA) &&
- (!fDynamicValidation && fValidation ||
- fDynamicValidation && fSeenDoctypeDecl) &&
- (fDTDValidation || fSeenDoctypeDecl);
- }
-
- //REVISIT:we can convert into functions.. adding default attribute values.. and one validating.
-
- /** Add default attributes and validate. */
- protected void addDTDDefaultAttrsAndValidate(QName elementName, int elementIndex,
- XMLAttributes attributes)
- throws XNIException {
-
- // is there anything to do?
- if (elementIndex == -1 || fDTDGrammar == null) {
- return;
- }
-
- //
- // Check after all specified attrs are scanned
- // (1) report error for REQUIRED attrs that are missing (V_TAGc)
- // (2) add default attrs (FIXED and NOT_FIXED)
- //
- int attlistIndex = fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);
-
- while (attlistIndex != -1) {
-
- fDTDGrammar.getAttributeDecl(attlistIndex, fTempAttDecl);
-
- if (DEBUG_ATTRIBUTES) {
- if (fTempAttDecl != null) {
- XMLElementDecl elementDecl = new XMLElementDecl();
- fDTDGrammar.getElementDecl(elementIndex, elementDecl);
- System.out.println("element: "+(elementDecl.name.localpart));
- System.out.println("attlistIndex " + attlistIndex + "\n"+
- "attName : '"+(fTempAttDecl.name.localpart) + "'\n"
- + "attType : "+fTempAttDecl.simpleType.type + "\n"
- + "attDefaultType : "+fTempAttDecl.simpleType.defaultType + "\n"
- + "attDefaultValue : '"+fTempAttDecl.simpleType.defaultValue + "'\n"
- + attributes.getLength() +"\n"
- );
- }
- }
- String attPrefix = fTempAttDecl.name.prefix;
- String attLocalpart = fTempAttDecl.name.localpart;
- String attRawName = fTempAttDecl.name.rawname;
- String attType = getAttributeTypeName(fTempAttDecl);
- int attDefaultType =fTempAttDecl.simpleType.defaultType;
- String attValue = null;
-
- if (fTempAttDecl.simpleType.defaultValue != null) {
- attValue = fTempAttDecl.simpleType.defaultValue;
- }
-
- boolean specified = false;
- boolean required = attDefaultType == XMLSimpleType.DEFAULT_TYPE_REQUIRED;
- boolean cdata = attType == XMLSymbols.fCDATASymbol;
-
- if (!cdata || required || attValue != null) {
- int attrCount = attributes.getLength();
- for (int i = 0; i < attrCount; i++) {
- if (attributes.getQName(i) == attRawName) {
- specified = true;
- break;
- }
- }
- }
-
- if (!specified) {
- if (required) {
- if (fPerformValidation) {
- Object[] args = {elementName.localpart, attRawName};
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED", args,
- XMLErrorReporter.SEVERITY_ERROR);
- }
- }
- else if (attValue != null) {
- if (fPerformValidation && fGrammarBucket.getStandalone()) {
- if (fDTDGrammar.getAttributeDeclIsExternal(attlistIndex)) {
-
- Object[] args = { elementName.localpart, attRawName};
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED", args,
- XMLErrorReporter.SEVERITY_ERROR);
- }
- }
-
- // add namespace information
- if (fNamespaces) {
- int index = attRawName.indexOf(':');
- if (index != -1) {
- attPrefix = attRawName.substring(0, index);
- attPrefix = fSymbolTable.addSymbol(attPrefix);
- attLocalpart = attRawName.substring(index + 1);
- attLocalpart = fSymbolTable.addSymbol(attLocalpart);
- }
- }
-
- // add attribute
- fTempQName.setValues(attPrefix, attLocalpart, attRawName, fTempAttDecl.name.uri);
- int newAttr = attributes.addAttribute(fTempQName, attType, attValue);
- }
- }
- // get next att decl in the Grammar for this element
- attlistIndex = fDTDGrammar.getNextAttributeDeclIndex(attlistIndex);
- }
-
- // now iterate through the expanded attributes for
- // 1. if every attribute seen is declared in the DTD
- // 2. check if the VC: default_fixed holds
- // 3. validate every attribute.
- int attrCount = attributes.getLength();
- for (int i = 0; i < attrCount; i++) {
- String attrRawName = attributes.getQName(i);
- boolean declared = false;
- if (fPerformValidation) {
- if (fGrammarBucket.getStandalone()) {
- // check VC: Standalone Document Declaration, entities
- // references appear in the document.
- // REVISIT: this can be combined to a single check in
- // startEntity if we add one more argument in
- // startEnity, inAttrValue
- String nonNormalizedValue = attributes.getNonNormalizedValue(i);
- if (nonNormalizedValue != null) {
- String entityName = getExternalEntityRefInAttrValue(nonNormalizedValue);
- if (entityName != null) {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE",
- new Object[]{entityName},
- XMLErrorReporter.SEVERITY_ERROR);
- }
- }
- }
- }
- int attDefIndex = -1;
- int position =
- fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);
- while (position != -1) {
- fDTDGrammar.getAttributeDecl(position, fTempAttDecl);
- if (fTempAttDecl.name.rawname == attrRawName) {
- // found the match att decl,
- attDefIndex = position;
- declared = true;
- break;
- }
- position = fDTDGrammar.getNextAttributeDeclIndex(position);
- }
- if (!declared) {
- if (fPerformValidation) {
- // REVISIT - cache the elem/attr tuple so that we only
- // give this error once for each unique occurrence
- Object[] args = { elementName.rawname, attrRawName};
-
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_ATTRIBUTE_NOT_DECLARED",
- args,XMLErrorReporter.SEVERITY_ERROR);
- }
- continue;
- }
- // attribute is declared
-
- // fTempAttDecl should have the right value set now, so
- // the following is not needed
- // fGrammar.getAttributeDecl(attDefIndex,fTempAttDecl);
-
- String type = getAttributeTypeName(fTempAttDecl);
- attributes.setType(i, type);
- attributes.getAugmentations(i).putItem(Constants.ATTRIBUTE_DECLARED, Boolean.TRUE);
-
- boolean changedByNormalization = false;
- String oldValue = attributes.getValue(i);
- String attrValue = oldValue;
- if (attributes.isSpecified(i) && type != XMLSymbols.fCDATASymbol) {
- changedByNormalization = normalizeAttrValue(attributes, i);
- attrValue = attributes.getValue(i);
- if (fPerformValidation && fGrammarBucket.getStandalone()
- && changedByNormalization
- && fDTDGrammar.getAttributeDeclIsExternal(position)
- ) {
- // check VC: Standalone Document Declaration
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE",
- new Object[]{attrRawName, oldValue, attrValue},
- XMLErrorReporter.SEVERITY_ERROR);
- }
- }
- if (!fPerformValidation) {
- continue;
- }
- if (fTempAttDecl.simpleType.defaultType ==
- XMLSimpleType.DEFAULT_TYPE_FIXED) {
- String defaultValue = fTempAttDecl.simpleType.defaultValue;
-
- if (!attrValue.equals(defaultValue)) {
- Object[] args = {elementName.localpart,
- attrRawName,
- attrValue,
- defaultValue};
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_FIXED_ATTVALUE_INVALID",
- args, XMLErrorReporter.SEVERITY_ERROR);
- }
- }
-
- if (fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ENTITY ||
- fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ENUMERATION ||
- fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ID ||
- fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_IDREF ||
- fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_NMTOKEN ||
- fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_NOTATION
- ) {
- validateDTDattribute(elementName, attrValue, fTempAttDecl);
- }
- } // for all attributes
-
- } // addDTDDefaultAttrsAndValidate(int,XMLAttrList)
-
- /** Checks entities in attribute values for standalone VC. */
- protected String getExternalEntityRefInAttrValue(String nonNormalizedValue) {
- int valLength = nonNormalizedValue.length();
- int ampIndex = nonNormalizedValue.indexOf('&');
- while (ampIndex != -1) {
- if (ampIndex + 1 < valLength &&
- nonNormalizedValue.charAt(ampIndex+1) != '#') {
- int semicolonIndex = nonNormalizedValue.indexOf(';', ampIndex+1);
- String entityName = nonNormalizedValue.substring(ampIndex+1, semicolonIndex);
- entityName = fSymbolTable.addSymbol(entityName);
- int entIndex = fDTDGrammar.getEntityDeclIndex(entityName);
- if (entIndex > -1) {
- fDTDGrammar.getEntityDecl(entIndex, fEntityDecl);
- if (fEntityDecl.inExternal ||
- (entityName = getExternalEntityRefInAttrValue(fEntityDecl.value)) != null) {
- return entityName;
- }
- }
- }
- ampIndex = nonNormalizedValue.indexOf('&', ampIndex+1);
- }
- return null;
- } // isExternalEntityRefInAttrValue(String):String
-
- /**
- * Validate attributes in DTD fashion.
- */
- protected void validateDTDattribute(QName element, String attValue,
- XMLAttributeDecl attributeDecl)
- throws XNIException {
-
- switch (attributeDecl.simpleType.type) {
- case XMLSimpleType.TYPE_ENTITY: {
- // NOTE: Save this information because invalidStandaloneAttDef
- boolean isAlistAttribute = attributeDecl.simpleType.list;
-
- try {
- if (isAlistAttribute) {
- fValENTITIES.validate(attValue, fValidationState);
- }
- else {
- fValENTITY.validate(attValue, fValidationState);
- }
- }
- catch (InvalidDatatypeValueException ex) {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- ex.getKey(),
- ex.getArgs(),
- XMLErrorReporter.SEVERITY_ERROR );
-
- }
- break;
- }
-
- case XMLSimpleType.TYPE_NOTATION:
- case XMLSimpleType.TYPE_ENUMERATION: {
- boolean found = false;
- String [] enumVals = attributeDecl.simpleType.enumeration;
- if (enumVals == null) {
- found = false;
- }
- else
- for (int i = 0; i < enumVals.length; i++) {
- if (attValue == enumVals[i] || attValue.equals(enumVals[i])) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- StringBuffer enumValueString = new StringBuffer();
- if (enumVals != null)
- for (int i = 0; i < enumVals.length; i++) {
- enumValueString.append(enumVals[i]+" ");
- }
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_ATTRIBUTE_VALUE_NOT_IN_LIST",
- new Object[]{attributeDecl.name.rawname, attValue, enumValueString},
- XMLErrorReporter.SEVERITY_ERROR);
- }
- break;
- }
-
- case XMLSimpleType.TYPE_ID: {
- try {
- fValID.validate(attValue, fValidationState);
- }
- catch (InvalidDatatypeValueException ex) {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- ex.getKey(),
- ex.getArgs(),
- XMLErrorReporter.SEVERITY_ERROR );
- }
- break;
- }
-
- case XMLSimpleType.TYPE_IDREF: {
- boolean isAlistAttribute = attributeDecl.simpleType.list;//Caveat - Save this information because invalidStandaloneAttDef
-
- try {
- if (isAlistAttribute) {
- fValIDRefs.validate(attValue, fValidationState);
- }
- else {
- fValIDRef.validate(attValue, fValidationState);
- }
- }
- catch (InvalidDatatypeValueException ex) {
- if (isAlistAttribute) {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "IDREFSInvalid",
- new Object[]{attValue},
- XMLErrorReporter.SEVERITY_ERROR );
- }
- else {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- ex.getKey(),
- ex.getArgs(),
- XMLErrorReporter.SEVERITY_ERROR );
- }
-
- }
- break;
- }
-
- case XMLSimpleType.TYPE_NMTOKEN: {
- boolean isAlistAttribute = attributeDecl.simpleType.list;//Caveat - Save this information because invalidStandaloneAttDef
- //changes fTempAttDef
- try {
- if (isAlistAttribute) {
- fValNMTOKENS.validate(attValue, fValidationState);
- }
- else {
- fValNMTOKEN.validate(attValue, fValidationState);
- }
- }
- catch (InvalidDatatypeValueException ex) {
- if (isAlistAttribute) {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "NMTOKENSInvalid",
- new Object[] { attValue},
- XMLErrorReporter.SEVERITY_ERROR);
- }
- else {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "NMTOKENInvalid",
- new Object[] { attValue},
- XMLErrorReporter.SEVERITY_ERROR);
- }
- }
- break;
- }
-
- } // switch
-
- } // validateDTDattribute(QName,String,XMLAttributeDecl)
-
-
- /** Returns true if invalid standalone attribute definition. */
- protected boolean invalidStandaloneAttDef(QName element, QName attribute) {
- // REVISIT: This obviously needs to be fixed! -Ac
- boolean state = true;
- /*
- if (fStandaloneReader == -1) {
- return false;
- }
- // we are normalizing a default att value... this ok?
- if (element.rawname == -1) {
- return false;
- }
- return getAttDefIsExternal(element, attribute);
- */
- return state;
- }
-
-
- //
- // Private methods
- //
-
-
- /**
- * Normalize the attribute value of a non CDATA attributes collapsing
- * sequences of space characters (x20)
- *
- * @param attributes The list of attributes
- * @param index The index of the attribute to normalize
- */
- private boolean normalizeAttrValue(XMLAttributes attributes, int index) {
- // vars
- boolean leadingSpace = true;
- boolean spaceStart = false;
- boolean readingNonSpace = false;
- int count = 0;
- int eaten = 0;
- String attrValue = attributes.getValue(index);
- char[] attValue = new char[attrValue.length()];
-
- fBuffer.setLength(0);
- attrValue.getChars(0, attrValue.length(), attValue, 0);
- for (int i = 0; i < attValue.length; i++) {
-
- if (attValue[i] == ' ') {
-
- // now the tricky part
- if (readingNonSpace) {
- spaceStart = true;
- readingNonSpace = false;
- }
-
- if (spaceStart && !leadingSpace) {
- spaceStart = false;
- fBuffer.append(attValue[i]);
- count++;
- }
- else {
- if (leadingSpace || !spaceStart) {
- eaten ++;
- /*** BUG #3512 ***
- int entityCount = attributes.getEntityCount(index);
- for (int j = 0; j < entityCount; j++) {
- int offset = attributes.getEntityOffset(index, j);
- int length = attributes.getEntityLength(index, j);
- if (offset <= i-eaten+1) {
- if (offset+length >= i-eaten+1) {
- if (length > 0)
- length--;
- }
- }
- else {
- if (offset > 0)
- offset--;
- }
- attributes.setEntityOffset(index, j, offset);
- attributes.setEntityLength(index, j, length);
- }
- /***/
- }
- }
-
- }
- else {
- readingNonSpace = true;
- spaceStart = false;
- leadingSpace = false;
- fBuffer.append(attValue[i]);
- count++;
- }
- }
-
- // check if the last appended character is a space.
- if (count > 0 && fBuffer.charAt(count-1) == ' ') {
- fBuffer.setLength(count-1);
- /*** BUG #3512 ***
- int entityCount = attributes.getEntityCount(index);
- for (int j=0; j < entityCount; j++) {
- int offset = attributes.getEntityOffset(index, j);
- int length = attributes.getEntityLength(index, j);
- if (offset < count-1) {
- if (offset+length == count) {
- length--;
- }
- }
- else {
- offset--;
- }
- attributes.setEntityOffset(index, j, offset);
- attributes.setEntityLength(index, j, length);
- }
- /***/
- }
- String newValue = fBuffer.toString();
- attributes.setValue(index, newValue);
- return ! attrValue.equals(newValue);
- }
-
- /** Root element specified. */
- private final void rootElementSpecified(QName rootElement) throws XNIException {
- if (fPerformValidation) {
- String root1 = fRootElement.rawname;
- String root2 = rootElement.rawname;
- if (root1 == null || !root1.equals(root2)) {
- fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
- "RootElementTypeMustMatchDoctypedecl",
- new Object[]{root1, root2},
- XMLErrorReporter.SEVERITY_ERROR);
- }
- }
- } // rootElementSpecified(QName)
-
- /**
- * Check that the content of an element is valid.
- * <p>
- * This is the method of primary concern to the validator. This method is called
- * upon the scanner reaching the end tag of an element. At that time, the
- * element's children must be structurally validated, so it calls this method.
- * The index of the element being checked (in the decl pool), is provided as
- * well as an array of element name indexes of the children. The validator must
- * confirm that this element can have these children in this order.
- * <p>
- * This can also be called to do 'what if' testing of content models just to see
- * if they would be valid.
- * <p>
- * Note that the element index is an index into the element decl pool, whereas
- * the children indexes are name indexes, i.e. into the string pool.
- * <p>
- * A value of -1 in the children array indicates a PCDATA node. All other
- * indexes will be positive and represent child elements. The count can be
- * zero, since some elements have the EMPTY content model and that must be
- * confirmed.
- *
- * @param elementIndex The index within the <code>ElementDeclPool</code> of this
- * element.
- * @param childCount The number of entries in the <code>children</code> array.
- * @param children The children of this element.
- *
- * @return The value -1 if fully valid, else the 0 based index of the child
- * that first failed. If the value returned is equal to the number
- * of children, then additional content is required to reach a valid
- * ending state.
- *
- * @exception Exception Thrown on error.
- */
- private int checkContent(int elementIndex,
- QName[] children,
- int childOffset,
- int childCount) throws XNIException {
-
- fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
-
- // Get the element name index from the element
- final String elementType = fCurrentElement.rawname;
-
- // Get out the content spec for this element
- final int contentType = fCurrentContentSpecType;
-
-
- //
- // Deal with the possible types of content. We try to optimized here
- // by dealing specially with content models that don't require the
- // full DFA treatment.
- //
- if (contentType == XMLElementDecl.TYPE_EMPTY) {
- //
- // If the child count is greater than zero, then this is
- // an error right off the bat at index 0.
- //
- if (childCount != 0) {
- return 0;
- }
- }
- else if (contentType == XMLElementDecl.TYPE_ANY) {
- //
- // This one is open game so we don't pass any judgement on it
- // at all. Its assumed to fine since it can hold anything.
- //
- }
- else if (contentType == XMLElementDecl.TYPE_MIXED ||
- contentType == XMLElementDecl.TYPE_CHILDREN) {
- // Get the content model for this element, faulting it in if needed
- ContentModelValidator cmElem = null;
- cmElem = fTempElementDecl.contentModelValidator;
- int result = cmElem.validate(children, childOffset, childCount);
- return result;
- }
- else if (contentType == -1) {
- //REVISIT
- /****
- reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
- XMLMessages.VC_ELEMENT_VALID,
- elementType);
- /****/
- }
- else if (contentType == XMLElementDecl.TYPE_SIMPLE) {
-
- //REVISIT
- // this should never be reached in the case of DTD validation.
-
- }
- else {
- //REVISIT
- /****
- fErrorReporter.reportError(fErrorReporter.getLocator(),
- ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
- ImplementationMessages.VAL_CST,
- 0,
- null,
- XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
- /****/
- }
-
- // We succeeded
- return -1;
-
- } // checkContent(int,int,QName[]):int
-
- /** Returns the content spec type for an element index. */
- private int getContentSpecType(int elementIndex) {
-
- int contentSpecType = -1;
- if (elementIndex > -1) {
- if (fDTDGrammar.getElementDecl(elementIndex,fTempElementDecl)) {
- contentSpecType = fTempElementDecl.type;
- }
- }
- return contentSpecType;
- }
-
- /** Character data in content. */
- private void charDataInContent() {
-
- if (DEBUG_ELEMENT_CHILDREN) {
- System.out.println("charDataInContent()");
- }
- if (fElementChildren.length <= fElementChildrenLength) {
- QName[] newarray = new QName[fElementChildren.length * 2];
- System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
- fElementChildren = newarray;
- }
- QName qname = fElementChildren[fElementChildrenLength];
- if (qname == null) {
- for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
- fElementChildren[i] = new QName();
- }
- qname = fElementChildren[fElementChildrenLength];
- }
- qname.clear();
- fElementChildrenLength++;
-
- } // charDataInCount()
-
- /** convert attribute type from ints to strings */
- private String getAttributeTypeName(XMLAttributeDecl attrDecl) {
-
- switch (attrDecl.simpleType.type) {
- case XMLSimpleType.TYPE_ENTITY: {
- return attrDecl.simpleType.list ? XMLSymbols.fENTITIESSymbol : XMLSymbols.fENTITYSymbol;
- }
- case XMLSimpleType.TYPE_ENUMERATION: {
- StringBuffer buffer = new StringBuffer();
- buffer.append('(');
- for (int i=0; i<attrDecl.simpleType.enumeration.length ; i++) {
- if (i > 0) {
- buffer.append("|");
- }
- buffer.append(attrDecl.simpleType.enumeration[i]);
- }
- buffer.append(')');
- return fSymbolTable.addSymbol(buffer.toString());
- }
- case XMLSimpleType.TYPE_ID: {
- return XMLSymbols.fIDSymbol;
- }
- case XMLSimpleType.TYPE_IDREF: {
- return attrDecl.simpleType.list ? XMLSymbols.fIDREFSSymbol : XMLSymbols.fIDREFSymbol;
- }
- case XMLSimpleType.TYPE_NMTOKEN: {
- return attrDecl.simpleType.list ? XMLSymbols.fNMTOKENSSymbol : XMLSymbols.fNMTOKENSymbol;
- }
- case XMLSimpleType.TYPE_NOTATION: {
- return XMLSymbols.fNOTATIONSymbol;
- }
- }
- return XMLSymbols.fCDATASymbol;
-
- } // getAttributeTypeName(XMLAttributeDecl):String
-
- /** initialization */
- protected void init() {
-
- // datatype validators
- if (fValidation || fDynamicValidation) {
- try {
- //REVISIT: datatypeRegistry + initialization of datatype
- // why do we cast to ListDatatypeValidator?
- fValID = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDSymbol);
- fValIDRef = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDREFSymbol);
- fValIDRefs = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDREFSSymbol);
- fValENTITY = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fENTITYSymbol);
- fValENTITIES = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fENTITIESSymbol);
- fValNMTOKEN = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNMTOKENSymbol);
- fValNMTOKENS = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNMTOKENSSymbol);
- fValNOTATION = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNOTATIONSymbol);
-
- }
- catch (Exception e) {
- // should never happen
- e.printStackTrace(System.err);
- }
-
- }
-
- } // init()
-
- /** ensure element stack capacity */
- private void ensureStackCapacity ( int newElementDepth) {
- if (newElementDepth == fElementQNamePartsStack.length) {
- int[] newStack = new int[newElementDepth * 2];
-
- QName[] newStackOfQueue = new QName[newElementDepth * 2];
- System.arraycopy(this.fElementQNamePartsStack, 0, newStackOfQueue, 0, newElementDepth );
- fElementQNamePartsStack = newStackOfQueue;
-
- QName qname = fElementQNamePartsStack[newElementDepth];
- if (qname == null) {
- for (int i = newElementDepth; i < fElementQNamePartsStack.length; i++) {
- fElementQNamePartsStack[i] = new QName();
- }
- }
-
- newStack = new int[newElementDepth * 2];
- System.arraycopy(fElementIndexStack, 0, newStack, 0, newElementDepth);
- fElementIndexStack = newStack;
-
- newStack = new int[newElementDepth * 2];
- System.arraycopy(fContentSpecTypeStack, 0, newStack, 0, newElementDepth);
- fContentSpecTypeStack = newStack;
-
- }
- } // ensureStackCapacity
-
-
- //
- // Protected methods
- //
-
- /** Handle element
- * @return true if validator is removed from the pipeline
- */
- protected boolean handleStartElement(QName element, XMLAttributes attributes, Augmentations augs)
- throws XNIException {
-
-
- // VC: Root Element Type
- // see if the root element's name matches the one in DoctypeDecl
- if (!fSeenRootElement) {
- // REVISIT: Here are current assumptions about validation features
- // given that XMLSchema validator is in the pipeline
- //
- // http://xml.org/sax/features/validation = true
- // http://apache.org/xml/features/validation/schema = true
- //
- // [1] XML instance document only has reference to a DTD
- // Outcome: report validation errors only against dtd.
- //
- // [2] XML instance document has only XML Schema grammars:
- // Outcome: report validation errors only against schemas (no errors produced from DTD validator)
- //
- // [3] XML instance document has DTD and XML schemas:
- // [a] if schema language is not set outcome - validation errors reported against both grammars: DTD and schemas.
- // [b] if schema language is set to XML Schema - do not report validation errors
- //
- // if dynamic validation is on
- // validate only against grammar we've found (depending on settings
- // for schema feature)
- //
- //
- fPerformValidation = validate();
- fSeenRootElement = true;
- fValidationManager.setEntityState(fDTDGrammar);
- fValidationManager.setGrammarFound(fSeenDoctypeDecl);
- rootElementSpecified(element);
- }
- if (fDTDGrammar == null) {
-
- if (!fPerformValidation) {
- fCurrentElementIndex = -1;
- fCurrentContentSpecType = -1;
- fInElementContent = false;
- }
- if (fPerformValidation) {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_GRAMMAR_NOT_FOUND",
- new Object[]{ element.rawname},
- XMLErrorReporter.SEVERITY_ERROR);
- }
- // modify pipeline
- if (fDocumentSource !=null ) {
- fDocumentSource.setDocumentHandler(fDocumentHandler);
- if (fDocumentHandler != null)
- fDocumentHandler.setDocumentSource(fDocumentSource);
- return true;
- }
- }
- else {
- // resolve the element
- fCurrentElementIndex = fDTDGrammar.getElementDeclIndex(element);
- //changed here.. new function for getContentSpecType
- fCurrentContentSpecType = fDTDGrammar.getContentSpecType(fCurrentElementIndex);
- if (fCurrentContentSpecType == -1 && fPerformValidation) {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_ELEMENT_NOT_DECLARED",
- new Object[]{ element.rawname},
- XMLErrorReporter.SEVERITY_ERROR);
- }
-
- // 0. insert default attributes
- // 1. normalize the attributes
- // 2. validate the attrivute list.
- // TO DO:
- //changed here.. also pass element name,
- addDTDDefaultAttrsAndValidate(element, fCurrentElementIndex, attributes);
- }
-
- // set element content state
- fInElementContent = fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN;
-
- // increment the element depth, add this element's
- // QName to its enclosing element 's children list
- fElementDepth++;
- if (fPerformValidation) {
- // push current length onto stack
- if (fElementChildrenOffsetStack.length <= fElementDepth) {
- int newarray[] = new int[fElementChildrenOffsetStack.length * 2];
- System.arraycopy(fElementChildrenOffsetStack, 0, newarray, 0, fElementChildrenOffsetStack.length);
- fElementChildrenOffsetStack = newarray;
- }
- fElementChildrenOffsetStack[fElementDepth] = fElementChildrenLength;
-
- // add this element to children
- if (fElementChildren.length <= fElementChildrenLength) {
- QName[] newarray = new QName[fElementChildrenLength * 2];
- System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
- fElementChildren = newarray;
- }
- QName qname = fElementChildren[fElementChildrenLength];
- if (qname == null) {
- for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
- fElementChildren[i] = new QName();
- }
- qname = fElementChildren[fElementChildrenLength];
- }
- qname.setValues(element);
- fElementChildrenLength++;
- }
-
- // save current element information
- fCurrentElement.setValues(element);
- ensureStackCapacity(fElementDepth);
- fElementQNamePartsStack[fElementDepth].setValues(fCurrentElement);
- fElementIndexStack[fElementDepth] = fCurrentElementIndex;
- fContentSpecTypeStack[fElementDepth] = fCurrentContentSpecType;
- startNamespaceScope(element, attributes, augs);
- return false;
-
- } // handleStartElement(QName,XMLAttributes)
-
- protected void startNamespaceScope(QName element, XMLAttributes attributes, Augmentations augs){
- }
-
- /** Handle end element. */
- protected void handleEndElement(QName element, Augmentations augs, boolean isEmpty)
- throws XNIException {
-
- // decrease element depth
- fElementDepth--;
-
- // validate
- if (fPerformValidation) {
- int elementIndex = fCurrentElementIndex;
- if (elementIndex != -1 && fCurrentContentSpecType != -1) {
- QName children[] = fElementChildren;
- int childrenOffset = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
- int childrenLength = fElementChildrenLength - childrenOffset;
- int result = checkContent(elementIndex,
- children, childrenOffset, childrenLength);
-
- if (result != -1) {
- fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
- if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- "MSG_CONTENT_INVALID",
- new Object[]{ element.rawname, "EMPTY"},
- XMLErrorReporter.SEVERITY_ERROR);
- }
- else {
- String messageKey = result != childrenLength ?
- "MSG_CONTENT_INVALID" : "MSG_CONTENT_INCOMPLETE";
- fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
- messageKey,
- new Object[]{ element.rawname,
- fDTDGrammar.getContentSpecAsString(elementIndex)},
- XMLErrorReporter.SEVERITY_ERROR);
- }
- }
- }
- fElementChildrenLength = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
- }
-
- endNamespaceScope(fCurrentElement, augs, isEmpty);
-
- // now pop this element off the top of the element stack
- if (fElementDepth < -1) {
- throw new RuntimeException("FWK008 Element stack underflow");
- }
- if (fElementDepth < 0) {
- fCurrentElement.clear();
- fCurrentElementIndex = -1;
- fCurrentContentSpecType = -1;
- fInElementContent = false;
-
- // TO DO : fix this
- //
- // Check after document is fully parsed
- // (1) check that there was an element with a matching id for every
- // IDREF and IDREFS attr (V_IDREF0)
- //
- if (fPerformValidation) {
- String value = fValidationState.checkIDRefID();
- if (value != null) {
- fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
- "MSG_ELEMENT_WITH_ID_REQUIRED",
- new Object[]{value},
- XMLErrorReporter.SEVERITY_ERROR );
- }
- }
- return;
- }
-
- // If Namespace enable then localName != rawName
- fCurrentElement.setValues(fElementQNamePartsStack[fElementDepth]);
-
- fCurrentElementIndex = fElementIndexStack[fElementDepth];
- fCurrentContentSpecType = fContentSpecTypeStack[fElementDepth];
- fInElementContent = (fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN);
-
- } // handleEndElement(QName,boolean)
-
- protected void endNamespaceScope(QName element, Augmentations augs, boolean isEmpty){
-
- // call handlers
- if (fDocumentHandler != null && !isEmpty) {
- // NOTE: The binding of the element doesn't actually happen
- // yet because the namespace binder does that. However,
- // if it does it before this point, then the endPrefix-
- // Mapping calls get made too soon! As long as the
- // rawnames match, we know it'll have a good binding,
- // so we can just use the current element. -Ac
- fDocumentHandler.endElement(fCurrentElement, augs);
- }
- }
-
- // returns whether a character is space according to the
- // version of XML this validator supports.
- protected boolean isSpace(int c) {
- return XMLChar.isSpace(c);
- } // isSpace(int): boolean
-
- } // class XMLDTDValidator