1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xerces.internal.impl.xs.traversers; 23 24 import com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOMParser; 25 import com.sun.org.apache.xerces.internal.util.NamespaceSupport; 26 import com.sun.org.apache.xerces.internal.util.SAXLocatorWrapper; 27 import com.sun.org.apache.xerces.internal.util.SymbolTable; 28 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; 29 import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; 30 import com.sun.org.apache.xerces.internal.util.XMLSymbols; 31 import com.sun.org.apache.xerces.internal.xni.NamespaceContext; 32 import com.sun.org.apache.xerces.internal.xni.QName; 33 import com.sun.org.apache.xerces.internal.xni.XMLString; 34 import com.sun.org.apache.xerces.internal.xni.XNIException; 35 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException; 36 import org.w3c.dom.Document; 37 import org.xml.sax.Attributes; 38 import org.xml.sax.ContentHandler; 39 import org.xml.sax.Locator; 40 import org.xml.sax.SAXException; 41 import org.xml.sax.SAXParseException; 42 import org.xml.sax.helpers.LocatorImpl; 43 44 /** 45 * <p>SchemaContentHandler converts SAX events into XNI 46 * and passes them directly to the SchemaDOMParser.</p> 47 * 48 * @xerces.internal 49 * 50 * @author Michael Glavassevich, IBM 51 * @author Jack Z. Wang, IBM 52 * 53 */ 54 final class SchemaContentHandler implements ContentHandler { 55 56 /** Symbol table **/ 57 private SymbolTable fSymbolTable; 58 59 /** SchemaDOMParser, events will be delegated to SchemaDOMParser to pass */ 60 private SchemaDOMParser fSchemaDOMParser; 61 62 /** XML Locator wrapper for SAX. **/ 63 private final SAXLocatorWrapper fSAXLocatorWrapper = new SAXLocatorWrapper(); 64 65 /** The namespace context of this document: stores namespaces in scope */ 66 private NamespaceSupport fNamespaceContext = new NamespaceSupport(); 67 68 /** Indicate if push NamespaceContest is needed */ 69 private boolean fNeedPushNSContext; 70 71 /** Flag used to track whether namespace declarations are reported as attributes. */ 72 private boolean fNamespacePrefixes = false; 73 74 /** Flag used to track whether XML names and Namespace URIs have been internalized. */ 75 private boolean fStringsInternalized = false; 76 77 /** Fields for start element, end element and characters. */ 78 private final QName fElementQName = new QName(); 79 private final QName fAttributeQName = new QName(); 80 private final XMLAttributesImpl fAttributes = new XMLAttributesImpl(); 81 private final XMLString fTempString = new XMLString(); 82 private final XMLStringBuffer fStringBuffer = new XMLStringBuffer(); 83 84 /** 85 * <p>Constructs an SchemaContentHandler.</p> 86 */ SchemaContentHandler()87 public SchemaContentHandler() {} 88 89 /* 90 * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator) 91 */ getDocument()92 public Document getDocument() { 93 return fSchemaDOMParser.getDocument(); 94 } 95 96 /* 97 * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator) 98 */ setDocumentLocator(Locator locator)99 public void setDocumentLocator(Locator locator) { 100 fSAXLocatorWrapper.setLocator(locator); 101 } 102 103 /* 104 * @see org.xml.sax.ContentHandler#startDocument() 105 */ startDocument()106 public void startDocument() throws SAXException { 107 fNeedPushNSContext = true; 108 fNamespaceContext.reset(); 109 try { 110 fSchemaDOMParser.startDocument(fSAXLocatorWrapper, null, fNamespaceContext, null); 111 } 112 catch (XMLParseException e) { 113 convertToSAXParseException(e); 114 } 115 catch (XNIException e) { 116 convertToSAXException(e); 117 } 118 } 119 120 /* 121 * @see org.xml.sax.ContentHandler#endDocument() 122 */ endDocument()123 public void endDocument() throws SAXException { 124 fSAXLocatorWrapper.setLocator(null); 125 try { 126 fSchemaDOMParser.endDocument(null); 127 } 128 catch (XMLParseException e) { 129 convertToSAXParseException(e); 130 } 131 catch (XNIException e) { 132 convertToSAXException(e); 133 } 134 } 135 136 /* 137 * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String) 138 */ startPrefixMapping(String prefix, String uri)139 public void startPrefixMapping(String prefix, String uri) throws SAXException { 140 if (fNeedPushNSContext) { 141 fNeedPushNSContext = false; 142 fNamespaceContext.pushContext(); 143 } 144 if (!fStringsInternalized) { 145 prefix = (prefix != null) ? fSymbolTable.addSymbol(prefix) : XMLSymbols.EMPTY_STRING; 146 uri = (uri != null && uri.length() > 0) ? fSymbolTable.addSymbol(uri) : null; 147 } 148 else { 149 if (prefix == null) { 150 prefix = XMLSymbols.EMPTY_STRING; 151 } 152 if (uri != null && uri.length() == 0) { 153 uri = null; 154 } 155 } 156 fNamespaceContext.declarePrefix(prefix, uri); 157 } 158 159 /* 160 * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String) 161 */ endPrefixMapping(String prefix)162 public void endPrefixMapping(String prefix) throws SAXException { 163 // do nothing 164 } 165 166 /* 167 * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) 168 */ startElement(String uri, String localName, String qName, Attributes atts)169 public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { 170 if (fNeedPushNSContext) { 171 fNamespaceContext.pushContext(); 172 } 173 fNeedPushNSContext = true; 174 175 // Fill element QName and XMLAttributes 176 fillQName(fElementQName, uri, localName, qName); 177 fillXMLAttributes(atts); 178 179 // Add namespace declarations if necessary 180 if (!fNamespacePrefixes) { 181 final int prefixCount = fNamespaceContext.getDeclaredPrefixCount(); 182 if (prefixCount > 0) { 183 addNamespaceDeclarations(prefixCount); 184 } 185 } 186 187 try { 188 fSchemaDOMParser.startElement(fElementQName, fAttributes, null); 189 } 190 catch (XMLParseException e) { 191 convertToSAXParseException(e); 192 } 193 catch (XNIException e) { 194 convertToSAXException(e); 195 } 196 } 197 198 /* 199 * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String) 200 */ endElement(String uri, String localName, String qName)201 public void endElement(String uri, String localName, String qName) throws SAXException { 202 fillQName(fElementQName, uri, localName, qName); 203 try { 204 fSchemaDOMParser.endElement(fElementQName, null); 205 } 206 catch (XMLParseException e) { 207 convertToSAXParseException(e); 208 } 209 catch (XNIException e) { 210 convertToSAXException(e); 211 } 212 finally { 213 fNamespaceContext.popContext(); 214 } 215 } 216 217 /* 218 * @see org.xml.sax.ContentHandler#characters(char[], int, int) 219 */ characters(char[] ch, int start, int length)220 public void characters(char[] ch, int start, int length) throws SAXException { 221 try { 222 fTempString.setValues(ch, start, length); 223 fSchemaDOMParser.characters(fTempString, null); 224 } 225 catch (XMLParseException e) { 226 convertToSAXParseException(e); 227 } 228 catch (XNIException e) { 229 convertToSAXException(e); 230 } 231 } 232 233 /* 234 * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int) 235 */ ignorableWhitespace(char[] ch, int start, int length)236 public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { 237 try { 238 fTempString.setValues(ch, start, length); 239 fSchemaDOMParser.ignorableWhitespace(fTempString, null); 240 } 241 catch (XMLParseException e) { 242 convertToSAXParseException(e); 243 } 244 catch (XNIException e) { 245 convertToSAXException(e); 246 } 247 } 248 249 /* 250 * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String) 251 */ processingInstruction(String target, String data)252 public void processingInstruction(String target, String data) throws SAXException { 253 try { 254 fTempString.setValues(data.toCharArray(), 0, data.length()); 255 fSchemaDOMParser.processingInstruction(target, fTempString, null); 256 } 257 catch (XMLParseException e) { 258 convertToSAXParseException(e); 259 } 260 catch (XNIException e) { 261 convertToSAXException(e); 262 } 263 } 264 265 /* 266 * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String) 267 */ skippedEntity(String arg)268 public void skippedEntity(String arg) throws SAXException { 269 // do-nothing 270 } 271 272 /* 273 * Other methods 274 */ 275 fillQName(QName toFill, String uri, String localpart, String rawname)276 private void fillQName(QName toFill, String uri, String localpart, String rawname) { 277 if (!fStringsInternalized) { 278 uri = (uri != null && uri.length() > 0) ? fSymbolTable.addSymbol(uri) : null; 279 localpart = (localpart != null) ? fSymbolTable.addSymbol(localpart) : XMLSymbols.EMPTY_STRING; 280 rawname = (rawname != null) ? fSymbolTable.addSymbol(rawname) : XMLSymbols.EMPTY_STRING; 281 } 282 else { 283 if (uri != null && uri.length() == 0) { 284 uri = null; 285 } 286 if (localpart == null) { 287 localpart = XMLSymbols.EMPTY_STRING; 288 } 289 if (rawname == null) { 290 rawname = XMLSymbols.EMPTY_STRING; 291 } 292 } 293 String prefix = XMLSymbols.EMPTY_STRING; 294 int prefixIdx = rawname.indexOf(':'); 295 if (prefixIdx != -1) { 296 prefix = fSymbolTable.addSymbol(rawname.substring(0, prefixIdx)); 297 // local part may be an empty string if this is a namespace declaration 298 if (localpart == XMLSymbols.EMPTY_STRING) { 299 localpart = fSymbolTable.addSymbol(rawname.substring(prefixIdx + 1)); 300 } 301 } 302 // local part may be an empty string if this is a namespace declaration 303 else if (localpart == XMLSymbols.EMPTY_STRING) { 304 localpart = rawname; 305 } 306 toFill.setValues(prefix, localpart, rawname, uri); 307 } 308 fillXMLAttributes(Attributes atts)309 private void fillXMLAttributes(Attributes atts) { 310 fAttributes.removeAllAttributes(); 311 final int attrCount = atts.getLength(); 312 for (int i = 0; i < attrCount; ++i) { 313 fillQName(fAttributeQName, atts.getURI(i), atts.getLocalName(i), atts.getQName(i)); 314 String type = atts.getType(i); 315 fAttributes.addAttributeNS(fAttributeQName, (type != null) ? type : XMLSymbols.fCDATASymbol, atts.getValue(i)); 316 fAttributes.setSpecified(i, true); 317 } 318 } 319 addNamespaceDeclarations(final int prefixCount)320 private void addNamespaceDeclarations(final int prefixCount) { 321 String prefix = null; 322 String localpart = null; 323 String rawname = null; 324 String nsPrefix = null; 325 String nsURI = null; 326 for (int i = 0; i < prefixCount; ++i) { 327 nsPrefix = fNamespaceContext.getDeclaredPrefixAt(i); 328 nsURI = fNamespaceContext.getURI(nsPrefix); 329 if (nsPrefix.length() > 0) { 330 prefix = XMLSymbols.PREFIX_XMLNS; 331 localpart = nsPrefix; 332 fStringBuffer.clear(); 333 fStringBuffer.append(prefix); 334 fStringBuffer.append(':'); 335 fStringBuffer.append(localpart); 336 rawname = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length); 337 } 338 else { 339 prefix = XMLSymbols.EMPTY_STRING; 340 localpart = XMLSymbols.PREFIX_XMLNS; 341 rawname = XMLSymbols.PREFIX_XMLNS; 342 } 343 fAttributeQName.setValues(prefix, localpart, rawname, NamespaceContext.XMLNS_URI); 344 fAttributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, 345 (nsURI != null) ? nsURI : XMLSymbols.EMPTY_STRING); 346 } 347 } 348 reset(SchemaDOMParser schemaDOMParser, SymbolTable symbolTable, boolean namespacePrefixes, boolean stringsInternalized)349 public void reset(SchemaDOMParser schemaDOMParser, SymbolTable symbolTable, 350 boolean namespacePrefixes, boolean stringsInternalized) { 351 fSchemaDOMParser = schemaDOMParser; 352 fSymbolTable = symbolTable; 353 fNamespacePrefixes = namespacePrefixes; 354 fStringsInternalized = stringsInternalized; 355 } 356 357 /* 358 * Static methods 359 */ 360 convertToSAXParseException(XMLParseException e)361 static void convertToSAXParseException(XMLParseException e) throws SAXException { 362 Exception ex = e.getException(); 363 if (ex == null) { 364 // must be a parser exception; mine it for locator info and throw 365 // a SAXParseException 366 LocatorImpl locatorImpl = new LocatorImpl(); 367 locatorImpl.setPublicId(e.getPublicId()); 368 locatorImpl.setSystemId(e.getExpandedSystemId()); 369 locatorImpl.setLineNumber(e.getLineNumber()); 370 locatorImpl.setColumnNumber(e.getColumnNumber()); 371 throw new SAXParseException(e.getMessage(), locatorImpl); 372 } 373 if (ex instanceof SAXException) { 374 // why did we create an XMLParseException? 375 throw (SAXException) ex; 376 } 377 throw new SAXException(ex); 378 } 379 convertToSAXException(XNIException e)380 static void convertToSAXException(XNIException e) throws SAXException { 381 Exception ex = e.getException(); 382 if (ex == null) { 383 throw new SAXException(e.getMessage()); 384 } 385 if (ex instanceof SAXException) { 386 throw (SAXException) ex; 387 } 388 throw new SAXException(ex); 389 } 390 391 } // SchemaContentHandler 392