/** * This method notifies of the start of an entity. The document entity has the pseudo-name of * "[xml]" the DTD has the pseudo-name of "[dtd]" parameter entity names start with '%'; and * general entities are just specified by their name. * * @param name The name of the entity. * @param identifier The resource identifier. * @param encoding The auto-detected IANA encoding name of the entity stream. This value will be * null in those situations where the entity encoding is not auto-detected (e.g. internal * entities or a document entity that is parsed from a java.io.Reader). * @throws XNIException Thrown by handler to signal an error. */ public void startEntity( String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) throws XNIException { // keep track of the entity depth fEntityDepth++; // must reset entity scanner fEntityScanner = fEntityManager.getEntityScanner(); fEntityStore = fEntityManager.getEntityStore(); } // startEntity(String,XMLResourceIdentifier,String)
/** * @param componentManager The component manager. * @throws SAXException Throws exception if required features and properties cannot be found. */ public void reset(XMLComponentManager componentManager) throws XMLConfigurationException { fParserSettings = componentManager.getFeature(PARSER_SETTINGS, true); if (!fParserSettings) { // parser settings have not been changed init(); return; } // Xerces properties fSymbolTable = (SymbolTable) componentManager.getProperty(SYMBOL_TABLE); fErrorReporter = (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER); fEntityManager = (XMLEntityManager) componentManager.getProperty(ENTITY_MANAGER); fSecurityManager = (XMLSecurityManager) componentManager.getProperty(SECURITY_MANAGER); // this step is extra because we have separated the storage of entity fEntityStore = fEntityManager.getEntityStore(); // sax features fValidation = componentManager.getFeature(VALIDATION, false); fNamespaces = componentManager.getFeature(NAMESPACES, true); fNotifyCharRefs = componentManager.getFeature(NOTIFY_CHAR_REFS, false); init(); } // reset(XMLComponentManager)
public void reset(PropertyManager propertyManager) { init(); // Xerces properties fSymbolTable = (SymbolTable) propertyManager.getProperty( Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY); fErrorReporter = (XMLErrorReporter) propertyManager.getProperty( Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY); fEntityManager = (XMLEntityManager) propertyManager.getProperty(ENTITY_MANAGER); fEntityStore = fEntityManager.getEntityStore(); fEntityScanner = (XMLEntityScanner) fEntityManager.getEntityScanner(); // fEntityManager.reset(); // DTD preparsing defaults: fValidation = false; fNotifyCharRefs = false; }
/** * Scans an attribute value and normalizes whitespace converting all whitespace characters to * space characters. * * <p>[10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'" * * @param value The XMLString to fill in with the value. * @param nonNormalizedValue The XMLString to fill in with the non-normalized value. * @param atName The name of the attribute being parsed (for error msgs). * @param checkEntities true if undeclared entities should be reported as VC violation, false if * undeclared entities should be reported as WFC violation. * @param eleName The name of element to which this attribute belongs. * <p><strong>Note:</strong> This method uses fStringBuffer2, anything in it at the time of * calling is lost. */ protected void scanAttributeValue( XMLString value, XMLString nonNormalizedValue, String atName, boolean checkEntities, String eleName) throws IOException, XNIException { // quote int quote = fEntityScanner.peekChar(); if (quote != '\'' && quote != '"') { reportFatalError("OpenQuoteExpected", new Object[] {eleName, atName}); } fEntityScanner.scanChar(); int entityDepth = fEntityDepth; int c = fEntityScanner.scanLiteral(quote, value); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** scanLiteral -> \"" + value.toString() + "\""); } fStringBuffer2.clear(); fStringBuffer2.append(value); normalizeWhitespace(value); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** normalizeWhitespace -> \"" + value.toString() + "\""); } if (c != quote) { fScanningAttribute = true; fStringBuffer.clear(); do { fStringBuffer.append(value); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** value2: \"" + fStringBuffer.toString() + "\""); } if (c == '&') { fEntityScanner.skipChar('&'); if (entityDepth == fEntityDepth) { fStringBuffer2.append('&'); } if (fEntityScanner.skipChar('#')) { if (entityDepth == fEntityDepth) { fStringBuffer2.append('#'); } int ch = scanCharReferenceValue(fStringBuffer, fStringBuffer2); if (ch != -1) { if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** value3: \"" + fStringBuffer.toString() + "\""); } } } else { String entityName = fEntityScanner.scanName(); if (entityName == null) { reportFatalError("NameRequiredInReference", null); } else if (entityDepth == fEntityDepth) { fStringBuffer2.append(entityName); } if (!fEntityScanner.skipChar(';')) { reportFatalError("SemicolonRequiredInReference", new Object[] {entityName}); } else if (entityDepth == fEntityDepth) { fStringBuffer2.append(';'); } if (entityName == fAmpSymbol) { fStringBuffer.append('&'); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** value5: \"" + fStringBuffer.toString() + "\""); } } else if (entityName == fAposSymbol) { fStringBuffer.append('\''); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** value7: \"" + fStringBuffer.toString() + "\""); } } else if (entityName == fLtSymbol) { fStringBuffer.append('<'); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** value9: \"" + fStringBuffer.toString() + "\""); } } else if (entityName == fGtSymbol) { fStringBuffer.append('>'); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** valueB: \"" + fStringBuffer.toString() + "\""); } } else if (entityName == fQuotSymbol) { fStringBuffer.append('"'); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** valueD: \"" + fStringBuffer.toString() + "\""); } } else { if (fEntityManager.isExternalEntity(entityName)) { reportFatalError("ReferenceToExternalEntity", new Object[] {entityName}); } else { if (!fEntityManager.isDeclaredEntity(entityName)) { // WFC & VC: Entity Declared if (checkEntities) { if (fValidation) { fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN, "EntityNotDeclared", new Object[] {entityName}, XMLErrorReporter.SEVERITY_ERROR); } } else { reportFatalError("EntityNotDeclared", new Object[] {entityName}); } } fEntityManager.startEntity(entityName, true); } } } } else if (c == '<') { reportFatalError("LessthanInAttValue", new Object[] {eleName, atName}); fEntityScanner.scanChar(); if (entityDepth == fEntityDepth) { fStringBuffer2.append((char) c); } } else if (c == '%' || c == ']') { fEntityScanner.scanChar(); fStringBuffer.append((char) c); if (entityDepth == fEntityDepth) { fStringBuffer2.append((char) c); } if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** valueF: \"" + fStringBuffer.toString() + "\""); } } else if (c == '\n' || c == '\r') { fEntityScanner.scanChar(); fStringBuffer.append(' '); if (entityDepth == fEntityDepth) { fStringBuffer2.append('\n'); } } else if (c != -1 && XMLChar.isHighSurrogate(c)) { fStringBuffer3.clear(); if (scanSurrogates(fStringBuffer3)) { fStringBuffer.append(fStringBuffer3); if (entityDepth == fEntityDepth) { fStringBuffer2.append(fStringBuffer3); } if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** valueI: \"" + fStringBuffer.toString() + "\""); } } } else if (c != -1 && isInvalidLiteral(c)) { reportFatalError( "InvalidCharInAttValue", new Object[] {eleName, atName, Integer.toString(c, 16)}); fEntityScanner.scanChar(); if (entityDepth == fEntityDepth) { fStringBuffer2.append((char) c); } } c = fEntityScanner.scanLiteral(quote, value); if (entityDepth == fEntityDepth) { fStringBuffer2.append(value); } normalizeWhitespace(value); } while (c != quote || entityDepth != fEntityDepth); fStringBuffer.append(value); if (DEBUG_ATTR_NORMALIZATION) { System.out.println("** valueN: \"" + fStringBuffer.toString() + "\""); } value.setValues(fStringBuffer); fScanningAttribute = false; } nonNormalizedValue.setValues(fStringBuffer2); // quote int cquote = fEntityScanner.scanChar(); if (cquote != quote) { reportFatalError("CloseQuoteExpected", new Object[] {eleName, atName}); } } // scanAttributeValue()
/** * 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 { // REVISIT: This method is used for generic scanning of // pseudo attributes, but since there are only three such // attributes: version, encoding, and standalone there are // for performant ways of scanning them. Every decl must // have a version, and in TextDecls this version must // be followed by an encoding declaration. Also the // methods we invoke on the scanners allow non-ASCII // characters to be parsed in the decls, but since // we don't even know what the actual encoding of the // document is until we scan the encoding declaration // you cannot reliably read any characters outside // of the ASCII range here. -- mrglavas String name = fEntityScanner.scanName(); XMLEntityManager.print(fEntityManager.getCurrentEntity()); if (name == null) { reportFatalError("PseudoAttrNameExpected", null); } fEntityScanner.skipDeclSpaces(); if (!fEntityScanner.skipChar('=')) { reportFatalError( scanningTextDecl ? "EqRequiredInTextDecl" : "EqRequiredInXMLDecl", new Object[] {name}); } fEntityScanner.skipDeclSpaces(); 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()); } // REVISIT: Even if you could reliably read non-ASCII chars // why bother scanning for surrogates here? Only ASCII chars // match the productions in XMLDecls and TextDecls. -- mrglavas 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
/** * 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.skipDeclSpaces(); // 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" XMLEntityManager.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 == fVersionSymbol) { if (!sawSpace) { reportFatalError( scanningTextDecl ? "SpaceRequiredBeforeVersionInTextDecl" : "SpaceRequiredBeforeVersionInXMLDecl", null); } version = fString.toString(); state = STATE_ENCODING; if (!versionSupported(version)) { reportFatalError(getVersionNotSupportedKey(), new Object[] {version}); } } else if (name == 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 == 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 == 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 == 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.skipDeclSpaces(); } // 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)
/** * 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)