1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999-2003 The Apache Software Foundation.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xerces" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, International
  53. * Business Machines, Inc., http://www.apache.org. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package com.sun.org.apache.xerces.internal.impl.dtd;
  58. import com.sun.org.apache.xerces.internal.impl.Constants;
  59. import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
  60. import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
  61. import com.sun.org.apache.xerces.internal.impl.dtd.models.ContentModelValidator;
  62. import com.sun.org.apache.xerces.internal.impl.dv.DTDDVFactory;
  63. import com.sun.org.apache.xerces.internal.impl.dv.DatatypeValidator;
  64. import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
  65. import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
  66. import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
  67. import com.sun.org.apache.xerces.internal.impl.validation.ValidationState;
  68. import com.sun.org.apache.xerces.internal.util.SymbolTable;
  69. import com.sun.org.apache.xerces.internal.util.XMLChar;
  70. import com.sun.org.apache.xerces.internal.util.XMLSymbols;
  71. import com.sun.org.apache.xerces.internal.xni.Augmentations;
  72. import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
  73. import com.sun.org.apache.xerces.internal.xni.QName;
  74. import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
  75. import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
  76. import com.sun.org.apache.xerces.internal.xni.XMLLocator;
  77. import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
  78. import com.sun.org.apache.xerces.internal.xni.XMLString;
  79. import com.sun.org.apache.xerces.internal.xni.XNIException;
  80. import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
  81. import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
  82. import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  83. import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
  84. import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  85. import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  86. import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentFilter;
  87. import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
  88. /**
  89. * The DTD validator. The validator implements a document
  90. * filter: receiving document events from the scanner; validating
  91. * the content and structure; augmenting the InfoSet, if applicable;
  92. * and notifying the parser of the information resulting from the
  93. * validation process.
  94. * <p> Formerly, this component also handled DTD events and grammar construction.
  95. * To facilitate the development of a meaningful DTD grammar caching/preparsing
  96. * framework, this functionality has been moved into the XMLDTDLoader
  97. * class. Therefore, this class no longer implements the DTDFilter
  98. * or DTDContentModelFilter interfaces.
  99. * <p>
  100. * This component requires the following features and properties from the
  101. * component manager that uses it:
  102. * <ul>
  103. * <li>http://xml.org/sax/features/namespaces</li>
  104. * <li>http://xml.org/sax/features/validation</li>
  105. * <li>http://apache.org/xml/features/validation/dynamic</li>
  106. * <li>http://apache.org/xml/properties/internal/symbol-table</li>
  107. * <li>http://apache.org/xml/properties/internal/error-reporter</li>
  108. * <li>http://apache.org/xml/properties/internal/grammar-pool</li>
  109. * <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
  110. * </ul>
  111. *
  112. * @author Eric Ye, IBM
  113. * @author Andy Clark, IBM
  114. * @author Jeffrey Rodriguez IBM
  115. * @author Neil Graham, IBM
  116. *
  117. * @version $Id: XMLDTDValidator.java,v 1.59 2004/04/25 05:05:49 mrglavas Exp $
  118. */
  119. public class XMLDTDValidator
  120. implements XMLComponent, XMLDocumentFilter, XMLDTDValidatorFilter {
  121. //
  122. // Constants
  123. //
  124. /** Symbol: "<<datatypes>>". */
  125. /** Top level scope (-1). */
  126. private static final int TOP_LEVEL_SCOPE = -1;
  127. // feature identifiers
  128. /** Feature identifier: namespaces. */
  129. protected static final String NAMESPACES =
  130. Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
  131. /** Feature identifier: validation. */
  132. protected static final String VALIDATION =
  133. Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
  134. /** Feature identifier: dynamic validation. */
  135. protected static final String DYNAMIC_VALIDATION =
  136. Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
  137. /** Feature identifier: warn on duplicate attdef */
  138. protected static final String WARN_ON_DUPLICATE_ATTDEF =
  139. Constants.XERCES_FEATURE_PREFIX +Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
  140. protected static final String PARSER_SETTINGS =
  141. Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
  142. // property identifiers
  143. /** Property identifier: symbol table. */
  144. protected static final String SYMBOL_TABLE =
  145. Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
  146. /** Property identifier: error reporter. */
  147. protected static final String ERROR_REPORTER =
  148. Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
  149. /** Property identifier: grammar pool. */
  150. protected static final String GRAMMAR_POOL =
  151. Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
  152. /** Property identifier: datatype validator factory. */
  153. protected static final String DATATYPE_VALIDATOR_FACTORY =
  154. Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
  155. // property identifier: ValidationManager
  156. protected static final String VALIDATION_MANAGER =
  157. Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
  158. // recognized features and properties
  159. /** Recognized features. */
  160. private static final String[] RECOGNIZED_FEATURES = {
  161. NAMESPACES,
  162. VALIDATION,
  163. DYNAMIC_VALIDATION
  164. };
  165. /** Feature defaults. */
  166. private static final Boolean[] FEATURE_DEFAULTS = {
  167. null,
  168. null,
  169. Boolean.FALSE,
  170. };
  171. /** Recognized properties. */
  172. private static final String[] RECOGNIZED_PROPERTIES = {
  173. SYMBOL_TABLE,
  174. ERROR_REPORTER,
  175. GRAMMAR_POOL,
  176. DATATYPE_VALIDATOR_FACTORY,
  177. VALIDATION_MANAGER
  178. };
  179. /** Property defaults. */
  180. private static final Object[] PROPERTY_DEFAULTS = {
  181. null,
  182. null,
  183. null,
  184. null,
  185. null,
  186. };
  187. // debugging
  188. /** Compile to true to debug attributes. */
  189. private static final boolean DEBUG_ATTRIBUTES = false;
  190. /** Compile to true to debug element children. */
  191. private static final boolean DEBUG_ELEMENT_CHILDREN = false;
  192. //
  193. // Data
  194. //
  195. // updated during reset
  196. protected ValidationManager fValidationManager = null;
  197. // validation state
  198. protected ValidationState fValidationState = new ValidationState();
  199. // features
  200. /** Namespaces. */
  201. protected boolean fNamespaces;
  202. /** Validation. */
  203. protected boolean fValidation;
  204. /** Validation against only DTD */
  205. protected boolean fDTDValidation;
  206. /**
  207. * Dynamic validation. This state of this feature is only useful when
  208. * the validation feature is set to <code>true</code>.
  209. */
  210. protected boolean fDynamicValidation;
  211. /** warn on duplicate attribute definition, this feature works only when validation is true */
  212. protected boolean fWarnDuplicateAttdef;
  213. // properties
  214. /** Symbol table. */
  215. protected SymbolTable fSymbolTable;
  216. /** Error reporter. */
  217. protected XMLErrorReporter fErrorReporter;
  218. // the grammar pool
  219. protected XMLGrammarPool fGrammarPool;
  220. /** Grammar bucket. */
  221. protected DTDGrammarBucket fGrammarBucket;
  222. /* location of the document as passed in from startDocument call */
  223. protected XMLLocator fDocLocation;
  224. /** Namespace support. */
  225. protected NamespaceContext fNamespaceContext = null;
  226. /** Datatype validator factory. */
  227. protected DTDDVFactory fDatatypeValidatorFactory;
  228. // handlers
  229. /** Document handler. */
  230. protected XMLDocumentHandler fDocumentHandler;
  231. protected XMLDocumentSource fDocumentSource;
  232. // grammars
  233. /** DTD Grammar. */
  234. protected DTDGrammar fDTDGrammar;
  235. // state
  236. /** True if seen DOCTYPE declaration. */
  237. protected boolean fSeenDoctypeDecl = false;
  238. /** Perform validation. */
  239. private boolean fPerformValidation;
  240. /** Schema type: None, DTD, Schema */
  241. private String fSchemaType;
  242. // information regarding the current element
  243. /** Current element name. */
  244. private final QName fCurrentElement = new QName();
  245. /** Current element index. */
  246. private int fCurrentElementIndex = -1;
  247. /** Current content spec type. */
  248. private int fCurrentContentSpecType = -1;
  249. /** The root element name. */
  250. private final QName fRootElement = new QName();
  251. private boolean fInCDATASection = false;
  252. // element stack
  253. /** Element index stack. */
  254. private int[] fElementIndexStack = new int[8];
  255. /** Content spec type stack. */
  256. private int[] fContentSpecTypeStack = new int[8];
  257. /** Element name stack. */
  258. private QName[] fElementQNamePartsStack = new QName[8];
  259. // children list and offset stack
  260. /**
  261. * Element children. This data structure is a growing stack that
  262. * holds the children of elements from the root to the current
  263. * element depth. This structure never gets "deeper" than the
  264. * deepest element. Space is re-used once each element is closed.
  265. * <p>
  266. * <strong>Note:</strong> This is much more efficient use of memory
  267. * than creating new arrays for each element depth.
  268. * <p>
  269. * <strong>Note:</strong> The use of this data structure is for
  270. * validation "on the way out". If the validation model changes to
  271. * "on the way in", then this data structure is not needed.
  272. */
  273. private QName[] fElementChildren = new QName[32];
  274. /** Element children count. */
  275. private int fElementChildrenLength = 0;
  276. /**
  277. * Element children offset stack. This stack refers to offsets
  278. * into the <code>fElementChildren</code> array.
  279. * @see #fElementChildren
  280. */
  281. private int[] fElementChildrenOffsetStack = new int[32];
  282. /** Element depth. */
  283. private int fElementDepth = -1;
  284. // validation states
  285. /** True if seen the root element. */
  286. private boolean fSeenRootElement = false;
  287. /** True if inside of element content. */
  288. private boolean fInElementContent = false;
  289. // temporary variables
  290. /** Temporary element declaration. */
  291. private XMLElementDecl fTempElementDecl = new XMLElementDecl();
  292. /** Temporary atribute declaration. */
  293. private XMLAttributeDecl fTempAttDecl = new XMLAttributeDecl();
  294. /** Temporary entity declaration. */
  295. private XMLEntityDecl fEntityDecl = new XMLEntityDecl();
  296. /** Temporary qualified name. */
  297. private QName fTempQName = new QName();
  298. /** Temporary string buffers. */
  299. private StringBuffer fBuffer = new StringBuffer();
  300. // symbols: general
  301. // attribute validators
  302. /** Datatype validator: ID. */
  303. protected DatatypeValidator fValID;
  304. /** Datatype validator: IDREF. */
  305. protected DatatypeValidator fValIDRef;
  306. /** Datatype validator: IDREFS. */
  307. protected DatatypeValidator fValIDRefs;
  308. /** Datatype validator: ENTITY. */
  309. protected DatatypeValidator fValENTITY;
  310. /** Datatype validator: ENTITIES. */
  311. protected DatatypeValidator fValENTITIES;
  312. /** Datatype validator: NMTOKEN. */
  313. protected DatatypeValidator fValNMTOKEN;
  314. /** Datatype validator: NMTOKENS. */
  315. protected DatatypeValidator fValNMTOKENS;
  316. /** Datatype validator: NOTATION. */
  317. protected DatatypeValidator fValNOTATION;
  318. // to check for duplicate ID or ANNOTATION attribute declare in
  319. // ATTLIST, and misc VCs
  320. //
  321. // Constructors
  322. //
  323. /** Default constructor. */
  324. public XMLDTDValidator() {
  325. // initialize data
  326. for (int i = 0; i < fElementQNamePartsStack.length; i++) {
  327. fElementQNamePartsStack[i] = new QName();
  328. }
  329. fGrammarBucket = new DTDGrammarBucket();
  330. } // <init>()
  331. DTDGrammarBucket getGrammarBucket() {
  332. return fGrammarBucket;
  333. } // getGrammarBucket(): DTDGrammarBucket
  334. //
  335. // XMLComponent methods
  336. //
  337. /*
  338. * Resets the component. The component can query the component manager
  339. * about any features and properties that affect the operation of the
  340. * component.
  341. *
  342. * @param componentManager The component manager.
  343. *
  344. * @throws SAXException Thrown by component on finitialization error.
  345. * For example, if a feature or property is
  346. * required for the operation of the component, the
  347. * component manager may throw a
  348. * SAXNotRecognizedException or a
  349. * SAXNotSupportedException.
  350. */
  351. public void reset(XMLComponentManager componentManager)
  352. throws XMLConfigurationException {
  353. // clear grammars
  354. fDTDGrammar = null;
  355. fSeenDoctypeDecl = false;
  356. fInCDATASection = false;
  357. // initialize state
  358. fSeenRootElement = false;
  359. fInElementContent = false;
  360. fCurrentElementIndex = -1;
  361. fCurrentContentSpecType = -1;
  362. fRootElement.clear();
  363. fValidationState.resetIDTables();
  364. fGrammarBucket.clear();
  365. fElementDepth = -1;
  366. fElementChildrenLength = 0;
  367. boolean parser_settings;
  368. try {
  369. parser_settings = componentManager.getFeature(PARSER_SETTINGS);
  370. }
  371. catch (XMLConfigurationException e){
  372. parser_settings = true;
  373. }
  374. if (!parser_settings){
  375. // parser settings have not been changed
  376. fValidationManager.addValidationState(fValidationState);
  377. return;
  378. }
  379. // sax features
  380. try {
  381. fNamespaces = componentManager.getFeature(NAMESPACES);
  382. }
  383. catch (XMLConfigurationException e) {
  384. fNamespaces = true;
  385. }
  386. try {
  387. fValidation = componentManager.getFeature(VALIDATION);
  388. }
  389. catch (XMLConfigurationException e) {
  390. fValidation = false;
  391. }
  392. try {
  393. fDTDValidation = !(componentManager.getFeature(Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE));
  394. }
  395. catch (XMLConfigurationException e) {
  396. // must be in a schema-less configuration!
  397. fDTDValidation = true;
  398. }
  399. // Xerces features
  400. try {
  401. fDynamicValidation = componentManager.getFeature(DYNAMIC_VALIDATION);
  402. }
  403. catch (XMLConfigurationException e) {
  404. fDynamicValidation = false;
  405. }
  406. try {
  407. fWarnDuplicateAttdef = componentManager.getFeature(WARN_ON_DUPLICATE_ATTDEF);
  408. }
  409. catch (XMLConfigurationException e) {
  410. fWarnDuplicateAttdef = false;
  411. }
  412. try {
  413. fSchemaType = (String)componentManager.getProperty (Constants.JAXP_PROPERTY_PREFIX
  414. + Constants.SCHEMA_LANGUAGE);
  415. }
  416. catch (XMLConfigurationException e){
  417. fSchemaType = null;
  418. }
  419. fValidationManager= (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER);
  420. fValidationManager.addValidationState(fValidationState);
  421. fValidationState.setUsingNamespaces(fNamespaces);
  422. // get needed components
  423. fErrorReporter = (XMLErrorReporter)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX+Constants.ERROR_REPORTER_PROPERTY);
  424. fSymbolTable = (SymbolTable)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX+Constants.SYMBOL_TABLE_PROPERTY);
  425. try {
  426. fGrammarPool= (XMLGrammarPool)componentManager.getProperty(GRAMMAR_POOL);
  427. } catch (XMLConfigurationException e) {
  428. fGrammarPool = null;
  429. }
  430. fDatatypeValidatorFactory = (DTDDVFactory)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY);
  431. init();
  432. } // reset(XMLComponentManager)
  433. /**
  434. * Returns a list of feature identifiers that are recognized by
  435. * this component. This method may return null if no features
  436. * are recognized by this component.
  437. */
  438. public String[] getRecognizedFeatures() {
  439. return (String[])(RECOGNIZED_FEATURES.clone());
  440. } // getRecognizedFeatures():String[]
  441. /**
  442. * Sets the state of a feature. This method is called by the component
  443. * manager any time after reset when a feature changes state.
  444. * <p>
  445. * <strong>Note:</strong> Components should silently ignore features
  446. * that do not affect the operation of the component.
  447. *
  448. * @param featureId The feature identifier.
  449. * @param state The state of the feature.
  450. *
  451. * @throws SAXNotRecognizedException The component should not throw
  452. * this exception.
  453. * @throws SAXNotSupportedException The component should not throw
  454. * this exception.
  455. */
  456. public void setFeature(String featureId, boolean state)
  457. throws XMLConfigurationException {
  458. } // setFeature(String,boolean)
  459. /**
  460. * Returns a list of property identifiers that are recognized by
  461. * this component. This method may return null if no properties
  462. * are recognized by this component.
  463. */
  464. public String[] getRecognizedProperties() {
  465. return (String[])(RECOGNIZED_PROPERTIES.clone());
  466. } // getRecognizedProperties():String[]
  467. /**
  468. * Sets the value of a property. This method is called by the component
  469. * manager any time after reset when a property changes value.
  470. * <p>
  471. * <strong>Note:</strong> Components should silently ignore properties
  472. * that do not affect the operation of the component.
  473. *
  474. * @param propertyId The property identifier.
  475. * @param value The value of the property.
  476. *
  477. * @throws SAXNotRecognizedException The component should not throw
  478. * this exception.
  479. * @throws SAXNotSupportedException The component should not throw
  480. * this exception.
  481. */
  482. public void setProperty(String propertyId, Object value)
  483. throws XMLConfigurationException {
  484. } // setProperty(String,Object)
  485. /**
  486. * Returns the default state for a feature, or null if this
  487. * component does not want to report a default value for this
  488. * feature.
  489. *
  490. * @param featureId The feature identifier.
  491. *
  492. * @since Xerces 2.2.0
  493. */
  494. public Boolean getFeatureDefault(String featureId) {
  495. for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
  496. if (RECOGNIZED_FEATURES[i].equals(featureId)) {
  497. return FEATURE_DEFAULTS[i];
  498. }
  499. }
  500. return null;
  501. } // getFeatureDefault(String):Boolean
  502. /**
  503. * Returns the default state for a property, or null if this
  504. * component does not want to report a default value for this
  505. * property.
  506. *
  507. * @param propertyId The property identifier.
  508. *
  509. * @since Xerces 2.2.0
  510. */
  511. public Object getPropertyDefault(String propertyId) {
  512. for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
  513. if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
  514. return PROPERTY_DEFAULTS[i];
  515. }
  516. }
  517. return null;
  518. } // getPropertyDefault(String):Object
  519. //
  520. // XMLDocumentSource methods
  521. //
  522. /** Sets the document handler to receive information about the document. */
  523. public void setDocumentHandler(XMLDocumentHandler documentHandler) {
  524. fDocumentHandler = documentHandler;
  525. } // setDocumentHandler(XMLDocumentHandler)
  526. /** Returns the document handler */
  527. public XMLDocumentHandler getDocumentHandler() {
  528. return fDocumentHandler;
  529. } // getDocumentHandler(): XMLDocumentHandler
  530. //
  531. // XMLDocumentHandler methods
  532. //
  533. /** Sets the document source */
  534. public void setDocumentSource(XMLDocumentSource source){
  535. fDocumentSource = source;
  536. } // setDocumentSource
  537. /** Returns the document source */
  538. public XMLDocumentSource getDocumentSource (){
  539. return fDocumentSource;
  540. } // getDocumentSource
  541. /**
  542. * The start of the document.
  543. *
  544. * @param locator The system identifier of the entity if the entity
  545. * is external, null otherwise.
  546. * @param encoding The auto-detected IANA encoding name of the entity
  547. * stream. This value will be null in those situations
  548. * where the entity encoding is not auto-detected (e.g.
  549. * internal entities or a document entity that is
  550. * parsed from a java.io.Reader).
  551. * @param namespaceContext
  552. * The namespace context in effect at the
  553. * start of this document.
  554. * This object represents the current context.
  555. * Implementors of this class are responsible
  556. * for copying the namespace bindings from the
  557. * the current context (and its parent contexts)
  558. * if that information is important.
  559. * @param augs Additional information that may include infoset augmentations
  560. *
  561. * @throws XNIException Thrown by handler to signal an error.
  562. */
  563. public void startDocument(XMLLocator locator, String encoding,
  564. NamespaceContext namespaceContext, Augmentations augs)
  565. throws XNIException {
  566. // call handlers
  567. // get initial grammars
  568. if(fGrammarPool != null) {
  569. Grammar [] grammars = fGrammarPool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_DTD);
  570. for(int i = 0; i<grammars.length; i++) {
  571. fGrammarBucket.putGrammar((DTDGrammar)grammars[i]);
  572. }
  573. }
  574. fDocLocation = locator;
  575. fNamespaceContext = namespaceContext;
  576. if (fDocumentHandler != null) {
  577. fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
  578. }
  579. } // startDocument(XMLLocator,String)
  580. /**
  581. * Notifies of the presence of an XMLDecl line in the document. If
  582. * present, this method will be called immediately following the
  583. * startDocument call.
  584. *
  585. * @param version The XML version.
  586. * @param encoding The IANA encoding name of the document, or null if
  587. * not specified.
  588. * @param standalone The standalone value, or null if not specified.
  589. * @param augs Additional information that may include infoset augmentations
  590. *
  591. * @throws XNIException Thrown by handler to signal an error.
  592. */
  593. public void xmlDecl(String version, String encoding, String standalone, Augmentations augs)
  594. throws XNIException {
  595. // save standalone state
  596. fGrammarBucket.setStandalone(standalone != null && standalone.equals("yes"));
  597. // call handlers
  598. if (fDocumentHandler != null) {
  599. fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
  600. }
  601. } // xmlDecl(String,String,String)
  602. /**
  603. * Notifies of the presence of the DOCTYPE line in the document.
  604. *
  605. * @param rootElement The name of the root element.
  606. * @param publicId The public identifier if an external DTD or null
  607. * if the external DTD is specified using SYSTEM.
  608. * @param systemId The system identifier if an external DTD, null
  609. * otherwise.
  610. * @param augs Additional information that may include infoset augmentations
  611. *
  612. * @throws XNIException Thrown by handler to signal an error.
  613. */
  614. public void doctypeDecl(String rootElement, String publicId, String systemId,
  615. Augmentations augs)
  616. throws XNIException {
  617. // save root element state
  618. fSeenDoctypeDecl = true;
  619. fRootElement.setValues(null, rootElement, rootElement, null);
  620. // find or create grammar:
  621. String eid = null;
  622. try {
  623. eid = XMLEntityManager.expandSystemId(systemId, fDocLocation.getExpandedSystemId(), false);
  624. } catch (java.io.IOException e) {
  625. }
  626. XMLDTDDescription grammarDesc = new XMLDTDDescription(publicId, systemId, fDocLocation.getExpandedSystemId(), eid, rootElement);
  627. fDTDGrammar = fGrammarBucket.getGrammar(grammarDesc);
  628. if(fDTDGrammar == null) {
  629. // give grammar pool a chance...
  630. if(fGrammarPool != null) {
  631. fDTDGrammar = (DTDGrammar)fGrammarPool.retrieveGrammar(grammarDesc);
  632. }
  633. }
  634. if(fDTDGrammar == null) {
  635. // we'll have to create it...
  636. fDTDGrammar = new DTDGrammar(fSymbolTable, grammarDesc);
  637. } else {
  638. // we've found a cached one;so let's make sure not to read
  639. // any external subset!
  640. fValidationManager.setCachedDTD(true);
  641. }
  642. fGrammarBucket.setActiveGrammar(fDTDGrammar);
  643. // call handlers
  644. if (fDocumentHandler != null) {
  645. fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
  646. }
  647. } // doctypeDecl(String,String,String, Augmentations)
  648. /**
  649. * The start of an element.
  650. *
  651. * @param element The name of the element.
  652. * @param attributes The element attributes.
  653. * @param augs Additional information that may include infoset augmentations
  654. *
  655. * @throws XNIException Thrown by handler to signal an error.
  656. */
  657. public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
  658. throws XNIException {
  659. handleStartElement(element, attributes, augs);
  660. // call handlers
  661. if (fDocumentHandler != null) {
  662. fDocumentHandler.startElement(element, attributes, augs);
  663. }
  664. } // startElement(QName,XMLAttributes)
  665. /**
  666. * An empty element.
  667. *
  668. * @param element The name of the element.
  669. * @param attributes The element attributes.
  670. * @param augs Additional information that may include infoset augmentations
  671. *
  672. * @throws XNIException Thrown by handler to signal an error.
  673. */
  674. public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
  675. throws XNIException {
  676. boolean removed = handleStartElement(element, attributes, augs);
  677. if (fDocumentHandler !=null) {
  678. fDocumentHandler.emptyElement(element, attributes, augs);
  679. }
  680. if (!removed) {
  681. handleEndElement(element, augs, true);
  682. }
  683. } // emptyElement(QName,XMLAttributes)
  684. /**
  685. * Character content.
  686. *
  687. * @param text The content.
  688. *
  689. * @param augs Additional information that may include infoset augmentations
  690. *
  691. * @throws XNIException Thrown by handler to signal an error.
  692. */
  693. public void characters(XMLString text, Augmentations augs) throws XNIException {
  694. boolean callNextCharacters = true;
  695. // REVISIT: [Q] Is there a more efficient way of doing this?
  696. // Perhaps if the scanner told us so we don't have to
  697. // look at the characters again. -Ac
  698. boolean allWhiteSpace = true;
  699. for (int i=text.offset; i< text.offset+text.length; i++) {
  700. if (!isSpace(text.ch[i])) {
  701. allWhiteSpace = false;
  702. break;
  703. }
  704. }
  705. // call the ignoreableWhiteSpace callback
  706. // never call ignorableWhitespace if we are in cdata section
  707. if (fInElementContent && allWhiteSpace && !fInCDATASection) {
  708. if (fDocumentHandler != null) {
  709. fDocumentHandler.ignorableWhitespace(text, augs);
  710. callNextCharacters = false;
  711. }
  712. }
  713. // validate
  714. if (fPerformValidation) {
  715. if (fInElementContent) {
  716. if (fGrammarBucket.getStandalone() &&
  717. fDTDGrammar.getElementDeclIsExternal(fCurrentElementIndex)) {
  718. if (allWhiteSpace) {
  719. fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
  720. "MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE",
  721. null, XMLErrorReporter.SEVERITY_ERROR);
  722. }
  723. }
  724. if (!allWhiteSpace) {
  725. charDataInContent();
  726. }
  727. // For E15.2
  728. if (augs != null && augs.getItem(Constants.CHAR_REF_PROBABLE_WS) == Boolean.TRUE) {
  729. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  730. "MSG_CONTENT_INVALID_SPECIFIED",
  731. new Object[]{ fCurrentElement.rawname,
  732. fDTDGrammar.getContentSpecAsString(fElementDepth),
  733. "character reference"},
  734. XMLErrorReporter.SEVERITY_ERROR);
  735. }
  736. }
  737. if (fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
  738. charDataInContent();
  739. }
  740. }
  741. // call handlers
  742. if (callNextCharacters && fDocumentHandler != null) {
  743. fDocumentHandler.characters(text, augs);
  744. }
  745. } // characters(XMLString)
  746. /**
  747. * Ignorable whitespace. For this method to be called, the document
  748. * source must have some way of determining that the text containing
  749. * only whitespace characters should be considered ignorable. For
  750. * example, the validator can determine if a length of whitespace
  751. * characters in the document are ignorable based on the element
  752. * content model.
  753. *
  754. * @param text The ignorable whitespace.
  755. * @param augs Additional information that may include infoset augmentations
  756. *
  757. * @throws XNIException Thrown by handler to signal an error.
  758. */
  759. public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
  760. // call handlers
  761. if (fDocumentHandler != null) {
  762. fDocumentHandler.ignorableWhitespace(text, augs);
  763. }
  764. } // ignorableWhitespace(XMLString)
  765. /**
  766. * The end of an element.
  767. *
  768. * @param element The name of the element.
  769. * @param augs Additional information that may include infoset augmentations
  770. *
  771. * @throws XNIException Thrown by handler to signal an error.
  772. */
  773. public void endElement(QName element, Augmentations augs) throws XNIException {
  774. handleEndElement(element, augs, false);
  775. } // endElement(QName)
  776. /**
  777. * The start of a CDATA section.
  778. * @param augs Additional information that may include infoset augmentations
  779. *
  780. * @throws XNIException Thrown by handler to signal an error.
  781. */
  782. public void startCDATA(Augmentations augs) throws XNIException {
  783. if (fPerformValidation && fInElementContent) {
  784. charDataInContent();
  785. }
  786. fInCDATASection = true;
  787. // call handlers
  788. if (fDocumentHandler != null) {
  789. fDocumentHandler.startCDATA(augs);
  790. }
  791. } // startCDATA()
  792. /**
  793. * The end of a CDATA section.
  794. * @param augs Additional information that may include infoset augmentations
  795. *
  796. * @throws XNIException Thrown by handler to signal an error.
  797. */
  798. public void endCDATA(Augmentations augs) throws XNIException {
  799. fInCDATASection = false;
  800. // call handlers
  801. if (fDocumentHandler != null) {
  802. fDocumentHandler.endCDATA(augs);
  803. }
  804. } // endCDATA()
  805. /**
  806. * The end of the document.
  807. * @param augs Additional information that may include infoset augmentations
  808. *
  809. * @throws XNIException Thrown by handler to signal an error.
  810. */
  811. public void endDocument(Augmentations augs) throws XNIException {
  812. // call handlers
  813. if (fDocumentHandler != null) {
  814. fDocumentHandler.endDocument(augs);
  815. }
  816. } // endDocument()
  817. /**
  818. * A comment.
  819. *
  820. * @param text The text in the comment.
  821. * @param augs Additional information that may include infoset augmentations
  822. *
  823. * @throws XNIException Thrown by application to signal an error.
  824. */
  825. public void comment(XMLString text, Augmentations augs) throws XNIException {
  826. // fixes E15.1
  827. if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
  828. fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
  829. if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
  830. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  831. "MSG_CONTENT_INVALID_SPECIFIED",
  832. new Object[]{ fCurrentElement.rawname,
  833. "EMPTY",
  834. "comment"},
  835. XMLErrorReporter.SEVERITY_ERROR);
  836. }
  837. }
  838. // call handlers
  839. if (fDocumentHandler != null) {
  840. fDocumentHandler.comment(text, augs);
  841. }
  842. } // comment(XMLString)
  843. /**
  844. * A processing instruction. Processing instructions consist of a
  845. * target name and, optionally, text data. The data is only meaningful
  846. * to the application.
  847. * <p>
  848. * Typically, a processing instruction's data will contain a series
  849. * of pseudo-attributes. These pseudo-attributes follow the form of
  850. * element attributes but are <strong>not</strong> parsed or presented
  851. * to the application as anything other than text. The application is
  852. * responsible for parsing the data.
  853. *
  854. * @param target The target.
  855. * @param data The data or null if none specified.
  856. * @param augs Additional information that may include infoset augmentations
  857. *
  858. * @throws XNIException Thrown by handler to signal an error.
  859. */
  860. public void processingInstruction(String target, XMLString data, Augmentations augs)
  861. throws XNIException {
  862. // fixes E15.1
  863. if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
  864. fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
  865. if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
  866. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  867. "MSG_CONTENT_INVALID_SPECIFIED",
  868. new Object[]{ fCurrentElement.rawname,
  869. "EMPTY",
  870. "processing instruction"},
  871. XMLErrorReporter.SEVERITY_ERROR);
  872. }
  873. }
  874. // call handlers
  875. if (fDocumentHandler != null) {
  876. fDocumentHandler.processingInstruction(target, data, augs);
  877. }
  878. } // processingInstruction(String,XMLString)
  879. /**
  880. * This method notifies the start of a general entity.
  881. * <p>
  882. * <strong>Note:</strong> This method is not called for entity references
  883. * appearing as part of attribute values.
  884. *
  885. * @param name The name of the general entity.
  886. * @param identifier The resource identifier.
  887. * @param encoding The auto-detected IANA encoding name of the entity
  888. * stream. This value will be null in those situations
  889. * where the entity encoding is not auto-detected (e.g.
  890. * internal entities or a document entity that is
  891. * parsed from a java.io.Reader).
  892. * @param augs Additional information that may include infoset augmentations
  893. *
  894. * @exception XNIException Thrown by handler to signal an error.
  895. */
  896. public void startGeneralEntity(String name,
  897. XMLResourceIdentifier identifier,
  898. String encoding,
  899. Augmentations augs) throws XNIException {
  900. if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
  901. fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
  902. // fixes E15.1
  903. if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
  904. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  905. "MSG_CONTENT_INVALID_SPECIFIED",
  906. new Object[]{ fCurrentElement.rawname,
  907. "EMPTY", "ENTITY"},
  908. XMLErrorReporter.SEVERITY_ERROR);
  909. }
  910. if (fGrammarBucket.getStandalone()) {
  911. XMLDTDLoader.checkStandaloneEntityRef(name, fDTDGrammar, fEntityDecl, fErrorReporter);
  912. }
  913. }
  914. if (fDocumentHandler != null) {
  915. fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
  916. }
  917. }
  918. /**
  919. * This method notifies the end of a general entity.
  920. * <p>
  921. * <strong>Note:</strong> This method is not called for entity references
  922. * appearing as part of attribute values.
  923. *
  924. * @param name The name of the entity.
  925. * @param augs Additional information that may include infoset augmentations
  926. *
  927. * @exception XNIException
  928. * Thrown by handler to signal an error.
  929. */
  930. public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
  931. // call handlers
  932. if (fDocumentHandler != null) {
  933. fDocumentHandler.endGeneralEntity(name, augs);
  934. }
  935. } // endEntity(String)
  936. /**
  937. * Notifies of the presence of a TextDecl line in an entity. If present,
  938. * this method will be called immediately following the startParameterEntity call.
  939. * <p>
  940. * <strong>Note:</strong> This method is only called for external
  941. * parameter entities referenced in the DTD.
  942. *
  943. * @param version The XML version, or null if not specified.
  944. * @param encoding The IANA encoding name of the entity.
  945. * @param augs Additional information that may include infoset
  946. * augmentations.
  947. *
  948. * @throws XNIException Thrown by handler to signal an error.
  949. */
  950. public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
  951. // call handlers
  952. if (fDocumentHandler != null) {
  953. fDocumentHandler.textDecl(version, encoding, augs);
  954. }
  955. }
  956. public final boolean hasGrammar(){
  957. return (fDTDGrammar != null);
  958. }
  959. public final boolean validate(){
  960. // Do validation if all of the following are true:
  961. // 1. The JAXP Schema Language property is not XML Schema
  962. // REVISIT: since only DTD and Schema are supported at this time,
  963. // such checking is sufficient. but if more schema types
  964. // are introduced in the future, we'll need to change it
  965. // to something like
  966. // (fSchemaType == null || fSchemaType == NS_XML_DTD)
  967. // 2. One of the following is true (validation features)
  968. // 2.1 Dynamic validation is off, and validation is on
  969. // 2.2 Dynamic validation is on, and DOCTYPE was seen
  970. // 3 Xerces schema validation feature is off, or DOCTYPE was seen.
  971. return (fSchemaType != Constants.NS_XMLSCHEMA) &&
  972. (!fDynamicValidation && fValidation ||
  973. fDynamicValidation && fSeenDoctypeDecl) &&
  974. (fDTDValidation || fSeenDoctypeDecl);
  975. }
  976. //REVISIT:we can convert into functions.. adding default attribute values.. and one validating.
  977. /** Add default attributes and validate. */
  978. protected void addDTDDefaultAttrsAndValidate(QName elementName, int elementIndex,
  979. XMLAttributes attributes)
  980. throws XNIException {
  981. // is there anything to do?
  982. if (elementIndex == -1 || fDTDGrammar == null) {
  983. return;
  984. }
  985. //
  986. // Check after all specified attrs are scanned
  987. // (1) report error for REQUIRED attrs that are missing (V_TAGc)
  988. // (2) add default attrs (FIXED and NOT_FIXED)
  989. //
  990. int attlistIndex = fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);
  991. while (attlistIndex != -1) {
  992. fDTDGrammar.getAttributeDecl(attlistIndex, fTempAttDecl);
  993. if (DEBUG_ATTRIBUTES) {
  994. if (fTempAttDecl != null) {
  995. XMLElementDecl elementDecl = new XMLElementDecl();
  996. fDTDGrammar.getElementDecl(elementIndex, elementDecl);
  997. System.out.println("element: "+(elementDecl.name.localpart));
  998. System.out.println("attlistIndex " + attlistIndex + "\n"+
  999. "attName : '"+(fTempAttDecl.name.localpart) + "'\n"
  1000. + "attType : "+fTempAttDecl.simpleType.type + "\n"
  1001. + "attDefaultType : "+fTempAttDecl.simpleType.defaultType + "\n"
  1002. + "attDefaultValue : '"+fTempAttDecl.simpleType.defaultValue + "'\n"
  1003. + attributes.getLength() +"\n"
  1004. );
  1005. }
  1006. }
  1007. String attPrefix = fTempAttDecl.name.prefix;
  1008. String attLocalpart = fTempAttDecl.name.localpart;
  1009. String attRawName = fTempAttDecl.name.rawname;
  1010. String attType = getAttributeTypeName(fTempAttDecl);
  1011. int attDefaultType =fTempAttDecl.simpleType.defaultType;
  1012. String attValue = null;
  1013. if (fTempAttDecl.simpleType.defaultValue != null) {
  1014. attValue = fTempAttDecl.simpleType.defaultValue;
  1015. }
  1016. boolean specified = false;
  1017. boolean required = attDefaultType == XMLSimpleType.DEFAULT_TYPE_REQUIRED;
  1018. boolean cdata = attType == XMLSymbols.fCDATASymbol;
  1019. if (!cdata || required || attValue != null) {
  1020. int attrCount = attributes.getLength();
  1021. for (int i = 0; i < attrCount; i++) {
  1022. if (attributes.getQName(i) == attRawName) {
  1023. specified = true;
  1024. break;
  1025. }
  1026. }
  1027. }
  1028. if (!specified) {
  1029. if (required) {
  1030. if (fPerformValidation) {
  1031. Object[] args = {elementName.localpart, attRawName};
  1032. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1033. "MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED", args,
  1034. XMLErrorReporter.SEVERITY_ERROR);
  1035. }
  1036. }
  1037. else if (attValue != null) {
  1038. if (fPerformValidation && fGrammarBucket.getStandalone()) {
  1039. if (fDTDGrammar.getAttributeDeclIsExternal(attlistIndex)) {
  1040. Object[] args = { elementName.localpart, attRawName};
  1041. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1042. "MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED", args,
  1043. XMLErrorReporter.SEVERITY_ERROR);
  1044. }
  1045. }
  1046. // add namespace information
  1047. if (fNamespaces) {
  1048. int index = attRawName.indexOf(':');
  1049. if (index != -1) {
  1050. attPrefix = attRawName.substring(0, index);
  1051. attPrefix = fSymbolTable.addSymbol(attPrefix);
  1052. attLocalpart = attRawName.substring(index + 1);
  1053. attLocalpart = fSymbolTable.addSymbol(attLocalpart);
  1054. }
  1055. }
  1056. // add attribute
  1057. fTempQName.setValues(attPrefix, attLocalpart, attRawName, fTempAttDecl.name.uri);
  1058. int newAttr = attributes.addAttribute(fTempQName, attType, attValue);
  1059. }
  1060. }
  1061. // get next att decl in the Grammar for this element
  1062. attlistIndex = fDTDGrammar.getNextAttributeDeclIndex(attlistIndex);
  1063. }
  1064. // now iterate through the expanded attributes for
  1065. // 1. if every attribute seen is declared in the DTD
  1066. // 2. check if the VC: default_fixed holds
  1067. // 3. validate every attribute.
  1068. int attrCount = attributes.getLength();
  1069. for (int i = 0; i < attrCount; i++) {
  1070. String attrRawName = attributes.getQName(i);
  1071. boolean declared = false;
  1072. if (fPerformValidation) {
  1073. if (fGrammarBucket.getStandalone()) {
  1074. // check VC: Standalone Document Declaration, entities
  1075. // references appear in the document.
  1076. // REVISIT: this can be combined to a single check in
  1077. // startEntity if we add one more argument in
  1078. // startEnity, inAttrValue
  1079. String nonNormalizedValue = attributes.getNonNormalizedValue(i);
  1080. if (nonNormalizedValue != null) {
  1081. String entityName = getExternalEntityRefInAttrValue(nonNormalizedValue);
  1082. if (entityName != null) {
  1083. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1084. "MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE",
  1085. new Object[]{entityName},
  1086. XMLErrorReporter.SEVERITY_ERROR);
  1087. }
  1088. }
  1089. }
  1090. }
  1091. int attDefIndex = -1;
  1092. int position =
  1093. fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);
  1094. while (position != -1) {
  1095. fDTDGrammar.getAttributeDecl(position, fTempAttDecl);
  1096. if (fTempAttDecl.name.rawname == attrRawName) {
  1097. // found the match att decl,
  1098. attDefIndex = position;
  1099. declared = true;
  1100. break;
  1101. }
  1102. position = fDTDGrammar.getNextAttributeDeclIndex(position);
  1103. }
  1104. if (!declared) {
  1105. if (fPerformValidation) {
  1106. // REVISIT - cache the elem/attr tuple so that we only
  1107. // give this error once for each unique occurrence
  1108. Object[] args = { elementName.rawname, attrRawName};
  1109. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1110. "MSG_ATTRIBUTE_NOT_DECLARED",
  1111. args,XMLErrorReporter.SEVERITY_ERROR);
  1112. }
  1113. continue;
  1114. }
  1115. // attribute is declared
  1116. // fTempAttDecl should have the right value set now, so
  1117. // the following is not needed
  1118. // fGrammar.getAttributeDecl(attDefIndex,fTempAttDecl);
  1119. String type = getAttributeTypeName(fTempAttDecl);
  1120. attributes.setType(i, type);
  1121. attributes.getAugmentations(i).putItem(Constants.ATTRIBUTE_DECLARED, Boolean.TRUE);
  1122. boolean changedByNormalization = false;
  1123. String oldValue = attributes.getValue(i);
  1124. String attrValue = oldValue;
  1125. if (attributes.isSpecified(i) && type != XMLSymbols.fCDATASymbol) {
  1126. changedByNormalization = normalizeAttrValue(attributes, i);
  1127. attrValue = attributes.getValue(i);
  1128. if (fPerformValidation && fGrammarBucket.getStandalone()
  1129. && changedByNormalization
  1130. && fDTDGrammar.getAttributeDeclIsExternal(position)
  1131. ) {
  1132. // check VC: Standalone Document Declaration
  1133. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1134. "MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE",
  1135. new Object[]{attrRawName, oldValue, attrValue},
  1136. XMLErrorReporter.SEVERITY_ERROR);
  1137. }
  1138. }
  1139. if (!fPerformValidation) {
  1140. continue;
  1141. }
  1142. if (fTempAttDecl.simpleType.defaultType ==
  1143. XMLSimpleType.DEFAULT_TYPE_FIXED) {
  1144. String defaultValue = fTempAttDecl.simpleType.defaultValue;
  1145. if (!attrValue.equals(defaultValue)) {
  1146. Object[] args = {elementName.localpart,
  1147. attrRawName,
  1148. attrValue,
  1149. defaultValue};
  1150. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1151. "MSG_FIXED_ATTVALUE_INVALID",
  1152. args, XMLErrorReporter.SEVERITY_ERROR);
  1153. }
  1154. }
  1155. if (fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ENTITY ||
  1156. fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ENUMERATION ||
  1157. fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ID ||
  1158. fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_IDREF ||
  1159. fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_NMTOKEN ||
  1160. fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_NOTATION
  1161. ) {
  1162. validateDTDattribute(elementName, attrValue, fTempAttDecl);
  1163. }
  1164. } // for all attributes
  1165. } // addDTDDefaultAttrsAndValidate(int,XMLAttrList)
  1166. /** Checks entities in attribute values for standalone VC. */
  1167. protected String getExternalEntityRefInAttrValue(String nonNormalizedValue) {
  1168. int valLength = nonNormalizedValue.length();
  1169. int ampIndex = nonNormalizedValue.indexOf('&');
  1170. while (ampIndex != -1) {
  1171. if (ampIndex + 1 < valLength &&
  1172. nonNormalizedValue.charAt(ampIndex+1) != '#') {
  1173. int semicolonIndex = nonNormalizedValue.indexOf(';', ampIndex+1);
  1174. String entityName = nonNormalizedValue.substring(ampIndex+1, semicolonIndex);
  1175. entityName = fSymbolTable.addSymbol(entityName);
  1176. int entIndex = fDTDGrammar.getEntityDeclIndex(entityName);
  1177. if (entIndex > -1) {
  1178. fDTDGrammar.getEntityDecl(entIndex, fEntityDecl);
  1179. if (fEntityDecl.inExternal ||
  1180. (entityName = getExternalEntityRefInAttrValue(fEntityDecl.value)) != null) {
  1181. return entityName;
  1182. }
  1183. }
  1184. }
  1185. ampIndex = nonNormalizedValue.indexOf('&', ampIndex+1);
  1186. }
  1187. return null;
  1188. } // isExternalEntityRefInAttrValue(String):String
  1189. /**
  1190. * Validate attributes in DTD fashion.
  1191. */
  1192. protected void validateDTDattribute(QName element, String attValue,
  1193. XMLAttributeDecl attributeDecl)
  1194. throws XNIException {
  1195. switch (attributeDecl.simpleType.type) {
  1196. case XMLSimpleType.TYPE_ENTITY: {
  1197. // NOTE: Save this information because invalidStandaloneAttDef
  1198. boolean isAlistAttribute = attributeDecl.simpleType.list;
  1199. try {
  1200. if (isAlistAttribute) {
  1201. fValENTITIES.validate(attValue, fValidationState);
  1202. }
  1203. else {
  1204. fValENTITY.validate(attValue, fValidationState);
  1205. }
  1206. }
  1207. catch (InvalidDatatypeValueException ex) {
  1208. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1209. ex.getKey(),
  1210. ex.getArgs(),
  1211. XMLErrorReporter.SEVERITY_ERROR );
  1212. }
  1213. break;
  1214. }
  1215. case XMLSimpleType.TYPE_NOTATION:
  1216. case XMLSimpleType.TYPE_ENUMERATION: {
  1217. boolean found = false;
  1218. String [] enumVals = attributeDecl.simpleType.enumeration;
  1219. if (enumVals == null) {
  1220. found = false;
  1221. }
  1222. else
  1223. for (int i = 0; i < enumVals.length; i++) {
  1224. if (attValue == enumVals[i] || attValue.equals(enumVals[i])) {
  1225. found = true;
  1226. break;
  1227. }
  1228. }
  1229. if (!found) {
  1230. StringBuffer enumValueString = new StringBuffer();
  1231. if (enumVals != null)
  1232. for (int i = 0; i < enumVals.length; i++) {
  1233. enumValueString.append(enumVals[i]+" ");
  1234. }
  1235. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1236. "MSG_ATTRIBUTE_VALUE_NOT_IN_LIST",
  1237. new Object[]{attributeDecl.name.rawname, attValue, enumValueString},
  1238. XMLErrorReporter.SEVERITY_ERROR);
  1239. }
  1240. break;
  1241. }
  1242. case XMLSimpleType.TYPE_ID: {
  1243. try {
  1244. fValID.validate(attValue, fValidationState);
  1245. }
  1246. catch (InvalidDatatypeValueException ex) {
  1247. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1248. ex.getKey(),
  1249. ex.getArgs(),
  1250. XMLErrorReporter.SEVERITY_ERROR );
  1251. }
  1252. break;
  1253. }
  1254. case XMLSimpleType.TYPE_IDREF: {
  1255. boolean isAlistAttribute = attributeDecl.simpleType.list;//Caveat - Save this information because invalidStandaloneAttDef
  1256. try {
  1257. if (isAlistAttribute) {
  1258. fValIDRefs.validate(attValue, fValidationState);
  1259. }
  1260. else {
  1261. fValIDRef.validate(attValue, fValidationState);
  1262. }
  1263. }
  1264. catch (InvalidDatatypeValueException ex) {
  1265. if (isAlistAttribute) {
  1266. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1267. "IDREFSInvalid",
  1268. new Object[]{attValue},
  1269. XMLErrorReporter.SEVERITY_ERROR );
  1270. }
  1271. else {
  1272. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1273. ex.getKey(),
  1274. ex.getArgs(),
  1275. XMLErrorReporter.SEVERITY_ERROR );
  1276. }
  1277. }
  1278. break;
  1279. }
  1280. case XMLSimpleType.TYPE_NMTOKEN: {
  1281. boolean isAlistAttribute = attributeDecl.simpleType.list;//Caveat - Save this information because invalidStandaloneAttDef
  1282. //changes fTempAttDef
  1283. try {
  1284. if (isAlistAttribute) {
  1285. fValNMTOKENS.validate(attValue, fValidationState);
  1286. }
  1287. else {
  1288. fValNMTOKEN.validate(attValue, fValidationState);
  1289. }
  1290. }
  1291. catch (InvalidDatatypeValueException ex) {
  1292. if (isAlistAttribute) {
  1293. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1294. "NMTOKENSInvalid",
  1295. new Object[] { attValue},
  1296. XMLErrorReporter.SEVERITY_ERROR);
  1297. }
  1298. else {
  1299. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1300. "NMTOKENInvalid",
  1301. new Object[] { attValue},
  1302. XMLErrorReporter.SEVERITY_ERROR);
  1303. }
  1304. }
  1305. break;
  1306. }
  1307. } // switch
  1308. } // validateDTDattribute(QName,String,XMLAttributeDecl)
  1309. /** Returns true if invalid standalone attribute definition. */
  1310. protected boolean invalidStandaloneAttDef(QName element, QName attribute) {
  1311. // REVISIT: This obviously needs to be fixed! -Ac
  1312. boolean state = true;
  1313. /*
  1314. if (fStandaloneReader == -1) {
  1315. return false;
  1316. }
  1317. // we are normalizing a default att value... this ok?
  1318. if (element.rawname == -1) {
  1319. return false;
  1320. }
  1321. return getAttDefIsExternal(element, attribute);
  1322. */
  1323. return state;
  1324. }
  1325. //
  1326. // Private methods
  1327. //
  1328. /**
  1329. * Normalize the attribute value of a non CDATA attributes collapsing
  1330. * sequences of space characters (x20)
  1331. *
  1332. * @param attributes The list of attributes
  1333. * @param index The index of the attribute to normalize
  1334. */
  1335. private boolean normalizeAttrValue(XMLAttributes attributes, int index) {
  1336. // vars
  1337. boolean leadingSpace = true;
  1338. boolean spaceStart = false;
  1339. boolean readingNonSpace = false;
  1340. int count = 0;
  1341. int eaten = 0;
  1342. String attrValue = attributes.getValue(index);
  1343. char[] attValue = new char[attrValue.length()];
  1344. fBuffer.setLength(0);
  1345. attrValue.getChars(0, attrValue.length(), attValue, 0);
  1346. for (int i = 0; i < attValue.length; i++) {
  1347. if (attValue[i] == ' ') {
  1348. // now the tricky part
  1349. if (readingNonSpace) {
  1350. spaceStart = true;
  1351. readingNonSpace = false;
  1352. }
  1353. if (spaceStart && !leadingSpace) {
  1354. spaceStart = false;
  1355. fBuffer.append(attValue[i]);
  1356. count++;
  1357. }
  1358. else {
  1359. if (leadingSpace || !spaceStart) {
  1360. eaten ++;
  1361. /*** BUG #3512 ***
  1362. int entityCount = attributes.getEntityCount(index);
  1363. for (int j = 0; j < entityCount; j++) {
  1364. int offset = attributes.getEntityOffset(index, j);
  1365. int length = attributes.getEntityLength(index, j);
  1366. if (offset <= i-eaten+1) {
  1367. if (offset+length >= i-eaten+1) {
  1368. if (length > 0)
  1369. length--;
  1370. }
  1371. }
  1372. else {
  1373. if (offset > 0)
  1374. offset--;
  1375. }
  1376. attributes.setEntityOffset(index, j, offset);
  1377. attributes.setEntityLength(index, j, length);
  1378. }
  1379. /***/
  1380. }
  1381. }
  1382. }
  1383. else {
  1384. readingNonSpace = true;
  1385. spaceStart = false;
  1386. leadingSpace = false;
  1387. fBuffer.append(attValue[i]);
  1388. count++;
  1389. }
  1390. }
  1391. // check if the last appended character is a space.
  1392. if (count > 0 && fBuffer.charAt(count-1) == ' ') {
  1393. fBuffer.setLength(count-1);
  1394. /*** BUG #3512 ***
  1395. int entityCount = attributes.getEntityCount(index);
  1396. for (int j=0; j < entityCount; j++) {
  1397. int offset = attributes.getEntityOffset(index, j);
  1398. int length = attributes.getEntityLength(index, j);
  1399. if (offset < count-1) {
  1400. if (offset+length == count) {
  1401. length--;
  1402. }
  1403. }
  1404. else {
  1405. offset--;
  1406. }
  1407. attributes.setEntityOffset(index, j, offset);
  1408. attributes.setEntityLength(index, j, length);
  1409. }
  1410. /***/
  1411. }
  1412. String newValue = fBuffer.toString();
  1413. attributes.setValue(index, newValue);
  1414. return ! attrValue.equals(newValue);
  1415. }
  1416. /** Root element specified. */
  1417. private final void rootElementSpecified(QName rootElement) throws XNIException {
  1418. if (fPerformValidation) {
  1419. String root1 = fRootElement.rawname;
  1420. String root2 = rootElement.rawname;
  1421. if (root1 == null || !root1.equals(root2)) {
  1422. fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
  1423. "RootElementTypeMustMatchDoctypedecl",
  1424. new Object[]{root1, root2},
  1425. XMLErrorReporter.SEVERITY_ERROR);
  1426. }
  1427. }
  1428. } // rootElementSpecified(QName)
  1429. /**
  1430. * Check that the content of an element is valid.
  1431. * <p>
  1432. * This is the method of primary concern to the validator. This method is called
  1433. * upon the scanner reaching the end tag of an element. At that time, the
  1434. * element's children must be structurally validated, so it calls this method.
  1435. * The index of the element being checked (in the decl pool), is provided as
  1436. * well as an array of element name indexes of the children. The validator must
  1437. * confirm that this element can have these children in this order.
  1438. * <p>
  1439. * This can also be called to do 'what if' testing of content models just to see
  1440. * if they would be valid.
  1441. * <p>
  1442. * Note that the element index is an index into the element decl pool, whereas
  1443. * the children indexes are name indexes, i.e. into the string pool.
  1444. * <p>
  1445. * A value of -1 in the children array indicates a PCDATA node. All other
  1446. * indexes will be positive and represent child elements. The count can be
  1447. * zero, since some elements have the EMPTY content model and that must be
  1448. * confirmed.
  1449. *
  1450. * @param elementIndex The index within the <code>ElementDeclPool</code> of this
  1451. * element.
  1452. * @param childCount The number of entries in the <code>children</code> array.
  1453. * @param children The children of this element.
  1454. *
  1455. * @return The value -1 if fully valid, else the 0 based index of the child
  1456. * that first failed. If the value returned is equal to the number
  1457. * of children, then additional content is required to reach a valid
  1458. * ending state.
  1459. *
  1460. * @exception Exception Thrown on error.
  1461. */
  1462. private int checkContent(int elementIndex,
  1463. QName[] children,
  1464. int childOffset,
  1465. int childCount) throws XNIException {
  1466. fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
  1467. // Get the element name index from the element
  1468. final String elementType = fCurrentElement.rawname;
  1469. // Get out the content spec for this element
  1470. final int contentType = fCurrentContentSpecType;
  1471. //
  1472. // Deal with the possible types of content. We try to optimized here
  1473. // by dealing specially with content models that don't require the
  1474. // full DFA treatment.
  1475. //
  1476. if (contentType == XMLElementDecl.TYPE_EMPTY) {
  1477. //
  1478. // If the child count is greater than zero, then this is
  1479. // an error right off the bat at index 0.
  1480. //
  1481. if (childCount != 0) {
  1482. return 0;
  1483. }
  1484. }
  1485. else if (contentType == XMLElementDecl.TYPE_ANY) {
  1486. //
  1487. // This one is open game so we don't pass any judgement on it
  1488. // at all. Its assumed to fine since it can hold anything.
  1489. //
  1490. }
  1491. else if (contentType == XMLElementDecl.TYPE_MIXED ||
  1492. contentType == XMLElementDecl.TYPE_CHILDREN) {
  1493. // Get the content model for this element, faulting it in if needed
  1494. ContentModelValidator cmElem = null;
  1495. cmElem = fTempElementDecl.contentModelValidator;
  1496. int result = cmElem.validate(children, childOffset, childCount);
  1497. return result;
  1498. }
  1499. else if (contentType == -1) {
  1500. //REVISIT
  1501. /****
  1502. reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
  1503. XMLMessages.VC_ELEMENT_VALID,
  1504. elementType);
  1505. /****/
  1506. }
  1507. else if (contentType == XMLElementDecl.TYPE_SIMPLE) {
  1508. //REVISIT
  1509. // this should never be reached in the case of DTD validation.
  1510. }
  1511. else {
  1512. //REVISIT
  1513. /****
  1514. fErrorReporter.reportError(fErrorReporter.getLocator(),
  1515. ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
  1516. ImplementationMessages.VAL_CST,
  1517. 0,
  1518. null,
  1519. XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
  1520. /****/
  1521. }
  1522. // We succeeded
  1523. return -1;
  1524. } // checkContent(int,int,QName[]):int
  1525. /** Returns the content spec type for an element index. */
  1526. private int getContentSpecType(int elementIndex) {
  1527. int contentSpecType = -1;
  1528. if (elementIndex > -1) {
  1529. if (fDTDGrammar.getElementDecl(elementIndex,fTempElementDecl)) {
  1530. contentSpecType = fTempElementDecl.type;
  1531. }
  1532. }
  1533. return contentSpecType;
  1534. }
  1535. /** Character data in content. */
  1536. private void charDataInContent() {
  1537. if (DEBUG_ELEMENT_CHILDREN) {
  1538. System.out.println("charDataInContent()");
  1539. }
  1540. if (fElementChildren.length <= fElementChildrenLength) {
  1541. QName[] newarray = new QName[fElementChildren.length * 2];
  1542. System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
  1543. fElementChildren = newarray;
  1544. }
  1545. QName qname = fElementChildren[fElementChildrenLength];
  1546. if (qname == null) {
  1547. for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
  1548. fElementChildren[i] = new QName();
  1549. }
  1550. qname = fElementChildren[fElementChildrenLength];
  1551. }
  1552. qname.clear();
  1553. fElementChildrenLength++;
  1554. } // charDataInCount()
  1555. /** convert attribute type from ints to strings */
  1556. private String getAttributeTypeName(XMLAttributeDecl attrDecl) {
  1557. switch (attrDecl.simpleType.type) {
  1558. case XMLSimpleType.TYPE_ENTITY: {
  1559. return attrDecl.simpleType.list ? XMLSymbols.fENTITIESSymbol : XMLSymbols.fENTITYSymbol;
  1560. }
  1561. case XMLSimpleType.TYPE_ENUMERATION: {
  1562. StringBuffer buffer = new StringBuffer();
  1563. buffer.append('(');
  1564. for (int i=0; i<attrDecl.simpleType.enumeration.length ; i++) {
  1565. if (i > 0) {
  1566. buffer.append("|");
  1567. }
  1568. buffer.append(attrDecl.simpleType.enumeration[i]);
  1569. }
  1570. buffer.append(')');
  1571. return fSymbolTable.addSymbol(buffer.toString());
  1572. }
  1573. case XMLSimpleType.TYPE_ID: {
  1574. return XMLSymbols.fIDSymbol;
  1575. }
  1576. case XMLSimpleType.TYPE_IDREF: {
  1577. return attrDecl.simpleType.list ? XMLSymbols.fIDREFSSymbol : XMLSymbols.fIDREFSymbol;
  1578. }
  1579. case XMLSimpleType.TYPE_NMTOKEN: {
  1580. return attrDecl.simpleType.list ? XMLSymbols.fNMTOKENSSymbol : XMLSymbols.fNMTOKENSymbol;
  1581. }
  1582. case XMLSimpleType.TYPE_NOTATION: {
  1583. return XMLSymbols.fNOTATIONSymbol;
  1584. }
  1585. }
  1586. return XMLSymbols.fCDATASymbol;
  1587. } // getAttributeTypeName(XMLAttributeDecl):String
  1588. /** initialization */
  1589. protected void init() {
  1590. // datatype validators
  1591. if (fValidation || fDynamicValidation) {
  1592. try {
  1593. //REVISIT: datatypeRegistry + initialization of datatype
  1594. // why do we cast to ListDatatypeValidator?
  1595. fValID = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDSymbol);
  1596. fValIDRef = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDREFSymbol);
  1597. fValIDRefs = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDREFSSymbol);
  1598. fValENTITY = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fENTITYSymbol);
  1599. fValENTITIES = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fENTITIESSymbol);
  1600. fValNMTOKEN = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNMTOKENSymbol);
  1601. fValNMTOKENS = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNMTOKENSSymbol);
  1602. fValNOTATION = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNOTATIONSymbol);
  1603. }
  1604. catch (Exception e) {
  1605. // should never happen
  1606. e.printStackTrace(System.err);
  1607. }
  1608. }
  1609. } // init()
  1610. /** ensure element stack capacity */
  1611. private void ensureStackCapacity ( int newElementDepth) {
  1612. if (newElementDepth == fElementQNamePartsStack.length) {
  1613. int[] newStack = new int[newElementDepth * 2];
  1614. QName[] newStackOfQueue = new QName[newElementDepth * 2];
  1615. System.arraycopy(this.fElementQNamePartsStack, 0, newStackOfQueue, 0, newElementDepth );
  1616. fElementQNamePartsStack = newStackOfQueue;
  1617. QName qname = fElementQNamePartsStack[newElementDepth];
  1618. if (qname == null) {
  1619. for (int i = newElementDepth; i < fElementQNamePartsStack.length; i++) {
  1620. fElementQNamePartsStack[i] = new QName();
  1621. }
  1622. }
  1623. newStack = new int[newElementDepth * 2];
  1624. System.arraycopy(fElementIndexStack, 0, newStack, 0, newElementDepth);
  1625. fElementIndexStack = newStack;
  1626. newStack = new int[newElementDepth * 2];
  1627. System.arraycopy(fContentSpecTypeStack, 0, newStack, 0, newElementDepth);
  1628. fContentSpecTypeStack = newStack;
  1629. }
  1630. } // ensureStackCapacity
  1631. //
  1632. // Protected methods
  1633. //
  1634. /** Handle element
  1635. * @return true if validator is removed from the pipeline
  1636. */
  1637. protected boolean handleStartElement(QName element, XMLAttributes attributes, Augmentations augs)
  1638. throws XNIException {
  1639. // VC: Root Element Type
  1640. // see if the root element's name matches the one in DoctypeDecl
  1641. if (!fSeenRootElement) {
  1642. // REVISIT: Here are current assumptions about validation features
  1643. // given that XMLSchema validator is in the pipeline
  1644. //
  1645. // http://xml.org/sax/features/validation = true
  1646. // http://apache.org/xml/features/validation/schema = true
  1647. //
  1648. // [1] XML instance document only has reference to a DTD
  1649. // Outcome: report validation errors only against dtd.
  1650. //
  1651. // [2] XML instance document has only XML Schema grammars:
  1652. // Outcome: report validation errors only against schemas (no errors produced from DTD validator)
  1653. //
  1654. // [3] XML instance document has DTD and XML schemas:
  1655. // [a] if schema language is not set outcome - validation errors reported against both grammars: DTD and schemas.
  1656. // [b] if schema language is set to XML Schema - do not report validation errors
  1657. //
  1658. // if dynamic validation is on
  1659. // validate only against grammar we've found (depending on settings
  1660. // for schema feature)
  1661. //
  1662. //
  1663. fPerformValidation = validate();
  1664. fSeenRootElement = true;
  1665. fValidationManager.setEntityState(fDTDGrammar);
  1666. fValidationManager.setGrammarFound(fSeenDoctypeDecl);
  1667. rootElementSpecified(element);
  1668. }
  1669. if (fDTDGrammar == null) {
  1670. if (!fPerformValidation) {
  1671. fCurrentElementIndex = -1;
  1672. fCurrentContentSpecType = -1;
  1673. fInElementContent = false;
  1674. }
  1675. if (fPerformValidation) {
  1676. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1677. "MSG_GRAMMAR_NOT_FOUND",
  1678. new Object[]{ element.rawname},
  1679. XMLErrorReporter.SEVERITY_ERROR);
  1680. }
  1681. // modify pipeline
  1682. if (fDocumentSource !=null ) {
  1683. fDocumentSource.setDocumentHandler(fDocumentHandler);
  1684. if (fDocumentHandler != null)
  1685. fDocumentHandler.setDocumentSource(fDocumentSource);
  1686. return true;
  1687. }
  1688. }
  1689. else {
  1690. // resolve the element
  1691. fCurrentElementIndex = fDTDGrammar.getElementDeclIndex(element);
  1692. //changed here.. new function for getContentSpecType
  1693. fCurrentContentSpecType = fDTDGrammar.getContentSpecType(fCurrentElementIndex);
  1694. if (fCurrentContentSpecType == -1 && fPerformValidation) {
  1695. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1696. "MSG_ELEMENT_NOT_DECLARED",
  1697. new Object[]{ element.rawname},
  1698. XMLErrorReporter.SEVERITY_ERROR);
  1699. }
  1700. // 0. insert default attributes
  1701. // 1. normalize the attributes
  1702. // 2. validate the attrivute list.
  1703. // TO DO:
  1704. //changed here.. also pass element name,
  1705. addDTDDefaultAttrsAndValidate(element, fCurrentElementIndex, attributes);
  1706. }
  1707. // set element content state
  1708. fInElementContent = fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN;
  1709. // increment the element depth, add this element's
  1710. // QName to its enclosing element 's children list
  1711. fElementDepth++;
  1712. if (fPerformValidation) {
  1713. // push current length onto stack
  1714. if (fElementChildrenOffsetStack.length <= fElementDepth) {
  1715. int newarray[] = new int[fElementChildrenOffsetStack.length * 2];
  1716. System.arraycopy(fElementChildrenOffsetStack, 0, newarray, 0, fElementChildrenOffsetStack.length);
  1717. fElementChildrenOffsetStack = newarray;
  1718. }
  1719. fElementChildrenOffsetStack[fElementDepth] = fElementChildrenLength;
  1720. // add this element to children
  1721. if (fElementChildren.length <= fElementChildrenLength) {
  1722. QName[] newarray = new QName[fElementChildrenLength * 2];
  1723. System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
  1724. fElementChildren = newarray;
  1725. }
  1726. QName qname = fElementChildren[fElementChildrenLength];
  1727. if (qname == null) {
  1728. for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
  1729. fElementChildren[i] = new QName();
  1730. }
  1731. qname = fElementChildren[fElementChildrenLength];
  1732. }
  1733. qname.setValues(element);
  1734. fElementChildrenLength++;
  1735. }
  1736. // save current element information
  1737. fCurrentElement.setValues(element);
  1738. ensureStackCapacity(fElementDepth);
  1739. fElementQNamePartsStack[fElementDepth].setValues(fCurrentElement);
  1740. fElementIndexStack[fElementDepth] = fCurrentElementIndex;
  1741. fContentSpecTypeStack[fElementDepth] = fCurrentContentSpecType;
  1742. startNamespaceScope(element, attributes, augs);
  1743. return false;
  1744. } // handleStartElement(QName,XMLAttributes)
  1745. protected void startNamespaceScope(QName element, XMLAttributes attributes, Augmentations augs){
  1746. }
  1747. /** Handle end element. */
  1748. protected void handleEndElement(QName element, Augmentations augs, boolean isEmpty)
  1749. throws XNIException {
  1750. // decrease element depth
  1751. fElementDepth--;
  1752. // validate
  1753. if (fPerformValidation) {
  1754. int elementIndex = fCurrentElementIndex;
  1755. if (elementIndex != -1 && fCurrentContentSpecType != -1) {
  1756. QName children[] = fElementChildren;
  1757. int childrenOffset = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
  1758. int childrenLength = fElementChildrenLength - childrenOffset;
  1759. int result = checkContent(elementIndex,
  1760. children, childrenOffset, childrenLength);
  1761. if (result != -1) {
  1762. fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
  1763. if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
  1764. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1765. "MSG_CONTENT_INVALID",
  1766. new Object[]{ element.rawname, "EMPTY"},
  1767. XMLErrorReporter.SEVERITY_ERROR);
  1768. }
  1769. else {
  1770. String messageKey = result != childrenLength ?
  1771. "MSG_CONTENT_INVALID" : "MSG_CONTENT_INCOMPLETE";
  1772. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1773. messageKey,
  1774. new Object[]{ element.rawname,
  1775. fDTDGrammar.getContentSpecAsString(elementIndex)},
  1776. XMLErrorReporter.SEVERITY_ERROR);
  1777. }
  1778. }
  1779. }
  1780. fElementChildrenLength = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
  1781. }
  1782. endNamespaceScope(fCurrentElement, augs, isEmpty);
  1783. // now pop this element off the top of the element stack
  1784. if (fElementDepth < -1) {
  1785. throw new RuntimeException("FWK008 Element stack underflow");
  1786. }
  1787. if (fElementDepth < 0) {
  1788. fCurrentElement.clear();
  1789. fCurrentElementIndex = -1;
  1790. fCurrentContentSpecType = -1;
  1791. fInElementContent = false;
  1792. // TO DO : fix this
  1793. //
  1794. // Check after document is fully parsed
  1795. // (1) check that there was an element with a matching id for every
  1796. // IDREF and IDREFS attr (V_IDREF0)
  1797. //
  1798. if (fPerformValidation) {
  1799. String value = fValidationState.checkIDRefID();
  1800. if (value != null) {
  1801. fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
  1802. "MSG_ELEMENT_WITH_ID_REQUIRED",
  1803. new Object[]{value},
  1804. XMLErrorReporter.SEVERITY_ERROR );
  1805. }
  1806. }
  1807. return;
  1808. }
  1809. // If Namespace enable then localName != rawName
  1810. fCurrentElement.setValues(fElementQNamePartsStack[fElementDepth]);
  1811. fCurrentElementIndex = fElementIndexStack[fElementDepth];
  1812. fCurrentContentSpecType = fContentSpecTypeStack[fElementDepth];
  1813. fInElementContent = (fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN);
  1814. } // handleEndElement(QName,boolean)
  1815. protected void endNamespaceScope(QName element, Augmentations augs, boolean isEmpty){
  1816. // call handlers
  1817. if (fDocumentHandler != null && !isEmpty) {
  1818. // NOTE: The binding of the element doesn't actually happen
  1819. // yet because the namespace binder does that. However,
  1820. // if it does it before this point, then the endPrefix-
  1821. // Mapping calls get made too soon! As long as the
  1822. // rawnames match, we know it'll have a good binding,
  1823. // so we can just use the current element. -Ac
  1824. fDocumentHandler.endElement(fCurrentElement, augs);
  1825. }
  1826. }
  1827. // returns whether a character is space according to the
  1828. // version of XML this validator supports.
  1829. protected boolean isSpace(int c) {
  1830. return XMLChar.isSpace(c);
  1831. } // isSpace(int): boolean
  1832. } // class XMLDTDValidator