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 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. *
  92. * @version $Id: XMLNSDTDValidator.java,v 1.7 2003/10/10 18:25:40 mrglavas Exp $
  93. */
  94. public class XMLNSDTDValidator
  95. extends XMLDTDValidator{
  96. /** Attribute QName. */
  97. private QName fAttributeQName = new QName();
  98. /** Bind namespaces */
  99. protected final void startNamespaceScope (QName element, XMLAttributes attributes,
  100. Augmentations augs) throws XNIException {
  101. // add new namespace context
  102. fNamespaceContext.pushContext();
  103. if (element.prefix == XMLSymbols.PREFIX_XMLNS) {
  104. fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  105. "ElementXMLNSPrefix",
  106. new Object[]{element.rawname},
  107. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  108. }
  109. // search for new namespace bindings
  110. int length = attributes.getLength();
  111. for (int i = 0; i < length; i++) {
  112. String localpart = attributes.getLocalName(i);
  113. String prefix = attributes.getPrefix(i);
  114. // when it's of form xmlns="..." or xmlns:prefix="...",
  115. // it's a namespace declaration. but prefix:xmlns="..." isn't.
  116. if (prefix == XMLSymbols.PREFIX_XMLNS ||
  117. prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) {
  118. // get the internalized value of this attribute
  119. String uri = fSymbolTable.addSymbol(attributes.getValue(i));
  120. // 1. "xmlns" can't be bound to any namespace
  121. if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) {
  122. fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  123. "CantBindXMLNS",
  124. new Object[]{attributes.getQName(i)},
  125. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  126. }
  127. // 2. the namespace for "xmlns" can't be bound to any prefix
  128. if (uri == NamespaceContext.XMLNS_URI) {
  129. fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  130. "CantBindXMLNS",
  131. new Object[]{attributes.getQName(i)},
  132. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  133. }
  134. // 3. "xml" can't be bound to any other namespace than it's own
  135. if (localpart == XMLSymbols.PREFIX_XML) {
  136. if (uri != NamespaceContext.XML_URI) {
  137. fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  138. "CantBindXML",
  139. new Object[]{attributes.getQName(i)},
  140. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  141. }
  142. }
  143. // 4. the namespace for "xml" can't be bound to any other prefix
  144. else {
  145. if (uri ==NamespaceContext.XML_URI) {
  146. fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  147. "CantBindXML",
  148. new Object[]{attributes.getQName(i)},
  149. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  150. }
  151. }
  152. prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING;
  153. // http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-prefix
  154. // We should only report an error if there is a prefix,
  155. // that is, the local part is not "xmlns". -SG
  156. if (uri == XMLSymbols.EMPTY_STRING && localpart != XMLSymbols.PREFIX_XMLNS) {
  157. fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  158. "EmptyPrefixedAttName",
  159. new Object[]{attributes.getQName(i)},
  160. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  161. continue;
  162. }
  163. // declare prefix in context
  164. fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null);
  165. }
  166. }
  167. // bind the element
  168. String prefix = element.prefix != null
  169. ? element.prefix : XMLSymbols.EMPTY_STRING;
  170. element.uri = fNamespaceContext.getURI(prefix);
  171. if (element.prefix == null && element.uri != null) {
  172. element.prefix = XMLSymbols.EMPTY_STRING;
  173. }
  174. if (element.prefix != null && element.uri == null) {
  175. fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  176. "ElementPrefixUnbound",
  177. new Object[]{element.prefix, element.rawname},
  178. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  179. }
  180. // bind the attributes
  181. for (int i = 0; i < length; i++) {
  182. attributes.getName(i, fAttributeQName);
  183. String aprefix = fAttributeQName.prefix != null
  184. ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
  185. String arawname = fAttributeQName.rawname;
  186. if (arawname == XMLSymbols.PREFIX_XMLNS) {
  187. fAttributeQName.uri = fNamespaceContext.getURI(XMLSymbols.PREFIX_XMLNS);
  188. attributes.setName(i, fAttributeQName);
  189. }
  190. else if (aprefix != XMLSymbols.EMPTY_STRING) {
  191. fAttributeQName.uri = fNamespaceContext.getURI(aprefix);
  192. if (fAttributeQName.uri == null) {
  193. fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  194. "AttributePrefixUnbound",
  195. new Object[]{element.rawname,arawname,aprefix},
  196. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  197. }
  198. attributes.setName(i, fAttributeQName);
  199. }
  200. }
  201. // verify that duplicate attributes don't exist
  202. // Example: <foo xmlns:a='NS' xmlns:b='NS' a:attr='v1' b:attr='v2'/>
  203. int attrCount = attributes.getLength();
  204. for (int i = 0; i < attrCount - 1; i++) {
  205. String auri = attributes.getURI(i);
  206. if (auri == null || auri == NamespaceContext.XMLNS_URI) {
  207. continue;
  208. }
  209. String alocalpart = attributes.getLocalName(i);
  210. for (int j = i + 1; j < attrCount; j++) {
  211. String blocalpart = attributes.getLocalName(j);
  212. String buri = attributes.getURI(j);
  213. if (alocalpart == blocalpart && auri == buri) {
  214. fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
  215. "AttributeNSNotUnique",
  216. new Object[]{element.rawname,alocalpart, auri},
  217. XMLErrorReporter.SEVERITY_FATAL_ERROR);
  218. }
  219. }
  220. }
  221. } // startNamespaceScope(QName,XMLAttributes)
  222. /** Handles end element. */
  223. protected void endNamespaceScope(QName element, Augmentations augs, boolean isEmpty)
  224. throws XNIException {
  225. // bind element
  226. String eprefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING;
  227. element.uri = fNamespaceContext.getURI(eprefix);
  228. if (element.uri != null) {
  229. element.prefix = eprefix;
  230. }
  231. // call handlers
  232. if (fDocumentHandler != null) {
  233. if (!isEmpty) {
  234. fDocumentHandler.endElement(element, augs);
  235. }
  236. }
  237. // pop context
  238. fNamespaceContext.popContext();
  239. } // endNamespaceScope(QName,boolean)
  240. }