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) 2002, 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.XMLErrorReporter;
  59. import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
  60. import com.sun.org.apache.xerces.internal.util.XMLSymbols;
  61. import com.sun.org.apache.xerces.internal.xni.Augmentations;
  62. import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
  63. import com.sun.org.apache.xerces.internal.xni.QName;
  64. import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
  65. import com.sun.org.apache.xerces.internal.xni.XNIException;
  66. /**
  67. * The DTD validator. The validator implements a document
  68. * filter: receiving document events from the scanner; validating
  69. * the content and structure; augmenting the InfoSet, if applicable;
  70. * and notifying the parser of the information resulting from the
  71. * validation process.
  72. * <p> Formerly, this component also handled DTD events and grammar construction.
  73. * To facilitate the development of a meaningful DTD grammar caching/preparsing
  74. * framework, this functionality has been moved into the XMLDTDLoader
  75. * class. Therefore, this class no longer implements the DTDFilter
  76. * or DTDContentModelFilter interfaces.
  77. * <p>
  78. * This component requires the following features and properties from the
  79. * component manager that uses it:
  80. * <ul>
  81. * <li>http://xml.org/sax/features/namespaces</li>
  82. * <li>http://xml.org/sax/features/validation</li>
  83. * <li>http://apache.org/xml/features/validation/dynamic</li>
  84. * <li>http://apache.org/xml/properties/internal/symbol-table</li>
  85. * <li>http://apache.org/xml/properties/internal/error-reporter</li>
  86. * <li>http://apache.org/xml/properties/internal/grammar-pool</li>
  87. * <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
  88. * </ul>
  89. *
  90. * @author Elena Litani, IBM
  91. * @author Michael Glavassevich, IBM
  92. *
  93. * @version $Id: XML11NSDTDValidator.java,v 1.2 2003/10/10 18:25:40 mrglavas Exp $
  94. */
  95. public class XML11NSDTDValidator extends XML11DTDValidator {
  96. /** Attribute QName. */
  97. private QName fAttributeQName = new QName();
  98. /** Bind namespaces */
  99. protected final void startNamespaceScope(QName element, XMLAttributes attributes, Augmentations augs)
  100. throws XNIException {
  101. // add new namespace context
  102. fNamespaceContext.pushContext();
  103. if (element.prefix == XMLSymbols.PREFIX_XMLNS) {
  104. fErrorReporter.reportError(
  105. XMLMessageFormatter.XMLNS_DOMAIN,
  106. "ElementXMLNSPrefix",
  107. new Object[] { element.rawname },
  108. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  109. }
  110. // search for new namespace bindings
  111. int length = attributes.getLength();
  112. for (int i = 0; i < length; i++) {
  113. String localpart = attributes.getLocalName(i);
  114. String prefix = attributes.getPrefix(i);
  115. // when it's of form xmlns="..." or xmlns:prefix="...",
  116. // it's a namespace declaration. but prefix:xmlns="..." isn't.
  117. if (prefix == XMLSymbols.PREFIX_XMLNS || prefix == XMLSymbols.EMPTY_STRING
  118. && localpart == XMLSymbols.PREFIX_XMLNS) {
  119. // get the internalized value of this attribute
  120. String uri = fSymbolTable.addSymbol(attributes.getValue(i));
  121. // 1. "xmlns" can't be bound to any namespace
  122. if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) {
  123. fErrorReporter.reportError(
  124. XMLMessageFormatter.XMLNS_DOMAIN,
  125. "CantBindXMLNS",
  126. new Object[] { attributes.getQName(i)},
  127. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  128. }
  129. // 2. the namespace for "xmlns" can't be bound to any prefix
  130. if (uri == NamespaceContext.XMLNS_URI) {
  131. fErrorReporter.reportError(
  132. XMLMessageFormatter.XMLNS_DOMAIN,
  133. "CantBindXMLNS",
  134. new Object[] { attributes.getQName(i)},
  135. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  136. }
  137. // 3. "xml" can't be bound to any other namespace than it's own
  138. if (localpart == XMLSymbols.PREFIX_XML) {
  139. if (uri != NamespaceContext.XML_URI) {
  140. fErrorReporter.reportError(
  141. XMLMessageFormatter.XMLNS_DOMAIN,
  142. "CantBindXML",
  143. new Object[] { attributes.getQName(i)},
  144. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  145. }
  146. }
  147. // 4. the namespace for "xml" can't be bound to any other prefix
  148. else {
  149. if (uri == NamespaceContext.XML_URI) {
  150. fErrorReporter.reportError(
  151. XMLMessageFormatter.XMLNS_DOMAIN,
  152. "CantBindXML",
  153. new Object[] { attributes.getQName(i)},
  154. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  155. }
  156. }
  157. prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING;
  158. // Declare prefix in context. Removing the association between a prefix and a
  159. // namespace name is permitted in XML 1.1, so if the uri value is the empty string,
  160. // the prefix is being unbound. -- mrglavas
  161. fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null);
  162. }
  163. }
  164. // bind the element
  165. String prefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING;
  166. element.uri = fNamespaceContext.getURI(prefix);
  167. if (element.prefix == null && element.uri != null) {
  168. element.prefix = XMLSymbols.EMPTY_STRING;
  169. }
  170. if (element.prefix != null && element.uri == null) {
  171. fErrorReporter.reportError(
  172. XMLMessageFormatter.XMLNS_DOMAIN,
  173. "ElementPrefixUnbound",
  174. new Object[] { element.prefix, element.rawname },
  175. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  176. }
  177. // bind the attributes
  178. for (int i = 0; i < length; i++) {
  179. attributes.getName(i, fAttributeQName);
  180. String aprefix = fAttributeQName.prefix != null ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
  181. String arawname = fAttributeQName.rawname;
  182. if (arawname == XMLSymbols.PREFIX_XMLNS) {
  183. fAttributeQName.uri = fNamespaceContext.getURI(XMLSymbols.PREFIX_XMLNS);
  184. attributes.setName(i, fAttributeQName);
  185. } else if (aprefix != XMLSymbols.EMPTY_STRING) {
  186. fAttributeQName.uri = fNamespaceContext.getURI(aprefix);
  187. if (fAttributeQName.uri == null) {
  188. fErrorReporter.reportError(
  189. XMLMessageFormatter.XMLNS_DOMAIN,
  190. "AttributePrefixUnbound",
  191. new Object[] { element.rawname, arawname, aprefix },
  192. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  193. }
  194. attributes.setName(i, fAttributeQName);
  195. }
  196. }
  197. // verify that duplicate attributes don't exist
  198. // Example: <foo xmlns:a='NS' xmlns:b='NS' a:attr='v1' b:attr='v2'/>
  199. int attrCount = attributes.getLength();
  200. for (int i = 0; i < attrCount - 1; i++) {
  201. String auri = attributes.getURI(i);
  202. if (auri == null || auri == NamespaceContext.XMLNS_URI) {
  203. continue;
  204. }
  205. String alocalpart = attributes.getLocalName(i);
  206. for (int j = i + 1; j < attrCount; j++) {
  207. String blocalpart = attributes.getLocalName(j);
  208. String buri = attributes.getURI(j);
  209. if (alocalpart == blocalpart && auri == buri) {
  210. fErrorReporter.reportError(
  211. XMLMessageFormatter.XMLNS_DOMAIN,
  212. "AttributeNSNotUnique",
  213. new Object[] { element.rawname, alocalpart, auri },
  214. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  215. }
  216. }
  217. }
  218. } // startNamespaceScope(QName,XMLAttributes)
  219. /** Handles end element. */
  220. protected void endNamespaceScope(QName element, Augmentations augs, boolean isEmpty)
  221. throws XNIException {
  222. // bind element
  223. String eprefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING;
  224. element.uri = fNamespaceContext.getURI(eprefix);
  225. if (element.uri != null) {
  226. element.prefix = eprefix;
  227. }
  228. // call handlers
  229. if (fDocumentHandler != null) {
  230. if (!isEmpty) {
  231. fDocumentHandler.endElement(element, augs);
  232. }
  233. }
  234. // pop context
  235. fNamespaceContext.popContext();
  236. } // endNamespaceScope(QName,boolean)
  237. }