/* * reserved comment block * DO NOT REMOVE OR ALTER! */ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.sun.org.apache.xerces.internal.xpointer; import java.util.ArrayList; import java.util.HashMap; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; import com.sun.org.apache.xerces.internal.util.SymbolTable; import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLSymbols; import com.sun.org.apache.xerces.internal.xinclude.XIncludeHandler; import com.sun.org.apache.xerces.internal.xinclude.XIncludeNamespaceSupport; import com.sun.org.apache.xerces.internal.xni.Augmentations; import com.sun.org.apache.xerces.internal.xni.QName; import com.sun.org.apache.xerces.internal.xni.XMLAttributes; import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; import com.sun.org.apache.xerces.internal.xni.XMLString; import com.sun.org.apache.xerces.internal.xni.XNIException; import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler; /** *

* This is a pipeline component which extends the XIncludeHandler to perform * XPointer specific processing specified in the W3C XPointerFramework and * element() Scheme Recommendations. *

* *

* This component analyzes each event in the pipeline, looking for an element * that matches a PointerPart in the parent XInclude element's xpointer attribute * value. If the match succeeds, all children are passed by this component. *

* *

* See the XPointer Framework Recommendation for * more information on the XPointer Framework and ShortHand Pointers. * See the XPointer element() Scheme Recommendation for * more information on the XPointer element() Scheme. *

* * @xerces.internal * */ public final class XPointerHandler extends XIncludeHandler implements XPointerProcessor { // Fields // An ArrayList of XPointerParts protected ArrayList fXPointerParts = null; // The current XPointerPart protected XPointerPart fXPointerPart = null; // Has the fXPointerPart resolved successfully protected boolean fFoundMatchingPtrPart = false; // The XPointer Error reporter protected XMLErrorReporter fXPointerErrorReporter; // The XPointer Error Handler protected XMLErrorHandler fErrorHandler; // XPointerFramework symbol table protected SymbolTable fSymbolTable = null; // Supported schemes private final String ELEMENT_SCHEME_NAME = "element"; // Has the XPointer resolved the subresource protected boolean fIsXPointerResolved = false; // Fixup xml:base and xml:lang attributes protected boolean fFixupBase = false; protected boolean fFixupLang = false; // ************************************************************************ // Constructors // ************************************************************************ /** * */ public XPointerHandler() { super(); fXPointerParts = new ArrayList<>(); fSymbolTable = new SymbolTable(); } public XPointerHandler(SymbolTable symbolTable, XMLErrorHandler errorHandler, XMLErrorReporter errorReporter) { super(); fXPointerParts = new ArrayList<>(); fSymbolTable = symbolTable; fErrorHandler = errorHandler; fXPointerErrorReporter = errorReporter; //fErrorReporter = errorReporter; // The XInclude ErrorReporter } public void setDocumentHandler(XMLDocumentHandler handler) { fDocumentHandler = handler; } // ************************************************************************ // Implementation of the XPointerProcessor interface. // ************************************************************************ /** * Parses the XPointer framework expression and delegates scheme specific parsing. * * @see com.sun.org.apache.xerces.internal.xpointer.XPointerProcessor#parseXPointer(java.lang.String) */ public void parseXPointer(String xpointer) throws XNIException { // Initialize init(); // tokens final Tokens tokens = new Tokens(fSymbolTable); // scanner Scanner scanner = new Scanner(fSymbolTable) { protected void addToken(Tokens tokens, int token) throws XNIException { if (token == Tokens.XPTRTOKEN_OPEN_PAREN || token == Tokens.XPTRTOKEN_CLOSE_PAREN || token == Tokens.XPTRTOKEN_SCHEMENAME || token == Tokens.XPTRTOKEN_SCHEMEDATA || token == Tokens.XPTRTOKEN_SHORTHAND) { super.addToken(tokens, token); return; } reportError("InvalidXPointerToken", new Object[] { tokens .getTokenString(token) }); } }; // scan the XPointer expression int length = xpointer.length(); boolean success = scanner.scanExpr(fSymbolTable, tokens, xpointer, 0, length); if (!success) reportError("InvalidXPointerExpression", new Object[] { xpointer }); while (tokens.hasMore()) { int token = tokens.nextToken(); switch (token) { case Tokens.XPTRTOKEN_SHORTHAND: { // The shortHand name token = tokens.nextToken(); String shortHandPointerName = tokens.getTokenString(token); if (shortHandPointerName == null) { reportError("InvalidXPointerExpression", new Object[] { xpointer }); } XPointerPart shortHandPointer = new ShortHandPointer( fSymbolTable); shortHandPointer.setSchemeName(shortHandPointerName); fXPointerParts.add(shortHandPointer); break; } case Tokens.XPTRTOKEN_SCHEMENAME: { // Retreive the local name and prefix to form the scheme name token = tokens.nextToken(); String prefix = tokens.getTokenString(token); token = tokens.nextToken(); String localName = tokens.getTokenString(token); String schemeName = prefix + localName; // The next character should be an open parenthesis int openParenCount = 0; int closeParenCount = 0; token = tokens.nextToken(); String openParen = tokens.getTokenString(token); if (openParen != "XPTRTOKEN_OPEN_PAREN") { // can not have more than one ShortHand Pointer if (token == Tokens.XPTRTOKEN_SHORTHAND) { reportError("MultipleShortHandPointers", new Object[] { xpointer }); } else { reportError("InvalidXPointerExpression", new Object[] { xpointer }); } } openParenCount++; // followed by zero or more ( and the schemeData String schemeData = null; while (tokens.hasMore()) { token = tokens.nextToken(); schemeData = tokens.getTokenString(token); if (schemeData != "XPTRTOKEN_OPEN_PAREN") { break; } openParenCount++; } token = tokens.nextToken(); schemeData = tokens.getTokenString(token); // followed by the same number of ) token = tokens.nextToken(); String closeParen = tokens.getTokenString(token); if (closeParen != "XPTRTOKEN_CLOSE_PAREN") { reportError("SchemeDataNotFollowedByCloseParenthesis", new Object[] { xpointer }); } closeParenCount++; while (tokens.hasMore()) { if (tokens.getTokenString(tokens.peekToken()) != "XPTRTOKEN_OPEN_PAREN") { break; } closeParenCount++; } // check if the number of open parenthesis are equal to the number of close parenthesis if (openParenCount != closeParenCount) { reportError("UnbalancedParenthesisInXPointerExpression", new Object[] { xpointer, new Integer(openParenCount), new Integer(closeParenCount) }); } // Perform scheme specific parsing of the pointer part if (schemeName.equals(ELEMENT_SCHEME_NAME)) { XPointerPart elementSchemePointer = new ElementSchemePointer( fSymbolTable, fErrorReporter); elementSchemePointer.setSchemeName(schemeName); elementSchemePointer.setSchemeData(schemeData); // If an exception occurs while parsing the element() scheme expression // ignore it and move on to the next pointer part try { elementSchemePointer.parseXPointer(schemeData); fXPointerParts.add(elementSchemePointer); } catch (XNIException e) { // Re-throw the XPointer element() scheme syntax error. throw new XNIException (e); } } else { // ???? reportWarning("SchemeUnsupported", new Object[] { schemeName }); } break; } default: reportError("InvalidXPointerExpression", new Object[] { xpointer }); } } } /** * * @see com.sun.org.apache.xerces.internal.xpointer.XPointerProcessor#resolveXPointer(com.sun.org.apache.xerces.internal.xni.QName, com.sun.org.apache.xerces.internal.xni.XMLAttributes, com.sun.org.apache.xerces.internal.xni.Augmentations, int event) */ public boolean resolveXPointer(QName element, XMLAttributes attributes, Augmentations augs, int event) throws XNIException { boolean resolved = false; // The result of the first pointer part whose evaluation identifies // one or more subresources is reported by the XPointer processor as the // result of the pointer as a whole, and evaluation stops. // In our implementation, typically the first xpointer scheme that // matches an element is the document is considered. // If the pointer part resolved then use it, else search for the fragment // using next pointer part from lef-right. if (!fFoundMatchingPtrPart) { // for each element, attempt to resolve it against each pointer part // in the XPointer expression until a matching element is found. for (int i = 0; i < fXPointerParts.size(); i++) { fXPointerPart = fXPointerParts.get(i); if (fXPointerPart.resolveXPointer(element, attributes, augs, event)) { fFoundMatchingPtrPart = true; resolved = true; } } } else { if (fXPointerPart.resolveXPointer(element, attributes, augs, event)) { resolved = true; } } if (!fIsXPointerResolved) { fIsXPointerResolved = resolved; } return resolved; } /** * Returns true if the Node fragment is resolved. * * @see com.sun.org.apache.xerces.internal.xpointer.XPointerProcessor#isFragmentResolved() */ public boolean isFragmentResolved() throws XNIException { boolean resolved = (fXPointerPart != null) ? fXPointerPart.isFragmentResolved() : false; if (!fIsXPointerResolved) { fIsXPointerResolved = resolved; } return resolved; } /** * Returns true if the XPointer expression resolves to a non-element child * of the current resource fragment. * * @see com.sun.org.apache.xerces.internal.xpointer.XPointerPart#isChildFragmentResolved() * */ public boolean isChildFragmentResolved() throws XNIException { boolean resolved = (fXPointerPart != null) ? fXPointerPart .isChildFragmentResolved() : false; return resolved; } /** * Returns true if the XPointer successfully found a sub-resource . * * @see com.sun.org.apache.xerces.internal.xpointer.XPointerProcessor#isFragmentResolved() */ public boolean isXPointerResolved() throws XNIException { return fIsXPointerResolved; } /** * Returns the pointer part used to resolve the document fragment. * * @return String - The pointer part used to resolve the document fragment. */ public XPointerPart getXPointerPart() { return fXPointerPart; } /** * Reports XPointer Errors * */ private void reportError(String key, Object[] arguments) throws XNIException { /* fXPointerErrorReporter.reportError( XPointerMessageFormatter.XPOINTER_DOMAIN, key, arguments, XMLErrorReporter.SEVERITY_ERROR); */ throw new XNIException((fErrorReporter .getMessageFormatter(XPointerMessageFormatter.XPOINTER_DOMAIN)) .formatMessage(fErrorReporter.getLocale(), key, arguments)); } /** * Reports XPointer Warnings * */ private void reportWarning(String key, Object[] arguments) throws XNIException { fXPointerErrorReporter.reportError( XPointerMessageFormatter.XPOINTER_DOMAIN, key, arguments, XMLErrorReporter.SEVERITY_WARNING); } /** * Initializes error handling objects * */ protected void initErrorReporter() { if (fXPointerErrorReporter == null) { fXPointerErrorReporter = new XMLErrorReporter(); } if (fErrorHandler == null) { fErrorHandler = new XPointerErrorHandler(); } /* fXPointerErrorReporter.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY, fErrorHandler); */ fXPointerErrorReporter.putMessageFormatter( XPointerMessageFormatter.XPOINTER_DOMAIN, new XPointerMessageFormatter()); } /** * Initializes the XPointer Processor; */ protected void init() { fXPointerParts.clear(); fXPointerPart = null; fFoundMatchingPtrPart = false; fIsXPointerResolved = false; //fFixupBase = false; //fFixupLang = false; initErrorReporter(); } /** * Returns an ArrayList of XPointerPart objects * * @return An ArrayList of XPointerPart objects. */ public ArrayList getPointerParts() { return fXPointerParts; } /** * List of XPointer Framework tokens. * * @xerces.internal * */ private final class Tokens { /** * XPointer Framework tokens * [1] Pointer ::= Shorthand | SchemeBased * [2] Shorthand ::= NCName * [3] SchemeBased ::= PointerPart (S? PointerPart)* * [4] PointerPart ::= SchemeName '(' SchemeData ')' * [5] SchemeName ::= QName * [6] SchemeData ::= EscapedData* * [7] EscapedData ::= NormalChar | '^(' | '^)' | '^^' | '(' SchemeData ')' * [8] NormalChar ::= UnicodeChar - [()^] * [9] UnicodeChar ::= [#x0-#x10FFFF] * */ private static final int XPTRTOKEN_OPEN_PAREN = 0, XPTRTOKEN_CLOSE_PAREN = 1, XPTRTOKEN_SHORTHAND = 2, XPTRTOKEN_SCHEMENAME = 3, XPTRTOKEN_SCHEMEDATA = 4; // Token names private final String[] fgTokenNames = { "XPTRTOKEN_OPEN_PAREN", "XPTRTOKEN_CLOSE_PAREN", "XPTRTOKEN_SHORTHAND", "XPTRTOKEN_SCHEMENAME", "XPTRTOKEN_SCHEMEDATA" }; // Token count private static final int INITIAL_TOKEN_COUNT = 1 << 8; private int[] fTokens = new int[INITIAL_TOKEN_COUNT]; private int fTokenCount = 0; // Current token position private int fCurrentTokenIndex; private SymbolTable fSymbolTable; private HashMap fTokenNames = new HashMap<>(); /** * Constructor * * @param symbolTable SymbolTable */ private Tokens(SymbolTable symbolTable) { fSymbolTable = symbolTable; fTokenNames.put(new Integer(XPTRTOKEN_OPEN_PAREN), "XPTRTOKEN_OPEN_PAREN"); fTokenNames.put(new Integer(XPTRTOKEN_CLOSE_PAREN), "XPTRTOKEN_CLOSE_PAREN"); fTokenNames.put(new Integer(XPTRTOKEN_SHORTHAND), "XPTRTOKEN_SHORTHAND"); fTokenNames.put(new Integer(XPTRTOKEN_SCHEMENAME), "XPTRTOKEN_SCHEMENAME"); fTokenNames.put(new Integer(XPTRTOKEN_SCHEMEDATA), "XPTRTOKEN_SCHEMEDATA"); } /** * Returns the token String * @param token The index of the token * @return String The token string */ private String getTokenString(int token) { return fTokenNames.get(new Integer(token)); } /** * Add the specified string as a token * * @param token The token string */ private void addToken(String tokenStr) { String str = fTokenNames.get(tokenStr); Integer tokenInt = str == null ? null : Integer.parseInt(str); if (tokenInt == null) { tokenInt = new Integer(fTokenNames.size()); fTokenNames.put(tokenInt, tokenStr); } addToken(tokenInt.intValue()); } /** * Add the specified int token * * @param token The int specifying the token */ private void addToken(int token) { try { fTokens[fTokenCount] = token; } catch (ArrayIndexOutOfBoundsException ex) { int[] oldList = fTokens; fTokens = new int[fTokenCount << 1]; System.arraycopy(oldList, 0, fTokens, 0, fTokenCount); fTokens[fTokenCount] = token; } fTokenCount++; } /** * Resets the current position to the head of the token list. */ private void rewind() { fCurrentTokenIndex = 0; } /** * Returns true if the {@link #getNextToken()} method * returns a valid token. */ private boolean hasMore() { return fCurrentTokenIndex < fTokenCount; } /** * Obtains the token at the current position, then advance * the current position by one. * * throws If there's no such next token, this method throws * new XNIException("XPointerProcessingError");. */ private int nextToken() throws XNIException { if (fCurrentTokenIndex == fTokenCount) { reportError("XPointerProcessingError", null); } return fTokens[fCurrentTokenIndex++]; } /** * Obtains the token at the current position, without advancing * the current position. * * If there's no such next token, this method throws * new XNIException("XPointerProcessingError");. */ private int peekToken() throws XNIException { if (fCurrentTokenIndex == fTokenCount) { reportError("XPointerProcessingError", null); } return fTokens[fCurrentTokenIndex]; } /** * Obtains the token at the current position as a String. * * If there's no current token or if the current token * is not a string token, this method throws * If there's no such next token, this method throws * new XNIException("XPointerProcessingError");. */ private String nextTokenAsString() throws XNIException { String tokenStrint = getTokenString(nextToken()); if (tokenStrint == null) { reportError("XPointerProcessingError", null); } return tokenStrint; } } /** * * The XPointer expression scanner. Scans the XPointer framework expression. * * @xerces.internal * */ private class Scanner { /** * 7-bit ASCII subset * * 0 1 2 3 4 5 6 7 8 9 A B C D E F * 0, 0, 0, 0, 0, 0, 0, 0, 0, HT, LF, 0, 0, CR, 0, 0, // 0 * 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 * SP, !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, // 2 * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, :, ;, <, =, >, ?, // 3 * @, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, // 4 * P, Q, R, S, T, U, V, W, X, Y, Z, [, \, ], ^, _, // 5 * `, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, // 6 * p, q, r, s, t, u, v, w, x, y, z, {, |, }, ~, DEL // 7 */ private static final byte CHARTYPE_INVALID = 0, // invalid XML character CHARTYPE_OTHER = 1, // not special - one of "#%&;?\`{}~" or DEL CHARTYPE_WHITESPACE = 2, // one of "\t\n\r " (0x09, 0x0A, 0x0D, 0x20) CHARTYPE_CARRET = 3, // ^ CHARTYPE_OPEN_PAREN = 4, // '(' (0x28) CHARTYPE_CLOSE_PAREN = 5, // ')' (0x29) CHARTYPE_MINUS = 6, // '-' (0x2D) CHARTYPE_PERIOD = 7, // '.' (0x2E) CHARTYPE_SLASH = 8, // '/' (0x2F) CHARTYPE_DIGIT = 9, // '0'-'9' (0x30 to 0x39) CHARTYPE_COLON = 10, // ':' (0x3A) CHARTYPE_EQUAL = 11, // '=' (0x3D) CHARTYPE_LETTER = 12, // 'A'-'Z' or 'a'-'z' (0x41 to 0x5A and 0x61 to 0x7A) CHARTYPE_UNDERSCORE = 13, // '_' (0x5F) CHARTYPE_NONASCII = 14; // Non-ASCII Unicode codepoint (>= 0x80) private final byte[] fASCIICharMap = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 4, 5, 1, 1, 1, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 1, 1, 11, 1, 1, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 1, 3, 13, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 1, 1, 1 }; // // Data // /** Symbol table. */ private SymbolTable fSymbolTable; /** * Constructs an XPointer Framework expression scanner. * * @param symbolTable SymbolTable */ private Scanner(SymbolTable symbolTable) { // save pool and tokens fSymbolTable = symbolTable; } // (SymbolTable) /** * Scans the XPointer Expression * */ private boolean scanExpr(SymbolTable symbolTable, Tokens tokens, String data, int currentOffset, int endOffset) throws XNIException { int ch; int openParen = 0; int closeParen = 0; int nameOffset, dataOffset; boolean isQName = false; String name = null; String prefix = null; String schemeData = null; StringBuffer schemeDataBuff = new StringBuffer(); while (true) { if (currentOffset == endOffset) { break; } ch = data.charAt(currentOffset); // while (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D) { if (++currentOffset == endOffset) { break; } ch = data.charAt(currentOffset); } if (currentOffset == endOffset) { break; } // // [1] Pointer ::= Shorthand | SchemeBased // [2] Shorthand ::= NCName // [3] SchemeBased ::= PointerPart (S? PointerPart)* // [4] PointerPart ::= SchemeName '(' SchemeData ')' // [5] SchemeName ::= QName // [6] SchemeData ::= EscapedData* // [7] EscapedData ::= NormalChar | '^(' | '^)' | '^^' | '(' SchemeData ')' // [8] NormalChar ::= UnicodeChar - [()^] // [9] UnicodeChar ::= [#x0-#x10FFFF] // [?] QName ::= (NCName ':')? NCName // [?] NCName ::= (Letter | '_') (NCNameChar)* // [?] NCNameChar ::= Letter | Digit | '.' | '-' | '_' (ascii subset of 'NCNameChar') // [?] Letter ::= [A-Za-z] (ascii subset of 'Letter') // [?] Digit ::= [0-9] (ascii subset of 'Digit') // byte chartype = (ch >= 0x80) ? CHARTYPE_NONASCII : fASCIICharMap[ch]; switch (chartype) { case CHARTYPE_OPEN_PAREN: // '(' addToken(tokens, Tokens.XPTRTOKEN_OPEN_PAREN); openParen++; ++currentOffset; break; case CHARTYPE_CLOSE_PAREN: // ')' addToken(tokens, Tokens.XPTRTOKEN_CLOSE_PAREN); closeParen++; ++currentOffset; break; case CHARTYPE_CARRET: case CHARTYPE_COLON: case CHARTYPE_DIGIT: case CHARTYPE_EQUAL: case CHARTYPE_LETTER: case CHARTYPE_MINUS: case CHARTYPE_NONASCII: case CHARTYPE_OTHER: case CHARTYPE_PERIOD: case CHARTYPE_SLASH: case CHARTYPE_UNDERSCORE: case CHARTYPE_WHITESPACE: // Scanning SchemeName | Shorthand if (openParen == 0) { nameOffset = currentOffset; currentOffset = scanNCName(data, endOffset, currentOffset); if (currentOffset == nameOffset) { reportError("InvalidShortHandPointer", new Object[] { data }); return false; } if (currentOffset < endOffset) { ch = data.charAt(currentOffset); } else { ch = -1; } name = symbolTable.addSymbol(data.substring(nameOffset, currentOffset)); prefix = XMLSymbols.EMPTY_STRING; // The name is a QName => a SchemeName if (ch == ':') { if (++currentOffset == endOffset) { return false; } ch = data.charAt(currentOffset); prefix = name; nameOffset = currentOffset; currentOffset = scanNCName(data, endOffset, currentOffset); if (currentOffset == nameOffset) { return false; } if (currentOffset < endOffset) { ch = data.charAt(currentOffset); } else { ch = -1; } isQName = true; name = symbolTable.addSymbol(data.substring( nameOffset, currentOffset)); } // REVISIT: if (currentOffset != endOffset) { addToken(tokens, Tokens.XPTRTOKEN_SCHEMENAME); tokens.addToken(prefix); tokens.addToken(name); isQName = false; } else if (currentOffset == endOffset) { // NCName => Shorthand addToken(tokens, Tokens.XPTRTOKEN_SHORTHAND); tokens.addToken(name); isQName = false; } // reset open/close paren for the next pointer part closeParen = 0; break; } else if (openParen > 0 && closeParen == 0 && name != null) { // Scanning SchemeData dataOffset = currentOffset; currentOffset = scanData(data, schemeDataBuff, endOffset, currentOffset); if (currentOffset == dataOffset) { reportError("InvalidSchemeDataInXPointer", new Object[] { data }); return false; } if (currentOffset < endOffset) { ch = data.charAt(currentOffset); } else { ch = -1; } schemeData = symbolTable.addSymbol(schemeDataBuff .toString()); addToken(tokens, Tokens.XPTRTOKEN_SCHEMEDATA); tokens.addToken(schemeData); // reset open/close paren for the next pointer part openParen = 0; schemeDataBuff.delete(0, schemeDataBuff.length()); } else { // ex. schemeName() // Should we throw an exception with a more suitable message instead?? return false; } } } // end while return true; } /** * Scans a NCName. * From Namespaces in XML * [5] NCName ::= (Letter | '_') (NCNameChar)* * [6] NCNameChar ::= Letter | Digit | '.' | '-' | '_' | CombiningChar | Extender * * @param data A String containing the XPointer expression * @param endOffset The int XPointer expression length * @param currentOffset An int representing the current position of the XPointer expression pointer */ private int scanNCName(String data, int endOffset, int currentOffset) { int ch = data.charAt(currentOffset); if (ch >= 0x80) { if (!XMLChar.isNameStart(ch)) { return currentOffset; } } else { byte chartype = fASCIICharMap[ch]; if (chartype != CHARTYPE_LETTER && chartype != CHARTYPE_UNDERSCORE) { return currentOffset; } } //while (currentOffset++ < endOffset) { while (++currentOffset < endOffset) { ch = data.charAt(currentOffset); if (ch >= 0x80) { if (!XMLChar.isName(ch)) { break; } } else { byte chartype = fASCIICharMap[ch]; if (chartype != CHARTYPE_LETTER && chartype != CHARTYPE_DIGIT && chartype != CHARTYPE_PERIOD && chartype != CHARTYPE_MINUS && chartype != CHARTYPE_UNDERSCORE) { break; } } } return currentOffset; } /** * Scans the SchemeData. * [6] SchemeData ::= EscapedData* * [7] EscapedData ::= NormalChar | '^(' | '^)' | '^^' | '(' SchemeData ')' * [8] NormalChar ::= UnicodeChar - [()^] * [9] UnicodeChar ::= [#x0-#x10FFFF] * */ private int scanData(String data, StringBuffer schemeData, int endOffset, int currentOffset) { while (true) { if (currentOffset == endOffset) { break; } int ch = data.charAt(currentOffset); byte chartype = (ch >= 0x80) ? CHARTYPE_NONASCII : fASCIICharMap[ch]; if (chartype == CHARTYPE_OPEN_PAREN) { schemeData.append(ch); //schemeData.append(Tokens.XPTRTOKEN_OPEN_PAREN); currentOffset = scanData(data, schemeData, endOffset, ++currentOffset); if (currentOffset == endOffset) { return currentOffset; } ch = data.charAt(currentOffset); chartype = (ch >= 0x80) ? CHARTYPE_NONASCII : fASCIICharMap[ch]; if (chartype != CHARTYPE_CLOSE_PAREN) { return endOffset; } schemeData.append((char) ch); ++currentOffset;// } else if (chartype == CHARTYPE_CLOSE_PAREN) { return currentOffset; } else if (chartype == CHARTYPE_CARRET) { ch = data.charAt(++currentOffset); chartype = (ch >= 0x80) ? CHARTYPE_NONASCII : fASCIICharMap[ch]; if (chartype != CHARTYPE_CARRET && chartype != CHARTYPE_OPEN_PAREN && chartype != CHARTYPE_CLOSE_PAREN) { break; } schemeData.append((char) ch); ++currentOffset; } else { schemeData.append((char) ch); ++currentOffset;// } } return currentOffset; } // // Protected methods // /** * This method adds the specified token to the token list. By * default, this method allows all tokens. However, subclasses * of the XPathExprScanner can override this method in order * to disallow certain tokens from being used in the scanned * XPath expression. This is a convenient way of allowing only * a subset of XPath. */ protected void addToken(Tokens tokens, int token) throws XNIException { tokens.addToken(token); } // addToken(int) } // class Scanner // ************************************************************************ // Overridden XMLDocumentHandler methods // ************************************************************************ /** * If the comment is a child of a matched element, then pass else return. * * @param text The text in the comment. * @param augs Additional information that may include infoset augmentations * * @exception XNIException * Thrown by application to signal an error. */ public void comment(XMLString text, Augmentations augs) throws XNIException { if (!isChildFragmentResolved()) { return; } super.comment(text, augs); } /** * A processing instruction. Processing instructions consist of a * target name and, optionally, text data. The data is only meaningful * to the application. *

* Typically, a processing instruction's data will contain a series * of pseudo-attributes. These pseudo-attributes follow the form of * element attributes but are not parsed or presented * to the application as anything other than text. The application is * responsible for parsing the data. * * @param target The target. * @param data The data or null if none specified. * @param augs Additional information that may include infoset augmentations * * @exception XNIException * Thrown by handler to signal an error. */ public void processingInstruction(String target, XMLString data, Augmentations augs) throws XNIException { if (!isChildFragmentResolved()) { return; } super.processingInstruction(target, data, augs); } /** * The start of an element. * * @param element The name of the element. * @param attributes The element attributes. * @param augs Additional information that may include infoset augmentations * * @exception XNIException * Thrown by handler to signal an error. */ public void startElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { if (!resolveXPointer(element, attributes, augs, XPointerPart.EVENT_ELEMENT_START)) { // xml:base and xml:lang processing if (fFixupBase) { processXMLBaseAttributes(attributes); } if (fFixupLang) { processXMLLangAttributes(attributes); } // set the context invalid if the element till an element from the result infoset is included fNamespaceContext.setContextInvalid(); return; } super.startElement(element, attributes, augs); } /** * An empty element. * * @param element The name of the element. * @param attributes The element attributes. * @param augs Additional information that may include infoset augmentations * * @exception XNIException * Thrown by handler to signal an error. */ public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { if (!resolveXPointer(element, attributes, augs, XPointerPart.EVENT_ELEMENT_EMPTY)) { // xml:base and xml:lang processing if (fFixupBase) { processXMLBaseAttributes(attributes); } if (fFixupLang) { processXMLLangAttributes(attributes); } // no need to restore restoreBaseURI() for xml:base and xml:lang processing // set the context invalid if the element till an element from the result infoset is included fNamespaceContext.setContextInvalid(); return; } super.emptyElement(element, attributes, augs); } /** * Character content. * * @param text The content. * @param augs Additional information that may include infoset augmentations * * @exception XNIException * Thrown by handler to signal an error. */ public void characters(XMLString text, Augmentations augs) throws XNIException { if (!isChildFragmentResolved()) { return; } super.characters(text, augs); } /** * Ignorable whitespace. For this method to be called, the document * source must have some way of determining that the text containing * only whitespace characters should be considered ignorable. For * example, the validator can determine if a length of whitespace * characters in the document are ignorable based on the element * content model. * * @param text The ignorable whitespace. * @param augs Additional information that may include infoset augmentations * * @exception XNIException * Thrown by handler to signal an error. */ public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException { if (!isChildFragmentResolved()) { return; } super.ignorableWhitespace(text, augs); } /** * The end of an element. * * @param element The name of the element. * @param augs Additional information that may include infoset augmentations * * @exception XNIException * Thrown by handler to signal an error. */ public void endElement(QName element, Augmentations augs) throws XNIException { if (!resolveXPointer(element, null, augs, XPointerPart.EVENT_ELEMENT_END)) { // no need to restore restoreBaseURI() for xml:base and xml:lang processing return; } super.endElement(element, augs); } /** * The start of a CDATA section. * * @param augs Additional information that may include infoset augmentations * * @exception XNIException * Thrown by handler to signal an error. */ public void startCDATA(Augmentations augs) throws XNIException { if (!isChildFragmentResolved()) { return; } super.startCDATA(augs); } /** * The end of a CDATA section. * * @param augs Additional information that may include infoset augmentations * * @exception XNIException * Thrown by handler to signal an error. */ public void endCDATA(Augmentations augs) throws XNIException { if (!isChildFragmentResolved()) { return; } super.endCDATA(augs); } // ************************************************************************ // Overridden XMLComponent methods // ************************************************************************ /** *

* Sets the value of a property. This method is called by the component * manager any time after reset when a property changes value. *

* Note: Components should silently ignore properties * that do not affect the operation of the component. * * @param propertyId The property identifier. * @param value The value of the property. * * @throws XMLConfigurationException Thrown for configuration error. * In general, components should * only throw this exception if * it is really * a critical error. */ public void setProperty(String propertyId, Object value) throws XMLConfigurationException { // Error reporter if (propertyId == Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY) { if (value != null) { fXPointerErrorReporter = (XMLErrorReporter) value; } else { fXPointerErrorReporter = null; } } // Error handler if (propertyId == Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY) { if (value != null) { fErrorHandler = (XMLErrorHandler) value; } else { fErrorHandler = null; } } // xml:lang if (propertyId == Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_FIXUP_LANGUAGE_FEATURE) { if (value != null) { fFixupLang = ((Boolean)value).booleanValue(); } else { fFixupLang = false; } } // xml:base if (propertyId == Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_FIXUP_BASE_URIS_FEATURE) { if (value != null) { fFixupBase = ((Boolean)value).booleanValue(); } else { fFixupBase = false; } } // if (propertyId == Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY) { fNamespaceContext = (XIncludeNamespaceSupport) value; } super.setProperty(propertyId, value); } }