Save This Page
Home » Xerces-J-src.2.9.1 » org.apache.xerces » impl » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   package org.apache.xerces.impl;
   19   
   20   import java.io.CharConversionException;
   21   import java.io.EOFException;
   22   import java.io.IOException;
   23   
   24   import org.apache.xerces.impl.io.MalformedByteSequenceException;
   25   import org.apache.xerces.impl.msg.XMLMessageFormatter;
   26   import org.apache.xerces.util.SymbolTable;
   27   import org.apache.xerces.xni.parser.XMLComponentManager;
   28   import org.apache.xerces.xni.parser.XMLConfigurationException;
   29   import org.apache.xerces.xni.parser.XMLInputSource;
   30   
   31   /**
   32    * This class scans the version of the document to determine
   33    * which scanner to use: XML 1.1 or XML 1.0.
   34    * The version is scanned using XML 1.1. scanner.  
   35    * 
   36    * @xerces.internal
   37    * 
   38    * @author Neil Graham, IBM 
   39    * @author Elena Litani, IBM
   40    * @version $Id: XMLVersionDetector.java 572055 2007-09-02 17:55:43Z mrglavas $
   41    */
   42   public class XMLVersionDetector {
   43   
   44       //
   45       // Constants
   46       //
   47   
   48       private static final char[] XML11_VERSION = new char[]{'1', '.', '1'};
   49   
   50       // property identifiers
   51   
   52       /** Property identifier: symbol table. */
   53       protected static final String SYMBOL_TABLE = 
   54           Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
   55   
   56       /** Property identifier: error reporter. */
   57       protected static final String ERROR_REPORTER = 
   58           Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
   59   
   60       /** Property identifier: entity manager. */
   61       protected static final String ENTITY_MANAGER = 
   62           Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
   63   
   64       //
   65       // Data
   66       //
   67   
   68       /** Symbol: "version". */
   69       protected static final String fVersionSymbol = "version".intern();
   70   
   71       // symbol:  [xml]:
   72       protected static final String fXMLSymbol = "[xml]".intern();
   73   
   74       /** Symbol table. */
   75       protected SymbolTable fSymbolTable;
   76   
   77       /** Error reporter. */
   78       protected XMLErrorReporter fErrorReporter;
   79   
   80       /** Entity manager. */
   81       protected XMLEntityManager fEntityManager;
   82   
   83       protected String fEncoding = null;
   84   
   85       private final char [] fExpectedVersionString = {'<', '?', 'x', 'm', 'l', ' ', 'v', 'e', 'r', 's', 
   86                       'i', 'o', 'n', '=', ' ', ' ', ' ', ' ', ' '};
   87   
   88       /**
   89        * 
   90        * 
   91        * @param componentManager The component manager.
   92        *
   93        * @throws XNIException Throws exception if required features and
   94        *                      properties cannot be found.
   95        */
   96       public void reset(XMLComponentManager componentManager)
   97           throws XMLConfigurationException {
   98   
   99           // Xerces properties
  100           fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
  101           fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
  102           fEntityManager = (XMLEntityManager)componentManager.getProperty(ENTITY_MANAGER);
  103           for(int i=14; i<fExpectedVersionString.length; i++ )
  104               fExpectedVersionString[i] = ' ';
  105       } // reset(XMLComponentManager)
  106   
  107       /**
  108        * Reset the reference to the appropriate scanner given the version of the
  109        * document and start document scanning.
  110        * @param scanner - the scanner to use
  111        * @param version - the version of the document (XML 1.1 or XML 1.0).
  112        */
  113       public void startDocumentParsing(XMLEntityHandler scanner, short version){
  114   
  115           if (version == Constants.XML_VERSION_1_0){
  116               fEntityManager.setScannerVersion(Constants.XML_VERSION_1_0);
  117           }
  118           else {
  119               fEntityManager.setScannerVersion(Constants.XML_VERSION_1_1);
  120           }
  121           // Make sure the locator used by the error reporter is the current entity scanner.
  122           fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
  123           
  124           // Note: above we reset fEntityScanner in the entity manager, thus in startEntity
  125           // in each scanner fEntityScanner field must be reset to reflect the change.
  126           // 
  127           fEntityManager.setEntityHandler(scanner);
  128           
  129           scanner.startEntity(fXMLSymbol, fEntityManager.getCurrentResourceIdentifier(), fEncoding, null);        
  130       }
  131   
  132   
  133       /**
  134        * This methods scans the XML declaration to find out the version 
  135        * (and provisional encoding)  of the document.
  136        * The scanning is doing using XML 1.1 scanner.
  137        * @param inputSource
  138        * @return short - Constants.XML_VERSION_1_1 if document version 1.1, 
  139        *                  otherwise Constants.XML_VERSION_1_0 
  140        * @throws IOException
  141        */
  142       public short determineDocVersion(XMLInputSource inputSource) throws IOException {
  143           fEncoding = fEntityManager.setupCurrentEntity(fXMLSymbol, inputSource, false, true);
  144   
  145           // Must use XML 1.0 scanner to handle whitespace correctly
  146           // in the XML declaration.
  147           fEntityManager.setScannerVersion(Constants.XML_VERSION_1_0);
  148           XMLEntityScanner scanner = fEntityManager.getEntityScanner();
  149           try {
  150               if (!scanner.skipString("<?xml")) {
  151                   // definitely not a well-formed 1.1 doc!
  152                   return Constants.XML_VERSION_1_0;
  153               }
  154               if (!scanner.skipDeclSpaces()) {
  155                   fixupCurrentEntity(fEntityManager, fExpectedVersionString, 5);
  156                   return Constants.XML_VERSION_1_0;
  157               }
  158               if (!scanner.skipString("version")) {
  159                   fixupCurrentEntity(fEntityManager, fExpectedVersionString, 6);
  160                   return Constants.XML_VERSION_1_0;
  161               }
  162               scanner.skipDeclSpaces();
  163               // Check if the next character is '='. If it is then consume it.
  164               if (scanner.peekChar() != '=') {
  165                   fixupCurrentEntity(fEntityManager, fExpectedVersionString, 13);
  166                   return Constants.XML_VERSION_1_0;
  167               }
  168               scanner.scanChar();
  169               scanner.skipDeclSpaces();
  170               int quoteChar = scanner.scanChar();
  171               fExpectedVersionString[14] = (char) quoteChar;
  172               for (int versionPos = 0; versionPos < XML11_VERSION.length; versionPos++) {
  173                   fExpectedVersionString[15 + versionPos] = (char) scanner.scanChar();
  174               }
  175               // REVISIT:  should we check whether this equals quoteChar? 
  176               fExpectedVersionString[18] = (char) scanner.scanChar();
  177               fixupCurrentEntity(fEntityManager, fExpectedVersionString, 19);
  178               int matched = 0;
  179               for (; matched < XML11_VERSION.length; matched++) {
  180                   if (fExpectedVersionString[15 + matched] != XML11_VERSION[matched])
  181                       break;
  182               }
  183               return (matched == XML11_VERSION.length) ? 
  184                       Constants.XML_VERSION_1_1 :
  185                       Constants.XML_VERSION_1_0;
  186           }
  187           // encoding errors
  188           catch (MalformedByteSequenceException e) {
  189               fErrorReporter.reportError(e.getDomain(), e.getKey(), 
  190                   e.getArguments(), XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
  191               return Constants.XML_VERSION_ERROR;
  192           }
  193           catch (CharConversionException e) {
  194               fErrorReporter.reportError(
  195                       XMLMessageFormatter.XML_DOMAIN,
  196                       "CharConversionFailure",
  197                       null,
  198                       XMLErrorReporter.SEVERITY_FATAL_ERROR, e);
  199               return Constants.XML_VERSION_ERROR;
  200           }
  201           // premature end of file
  202           catch (EOFException e) {
  203               fErrorReporter.reportError(
  204                   XMLMessageFormatter.XML_DOMAIN,
  205                   "PrematureEOF",
  206                   null,
  207                   XMLErrorReporter.SEVERITY_FATAL_ERROR);
  208               return Constants.XML_VERSION_ERROR;
  209           }
  210       }
  211   
  212       // This method prepends "length" chars from the char array,
  213       // from offset 0, to the manager's fCurrentEntity.ch.
  214       private void fixupCurrentEntity(XMLEntityManager manager, 
  215                   char [] scannedChars, int length) {
  216           XMLEntityManager.ScannedEntity currentEntity = manager.getCurrentEntity();
  217           if(currentEntity.count-currentEntity.position+length > currentEntity.ch.length) {
  218               //resize array; this case is hard to imagine...
  219               char[] tempCh = currentEntity.ch;
  220               currentEntity.ch = new char[length+currentEntity.count-currentEntity.position+1];
  221               System.arraycopy(tempCh, 0, currentEntity.ch, 0, tempCh.length);
  222           }
  223           if(currentEntity.position < length) {
  224               // have to move sensitive stuff out of the way...
  225               System.arraycopy(currentEntity.ch, currentEntity.position, currentEntity.ch, length, currentEntity.count-currentEntity.position);
  226               currentEntity.count += length-currentEntity.position;
  227           } else {
  228               // have to reintroduce some whitespace so this parses:
  229               for(int i=length; i<currentEntity.position; i++) 
  230                   currentEntity.ch[i]=' ';
  231           }
  232           // prepend contents...
  233           System.arraycopy(scannedChars, 0, currentEntity.ch, 0, length);
  234           currentEntity.position = 0;
  235           currentEntity.baseCharOffset = 0;
  236           currentEntity.startPosition = 0;
  237           currentEntity.columnNumber = currentEntity.lineNumber = 1;
  238       }
  239   
  240   } // class XMLVersionDetector
  241   

Save This Page
Home » Xerces-J-src.2.9.1 » org.apache.xerces » impl » [javadoc | source]