content: /*
   *  This file is part of AndroidIDE.
   *
   *  AndroidIDE is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  AndroidIDE is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *   along with AndroidIDE.  If not, see <https://www.gnu.org/licenses/>.
   */
  
  /*
   * reserved comment block
   * DO NOT REMOVE OR ALTER!
   */
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.apache.org.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package jaxp.sun.org.apache.xerces.internal.impl.dtd;
  
  import jaxp.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
  import jaxp.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
  import jaxp.sun.org.apache.xerces.internal.util.XMLSymbols;
  import jaxp.sun.org.apache.xerces.internal.xni.Augmentations;
  import jaxp.sun.org.apache.xerces.internal.xni.NamespaceContext;
  import jaxp.sun.org.apache.xerces.internal.xni.QName;
  import jaxp.sun.org.apache.xerces.internal.xni.XMLAttributes;
  import jaxp.sun.org.apache.xerces.internal.xni.XNIException;
  
  
  /**
   * The DTD validator. The validator implements a document
   * filter: receiving document events from the scanner; validating
   * the content and structure; augmenting the InfoSet, if applicable;
   * and notifying the parser of the information resulting from the
   * validation process.
   * <p> Formerly, this component also handled DTD events and grammar construction.
   * To facilitate the development of a meaningful DTD grammar caching/preparsing
   * framework, this functionality has been moved into the XMLDTDLoader
   * class.  Therefore, this class no longer implements the DTDFilter
   * or DTDContentModelFilter interfaces.
   * <p>
   * This component requires the following features and properties from the
   * component manager that uses it:
   * <ul>
   *  <li>http://xml.org/sax/features/namespaces</li>
   *  <li>http://xml.org/sax/features/validation</li>
   *  <li>http://apache.org/xml/features/validation/dynamic</li>
   *  <li>http://apache.org/xml/properties/internal/symbol-table</li>
   *  <li>http://apache.org/xml/properties/internal/error-reporter</li>
   *  <li>http://apache.org/xml/properties/internal/grammar-pool</li>
   *  <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
   * </ul>
   *
   * @xerces.internal
   *
   * @author Elena Litani, IBM
   *
  
   */
  public class XMLNSDTDValidator
                extends XMLDTDValidator{
  
      /** Attribute QName. */
      private QName fAttributeQName = new QName();
  
  
      /** Bind namespaces */
      protected final void startNamespaceScope (QName element, XMLAttributes attributes,
                                        Augmentations augs) throws XNIException {
  
          // add new namespace context
          fNamespaceContext.pushContext();
  
          if (element.prefix == XMLSymbols.PREFIX_XMLNS) {
              fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                         "ElementXMLNSPrefix",
                                         new Object[]{element.rawname},
                                         XMLErrorReporter.SEVERITY_FATAL_ERROR);
          }
  
          // search for new namespace bindings
          int length = attributes.getLength();
          for (int i = 0; i < length; i++) {
              String localpart = attributes.getLocalName(i);
              String prefix = attributes.getPrefix(i);
              // when it's of form xmlns="..." or xmlns:prefix="...",
              // it's a namespace declaration. but prefix:xmlns="..." isn't.
              if (prefix == XMLSymbols.PREFIX_XMLNS ||
                  prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) {
  
                  // get the internalized value of this attribute
                  String uri = fSymbolTable.addSymbol(attributes.getValue(i));
  
                  // 1. "xmlns" can't be bound to any namespace
                  if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) {
                      fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                                 "CantBindXMLNS",
                                                 new Object[]{attributes.getQName(i)},
                                                 XMLErrorReporter.SEVERITY_FATAL_ERROR);
                  }
  
                  // 2. the namespace for "xmlns" can't be bound to any prefix
                  if (uri == NamespaceContext.XMLNS_URI) {
                      fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                                 "CantBindXMLNS",
                                                 new Object[]{attributes.getQName(i)},
                                                 XMLErrorReporter.SEVERITY_FATAL_ERROR);
                  }
  
                  // 3. "xml" can't be bound to any other namespace than it's own
                  if (localpart == XMLSymbols.PREFIX_XML) {
                      if (uri != NamespaceContext.XML_URI) {
                          fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                                     "CantBindXML",
                                                     new Object[]{attributes.getQName(i)},
                                                     XMLErrorReporter.SEVERITY_FATAL_ERROR);
                      }
                  }
                  // 4. the namespace for "xml" can't be bound to any other prefix
                  else {
                      if (uri ==NamespaceContext.XML_URI) {
                          fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                                     "CantBindXML",
                                                     new Object[]{attributes.getQName(i)},
                                                     XMLErrorReporter.SEVERITY_FATAL_ERROR);
                      }
                  }
  
                  prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING;
  
                  // http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-prefix
                  // We should only report an error if there is a prefix,
                  // that is, the local part is not "xmlns". -SG
                  if (uri == XMLSymbols.EMPTY_STRING && localpart != XMLSymbols.PREFIX_XMLNS) {
                      fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                                 "EmptyPrefixedAttName",
                                                 new Object[]{attributes.getQName(i)},
                                                 XMLErrorReporter.SEVERITY_FATAL_ERROR);
                      continue;
                  }
  
                  // declare prefix in context
                  fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null);
              }
          }
  
          // bind the element
          String prefix = element.prefix != null
                        ? element.prefix : XMLSymbols.EMPTY_STRING;
          element.uri = fNamespaceContext.getURI(prefix);
          if (element.prefix == null && element.uri != null) {
              element.prefix = XMLSymbols.EMPTY_STRING;
          }
          if (element.prefix != null && element.uri == null) {
              fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                         "ElementPrefixUnbound",
                                         new Object[]{element.prefix, element.rawname},
                                         XMLErrorReporter.SEVERITY_FATAL_ERROR);
          }
  
          // bind the attributes
          for (int i = 0; i < length; i++) {
              attributes.getName(i, fAttributeQName);
              String aprefix = fAttributeQName.prefix != null
                             ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
              String arawname = fAttributeQName.rawname;
              if (arawname == XMLSymbols.PREFIX_XMLNS) {
                  fAttributeQName.uri = fNamespaceContext.getURI(XMLSymbols.PREFIX_XMLNS);
                  attributes.setName(i, fAttributeQName);
              }
              else if (aprefix != XMLSymbols.EMPTY_STRING) {
                  fAttributeQName.uri = fNamespaceContext.getURI(aprefix);
                  if (fAttributeQName.uri == null) {
                      fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                                 "AttributePrefixUnbound",
                                                 new Object[]{element.rawname,arawname,aprefix},
                                                 XMLErrorReporter.SEVERITY_FATAL_ERROR);
                  }
                  attributes.setName(i, fAttributeQName);
              }
          }
  
          // verify that duplicate attributes don't exist
          // Example: <foo xmlns:a='NS' xmlns:b='NS' a:attr='v1' b:attr='v2'/>
          int attrCount = attributes.getLength();
          for (int i = 0; i < attrCount - 1; i++) {
              String auri = attributes.getURI(i);
              if (auri == null || auri == NamespaceContext.XMLNS_URI) {
                  continue;
              }
              String alocalpart = attributes.getLocalName(i);
              for (int j = i + 1; j < attrCount; j++) {
                  String blocalpart = attributes.getLocalName(j);
                  String buri = attributes.getURI(j);
                  if (alocalpart == blocalpart && auri == buri) {
                      fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                                 "AttributeNSNotUnique",
                                                 new Object[]{element.rawname,alocalpart, auri},
                                                 XMLErrorReporter.SEVERITY_FATAL_ERROR);
                  }
              }
          }
  
  
      } // startNamespaceScope(QName,XMLAttributes)
  
  
      /** Handles end element. */
      protected void endNamespaceScope(QName element, Augmentations augs, boolean isEmpty)
          throws XNIException {
  
          // bind element
          String eprefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING;
          element.uri = fNamespaceContext.getURI(eprefix);
          if (element.uri != null) {
              element.prefix = eprefix;
          }
  
          // call handlers
          if (fDocumentHandler != null) {
              if (!isEmpty) {
                  fDocumentHandler.endElement(element, augs);
              }
          }
  
          // pop context
          fNamespaceContext.popContext();
  
      } // endNamespaceScope(QName,boolean)
  
  }
  