|  |  | 
|  |  | 
|  |  */ | 
|  | /* | 
|  |  * 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; | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  | public final class XPointerHandler extends XIncludeHandler implements | 
|  |         XPointerProcessor { | 
|  |  | 
|  |     // Fields | 
|  |      | 
|  |     protected ArrayList<XPointerPart> fXPointerParts = null; | 
|  |  | 
|  |      | 
|  |     protected XPointerPart fXPointerPart = null; | 
|  |  | 
|  |      | 
|  |     protected boolean fFoundMatchingPtrPart = false; | 
|  |  | 
|  |      | 
|  |     protected XMLErrorReporter fXPointerErrorReporter; | 
|  |  | 
|  |      | 
|  |     protected XMLErrorHandler fErrorHandler; | 
|  |  | 
|  |      | 
|  |     protected SymbolTable fSymbolTable = null; | 
|  |  | 
|  |      | 
|  |     private final String ELEMENT_SCHEME_NAME = "element"; | 
|  |  | 
|  |     | 
|  |     protected boolean fIsXPointerResolved = false; | 
|  |  | 
|  |      | 
|  |     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. | 
|  |     // ************************************************************************ | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void parseXPointer(String xpointer) throws XNIException { | 
|  |  | 
|  |          | 
|  |         init(); | 
|  |  | 
|  |          | 
|  |         final Tokens tokens = new Tokens(fSymbolTable); | 
|  |  | 
|  |          | 
|  |         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) }); | 
|  |             } | 
|  |         }; | 
|  |  | 
|  |          | 
|  |         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: { | 
|  |  | 
|  |                  | 
|  |                 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: { | 
|  |  | 
|  |                  | 
|  |                 token = tokens.nextToken(); | 
|  |                 String prefix = tokens.getTokenString(token); | 
|  |                 token = tokens.nextToken(); | 
|  |                 String localName = tokens.getTokenString(token); | 
|  |  | 
|  |                 String schemeName = prefix + localName; | 
|  |  | 
|  |                  | 
|  |                 int openParenCount = 0; | 
|  |                 int closeParenCount = 0; | 
|  |  | 
|  |                 token = tokens.nextToken(); | 
|  |                 String openParen = tokens.getTokenString(token); | 
|  |                 if (openParen != "XPTRTOKEN_OPEN_PAREN") { | 
|  |  | 
|  |                      | 
|  |                     if (token == Tokens.XPTRTOKEN_SHORTHAND) { | 
|  |                         reportError("MultipleShortHandPointers", | 
|  |                                 new Object[] { xpointer }); | 
|  |                     } else { | 
|  |                         reportError("InvalidXPointerExpression", | 
|  |                                 new Object[] { xpointer }); | 
|  |                     } | 
|  |                 } | 
|  |                 openParenCount++; | 
|  |  | 
|  |                  | 
|  |                 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); | 
|  |  | 
|  |                  | 
|  |                 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++; | 
|  |                 } | 
|  |  | 
|  |                  | 
|  |                 if (openParenCount != closeParenCount) { | 
|  |                     reportError("UnbalancedParenthesisInXPointerExpression", | 
|  |                             new Object[] { xpointer, | 
|  |                                     openParenCount, | 
|  |                                     closeParenCount }); | 
|  |                 } | 
|  |  | 
|  |                  | 
|  |                 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 | 
|  |                      | 
|  |                     try { | 
|  |                         elementSchemePointer.parseXPointer(schemeData); | 
|  |                         fXPointerParts.add(elementSchemePointer); | 
|  |                     } catch (XNIException e) { | 
|  |                          | 
|  |                         throw new XNIException (e); | 
|  |                     } | 
|  |  | 
|  |                 } else { | 
|  |                      | 
|  |                     reportWarning("SchemeUnsupported", | 
|  |                             new Object[] { schemeName }); | 
|  |                 } | 
|  |  | 
|  |                 break; | 
|  |             } | 
|  |             default: | 
|  |                 reportError("InvalidXPointerExpression", | 
|  |                         new Object[] { xpointer }); | 
|  |             } | 
|  |         } | 
|  |  | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     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 | 
|  |          | 
|  |         if (!fFoundMatchingPtrPart) { | 
|  |  | 
|  |             // for each element, attempt to resolve it against each pointer part | 
|  |              | 
|  |             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; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public boolean isFragmentResolved() throws XNIException { | 
|  |         boolean resolved = (fXPointerPart != null) ? fXPointerPart.isFragmentResolved() | 
|  |                 : false; | 
|  |  | 
|  |         if (!fIsXPointerResolved) { | 
|  |             fIsXPointerResolved = resolved; | 
|  |         } | 
|  |  | 
|  |         return resolved; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public boolean isChildFragmentResolved() throws XNIException { | 
|  |         boolean resolved = (fXPointerPart != null) ? fXPointerPart | 
|  |                                 .isChildFragmentResolved() : false; | 
|  |                 return resolved; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public boolean isXPointerResolved() throws XNIException { | 
|  |         return fIsXPointerResolved; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public XPointerPart getXPointerPart() { | 
|  |         return fXPointerPart; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private void reportError(String key, Object[] arguments) | 
|  |             throws XNIException { | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |         */ | 
|  |         throw new XNIException((fErrorReporter | 
|  |                                 .getMessageFormatter(XPointerMessageFormatter.XPOINTER_DOMAIN)) | 
|  |                                 .formatMessage(fErrorReporter.getLocale(), key, arguments)); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private void reportWarning(String key, Object[] arguments) | 
|  |             throws XNIException { | 
|  |         fXPointerErrorReporter.reportError( | 
|  |                 XPointerMessageFormatter.XPOINTER_DOMAIN, key, arguments, | 
|  |                 XMLErrorReporter.SEVERITY_WARNING); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     protected void initErrorReporter() { | 
|  |         if (fXPointerErrorReporter == null) { | 
|  |             fXPointerErrorReporter = new XMLErrorReporter(); | 
|  |         } | 
|  |         if (fErrorHandler == null) { | 
|  |             fErrorHandler = new XPointerErrorHandler(); | 
|  |         } | 
|  |          | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         fXPointerErrorReporter.putMessageFormatter( | 
|  |                 XPointerMessageFormatter.XPOINTER_DOMAIN, | 
|  |                 new XPointerMessageFormatter()); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     protected void init() { | 
|  |         fXPointerParts.clear(); | 
|  |         fXPointerPart = null; | 
|  |         fFoundMatchingPtrPart = false; | 
|  |         fIsXPointerResolved = false; | 
|  |         //fFixupBase = false; | 
|  |         //fFixupLang = false; | 
|  |  | 
|  |         initErrorReporter(); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public ArrayList<XPointerPart> getPointerParts() { | 
|  |         return fXPointerParts; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private final class Tokens { | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private static final int XPTRTOKEN_OPEN_PAREN = 0, | 
|  |                 XPTRTOKEN_CLOSE_PAREN = 1, XPTRTOKEN_SHORTHAND = 2, | 
|  |                 XPTRTOKEN_SCHEMENAME = 3, XPTRTOKEN_SCHEMEDATA = 4; | 
|  |  | 
|  |          | 
|  |         private final String[] fgTokenNames = { "XPTRTOKEN_OPEN_PAREN", | 
|  |                 "XPTRTOKEN_CLOSE_PAREN", "XPTRTOKEN_SHORTHAND", | 
|  |                 "XPTRTOKEN_SCHEMENAME", "XPTRTOKEN_SCHEMEDATA" }; | 
|  |  | 
|  |          | 
|  |         private static final int INITIAL_TOKEN_COUNT = 1 << 8; | 
|  |  | 
|  |         private int[] fTokens = new int[INITIAL_TOKEN_COUNT]; | 
|  |  | 
|  |         private int fTokenCount = 0; | 
|  |  | 
|  |          | 
|  |         private int fCurrentTokenIndex; | 
|  |  | 
|  |         private SymbolTable fSymbolTable; | 
|  |  | 
|  |         private HashMap<Integer, String> fTokenNames = new HashMap<>(); | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private Tokens(SymbolTable symbolTable) { | 
|  |             fSymbolTable = symbolTable; | 
|  |  | 
|  |             fTokenNames.put(XPTRTOKEN_OPEN_PAREN, | 
|  |                     "XPTRTOKEN_OPEN_PAREN"); | 
|  |             fTokenNames.put(XPTRTOKEN_CLOSE_PAREN, | 
|  |                     "XPTRTOKEN_CLOSE_PAREN"); | 
|  |             fTokenNames.put(XPTRTOKEN_SHORTHAND, | 
|  |                     "XPTRTOKEN_SHORTHAND"); | 
|  |             fTokenNames.put(XPTRTOKEN_SCHEMENAME, | 
|  |                     "XPTRTOKEN_SCHEMENAME"); | 
|  |             fTokenNames.put(XPTRTOKEN_SCHEMEDATA, | 
|  |                     "XPTRTOKEN_SCHEMEDATA"); | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private String getTokenString(int token) { | 
|  |             return fTokenNames.get(token); | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private void addToken(String tokenStr) { | 
|  |             String str = fTokenNames.get(tokenStr); | 
|  |             Integer tokenInt = str == null ? null : Integer.parseInt(str); | 
|  |             if (tokenInt == null) { | 
|  |                 tokenInt = fTokenNames.size(); | 
|  |                 fTokenNames.put(tokenInt, tokenStr); | 
|  |             } | 
|  |             addToken(tokenInt.intValue()); | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         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++; | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |          */ | 
|  |         private void rewind() { | 
|  |             fCurrentTokenIndex = 0; | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private boolean hasMore() { | 
|  |             return fCurrentTokenIndex < fTokenCount; | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private int nextToken() throws XNIException { | 
|  |             if (fCurrentTokenIndex == fTokenCount) { | 
|  |                 reportError("XPointerProcessingError", null); | 
|  |             } | 
|  |             return fTokens[fCurrentTokenIndex++]; | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private int peekToken() throws XNIException { | 
|  |             if (fCurrentTokenIndex == fTokenCount) { | 
|  |                 reportError("XPointerProcessingError", null); | 
|  |             } | 
|  |             return fTokens[fCurrentTokenIndex]; | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private String nextTokenAsString() throws XNIException { | 
|  |             String tokenStrint = getTokenString(nextToken()); | 
|  |             if (tokenStrint == null) { | 
|  |                 reportError("XPointerProcessingError", null); | 
|  |             } | 
|  |             return tokenStrint; | 
|  |         } | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     private class Scanner { | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private static final byte CHARTYPE_INVALID = 0,  | 
|  |                 CHARTYPE_OTHER = 1,  | 
|  |                 CHARTYPE_WHITESPACE = 2,  | 
|  |                 CHARTYPE_CARRET = 3,  | 
|  |                 CHARTYPE_OPEN_PAREN = 4,  | 
|  |                 CHARTYPE_CLOSE_PAREN = 5,  | 
|  |                 CHARTYPE_MINUS = 6,  | 
|  |                 CHARTYPE_PERIOD = 7,  | 
|  |                 CHARTYPE_SLASH = 8,  | 
|  |                 CHARTYPE_DIGIT = 9,  | 
|  |                 CHARTYPE_COLON = 10,  | 
|  |                 CHARTYPE_EQUAL = 11,  | 
|  |                 CHARTYPE_LETTER = 12,  | 
|  |                 CHARTYPE_UNDERSCORE = 13,  | 
|  |                 CHARTYPE_NONASCII = 14;  | 
|  |  | 
|  |         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 | 
|  |         // | 
|  |          | 
|  |         private SymbolTable fSymbolTable; | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         private Scanner(SymbolTable symbolTable) { | 
|  |              | 
|  |             fSymbolTable = symbolTable; | 
|  |  | 
|  |         } // <init>(SymbolTable) | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         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: | 
|  |                      | 
|  |                     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; | 
|  |  | 
|  |                          | 
|  |                         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)); | 
|  |                         } | 
|  |  | 
|  |                          | 
|  |                         if (currentOffset != endOffset) { | 
|  |                             addToken(tokens, Tokens.XPTRTOKEN_SCHEMENAME); | 
|  |                             tokens.addToken(prefix); | 
|  |                             tokens.addToken(name); | 
|  |                             isQName = false; | 
|  |                         } else if (currentOffset == endOffset) { | 
|  |                              | 
|  |                             addToken(tokens, Tokens.XPTRTOKEN_SHORTHAND); | 
|  |                             tokens.addToken(name); | 
|  |                             isQName = false; | 
|  |                         } | 
|  |  | 
|  |                          | 
|  |                         closeParen = 0; | 
|  |  | 
|  |                         break; | 
|  |  | 
|  |                     } else if (openParen > 0 && closeParen == 0 && name != null) { | 
|  |                          | 
|  |                         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); | 
|  |  | 
|  |                          | 
|  |                         openParen = 0; | 
|  |                         schemeDataBuff.delete(0, schemeDataBuff.length()); | 
|  |  | 
|  |                     } else { | 
|  |                         // ex. schemeName() | 
|  |                          | 
|  |                         return false; | 
|  |                     } | 
|  |                 } | 
|  |             }  | 
|  |             return true; | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         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) { | 
|  |                 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; | 
|  |         } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         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); | 
|  |                      | 
|  |                     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 | 
|  |         // | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |         protected void addToken(Tokens tokens, int token) throws XNIException { | 
|  |             tokens.addToken(token); | 
|  |         } // addToken(int) | 
|  |  | 
|  |     } // class Scanner | 
|  |  | 
|  |     // ************************************************************************ | 
|  |     //  Overridden XMLDocumentHandler methods | 
|  |     // ************************************************************************ | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void comment(XMLString text, Augmentations augs) throws XNIException { | 
|  |         if (!isChildFragmentResolved()) { | 
|  |             return; | 
|  |         } | 
|  |         super.comment(text, augs); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void processingInstruction(String target, XMLString data, | 
|  |             Augmentations augs) throws XNIException { | 
|  |         if (!isChildFragmentResolved()) { | 
|  |             return; | 
|  |         } | 
|  |         super.processingInstruction(target, data, augs); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void startElement(QName element, XMLAttributes attributes, | 
|  |             Augmentations augs) throws XNIException { | 
|  |         if (!resolveXPointer(element, attributes, augs, | 
|  |                 XPointerPart.EVENT_ELEMENT_START)) { | 
|  |  | 
|  |              | 
|  |                 if (fFixupBase) { | 
|  |                 processXMLBaseAttributes(attributes); | 
|  |                 } | 
|  |             if (fFixupLang) { | 
|  |                 processXMLLangAttributes(attributes); | 
|  |             } | 
|  |  | 
|  |              | 
|  |             fNamespaceContext.setContextInvalid(); | 
|  |  | 
|  |             return; | 
|  |         } | 
|  |         super.startElement(element, attributes, augs); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void emptyElement(QName element, XMLAttributes attributes, | 
|  |             Augmentations augs) throws XNIException { | 
|  |         if (!resolveXPointer(element, attributes, augs, | 
|  |                 XPointerPart.EVENT_ELEMENT_EMPTY)) { | 
|  |              | 
|  |                 if (fFixupBase) { | 
|  |                 processXMLBaseAttributes(attributes); | 
|  |                 } | 
|  |             if (fFixupLang) { | 
|  |                 processXMLLangAttributes(attributes); | 
|  |             } | 
|  |             // no need to restore restoreBaseURI() for xml:base and xml:lang processing | 
|  |  | 
|  |              | 
|  |             fNamespaceContext.setContextInvalid(); | 
|  |             return; | 
|  |         } | 
|  |         super.emptyElement(element, attributes, augs); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void characters(XMLString text, Augmentations augs) | 
|  |             throws XNIException { | 
|  |         if (!isChildFragmentResolved()) { | 
|  |             return; | 
|  |         } | 
|  |         super.characters(text, augs); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void ignorableWhitespace(XMLString text, Augmentations augs) | 
|  |             throws XNIException { | 
|  |         if (!isChildFragmentResolved()) { | 
|  |             return; | 
|  |         } | 
|  |         super.ignorableWhitespace(text, augs); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void endElement(QName element, Augmentations augs) | 
|  |             throws XNIException { | 
|  |         if (!resolveXPointer(element, null, augs, | 
|  |                 XPointerPart.EVENT_ELEMENT_END)) { | 
|  |  | 
|  |              | 
|  |             return; | 
|  |         } | 
|  |         super.endElement(element, augs); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void startCDATA(Augmentations augs) throws XNIException { | 
|  |         if (!isChildFragmentResolved()) { | 
|  |             return; | 
|  |         } | 
|  |         super.startCDATA(augs); | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void endCDATA(Augmentations augs) throws XNIException { | 
|  |         if (!isChildFragmentResolved()) { | 
|  |             return; | 
|  |         } | 
|  |         super.endCDATA(augs); | 
|  |     } | 
|  |  | 
|  |     // ************************************************************************ | 
|  |     // Overridden XMLComponent methods | 
|  |     // ************************************************************************ | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void setProperty(String propertyId, Object value) | 
|  |             throws XMLConfigurationException { | 
|  |  | 
|  |          | 
|  |         if (propertyId == Constants.XERCES_PROPERTY_PREFIX | 
|  |                 + Constants.ERROR_REPORTER_PROPERTY) { | 
|  |             if (value != null) { | 
|  |                 fXPointerErrorReporter = (XMLErrorReporter) value; | 
|  |             } else { | 
|  |                 fXPointerErrorReporter = null; | 
|  |             } | 
|  |         } | 
|  |  | 
|  |          | 
|  |         if (propertyId == Constants.XERCES_PROPERTY_PREFIX | 
|  |                 + Constants.ERROR_HANDLER_PROPERTY) { | 
|  |             if (value != null) { | 
|  |                 fErrorHandler = (XMLErrorHandler) value; | 
|  |             } else { | 
|  |                 fErrorHandler = null; | 
|  |             } | 
|  |         } | 
|  |  | 
|  |          | 
|  |         if (propertyId == Constants.XERCES_FEATURE_PREFIX | 
|  |                 + Constants.XINCLUDE_FIXUP_LANGUAGE_FEATURE) { | 
|  |             if (value != null) { | 
|  |                 fFixupLang = ((Boolean)value).booleanValue(); | 
|  |             } else { | 
|  |                 fFixupLang = false; | 
|  |             } | 
|  |         } | 
|  |  | 
|  |          | 
|  |         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); | 
|  |     } | 
|  |  | 
|  | } |