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-2003 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) 2003, 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;
  
  import java.io.EOFException;
  import java.io.IOException;
  
  import jaxp.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
  import jaxp.sun.org.apache.xerces.internal.util.SymbolTable;
  import jaxp.sun.org.apache.xerces.internal.xni.XMLString;
  import jaxp.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  import jaxp.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  import jaxp.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  import jaxp.sun.xml.internal.stream.Entity;
  
  /**
   * This class scans the version of the document to determine
   * which scanner to use: XML 1.1 or XML 1.0.
   * The version is scanned using XML 1.1. scanner.
   *
   * @xerces.internal
   *
   * @author Neil Graham, IBM
   * @author Elena Litani, IBM
   */
  public class XMLVersionDetector {
  
      //
      // Constants
      //
  
      private final static char[] XML11_VERSION = new char[]{'1', '.', '1'};
  
  
      // property identifiers
  
      /** Property identifier: symbol table. */
      protected static final String SYMBOL_TABLE =
          Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
  
      /** Property identifier: error reporter. */
      protected static final String ERROR_REPORTER =
          Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
  
      /** Property identifier: entity manager. */
      protected static final String ENTITY_MANAGER =
          Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
  
      //
      // Data
      //
  
      /** Symbol: "version". */
      protected final static String fVersionSymbol = "version".intern();
  
      // symbol:  [xml]:
      protected static final String fXMLSymbol = "[xml]".intern();
  
      /** Symbol table. */
      protected SymbolTable fSymbolTable;
  
      /** Error reporter. */
      protected XMLErrorReporter fErrorReporter;
  
      /** Entity manager. */
      protected XMLEntityManager fEntityManager;
  
      protected String fEncoding = null;
  
      private XMLString fVersionNum = new XMLString();
  
      private final char [] fExpectedVersionString = {'<', '?', 'x', 'm', 'l', ' ', 'v', 'e', 'r', 's',
                      'i', 'o', 'n', '=', ' ', ' ', ' ', ' ', ' '};
  
      /**
       *
       *
       * @param componentManager The component manager.
       *
       * @throws SAXException Throws exception if required features and
       *                      properties cannot be found.
       */
      public void reset(XMLComponentManager componentManager)
          throws XMLConfigurationException {
  
          // Xerces properties
          fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
          fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
          fEntityManager = (XMLEntityManager)componentManager.getProperty(ENTITY_MANAGER);
          for(int i=14; i<fExpectedVersionString.length; i++ )
              fExpectedVersionString[i] = ' ';
      } // reset(XMLComponentManager)
  
      /**
       * Reset the reference to the appropriate scanner given the version of the
       * document and start document scanning.
       * @param scanner - the scanner to use
       * @param version - the version of the document (XML 1.1 or XML 1.0).
       */
      public void startDocumentParsing(XMLEntityHandler scanner, short version){
  
          if (version == Constants.XML_VERSION_1_0){
              fEntityManager.setScannerVersion(Constants.XML_VERSION_1_0);
          }
          else {
              fEntityManager.setScannerVersion(Constants.XML_VERSION_1_1);
          }
          // Make sure the locator used by the error reporter is the current entity scanner.
          fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
  
          // Note: above we reset fEntityScanner in the entity manager, thus in startEntity
          // in each scanner fEntityScanner field must be reset to reflect the change.
          //
          fEntityManager.setEntityHandler(scanner);
  
          scanner.startEntity(fXMLSymbol, fEntityManager.getCurrentResourceIdentifier(), fEncoding, null);
      }
  
  
      /**
       * This methods scans the XML declaration to find out the version
       * (and provisional encoding)  of the document.
       * The scanning is doing using XML 1.1 scanner.
       * @param inputSource
       * @return short - Constants.XML_VERSION_1_1 if document version 1.1,
       *                  otherwise Constants.XML_VERSION_1_0
       * @throws IOException
       */
      public short determineDocVersion(XMLInputSource inputSource) throws IOException {
          fEncoding = fEntityManager.setupCurrentEntity(fXMLSymbol, inputSource, false, true);
  
          // Must use XML 1.0 scanner to handle whitespace correctly
          // in the XML declaration.
          fEntityManager.setScannerVersion(Constants.XML_VERSION_1_0);
          XMLEntityScanner scanner = fEntityManager.getEntityScanner();
          try {
              if (!scanner.skipString("<?xml")) {
                  // definitely not a well-formed 1.1 doc!
                  return Constants.XML_VERSION_1_0;
              }
              if (!scanner.skipDeclSpaces()) {
                  fixupCurrentEntity(fEntityManager, fExpectedVersionString, 5);
                  return Constants.XML_VERSION_1_0;
              }
              if (!scanner.skipString("version")) {
                  fixupCurrentEntity(fEntityManager, fExpectedVersionString, 6);
                  return Constants.XML_VERSION_1_0;
              }
              scanner.skipDeclSpaces();
              // Check if the next character is '='. If it is then consume it.
              if (scanner.peekChar() != '=') {
                  fixupCurrentEntity(fEntityManager, fExpectedVersionString, 13);
                  return Constants.XML_VERSION_1_0;
              }
              scanner.scanChar();
              scanner.skipDeclSpaces();
              int quoteChar = scanner.scanChar();
              fExpectedVersionString[14] = (char) quoteChar;
              for (int versionPos = 0; versionPos < XML11_VERSION.length; versionPos++) {
                  fExpectedVersionString[15 + versionPos] = (char) scanner.scanChar();
              }
              // REVISIT:  should we check whether this equals quoteChar?
              fExpectedVersionString[18] = (char) scanner.scanChar();
              fixupCurrentEntity(fEntityManager, fExpectedVersionString, 19);
              int matched = 0;
              for (; matched < XML11_VERSION.length; matched++) {
                  if (fExpectedVersionString[15 + matched] != XML11_VERSION[matched])
                      break;
              }
              if (matched == XML11_VERSION.length)
                  return Constants.XML_VERSION_1_1;
              return Constants.XML_VERSION_1_0;
              // premature end of file
          }
          catch (EOFException e) {
              fErrorReporter.reportError(
                  XMLMessageFormatter.XML_DOMAIN,
                  "PrematureEOF",
                  null,
                  XMLErrorReporter.SEVERITY_FATAL_ERROR);
              return Constants.XML_VERSION_1_0;
  
          }
  
      }
  
      // This method prepends "length" chars from the char array,
      // from offset 0, to the manager's fCurrentEntity.ch.
      private void fixupCurrentEntity(XMLEntityManager manager,
                  char [] scannedChars, int length) {
          Entity.ScannedEntity currentEntity = manager.getCurrentEntity();
          if(currentEntity.count-currentEntity.position+length > currentEntity.ch.length) {
              //resize array; this case is hard to imagine...
              char[] tempCh = currentEntity.ch;
              currentEntity.ch = new char[length+currentEntity.count-currentEntity.position+1];
              System.arraycopy(tempCh, 0, currentEntity.ch, 0, tempCh.length);
          }
          if(currentEntity.position < length) {
              // have to move sensitive stuff out of the way...
              System.arraycopy(currentEntity.ch, currentEntity.position, currentEntity.ch, length, currentEntity.count-currentEntity.position);
              currentEntity.count += length-currentEntity.position;
          } else {
              // have to reintroduce some whitespace so this parses:
              for(int i=length; i<currentEntity.position; i++)
                  currentEntity.ch[i]=' ';
          }
          // prepend contents...
          System.arraycopy(scannedChars, 0, currentEntity.ch, 0, length);
          currentEntity.position = 0;
          currentEntity.baseCharOffset = 0;
          currentEntity.startPosition = 0;
          currentEntity.columnNumber = currentEntity.lineNumber = 1;
      }
  
  } // class XMLVersionDetector
  