예제 #1
0
  /**
   * Scans External ID and return the public and system IDs.
   *
   * @param identifiers An array of size 2 to return the system id, and public id (in that order).
   * @param optionalSystemId Specifies whether the system id is optional.
   *     <p><strong>Note:</strong> This method uses fString and fStringBuffer, anything in them at
   *     the time of calling is lost.
   */
  protected void scanExternalID(String[] identifiers, boolean optionalSystemId)
      throws IOException, XNIException {

    String systemId = null;
    String publicId = null;
    if (fEntityScanner.skipString("PUBLIC")) {
      if (!fEntityScanner.skipSpaces()) {
        reportFatalError("SpaceRequiredAfterPUBLIC", null);
      }
      scanPubidLiteral(fString);
      publicId = fString.toString();

      if (!fEntityScanner.skipSpaces() && !optionalSystemId) {
        reportFatalError("SpaceRequiredBetweenPublicAndSystem", null);
      }
    }

    if (publicId != null || fEntityScanner.skipString("SYSTEM")) {
      if (publicId == null && !fEntityScanner.skipSpaces()) {
        reportFatalError("SpaceRequiredAfterSYSTEM", null);
      }
      int quote = fEntityScanner.peekChar();
      if (quote != '\'' && quote != '"') {
        if (publicId != null && optionalSystemId) {
          // looks like we don't have any system id
          // simply return the public id
          identifiers[0] = null;
          identifiers[1] = publicId;
          return;
        }
        reportFatalError("QuoteRequiredInSystemID", null);
      }
      fEntityScanner.scanChar();
      XMLString ident = fString;
      if (fEntityScanner.scanLiteral(quote, ident) != quote) {
        fStringBuffer.clear();
        do {
          fStringBuffer.append(ident);
          int c = fEntityScanner.peekChar();
          if (XMLChar.isMarkup(c) || c == ']') {
            fStringBuffer.append((char) fEntityScanner.scanChar());
          } else if (c != -1 && isInvalidLiteral(c)) {
            reportFatalError("InvalidCharInSystemID", new Object[] {Integer.toString(c, 16)});
          }
        } while (fEntityScanner.scanLiteral(quote, ident) != quote);
        fStringBuffer.append(ident);
        ident = fStringBuffer;
      }
      systemId = ident.toString();
      if (!fEntityScanner.skipChar(quote)) {
        reportFatalError("SystemIDUnterminated", null);
      }
    }

    // store result in array
    identifiers[0] = systemId;
    identifiers[1] = publicId;
  }
예제 #2
0
  /**
   * Scans a pseudo attribute.
   *
   * @param scanningTextDecl True if scanning this pseudo-attribute for a TextDecl; false if
   *     scanning XMLDecl. This flag is needed to report the correct type of error.
   * @param value The string to fill in with the attribute value.
   * @return The name of the attribute
   *     <p><strong>Note:</strong> This method uses fStringBuffer2, anything in it at the time of
   *     calling is lost.
   */
  public String scanPseudoAttribute(boolean scanningTextDecl, XMLString value)
      throws IOException, XNIException {

    String name = scanPseudoAttributeName();
    // XMLEntityManager.print(fEntityManager.getCurrentEntity());

    if (name == null) {
      reportFatalError("PseudoAttrNameExpected", null);
    }
    fEntityScanner.skipSpaces();
    if (!fEntityScanner.skipChar('=')) {
      reportFatalError(
          scanningTextDecl ? "EqRequiredInTextDecl" : "EqRequiredInXMLDecl", new Object[] {name});
    }
    fEntityScanner.skipSpaces();
    int quote = fEntityScanner.peekChar();
    if (quote != '\'' && quote != '"') {
      reportFatalError(
          scanningTextDecl ? "QuoteRequiredInTextDecl" : "QuoteRequiredInXMLDecl",
          new Object[] {name});
    }
    fEntityScanner.scanChar();
    int c = fEntityScanner.scanLiteral(quote, value);
    if (c != quote) {
      fStringBuffer2.clear();
      do {
        fStringBuffer2.append(value);
        if (c != -1) {
          if (c == '&' || c == '%' || c == '<' || c == ']') {
            fStringBuffer2.append((char) fEntityScanner.scanChar());
          } else if (XMLChar.isHighSurrogate(c)) {
            scanSurrogates(fStringBuffer2);
          } else if (isInvalidLiteral(c)) {
            String key = scanningTextDecl ? "InvalidCharInTextDecl" : "InvalidCharInXMLDecl";
            reportFatalError(key, new Object[] {Integer.toString(c, 16)});
            fEntityScanner.scanChar();
          }
        }
        c = fEntityScanner.scanLiteral(quote, value);
      } while (c != quote);
      fStringBuffer2.append(value);
      value.setValues(fStringBuffer2);
    }
    if (!fEntityScanner.skipChar(quote)) {
      reportFatalError(
          scanningTextDecl ? "CloseQuoteMissingInTextDecl" : "CloseQuoteMissingInXMLDecl",
          new Object[] {name});
    }

    // return
    return name;
  } // scanPseudoAttribute(XMLString):String
예제 #3
0
  /**
   * Scans a processing data. This is needed to handle the situation where a document starts with a
   * processing instruction whose target name <em>starts with</em> "xml". (e.g. xmlfoo)
   *
   * <p><strong>Note:</strong> This method uses fStringBuffer, anything in it at the time of calling
   * is lost.
   *
   * @param target The PI target
   * @param data The string to fill in with the data
   */
  protected void scanPIData(String target, XMLString data) throws IOException, XNIException {

    // check target
    if (target.length() == 3) {
      char c0 = Character.toLowerCase(target.charAt(0));
      char c1 = Character.toLowerCase(target.charAt(1));
      char c2 = Character.toLowerCase(target.charAt(2));
      if (c0 == 'x' && c1 == 'm' && c2 == 'l') {
        reportFatalError("ReservedPITarget", null);
      }
    }

    // spaces
    if (!fEntityScanner.skipSpaces()) {
      if (fEntityScanner.skipString("?>")) {
        // we found the end, there is no data
        data.clear();
        return;
      } else {
        if (fNamespaces && fEntityScanner.peekChar() == ':') {
          fEntityScanner.scanChar();
          XMLStringBuffer colonName = new XMLStringBuffer(target);
          colonName.append(":");
          String str = fEntityScanner.scanName();
          if (str != null) colonName.append(str);
          reportFatalError("ColonNotLegalWithNS", new Object[] {colonName.toString()});
          fEntityScanner.skipSpaces();
        } else {
          // if there is data there should be some space
          reportFatalError("SpaceRequiredInPI", null);
        }
      }
    }

    fStringBuffer.clear();
    // data
    if (fEntityScanner.scanData("?>", fStringBuffer)) {
      do {
        int c = fEntityScanner.peekChar();
        if (c != -1) {
          if (XMLChar.isHighSurrogate(c)) {
            scanSurrogates(fStringBuffer);
          } else if (isInvalidLiteral(c)) {
            reportFatalError("InvalidCharInPI", new Object[] {Integer.toHexString(c)});
            fEntityScanner.scanChar();
          }
        }
      } while (fEntityScanner.scanData("?>", fStringBuffer));
    }
    data.setValues(fStringBuffer);
  } // scanPIData(String,XMLString)
예제 #4
0
  protected void scanPIData(String target, XMLStringBuffer data) throws IOException, XNIException {

    // check target
    if (target.length() == 3) {
      char c0 = Character.toLowerCase(target.charAt(0));
      char c1 = Character.toLowerCase(target.charAt(1));
      char c2 = Character.toLowerCase(target.charAt(2));
      if (c0 == 'x' && c1 == 'm' && c2 == 'l') {
        reportFatalError("ReservedPITarget", null);
      }
    }

    // spaces
    if (!fEntityScanner.skipSpaces()) {
      if (fEntityScanner.skipString("?>")) {
        // we found the end, there is no data just return
        return;
      } else {
        // if there is data there should be some space
        reportFatalError("SpaceRequiredInPI", null);
      }
    }

    // since scanData appends the parsed data to the buffer passed
    // a while loop would append the whole of parsed data to the buffer(data:XMLStringBuffer)
    // until all of the data is buffered.
    if (fEntityScanner.scanData("?>", data)) {
      do {
        int c = fEntityScanner.peekChar();
        if (c != -1) {
          if (XMLChar.isHighSurrogate(c)) {
            scanSurrogates(data);
          } else if (isInvalidLiteral(c)) {
            reportFatalError("InvalidCharInPI", new Object[] {Integer.toHexString(c)});
            fEntityScanner.scanChar();
          }
        }
      } while (fEntityScanner.scanData("?>", data));
    }
  } // scanPIData(String,XMLString)
예제 #5
0
  /**
   * Scans an XML or text declaration.
   *
   * <p>
   *
   * <pre>
   * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
   * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
   * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'" )
   * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
   * [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'")
   *                 | ('"' ('yes' | 'no') '"'))
   *
   * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
   * </pre>
   *
   * @param scanningTextDecl True if a text declaration is to be scanned instead of an XML
   *     declaration.
   * @param pseudoAttributeValues An array of size 3 to return the version, encoding and standalone
   *     pseudo attribute values (in that order).
   *     <p><strong>Note:</strong> This method uses fString, anything in it at the time of calling
   *     is lost.
   */
  protected void scanXMLDeclOrTextDecl(boolean scanningTextDecl, String[] pseudoAttributeValues)
      throws IOException, XNIException {

    // pseudo-attribute values
    String version = null;
    String encoding = null;
    String standalone = null;

    // scan pseudo-attributes
    final int STATE_VERSION = 0;
    final int STATE_ENCODING = 1;
    final int STATE_STANDALONE = 2;
    final int STATE_DONE = 3;
    int state = STATE_VERSION;

    boolean dataFoundForTarget = false;
    boolean sawSpace = fEntityScanner.skipSpaces();
    // since pseudoattributes are *not* attributes,
    // their quotes don't need to be preserved in external parameter entities.
    // the XMLEntityScanner#scanLiteral method will continue to
    // emit -1 in such cases when it finds a quote; this is
    // fine for other methods that parse scanned entities,
    // but not for the scanning of pseudoattributes.  So,
    // temporarily, we must mark the current entity as not being "literal"
    Entity.ScannedEntity currEnt = fEntityManager.getCurrentEntity();
    boolean currLiteral = currEnt.literal;
    currEnt.literal = false;
    while (fEntityScanner.peekChar() != '?') {
      dataFoundForTarget = true;
      String name = scanPseudoAttribute(scanningTextDecl, fString);
      switch (state) {
        case STATE_VERSION:
          {
            if (name.equals(fVersionSymbol)) {
              if (!sawSpace) {
                reportFatalError(
                    scanningTextDecl
                        ? "SpaceRequiredBeforeVersionInTextDecl"
                        : "SpaceRequiredBeforeVersionInXMLDecl",
                    null);
              }
              version = fString.toString();
              state = STATE_ENCODING;
              if (!versionSupported(version)) {
                reportFatalError("VersionNotSupported", new Object[] {version});
              }

              if (version.equals("1.1")) {
                Entity.ScannedEntity top = fEntityManager.getTopLevelEntity();
                if (top != null && (top.version == null || top.version.equals("1.0"))) {
                  reportFatalError("VersionMismatch", null);
                }
                fEntityManager.setScannerVersion(Constants.XML_VERSION_1_1);
              }

            } else if (name.equals(fEncodingSymbol)) {
              if (!scanningTextDecl) {
                reportFatalError("VersionInfoRequired", null);
              }
              if (!sawSpace) {
                reportFatalError(
                    scanningTextDecl
                        ? "SpaceRequiredBeforeEncodingInTextDecl"
                        : "SpaceRequiredBeforeEncodingInXMLDecl",
                    null);
              }
              encoding = fString.toString();
              state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;
            } else {
              if (scanningTextDecl) {
                reportFatalError("EncodingDeclRequired", null);
              } else {
                reportFatalError("VersionInfoRequired", null);
              }
            }
            break;
          }
        case STATE_ENCODING:
          {
            if (name.equals(fEncodingSymbol)) {
              if (!sawSpace) {
                reportFatalError(
                    scanningTextDecl
                        ? "SpaceRequiredBeforeEncodingInTextDecl"
                        : "SpaceRequiredBeforeEncodingInXMLDecl",
                    null);
              }
              encoding = fString.toString();
              state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;
              // TODO: check encoding name; set encoding on
              //       entity scanner
            } else if (!scanningTextDecl && name.equals(fStandaloneSymbol)) {
              if (!sawSpace) {
                reportFatalError("SpaceRequiredBeforeStandalone", null);
              }
              standalone = fString.toString();
              state = STATE_DONE;
              if (!standalone.equals("yes") && !standalone.equals("no")) {
                reportFatalError("SDDeclInvalid", new Object[] {standalone});
              }
            } else {
              reportFatalError("EncodingDeclRequired", null);
            }
            break;
          }
        case STATE_STANDALONE:
          {
            if (name.equals(fStandaloneSymbol)) {
              if (!sawSpace) {
                reportFatalError("SpaceRequiredBeforeStandalone", null);
              }
              standalone = fString.toString();
              state = STATE_DONE;
              if (!standalone.equals("yes") && !standalone.equals("no")) {
                reportFatalError("SDDeclInvalid", new Object[] {standalone});
              }
            } else {
              reportFatalError("SDDeclNameInvalid", null);
            }
            break;
          }
        default:
          {
            reportFatalError("NoMorePseudoAttributes", null);
          }
      }
      sawSpace = fEntityScanner.skipSpaces();
    }
    // restore original literal value
    if (currLiteral) {
      currEnt.literal = true;
    }
    // REVISIT: should we remove this error reporting?
    if (scanningTextDecl && state != STATE_DONE) {
      reportFatalError("MorePseudoAttributes", null);
    }

    // If there is no data in the xml or text decl then we fail to report error
    // for version or encoding info above.
    if (scanningTextDecl) {
      if (!dataFoundForTarget && encoding == null) {
        reportFatalError("EncodingDeclRequired", null);
      }
    } else {
      if (!dataFoundForTarget && version == null) {
        reportFatalError("VersionInfoRequired", null);
      }
    }

    // end
    if (!fEntityScanner.skipChar('?')) {
      reportFatalError("XMLDeclUnterminated", null);
    }
    if (!fEntityScanner.skipChar('>')) {
      reportFatalError("XMLDeclUnterminated", null);
    }

    // fill in return array
    pseudoAttributeValues[0] = version;
    pseudoAttributeValues[1] = encoding;
    pseudoAttributeValues[2] = standalone;
  } // scanXMLDeclOrTextDecl(boolean)
예제 #6
0
  /**
   * Scans an XML or text declaration.
   *
   * <p>
   *
   * <pre>
   * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
   * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
   * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'" )
   * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
   * [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'")
   *                 | ('"' ('yes' | 'no') '"'))
   *
   * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
   * </pre>
   *
   * @param scanningTextDecl True if a text declaration is to be scanned instead of an XML
   *     declaration.
   * @param pseudoAttributeValues An array of size 3 to return the version, encoding and standalone
   *     pseudo attribute values (in that order).
   *     <p><strong>Note:</strong> This method uses fString, anything in it at the time of calling
   *     is lost.
   */
  protected void scanXMLDeclOrTextDecl(boolean scanningTextDecl, String[] pseudoAttributeValues)
      throws IOException, XNIException {

    // pseudo-attribute values
    String version = null;
    String encoding = null;
    String standalone = null;

    // scan pseudo-attributes
    final int STATE_VERSION = 0;
    final int STATE_ENCODING = 1;
    final int STATE_STANDALONE = 2;
    final int STATE_DONE = 3;
    int state = STATE_VERSION;

    boolean dataFoundForTarget = false;
    boolean sawSpace = fEntityScanner.skipSpaces();
    while (fEntityScanner.peekChar() != '?') {
      dataFoundForTarget = true;
      String name = scanPseudoAttribute(scanningTextDecl, fString);
      switch (state) {
        case STATE_VERSION:
          {
            if (name.equals(fVersionSymbol)) {
              if (!sawSpace) {
                reportFatalError(
                    scanningTextDecl
                        ? "SpaceRequiredBeforeVersionInTextDecl"
                        : "SpaceRequiredBeforeVersionInXMLDecl",
                    null);
              }
              version = fString.toString();
              state = STATE_ENCODING;
              if (!versionSupported(version)) {
                reportFatalError("VersionNotSupported", new Object[] {version});
              }

              if (version.equals("1.1")) {
                Entity.ScannedEntity top = fEntityManager.getTopLevelEntity();
                if (top != null && (top.version == null || top.version.equals("1.0"))) {
                  reportFatalError("VersionMismatch", null);
                }
                fEntityManager.setScannerVersion(Constants.XML_VERSION_1_1);
              }

            } else if (name.equals(fEncodingSymbol)) {
              if (!scanningTextDecl) {
                reportFatalError("VersionInfoRequired", null);
              }
              if (!sawSpace) {
                reportFatalError(
                    scanningTextDecl
                        ? "SpaceRequiredBeforeEncodingInTextDecl"
                        : "SpaceRequiredBeforeEncodingInXMLDecl",
                    null);
              }
              encoding = fString.toString();
              state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;
            } else {
              if (scanningTextDecl) {
                reportFatalError("EncodingDeclRequired", null);
              } else {
                reportFatalError("VersionInfoRequired", null);
              }
            }
            break;
          }
        case STATE_ENCODING:
          {
            if (name.equals(fEncodingSymbol)) {
              if (!sawSpace) {
                reportFatalError(
                    scanningTextDecl
                        ? "SpaceRequiredBeforeEncodingInTextDecl"
                        : "SpaceRequiredBeforeEncodingInXMLDecl",
                    null);
              }
              encoding = fString.toString();
              state = scanningTextDecl ? STATE_DONE : STATE_STANDALONE;
              // TODO: check encoding name; set encoding on
              //       entity scanner
            } else if (!scanningTextDecl && name.equals(fStandaloneSymbol)) {
              if (!sawSpace) {
                reportFatalError("SpaceRequiredBeforeStandalone", null);
              }
              standalone = fString.toString();
              state = STATE_DONE;
              if (!standalone.equals("yes") && !standalone.equals("no")) {
                reportFatalError("SDDeclInvalid", new Object[] {standalone});
              }
            } else {
              reportFatalError("EncodingDeclRequired", null);
            }
            break;
          }
        case STATE_STANDALONE:
          {
            if (name.equals(fStandaloneSymbol)) {
              if (!sawSpace) {
                reportFatalError("SpaceRequiredBeforeStandalone", null);
              }
              standalone = fString.toString();
              state = STATE_DONE;
              if (!standalone.equals("yes") && !standalone.equals("no")) {
                reportFatalError("SDDeclInvalid", new Object[] {standalone});
              }
            } else {
              reportFatalError("EncodingDeclRequired", null);
            }
            break;
          }
        default:
          {
            reportFatalError("NoMorePseudoAttributes", null);
          }
      }
      sawSpace = fEntityScanner.skipSpaces();
    }
    // REVISIT: should we remove this error reporting?
    if (scanningTextDecl && state != STATE_DONE) {
      reportFatalError("MorePseudoAttributes", null);
    }

    // If there is no data in the xml or text decl then we fail to report error
    // for version or encoding info above.
    if (scanningTextDecl) {
      if (!dataFoundForTarget && encoding == null) {
        reportFatalError("EncodingDeclRequired", null);
      }
    } else {
      if (!dataFoundForTarget && version == null) {
        reportFatalError("VersionInfoRequired", null);
      }
    }

    // end
    if (!fEntityScanner.skipChar('?')) {
      reportFatalError("XMLDeclUnterminated", null);
    }
    if (!fEntityScanner.skipChar('>')) {
      reportFatalError("XMLDeclUnterminated", null);
    }

    // fill in return array
    pseudoAttributeValues[0] = version;
    pseudoAttributeValues[1] = encoding;
    pseudoAttributeValues[2] = standalone;
  } // scanXMLDeclOrTextDecl(boolean)