1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999-2002 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 java.util.Enumeration;
  59. import java.util.Hashtable;
  60. import java.util.Locale;
  61. import java.util.StringTokenizer;
  62. import java.util.Vector;
  63. import com.sun.org.apache.xerces.internal.impl.Constants;
  64. import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
  65. import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
  66. import com.sun.org.apache.xerces.internal.util.SymbolTable;
  67. import com.sun.org.apache.xerces.internal.util.XMLChar;
  68. import com.sun.org.apache.xerces.internal.util.XMLSymbols;
  69. import com.sun.org.apache.xerces.internal.xni.Augmentations;
  70. import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
  71. import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler;
  72. import com.sun.org.apache.xerces.internal.xni.XMLLocator;
  73. import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
  74. import com.sun.org.apache.xerces.internal.xni.XMLString;
  75. import com.sun.org.apache.xerces.internal.xni.XNIException;
  76. import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
  77. import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
  78. import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  79. import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
  80. import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  81. import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  82. import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelFilter;
  83. import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelSource;
  84. import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDFilter;
  85. import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource;
  86. /**
  87. * The DTD processor. The processor implements a DTD
  88. * filter: receiving DTD events from the DTD scanner; validating
  89. * the content and structure; building a grammar, if applicable;
  90. * and notifying the DTDHandler of the information resulting from the
  91. * process.
  92. * <p>
  93. * This component requires the following features and properties from the
  94. * component manager that uses it:
  95. * <ul>
  96. * <li>http://xml.org/sax/features/namespaces</li>
  97. * <li>http://apache.org/xml/properties/internal/symbol-table</li>
  98. * <li>http://apache.org/xml/properties/internal/error-reporter</li>
  99. * <li>http://apache.org/xml/properties/internal/grammar-pool</li>
  100. * <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
  101. * </ul>
  102. *
  103. * @author Neil Graham, IBM
  104. *
  105. * @version $Id: XMLDTDProcessor.java,v 1.11 2003/11/10 00:59:46 mrglavas Exp $
  106. */
  107. public class XMLDTDProcessor
  108. implements XMLComponent, XMLDTDFilter, XMLDTDContentModelFilter {
  109. //
  110. // Constants
  111. //
  112. /** Top level scope (-1). */
  113. private static final int TOP_LEVEL_SCOPE = -1;
  114. // feature identifiers
  115. /** Feature identifier: validation. */
  116. protected static final String VALIDATION =
  117. Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
  118. /** Feature identifier: notify character references. */
  119. protected static final String NOTIFY_CHAR_REFS =
  120. Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_CHAR_REFS_FEATURE;
  121. /** Feature identifier: warn on duplicate attdef */
  122. protected static final String WARN_ON_DUPLICATE_ATTDEF =
  123. Constants.XERCES_FEATURE_PREFIX +Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
  124. protected static final String PARSER_SETTINGS =
  125. Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
  126. // property identifiers
  127. /** Property identifier: symbol table. */
  128. protected static final String SYMBOL_TABLE =
  129. Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
  130. /** Property identifier: error reporter. */
  131. protected static final String ERROR_REPORTER =
  132. Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
  133. /** Property identifier: grammar pool. */
  134. protected static final String GRAMMAR_POOL =
  135. Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
  136. /** Property identifier: validator . */
  137. protected static final String DTD_VALIDATOR =
  138. Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY;
  139. // recognized features and properties
  140. /** Recognized features. */
  141. private static final String[] RECOGNIZED_FEATURES = {
  142. VALIDATION,
  143. WARN_ON_DUPLICATE_ATTDEF,
  144. NOTIFY_CHAR_REFS,
  145. };
  146. /** Feature defaults. */
  147. private static final Boolean[] FEATURE_DEFAULTS = {
  148. null,
  149. Boolean.FALSE,
  150. null,
  151. };
  152. /** Recognized properties. */
  153. private static final String[] RECOGNIZED_PROPERTIES = {
  154. SYMBOL_TABLE,
  155. ERROR_REPORTER,
  156. GRAMMAR_POOL,
  157. DTD_VALIDATOR,
  158. };
  159. /** Property defaults. */
  160. private static final Object[] PROPERTY_DEFAULTS = {
  161. null,
  162. null,
  163. null,
  164. null,
  165. };
  166. // debugging
  167. //
  168. // Data
  169. //
  170. // features
  171. /** Validation. */
  172. protected boolean fValidation;
  173. /** Validation against only DTD */
  174. protected boolean fDTDValidation;
  175. /** warn on duplicate attribute definition, this feature works only when validation is true */
  176. protected boolean fWarnDuplicateAttdef;
  177. // properties
  178. /** Symbol table. */
  179. protected SymbolTable fSymbolTable;
  180. /** Error reporter. */
  181. protected XMLErrorReporter fErrorReporter;
  182. /** Grammar bucket. */
  183. protected DTDGrammarBucket fGrammarBucket;
  184. // the validator to which we look for our grammar bucket (the
  185. // validator needs to hold the bucket so that it can initialize
  186. // the grammar with details like whether it's for a standalone document...
  187. protected XMLDTDValidator fValidator;
  188. // the grammar pool we'll try to add the grammar to:
  189. protected XMLGrammarPool fGrammarPool;
  190. // what's our Locale?
  191. protected Locale fLocale;
  192. // handlers
  193. /** DTD handler. */
  194. protected XMLDTDHandler fDTDHandler;
  195. /** DTD source. */
  196. protected XMLDTDSource fDTDSource;
  197. /** DTD content model handler. */
  198. protected XMLDTDContentModelHandler fDTDContentModelHandler;
  199. /** DTD content model source. */
  200. protected XMLDTDContentModelSource fDTDContentModelSource;
  201. // grammars
  202. /** DTD Grammar. */
  203. protected DTDGrammar fDTDGrammar;
  204. // state
  205. /** Perform validation. */
  206. private boolean fPerformValidation;
  207. /** True if in an ignore conditional section of the DTD. */
  208. protected boolean fInDTDIgnore;
  209. // information regarding the current element
  210. // validation states
  211. /** Mixed. */
  212. private boolean fMixed;
  213. // temporary variables
  214. /** Temporary entity declaration. */
  215. private XMLEntityDecl fEntityDecl = new XMLEntityDecl();
  216. /** Notation declaration hash. */
  217. private Hashtable fNDataDeclNotations = new Hashtable();
  218. /** DTD element declaration name. */
  219. private String fDTDElementDeclName = null;
  220. /** Mixed element type "hash". */
  221. private Vector fMixedElementTypes = new Vector();
  222. /** Element declarations in DTD. */
  223. private Vector fDTDElementDecls = new Vector();
  224. // to check for duplicate ID or ANNOTATION attribute declare in
  225. // ATTLIST, and misc VCs
  226. /** ID attribute names. */
  227. private Hashtable fTableOfIDAttributeNames;
  228. /** NOTATION attribute names. */
  229. private Hashtable fTableOfNOTATIONAttributeNames;
  230. /** NOTATION enumeration values. */
  231. private Hashtable fNotationEnumVals;
  232. //
  233. // Constructors
  234. //
  235. /** Default constructor. */
  236. public XMLDTDProcessor() {
  237. // initialize data
  238. } // <init>()
  239. //
  240. // XMLComponent methods
  241. //
  242. /*
  243. * Resets the component. The component can query the component manager
  244. * about any features and properties that affect the operation of the
  245. * component.
  246. *
  247. * @param componentManager The component manager.
  248. *
  249. * @throws SAXException Thrown by component on finitialization error.
  250. * For example, if a feature or property is
  251. * required for the operation of the component, the
  252. * component manager may throw a
  253. * SAXNotRecognizedException or a
  254. * SAXNotSupportedException.
  255. */
  256. public void reset(XMLComponentManager componentManager) throws XMLConfigurationException {
  257. boolean parser_settings;
  258. try {
  259. parser_settings = componentManager.getFeature(PARSER_SETTINGS);
  260. } catch (XMLConfigurationException e) {
  261. parser_settings = true;
  262. }
  263. if (!parser_settings) {
  264. // parser settings have not been changed
  265. reset();
  266. return;
  267. }
  268. // sax features
  269. try {
  270. fValidation = componentManager.getFeature(VALIDATION);
  271. } catch (XMLConfigurationException e) {
  272. fValidation = false;
  273. }
  274. try {
  275. fDTDValidation =
  276. !(componentManager
  277. .getFeature(
  278. Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE));
  279. } catch (XMLConfigurationException e) {
  280. // must be in a schema-less configuration!
  281. fDTDValidation = true;
  282. }
  283. // Xerces features
  284. try {
  285. fWarnDuplicateAttdef = componentManager.getFeature(WARN_ON_DUPLICATE_ATTDEF);
  286. } catch (XMLConfigurationException e) {
  287. fWarnDuplicateAttdef = false;
  288. }
  289. // get needed components
  290. fErrorReporter =
  291. (XMLErrorReporter) componentManager.getProperty(
  292. Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY);
  293. fSymbolTable =
  294. (SymbolTable) componentManager.getProperty(
  295. Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY);
  296. try {
  297. fGrammarPool = (XMLGrammarPool) componentManager.getProperty(GRAMMAR_POOL);
  298. } catch (XMLConfigurationException e) {
  299. fGrammarPool = null;
  300. }
  301. try {
  302. fValidator = (XMLDTDValidator) componentManager.getProperty(DTD_VALIDATOR);
  303. } catch (XMLConfigurationException e) {
  304. fValidator = null;
  305. } catch (ClassCastException e) {
  306. fValidator = null;
  307. }
  308. // we get our grammarBucket from the validator...
  309. if (fValidator != null) {
  310. fGrammarBucket = fValidator.getGrammarBucket();
  311. } else {
  312. fGrammarBucket = null;
  313. }
  314. reset();
  315. } // reset(XMLComponentManager)
  316. protected void reset() {
  317. // clear grammars
  318. fDTDGrammar = null;
  319. // initialize state
  320. fInDTDIgnore = false;
  321. fNDataDeclNotations.clear();
  322. // datatype validators
  323. if (fValidation) {
  324. if (fNotationEnumVals == null) {
  325. fNotationEnumVals = new Hashtable();
  326. }
  327. fNotationEnumVals.clear();
  328. fTableOfIDAttributeNames = new Hashtable();
  329. fTableOfNOTATIONAttributeNames = new Hashtable();
  330. }
  331. }
  332. /**
  333. * Returns a list of feature identifiers that are recognized by
  334. * this component. This method may return null if no features
  335. * are recognized by this component.
  336. */
  337. public String[] getRecognizedFeatures() {
  338. return (String[])(RECOGNIZED_FEATURES.clone());
  339. } // getRecognizedFeatures():String[]
  340. /**
  341. * Sets the state of a feature. This method is called by the component
  342. * manager any time after reset when a feature changes state.
  343. * <p>
  344. * <strong>Note:</strong> Components should silently ignore features
  345. * that do not affect the operation of the component.
  346. *
  347. * @param featureId The feature identifier.
  348. * @param state The state of the feature.
  349. *
  350. * @throws SAXNotRecognizedException The component should not throw
  351. * this exception.
  352. * @throws SAXNotSupportedException The component should not throw
  353. * this exception.
  354. */
  355. public void setFeature(String featureId, boolean state)
  356. throws XMLConfigurationException {
  357. } // setFeature(String,boolean)
  358. /**
  359. * Returns a list of property identifiers that are recognized by
  360. * this component. This method may return null if no properties
  361. * are recognized by this component.
  362. */
  363. public String[] getRecognizedProperties() {
  364. return (String[])(RECOGNIZED_PROPERTIES.clone());
  365. } // getRecognizedProperties():String[]
  366. /**
  367. * Sets the value of a property. This method is called by the component
  368. * manager any time after reset when a property changes value.
  369. * <p>
  370. * <strong>Note:</strong> Components should silently ignore properties
  371. * that do not affect the operation of the component.
  372. *
  373. * @param propertyId The property identifier.
  374. * @param value The value of the property.
  375. *
  376. * @throws SAXNotRecognizedException The component should not throw
  377. * this exception.
  378. * @throws SAXNotSupportedException The component should not throw
  379. * this exception.
  380. */
  381. public void setProperty(String propertyId, Object value)
  382. throws XMLConfigurationException {
  383. } // setProperty(String,Object)
  384. /**
  385. * Returns the default state for a feature, or null if this
  386. * component does not want to report a default value for this
  387. * feature.
  388. *
  389. * @param featureId The feature identifier.
  390. *
  391. * @since Xerces 2.2.0
  392. */
  393. public Boolean getFeatureDefault(String featureId) {
  394. for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
  395. if (RECOGNIZED_FEATURES[i].equals(featureId)) {
  396. return FEATURE_DEFAULTS[i];
  397. }
  398. }
  399. return null;
  400. } // getFeatureDefault(String):Boolean
  401. /**
  402. * Returns the default state for a property, or null if this
  403. * component does not want to report a default value for this
  404. * property.
  405. *
  406. * @param propertyId The property identifier.
  407. *
  408. * @since Xerces 2.2.0
  409. */
  410. public Object getPropertyDefault(String propertyId) {
  411. for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
  412. if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
  413. return PROPERTY_DEFAULTS[i];
  414. }
  415. }
  416. return null;
  417. } // getPropertyDefault(String):Object
  418. //
  419. // XMLDTDSource methods
  420. //
  421. /**
  422. * Sets the DTD handler.
  423. *
  424. * @param dtdHandler The DTD handler.
  425. */
  426. public void setDTDHandler(XMLDTDHandler dtdHandler) {
  427. fDTDHandler = dtdHandler;
  428. } // setDTDHandler(XMLDTDHandler)
  429. /**
  430. * Returns the DTD handler.
  431. *
  432. * @return The DTD handler.
  433. */
  434. public XMLDTDHandler getDTDHandler() {
  435. return fDTDHandler;
  436. } // getDTDHandler(): XMLDTDHandler
  437. //
  438. // XMLDTDContentModelSource methods
  439. //
  440. /**
  441. * Sets the DTD content model handler.
  442. *
  443. * @param dtdContentModelHandler The DTD content model handler.
  444. */
  445. public void setDTDContentModelHandler(XMLDTDContentModelHandler dtdContentModelHandler) {
  446. fDTDContentModelHandler = dtdContentModelHandler;
  447. } // setDTDContentModelHandler(XMLDTDContentModelHandler)
  448. /**
  449. * Gets the DTD content model handler.
  450. *
  451. * @return dtdContentModelHandler The DTD content model handler.
  452. */
  453. public XMLDTDContentModelHandler getDTDContentModelHandler() {
  454. return fDTDContentModelHandler;
  455. } // getDTDContentModelHandler(): XMLDTDContentModelHandler
  456. //
  457. // XMLDTDContentModelHandler and XMLDTDHandler methods
  458. //
  459. /**
  460. * The start of the DTD external subset.
  461. *
  462. * @param augs Additional information that may include infoset
  463. * augmentations.
  464. *
  465. * @throws XNIException Thrown by handler to signal an error.
  466. */
  467. public void startExternalSubset(XMLResourceIdentifier identifier,
  468. Augmentations augs) throws XNIException {
  469. if(fDTDGrammar != null)
  470. fDTDGrammar.startExternalSubset(identifier, augs);
  471. if(fDTDHandler != null){
  472. fDTDHandler.startExternalSubset(identifier, augs);
  473. }
  474. }
  475. /**
  476. * The end of the DTD external subset.
  477. *
  478. * @param augs Additional information that may include infoset
  479. * augmentations.
  480. *
  481. * @throws XNIException Thrown by handler to signal an error.
  482. */
  483. public void endExternalSubset(Augmentations augs) throws XNIException {
  484. if(fDTDGrammar != null)
  485. fDTDGrammar.endExternalSubset(augs);
  486. if(fDTDHandler != null){
  487. fDTDHandler.endExternalSubset(augs);
  488. }
  489. }
  490. /**
  491. * Check standalone entity reference.
  492. * Made static to make common between the validator and loader.
  493. *
  494. * @param name
  495. *@param grammar grammar to which entity belongs
  496. * @param tempEntityDecl empty entity declaration to put results in
  497. * @param errorReporter error reporter to send errors to
  498. *
  499. * @throws XNIException Thrown by application to signal an error.
  500. */
  501. protected static void checkStandaloneEntityRef(String name, DTDGrammar grammar,
  502. XMLEntityDecl tempEntityDecl, XMLErrorReporter errorReporter) throws XNIException {
  503. // check VC: Standalone Document Declartion, entities references appear in the document.
  504. int entIndex = grammar.getEntityDeclIndex(name);
  505. if (entIndex > -1) {
  506. grammar.getEntityDecl(entIndex, tempEntityDecl);
  507. if (tempEntityDecl.inExternal) {
  508. errorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
  509. "MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE",
  510. new Object[]{name}, XMLErrorReporter.SEVERITY_ERROR);
  511. }
  512. }
  513. }
  514. /**
  515. * A comment.
  516. *
  517. * @param text The text in the comment.
  518. * @param augs Additional information that may include infoset augmentations
  519. *
  520. * @throws XNIException Thrown by application to signal an error.
  521. */
  522. public void comment(XMLString text, Augmentations augs) throws XNIException {
  523. // call handlers
  524. if(fDTDGrammar != null)
  525. fDTDGrammar.comment(text, augs);
  526. if (fDTDHandler != null) {
  527. fDTDHandler.comment(text, augs);
  528. }
  529. } // comment(XMLString)
  530. /**
  531. * A processing instruction. Processing instructions consist of a
  532. * target name and, optionally, text data. The data is only meaningful
  533. * to the application.
  534. * <p>
  535. * Typically, a processing instruction's data will contain a series
  536. * of pseudo-attributes. These pseudo-attributes follow the form of
  537. * element attributes but are <strong>not</strong> parsed or presented
  538. * to the application as anything other than text. The application is
  539. * responsible for parsing the data.
  540. *
  541. * @param target The target.
  542. * @param data The data or null if none specified.
  543. * @param augs Additional information that may include infoset augmentations
  544. *
  545. * @throws XNIException Thrown by handler to signal an error.
  546. */
  547. public void processingInstruction(String target, XMLString data, Augmentations augs)
  548. throws XNIException {
  549. // call handlers
  550. if(fDTDGrammar != null)
  551. fDTDGrammar.processingInstruction(target, data, augs);
  552. if (fDTDHandler != null) {
  553. fDTDHandler.processingInstruction(target, data, augs);
  554. }
  555. } // processingInstruction(String,XMLString)
  556. //
  557. // XMLDTDHandler methods
  558. //
  559. /**
  560. * The start of the DTD.
  561. *
  562. * @param locator The document locator, or null if the document
  563. * location cannot be reported during the parsing of
  564. * the document DTD. However, it is <em>strongly</em>
  565. * recommended that a locator be supplied that can
  566. * at least report the base system identifier of the
  567. * DTD.
  568. * @param augs Additional information that may include infoset
  569. * augmentations.
  570. *
  571. * @throws XNIException Thrown by handler to signal an error.
  572. */
  573. public void startDTD(XMLLocator locator, Augmentations augs) throws XNIException {
  574. // initialize state
  575. fNDataDeclNotations.clear();
  576. fDTDElementDecls.removeAllElements();
  577. // the grammar bucket's DTDGrammar will now be the
  578. // one we want, whether we're constructing it or not.
  579. // if we're not constructing it, then we should not have a reference
  580. // to it!
  581. if( !fGrammarBucket.getActiveGrammar().isImmutable()) {
  582. fDTDGrammar = fGrammarBucket.getActiveGrammar();
  583. }
  584. // call handlers
  585. if(fDTDGrammar != null )
  586. fDTDGrammar.startDTD(locator, augs);
  587. if (fDTDHandler != null) {
  588. fDTDHandler.startDTD(locator, augs);
  589. }
  590. } // startDTD(XMLLocator)
  591. /**
  592. * Characters within an IGNORE conditional section.
  593. *
  594. * @param text The ignored text.
  595. * @param augs Additional information that may include infoset
  596. * augmentations.
  597. *
  598. * @throws XNIException Thrown by handler to signal an error.
  599. */
  600. public void ignoredCharacters(XMLString text, Augmentations augs) throws XNIException {
  601. // ignored characters in DTD
  602. if(fDTDGrammar != null )
  603. fDTDGrammar.ignoredCharacters(text, augs);
  604. if (fDTDHandler != null) {
  605. fDTDHandler.ignoredCharacters(text, augs);
  606. }
  607. }
  608. /**
  609. * Notifies of the presence of a TextDecl line in an entity. If present,
  610. * this method will be called immediately following the startParameterEntity call.
  611. * <p>
  612. * <strong>Note:</strong> This method is only called for external
  613. * parameter entities referenced in the DTD.
  614. *
  615. * @param version The XML version, or null if not specified.
  616. * @param encoding The IANA encoding name of the entity.
  617. * @param augs Additional information that may include infoset
  618. * augmentations.
  619. *
  620. * @throws XNIException Thrown by handler to signal an error.
  621. */
  622. public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
  623. // call handlers
  624. if(fDTDGrammar != null )
  625. fDTDGrammar.textDecl(version, encoding, augs);
  626. if (fDTDHandler != null) {
  627. fDTDHandler.textDecl(version, encoding, augs);
  628. }
  629. }
  630. /**
  631. * This method notifies of the start of a parameter entity. The parameter
  632. * entity name start with a '%' character.
  633. *
  634. * @param name The name of the parameter entity.
  635. * @param identifier The resource identifier.
  636. * @param encoding The auto-detected IANA encoding name of the entity
  637. * stream. This value will be null in those situations
  638. * where the entity encoding is not auto-detected (e.g.
  639. * internal parameter entities).
  640. * @param augs Additional information that may include infoset
  641. * augmentations.
  642. *
  643. * @throws XNIException Thrown by handler to signal an error.
  644. */
  645. public void startParameterEntity(String name,
  646. XMLResourceIdentifier identifier,
  647. String encoding,
  648. Augmentations augs) throws XNIException {
  649. if (fPerformValidation && fDTDGrammar != null &&
  650. fGrammarBucket.getStandalone()) {
  651. checkStandaloneEntityRef(name, fDTDGrammar, fEntityDecl, fErrorReporter);
  652. }
  653. // call handlers
  654. if(fDTDGrammar != null )
  655. fDTDGrammar.startParameterEntity(name, identifier, encoding, augs);
  656. if (fDTDHandler != null) {
  657. fDTDHandler.startParameterEntity(name, identifier, encoding, augs);
  658. }
  659. }
  660. /**
  661. * This method notifies the end of a parameter entity. Parameter entity
  662. * names begin with a '%' character.
  663. *
  664. * @param name The name of the parameter entity.
  665. * @param augs Additional information that may include infoset
  666. * augmentations.
  667. *
  668. * @throws XNIException Thrown by handler to signal an error.
  669. */
  670. public void endParameterEntity(String name, Augmentations augs) throws XNIException {
  671. // call handlers
  672. if(fDTDGrammar != null )
  673. fDTDGrammar.endParameterEntity(name, augs);
  674. if (fDTDHandler != null) {
  675. fDTDHandler.endParameterEntity(name, augs);
  676. }
  677. }
  678. /**
  679. * An element declaration.
  680. *
  681. * @param name The name of the element.
  682. * @param contentModel The element content model.
  683. * @param augs Additional information that may include infoset
  684. * augmentations.
  685. *
  686. * @throws XNIException Thrown by handler to signal an error.
  687. */
  688. public void elementDecl(String name, String contentModel, Augmentations augs)
  689. throws XNIException {
  690. //check VC: Unique Element Declaration
  691. if (fValidation) {
  692. if (fDTDElementDecls.contains(name)) {
  693. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  694. "MSG_ELEMENT_ALREADY_DECLARED",
  695. new Object[]{ name},
  696. XMLErrorReporter.SEVERITY_ERROR);
  697. }
  698. else {
  699. fDTDElementDecls.addElement(name);
  700. }
  701. }
  702. // call handlers
  703. if(fDTDGrammar != null )
  704. fDTDGrammar.elementDecl(name, contentModel, augs);
  705. if (fDTDHandler != null) {
  706. fDTDHandler.elementDecl(name, contentModel, augs);
  707. }
  708. } // elementDecl(String,String)
  709. /**
  710. * The start of an attribute list.
  711. *
  712. * @param elementName The name of the element that this attribute
  713. * list is associated with.
  714. * @param augs Additional information that may include infoset
  715. * augmentations.
  716. *
  717. * @throws XNIException Thrown by handler to signal an error.
  718. */
  719. public void startAttlist(String elementName, Augmentations augs)
  720. throws XNIException {
  721. // call handlers
  722. if(fDTDGrammar != null )
  723. fDTDGrammar.startAttlist(elementName, augs);
  724. if (fDTDHandler != null) {
  725. fDTDHandler.startAttlist(elementName, augs);
  726. }
  727. } // startAttlist(String)
  728. /**
  729. * An attribute declaration.
  730. *
  731. * @param elementName The name of the element that this attribute
  732. * is associated with.
  733. * @param attributeName The name of the attribute.
  734. * @param type The attribute type. This value will be one of
  735. * the following: "CDATA", "ENTITY", "ENTITIES",
  736. * "ENUMERATION", "ID", "IDREF", "IDREFS",
  737. * "NMTOKEN", "NMTOKENS", or "NOTATION".
  738. * @param enumeration If the type has the value "ENUMERATION" or
  739. * "NOTATION", this array holds the allowed attribute
  740. * values; otherwise, this array is null.
  741. * @param defaultType The attribute default type. This value will be
  742. * one of the following: "#FIXED", "#IMPLIED",
  743. * "#REQUIRED", or null.
  744. * @param defaultValue The attribute default value, or null if no
  745. * default value is specified.
  746. * @param nonNormalizedDefaultValue The attribute default value with no normalization
  747. * performed, or null if no default value is specified.
  748. * @param augs Additional information that may include infoset
  749. * augmentations.
  750. *
  751. * @throws XNIException Thrown by handler to signal an error.
  752. */
  753. public void attributeDecl(String elementName, String attributeName,
  754. String type, String[] enumeration,
  755. String defaultType, XMLString defaultValue,
  756. XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
  757. if (type != XMLSymbols.fCDATASymbol && defaultValue != null) {
  758. normalizeDefaultAttrValue(defaultValue);
  759. }
  760. if (fValidation) {
  761. boolean duplicateAttributeDef = false ;
  762. //Get Grammar index to grammar array
  763. DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar:fGrammarBucket.getActiveGrammar());
  764. int elementIndex = grammar.getElementDeclIndex( elementName);
  765. if (grammar.getAttributeDeclIndex(elementIndex, attributeName) != -1) {
  766. //more than one attribute definition is provided for the same attribute of a given element type.
  767. duplicateAttributeDef = true ;
  768. //this feature works only when validation is true.
  769. if(fWarnDuplicateAttdef){
  770. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  771. "MSG_DUPLICATE_ATTRIBUTE_DEFINITION",
  772. new Object[]{ elementName, attributeName },
  773. XMLErrorReporter.SEVERITY_WARNING );
  774. }
  775. }
  776. //
  777. // a) VC: One ID per Element Type, If duplicate ID attribute
  778. // b) VC: ID attribute Default. if there is a declareared attribute
  779. // default for ID it should be of type #IMPLIED or #REQUIRED
  780. if (type == XMLSymbols.fIDSymbol) {
  781. if (defaultValue != null && defaultValue.length != 0) {
  782. if (defaultType == null ||
  783. !(defaultType == XMLSymbols.fIMPLIEDSymbol ||
  784. defaultType == XMLSymbols.fREQUIREDSymbol)) {
  785. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  786. "IDDefaultTypeInvalid",
  787. new Object[]{ attributeName},
  788. XMLErrorReporter.SEVERITY_ERROR);
  789. }
  790. }
  791. if (!fTableOfIDAttributeNames.containsKey(elementName)) {
  792. fTableOfIDAttributeNames.put(elementName, attributeName);
  793. }
  794. else {
  795. //we should not report an error, when there is duplicate attribute definition for given element type
  796. //according to XML 1.0 spec, When more than one definition is provided for the same attribute of a given
  797. //element type, the first declaration is binding and later declaration are *ignored*. So processor should
  798. //ignore the second declarations, however an application would be warned of the duplicate attribute defintion
  799. // if http://apache.org/xml/features/validation/warn-on-duplicate-attdef feature is set to true,
  800. // one typical case where this could be a problem, when any XML file
  801. // provide the ID type information through internal subset so that it is available to the parser which read
  802. //only internal subset. Now that attribute declaration(ID Type) can again be part of external parsed entity
  803. //referenced. At that time if parser doesn't make this distinction it will throw an error for VC One ID per
  804. //Element Type, which (second defintion) actually should be ignored. Application behavior may differ on the
  805. //basis of error or warning thrown. - nb.
  806. if(!duplicateAttributeDef){
  807. String previousIDAttributeName = (String)fTableOfIDAttributeNames.get( elementName );//rule a)
  808. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  809. "MSG_MORE_THAN_ONE_ID_ATTRIBUTE",
  810. new Object[]{ elementName, previousIDAttributeName, attributeName},
  811. XMLErrorReporter.SEVERITY_ERROR);
  812. }
  813. }
  814. }
  815. //
  816. // VC: One Notation Per Element Type, should check if there is a
  817. // duplicate NOTATION attribute
  818. if (type == XMLSymbols.fNOTATIONSymbol) {
  819. // VC: Notation Attributes: all notation names in the
  820. // (attribute) declaration must be declared.
  821. for (int i=0; i<enumeration.length; i++) {
  822. fNotationEnumVals.put(enumeration[i], attributeName);
  823. }
  824. if (fTableOfNOTATIONAttributeNames.containsKey( elementName ) == false) {
  825. fTableOfNOTATIONAttributeNames.put( elementName, attributeName);
  826. }
  827. else {
  828. //we should not report an error, when there is duplicate attribute definition for given element type
  829. //according to XML 1.0 spec, When more than one definition is provided for the same attribute of a given
  830. //element type, the first declaration is binding and later declaration are *ignored*. So processor should
  831. //ignore the second declarations, however an application would be warned of the duplicate attribute defintion
  832. // if http://apache.org/xml/features/validation/warn-on-duplicate-attdef feature is set to true, Application behavior may differ on the basis of error or
  833. //warning thrown. - nb.
  834. if(!duplicateAttributeDef){
  835. String previousNOTATIONAttributeName = (String) fTableOfNOTATIONAttributeNames.get( elementName );
  836. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  837. "MSG_MORE_THAN_ONE_NOTATION_ATTRIBUTE",
  838. new Object[]{ elementName, previousNOTATIONAttributeName, attributeName},
  839. XMLErrorReporter.SEVERITY_ERROR);
  840. }
  841. }
  842. }
  843. // VC: No Duplicate Tokens
  844. // XML 1.0 SE Errata - E2
  845. if (type == XMLSymbols.fENUMERATIONSymbol || type == XMLSymbols.fNOTATIONSymbol) {
  846. outer:
  847. for (int i = 0; i < enumeration.length; ++i) {
  848. for (int j = i + 1; j < enumeration.length; ++j) {
  849. if (enumeration[i].equals(enumeration[j])) {
  850. // Only report the first uniqueness violation. There could be others,
  851. // but additional overhead would be incurred tracking unique tokens
  852. // that have already been encountered. -- mrglavas
  853. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  854. type == XMLSymbols.fENUMERATIONSymbol
  855. ? "MSG_DISTINCT_TOKENS_IN_ENUMERATION"
  856. : "MSG_DISTINCT_NOTATION_IN_ENUMERATION",
  857. new Object[]{ elementName, enumeration[i], attributeName },
  858. XMLErrorReporter.SEVERITY_ERROR);
  859. break outer;
  860. }
  861. }
  862. }
  863. }
  864. // VC: Attribute Default Legal
  865. boolean ok = true;
  866. if (defaultValue != null &&
  867. (defaultType == null ||
  868. (defaultType != null && defaultType == XMLSymbols.fFIXEDSymbol))) {
  869. String value = defaultValue.toString();
  870. if (type == XMLSymbols.fNMTOKENSSymbol ||
  871. type == XMLSymbols.fENTITIESSymbol ||
  872. type == XMLSymbols.fIDREFSSymbol) {
  873. StringTokenizer tokenizer = new StringTokenizer(value," ");
  874. if (tokenizer.hasMoreTokens()) {
  875. while (true) {
  876. String nmtoken = tokenizer.nextToken();
  877. if (type == XMLSymbols.fNMTOKENSSymbol) {
  878. if (!isValidNmtoken(nmtoken)) {
  879. ok = false;
  880. break;
  881. }
  882. }
  883. else if (type == XMLSymbols.fENTITIESSymbol ||
  884. type == XMLSymbols.fIDREFSSymbol) {
  885. if (!isValidName(nmtoken)) {
  886. ok = false;
  887. break;
  888. }
  889. }
  890. if (!tokenizer.hasMoreTokens()) {
  891. break;
  892. }
  893. }
  894. }
  895. }
  896. else {
  897. if (type == XMLSymbols.fENTITYSymbol ||
  898. type == XMLSymbols.fIDSymbol ||
  899. type == XMLSymbols.fIDREFSymbol ||
  900. type == XMLSymbols.fNOTATIONSymbol) {
  901. if (!isValidName(value)) {
  902. ok = false;
  903. }
  904. }
  905. else if (type == XMLSymbols.fNMTOKENSymbol ||
  906. type == XMLSymbols.fENUMERATIONSymbol) {
  907. if (!isValidNmtoken(value)) {
  908. ok = false;
  909. }
  910. }
  911. if (type == XMLSymbols.fNOTATIONSymbol ||
  912. type == XMLSymbols.fENUMERATIONSymbol) {
  913. ok = false;
  914. for (int i=0; i<enumeration.length; i++) {
  915. if (defaultValue.equals(enumeration[i])) {
  916. ok = true;
  917. }
  918. }
  919. }
  920. }
  921. if (!ok) {
  922. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  923. "MSG_ATT_DEFAULT_INVALID",
  924. new Object[]{attributeName, value},
  925. XMLErrorReporter.SEVERITY_ERROR);
  926. }
  927. }
  928. }
  929. // call handlers
  930. if(fDTDGrammar != null)
  931. fDTDGrammar.attributeDecl(elementName, attributeName,
  932. type, enumeration,
  933. defaultType, defaultValue, nonNormalizedDefaultValue, augs);
  934. if (fDTDHandler != null) {
  935. fDTDHandler.attributeDecl(elementName, attributeName,
  936. type, enumeration,
  937. defaultType, defaultValue, nonNormalizedDefaultValue, augs);
  938. }
  939. } // attributeDecl(String,String,String,String[],String,XMLString, XMLString, Augmentations)
  940. /**
  941. * The end of an attribute list.
  942. *
  943. * @param augs Additional information that may include infoset
  944. * augmentations.
  945. *
  946. * @throws XNIException Thrown by handler to signal an error.
  947. */
  948. public void endAttlist(Augmentations augs) throws XNIException {
  949. // call handlers
  950. if(fDTDGrammar != null)
  951. fDTDGrammar.endAttlist(augs);
  952. if (fDTDHandler != null) {
  953. fDTDHandler.endAttlist(augs);
  954. }
  955. } // endAttlist()
  956. /**
  957. * An internal entity declaration.
  958. *
  959. * @param name The name of the entity. Parameter entity names start with
  960. * '%', whereas the name of a general entity is just the
  961. * entity name.
  962. * @param text The value of the entity.
  963. * @param nonNormalizedText The non-normalized value of the entity. This
  964. * value contains the same sequence of characters that was in
  965. * the internal entity declaration, without any entity
  966. * references expanded.
  967. * @param augs Additional information that may include infoset
  968. * augmentations.
  969. *
  970. * @throws XNIException Thrown by handler to signal an error.
  971. */
  972. public void internalEntityDecl(String name, XMLString text,
  973. XMLString nonNormalizedText,
  974. Augmentations augs) throws XNIException {
  975. DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar: fGrammarBucket.getActiveGrammar());
  976. int index = grammar.getEntityDeclIndex(name) ;
  977. //If the same entity is declared more than once, the first declaration
  978. //encountered is binding, SAX requires only effective(first) declaration
  979. //to be reported to the application
  980. //REVISIT: Does it make sense to pass duplicate Entity information across
  981. //the pipeline -- nb?
  982. //its a new entity and hasn't been declared.
  983. if(index == -1){
  984. //store internal entity declaration in grammar
  985. if(fDTDGrammar != null)
  986. fDTDGrammar.internalEntityDecl(name, text, nonNormalizedText, augs);
  987. // call handlers
  988. if (fDTDHandler != null) {
  989. fDTDHandler.internalEntityDecl(name, text, nonNormalizedText, augs);
  990. }
  991. }
  992. } // internalEntityDecl(String,XMLString,XMLString)
  993. /**
  994. * An external entity declaration.
  995. *
  996. * @param name The name of the entity. Parameter entity names start
  997. * with '%', whereas the name of a general entity is just
  998. * the entity name.
  999. * @param identifier An object containing all location information
  1000. * pertinent to this external entity.
  1001. * @param augs Additional information that may include infoset
  1002. * augmentations.
  1003. *
  1004. * @throws XNIException Thrown by handler to signal an error.
  1005. */
  1006. public void externalEntityDecl(String name, XMLResourceIdentifier identifier,
  1007. Augmentations augs) throws XNIException {
  1008. DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar: fGrammarBucket.getActiveGrammar());
  1009. int index = grammar.getEntityDeclIndex(name) ;
  1010. //If the same entity is declared more than once, the first declaration
  1011. //encountered is binding, SAX requires only effective(first) declaration
  1012. //to be reported to the application
  1013. //REVISIT: Does it make sense to pass duplicate entity information across
  1014. //the pipeline -- nb?
  1015. //its a new entity and hasn't been declared.
  1016. if(index == -1){
  1017. //store external entity declaration in grammar
  1018. if(fDTDGrammar != null)
  1019. fDTDGrammar.externalEntityDecl(name, identifier, augs);
  1020. // call handlers
  1021. if (fDTDHandler != null) {
  1022. fDTDHandler.externalEntityDecl(name, identifier, augs);
  1023. }
  1024. }
  1025. } // externalEntityDecl(String,XMLResourceIdentifier, Augmentations)
  1026. /**
  1027. * An unparsed entity declaration.
  1028. *
  1029. * @param name The name of the entity.
  1030. * @param identifier An object containing all location information
  1031. * pertinent to this entity.
  1032. * @param notation The name of the notation.
  1033. * @param augs Additional information that may include infoset
  1034. * augmentations.
  1035. *
  1036. * @throws XNIException Thrown by handler to signal an error.
  1037. */
  1038. public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier,
  1039. String notation,
  1040. Augmentations augs) throws XNIException {
  1041. // VC: Notation declared, in the production of NDataDecl
  1042. if (fValidation) {
  1043. fNDataDeclNotations.put(name, notation);
  1044. }
  1045. // call handlers
  1046. if(fDTDGrammar != null)
  1047. fDTDGrammar.unparsedEntityDecl(name, identifier, notation, augs);
  1048. if (fDTDHandler != null) {
  1049. fDTDHandler.unparsedEntityDecl(name, identifier, notation, augs);
  1050. }
  1051. } // unparsedEntityDecl(String,XMLResourceIdentifier,String,Augmentations)
  1052. /**
  1053. * A notation declaration
  1054. *
  1055. * @param name The name of the notation.
  1056. * @param identifier An object containing all location information
  1057. * pertinent to this notation.
  1058. * @param augs Additional information that may include infoset
  1059. * augmentations.
  1060. *
  1061. * @throws XNIException Thrown by handler to signal an error.
  1062. */
  1063. public void notationDecl(String name, XMLResourceIdentifier identifier,
  1064. Augmentations augs) throws XNIException {
  1065. // VC: Unique Notation Name
  1066. if (fValidation) {
  1067. DTDGrammar grammar = (fDTDGrammar != null ? fDTDGrammar : fGrammarBucket.getActiveGrammar());
  1068. if (grammar.getNotationDeclIndex(name) != -1) {
  1069. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1070. "UniqueNotationName",
  1071. new Object[]{name},
  1072. XMLErrorReporter.SEVERITY_ERROR);
  1073. }
  1074. }
  1075. // call handlers
  1076. if(fDTDGrammar != null)
  1077. fDTDGrammar.notationDecl(name, identifier, augs);
  1078. if (fDTDHandler != null) {
  1079. fDTDHandler.notationDecl(name, identifier, augs);
  1080. }
  1081. } // notationDecl(String,XMLResourceIdentifier, Augmentations)
  1082. /**
  1083. * The start of a conditional section.
  1084. *
  1085. * @param type The type of the conditional section. This value will
  1086. * either be CONDITIONAL_INCLUDE or CONDITIONAL_IGNORE.
  1087. * @param augs Additional information that may include infoset
  1088. * augmentations.
  1089. *
  1090. * @throws XNIException Thrown by handler to signal an error.
  1091. *
  1092. * @see #CONDITIONAL_INCLUDE
  1093. * @see #CONDITIONAL_IGNORE
  1094. */
  1095. public void startConditional(short type, Augmentations augs) throws XNIException {
  1096. // set state
  1097. fInDTDIgnore = type == XMLDTDHandler.CONDITIONAL_IGNORE;
  1098. // call handlers
  1099. if(fDTDGrammar != null)
  1100. fDTDGrammar.startConditional(type, augs);
  1101. if (fDTDHandler != null) {
  1102. fDTDHandler.startConditional(type, augs);
  1103. }
  1104. } // startConditional(short)
  1105. /**
  1106. * The end of a conditional section.
  1107. *
  1108. * @param augs Additional information that may include infoset
  1109. * augmentations.
  1110. *
  1111. * @throws XNIException Thrown by handler to signal an error.
  1112. */
  1113. public void endConditional(Augmentations augs) throws XNIException {
  1114. // set state
  1115. fInDTDIgnore = false;
  1116. // call handlers
  1117. if(fDTDGrammar != null)
  1118. fDTDGrammar.endConditional(augs);
  1119. if (fDTDHandler != null) {
  1120. fDTDHandler.endConditional(augs);
  1121. }
  1122. } // endConditional()
  1123. /**
  1124. * The end of the DTD.
  1125. *
  1126. * @param augs Additional information that may include infoset
  1127. * augmentations.
  1128. *
  1129. * @throws XNIException Thrown by handler to signal an error.
  1130. */
  1131. public void endDTD(Augmentations augs) throws XNIException {
  1132. // save grammar
  1133. if(fDTDGrammar != null) {
  1134. fDTDGrammar.endDTD(augs);
  1135. if(fGrammarPool != null)
  1136. fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_DTD, new Grammar[] {fDTDGrammar});
  1137. }
  1138. // check VC: Notation declared, in the production of NDataDecl
  1139. if (fValidation) {
  1140. DTDGrammar grammar = (fDTDGrammar != null? fDTDGrammar: fGrammarBucket.getActiveGrammar());
  1141. // VC : Notation Declared. for external entity declaration [Production 76].
  1142. Enumeration entities = fNDataDeclNotations.keys();
  1143. while (entities.hasMoreElements()) {
  1144. String entity = (String) entities.nextElement();
  1145. String notation = (String) fNDataDeclNotations.get(entity);
  1146. if (grammar.getNotationDeclIndex(notation) == -1) {
  1147. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1148. "MSG_NOTATION_NOT_DECLARED_FOR_UNPARSED_ENTITYDECL",
  1149. new Object[]{entity, notation},
  1150. XMLErrorReporter.SEVERITY_ERROR);
  1151. }
  1152. }
  1153. // VC: Notation Attributes:
  1154. // all notation names in the (attribute) declaration must be declared.
  1155. Enumeration notationVals = fNotationEnumVals.keys();
  1156. while (notationVals.hasMoreElements()) {
  1157. String notation = (String) notationVals.nextElement();
  1158. String attributeName = (String) fNotationEnumVals.get(notation);
  1159. if (grammar.getNotationDeclIndex(notation) == -1) {
  1160. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1161. "MSG_NOTATION_NOT_DECLARED_FOR_NOTATIONTYPE_ATTRIBUTE",
  1162. new Object[]{attributeName, notation},
  1163. XMLErrorReporter.SEVERITY_ERROR);
  1164. }
  1165. }
  1166. // VC: No Notation on Empty Element
  1167. // An attribute of type NOTATION must not be declared on an element declared EMPTY.
  1168. Enumeration elementsWithNotations = fTableOfNOTATIONAttributeNames.keys();
  1169. while (elementsWithNotations.hasMoreElements()) {
  1170. String elementName = (String) elementsWithNotations.nextElement();
  1171. int elementIndex = grammar.getElementDeclIndex(elementName);
  1172. if (grammar.getContentSpecType(elementIndex) == XMLElementDecl.TYPE_EMPTY) {
  1173. String attributeName = (String) fTableOfNOTATIONAttributeNames.get(elementName);
  1174. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1175. "NoNotationOnEmptyElement",
  1176. new Object[]{elementName, attributeName},
  1177. XMLErrorReporter.SEVERITY_ERROR);
  1178. }
  1179. }
  1180. fTableOfIDAttributeNames = null;//should be safe to release these references
  1181. fTableOfNOTATIONAttributeNames = null;
  1182. }
  1183. // call handlers
  1184. if (fDTDHandler != null) {
  1185. fDTDHandler.endDTD(augs);
  1186. }
  1187. } // endDTD()
  1188. // sets the XMLDTDSource of this handler
  1189. public void setDTDSource(XMLDTDSource source ) {
  1190. fDTDSource = source;
  1191. } // setDTDSource(XMLDTDSource)
  1192. // returns the XMLDTDSource of this handler
  1193. public XMLDTDSource getDTDSource() {
  1194. return fDTDSource;
  1195. } // getDTDSource(): XMLDTDSource
  1196. //
  1197. // XMLDTDContentModelHandler methods
  1198. //
  1199. // sets the XMLContentModelDTDSource of this handler
  1200. public void setDTDContentModelSource(XMLDTDContentModelSource source ) {
  1201. fDTDContentModelSource = source;
  1202. } // setDTDContentModelSource(XMLDTDContentModelSource)
  1203. // returns the XMLDTDSource of this handler
  1204. public XMLDTDContentModelSource getDTDContentModelSource() {
  1205. return fDTDContentModelSource;
  1206. } // getDTDContentModelSource(): XMLDTDContentModelSource
  1207. /**
  1208. * The start of a content model. Depending on the type of the content
  1209. * model, specific methods may be called between the call to the
  1210. * startContentModel method and the call to the endContentModel method.
  1211. *
  1212. * @param elementName The name of the element.
  1213. * @param augs Additional information that may include infoset
  1214. * augmentations.
  1215. *
  1216. * @throws XNIException Thrown by handler to signal an error.
  1217. */
  1218. public void startContentModel(String elementName, Augmentations augs)
  1219. throws XNIException {
  1220. if (fValidation) {
  1221. fDTDElementDeclName = elementName;
  1222. fMixedElementTypes.removeAllElements();
  1223. }
  1224. // call handlers
  1225. if(fDTDGrammar != null)
  1226. fDTDGrammar.startContentModel(elementName, augs);
  1227. if (fDTDContentModelHandler != null) {
  1228. fDTDContentModelHandler.startContentModel(elementName, augs);
  1229. }
  1230. } // startContentModel(String)
  1231. /**
  1232. * A content model of ANY.
  1233. *
  1234. * @param augs Additional information that may include infoset
  1235. * augmentations.
  1236. *
  1237. * @throws XNIException Thrown by handler to signal an error.
  1238. *
  1239. * @see #empty
  1240. * @see #startGroup
  1241. */
  1242. public void any(Augmentations augs) throws XNIException {
  1243. if(fDTDGrammar != null)
  1244. fDTDGrammar.any(augs);
  1245. if (fDTDContentModelHandler != null) {
  1246. fDTDContentModelHandler.any(augs);
  1247. }
  1248. } // any()
  1249. /**
  1250. * A content model of EMPTY.
  1251. *
  1252. * @param augs Additional information that may include infoset
  1253. * augmentations.
  1254. *
  1255. * @throws XNIException Thrown by handler to signal an error.
  1256. *
  1257. * @see #any
  1258. * @see #startGroup
  1259. */
  1260. public void empty(Augmentations augs) throws XNIException {
  1261. if(fDTDGrammar != null)
  1262. fDTDGrammar.empty(augs);
  1263. if (fDTDContentModelHandler != null) {
  1264. fDTDContentModelHandler.empty(augs);
  1265. }
  1266. } // empty()
  1267. /**
  1268. * A start of either a mixed or children content model. A mixed
  1269. * content model will immediately be followed by a call to the
  1270. * <code>pcdata()</code> method. A children content model will
  1271. * contain additional groups and/or elements.
  1272. *
  1273. * @param augs Additional information that may include infoset
  1274. * augmentations.
  1275. *
  1276. * @throws XNIException Thrown by handler to signal an error.
  1277. *
  1278. * @see #any
  1279. * @see #empty
  1280. */
  1281. public void startGroup(Augmentations augs) throws XNIException {
  1282. fMixed = false;
  1283. // call handlers
  1284. if(fDTDGrammar != null)
  1285. fDTDGrammar.startGroup(augs);
  1286. if (fDTDContentModelHandler != null) {
  1287. fDTDContentModelHandler.startGroup(augs);
  1288. }
  1289. } // startGroup()
  1290. /**
  1291. * The appearance of "#PCDATA" within a group signifying a
  1292. * mixed content model. This method will be the first called
  1293. * following the content model's <code>startGroup()</code>.
  1294. *
  1295. * @param augs Additional information that may include infoset
  1296. * augmentations.
  1297. *
  1298. * @throws XNIException Thrown by handler to signal an error.
  1299. *
  1300. * @see #startGroup
  1301. */
  1302. public void pcdata(Augmentations augs) {
  1303. fMixed = true;
  1304. if(fDTDGrammar != null)
  1305. fDTDGrammar.pcdata(augs);
  1306. if (fDTDContentModelHandler != null) {
  1307. fDTDContentModelHandler.pcdata(augs);
  1308. }
  1309. } // pcdata()
  1310. /**
  1311. * A referenced element in a mixed or children content model.
  1312. *
  1313. * @param elementName The name of the referenced element.
  1314. * @param augs Additional information that may include infoset
  1315. * augmentations.
  1316. *
  1317. * @throws XNIException Thrown by handler to signal an error.
  1318. */
  1319. public void element(String elementName, Augmentations augs) throws XNIException {
  1320. // check VC: No duplicate Types, in a single mixed-content declaration
  1321. if (fMixed && fValidation) {
  1322. if (fMixedElementTypes.contains(elementName)) {
  1323. fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
  1324. "DuplicateTypeInMixedContent",
  1325. new Object[]{fDTDElementDeclName, elementName},
  1326. XMLErrorReporter.SEVERITY_ERROR);
  1327. }
  1328. else {
  1329. fMixedElementTypes.addElement(elementName);
  1330. }
  1331. }
  1332. // call handlers
  1333. if(fDTDGrammar != null)
  1334. fDTDGrammar.element(elementName, augs);
  1335. if (fDTDContentModelHandler != null) {
  1336. fDTDContentModelHandler.element(elementName, augs);
  1337. }
  1338. } // childrenElement(String)
  1339. /**
  1340. * The separator between choices or sequences of a mixed or children
  1341. * content model.
  1342. *
  1343. * @param separator The type of children separator.
  1344. * @param augs Additional information that may include infoset
  1345. * augmentations.
  1346. *
  1347. * @throws XNIException Thrown by handler to signal an error.
  1348. *
  1349. * @see #SEPARATOR_CHOICE
  1350. * @see #SEPARATOR_SEQUENCE
  1351. */
  1352. public void separator(short separator, Augmentations augs)
  1353. throws XNIException {
  1354. // call handlers
  1355. if(fDTDGrammar != null)
  1356. fDTDGrammar.separator(separator, augs);
  1357. if (fDTDContentModelHandler != null) {
  1358. fDTDContentModelHandler.separator(separator, augs);
  1359. }
  1360. } // separator(short)
  1361. /**
  1362. * The occurrence count for a child in a children content model or
  1363. * for the mixed content model group.
  1364. *
  1365. * @param occurrence The occurrence count for the last element
  1366. * or group.
  1367. * @param augs Additional information that may include infoset
  1368. * augmentations.
  1369. *
  1370. * @throws XNIException Thrown by handler to signal an error.
  1371. *
  1372. * @see #OCCURS_ZERO_OR_ONE
  1373. * @see #OCCURS_ZERO_OR_MORE
  1374. * @see #OCCURS_ONE_OR_MORE
  1375. */
  1376. public void occurrence(short occurrence, Augmentations augs)
  1377. throws XNIException {
  1378. // call handlers
  1379. if(fDTDGrammar != null)
  1380. fDTDGrammar.occurrence(occurrence, augs);
  1381. if (fDTDContentModelHandler != null) {
  1382. fDTDContentModelHandler.occurrence(occurrence, augs);
  1383. }
  1384. } // occurrence(short)
  1385. /**
  1386. * The end of a group for mixed or children content models.
  1387. *
  1388. * @param augs Additional information that may include infoset
  1389. * augmentations.
  1390. *
  1391. * @throws XNIException Thrown by handler to signal an error.
  1392. */
  1393. public void endGroup(Augmentations augs) throws XNIException {
  1394. // call handlers
  1395. if(fDTDGrammar != null)
  1396. fDTDGrammar.endGroup(augs);
  1397. if (fDTDContentModelHandler != null) {
  1398. fDTDContentModelHandler.endGroup(augs);
  1399. }
  1400. } // endGroup()
  1401. /**
  1402. * The end of a content model.
  1403. *
  1404. * @param augs Additional information that may include infoset
  1405. * augmentations.
  1406. *
  1407. * @throws XNIException Thrown by handler to signal an error.
  1408. */
  1409. public void endContentModel(Augmentations augs) throws XNIException {
  1410. // call handlers
  1411. if(fDTDGrammar != null)
  1412. fDTDGrammar.endContentModel(augs);
  1413. if (fDTDContentModelHandler != null) {
  1414. fDTDContentModelHandler.endContentModel(augs);
  1415. }
  1416. } // endContentModel()
  1417. //
  1418. // Private methods
  1419. //
  1420. /**
  1421. * Normalize the attribute value of a non CDATA default attribute
  1422. * collapsing sequences of space characters (x20)
  1423. *
  1424. * @param value The value to normalize
  1425. * @return Whether the value was changed or not.
  1426. */
  1427. private boolean normalizeDefaultAttrValue(XMLString value) {
  1428. int oldLength = value.length;
  1429. boolean skipSpace = true; // skip leading spaces
  1430. int current = value.offset;
  1431. int end = value.offset + value.length;
  1432. for (int i = value.offset; i < end; i++) {
  1433. if (value.ch[i] == ' ') {
  1434. if (!skipSpace) {
  1435. // take the first whitespace as a space and skip the others
  1436. value.ch[current++] = ' ';
  1437. skipSpace = true;
  1438. }
  1439. else {
  1440. // just skip it.
  1441. }
  1442. }
  1443. else {
  1444. // simply shift non space chars if needed
  1445. if (current != i) {
  1446. value.ch[current] = value.ch[i];
  1447. }
  1448. current++;
  1449. skipSpace = false;
  1450. }
  1451. }
  1452. if (current != end) {
  1453. if (skipSpace) {
  1454. // if we finished on a space trim it
  1455. current--;
  1456. }
  1457. // set the new value length
  1458. value.length = current - value.offset;
  1459. return true;
  1460. }
  1461. return false;
  1462. }
  1463. protected boolean isValidNmtoken(String nmtoken) {
  1464. return XMLChar.isValidNmtoken(nmtoken);
  1465. } // isValidNmtoken(String): boolean
  1466. protected boolean isValidName(String name) {
  1467. return XMLChar.isValidName(name);
  1468. } // isValidName(String): boolean
  1469. } // class XMLDTDProcessor