1 /* 2 * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 // XMLReaderAdapter.java - adapt an SAX2 XMLReader to a SAX1 Parser 27 // http://www.saxproject.org 28 // Written by David Megginson 29 // NO WARRANTY! This class is in the public domain. 30 // $Id: XMLReaderAdapter.java,v 1.3 2004/11/03 22:53:09 jsuttor Exp $ 31 32 package org.xml.sax.helpers; 33 34 import java.io.IOException; 35 import java.util.Locale; 36 37 import org.xml.sax.Parser; // deprecated 38 import org.xml.sax.Locator; 39 import org.xml.sax.InputSource; 40 import org.xml.sax.AttributeList; // deprecated 41 import org.xml.sax.EntityResolver; 42 import org.xml.sax.DTDHandler; 43 import org.xml.sax.DocumentHandler; // deprecated 44 import org.xml.sax.ErrorHandler; 45 import org.xml.sax.SAXException; 46 47 import org.xml.sax.XMLReader; 48 import org.xml.sax.Attributes; 49 import org.xml.sax.ContentHandler; 50 import org.xml.sax.SAXNotSupportedException; 51 52 53 /** 54 * Adapt a SAX2 XMLReader as a SAX1 Parser. 55 * 56 * <blockquote> 57 * <em>This module, both source code and documentation, is in the 58 * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> 59 * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> 60 * for further information. 61 * </blockquote> 62 * 63 * <p>This class wraps a SAX2 {@link org.xml.sax.XMLReader XMLReader} 64 * and makes it act as a SAX1 {@link org.xml.sax.Parser Parser}. The XMLReader 65 * must support a true value for the 66 * http://xml.org/sax/features/namespace-prefixes property or parsing will fail 67 * with a {@link org.xml.sax.SAXException SAXException}; if the XMLReader 68 * supports a false value for the http://xml.org/sax/features/namespaces 69 * property, that will also be used to improve efficiency.</p> 70 * 71 * @since 1.4, SAX 2.0 72 * @author David Megginson 73 * @see org.xml.sax.Parser 74 * @see org.xml.sax.XMLReader 75 */ 76 @SuppressWarnings("deprecation") 77 public class XMLReaderAdapter implements Parser, ContentHandler 78 { 79 80 81 //////////////////////////////////////////////////////////////////// 82 // Constructor. 83 //////////////////////////////////////////////////////////////////// 84 85 86 /** 87 * Create a new adapter. 88 * 89 * <p>Use the "org.xml.sax.driver" property to locate the SAX2 90 * driver to embed.</p> 91 * 92 * @exception org.xml.sax.SAXException If the embedded driver 93 * cannot be instantiated or if the 94 * org.xml.sax.driver property is not specified. 95 */ 96 public XMLReaderAdapter () 97 throws SAXException 98 { 99 setup(XMLReaderFactory.createXMLReader()); 100 } 101 102 103 /** 104 * Create a new adapter. 105 * 106 * <p>Create a new adapter, wrapped around a SAX2 XMLReader. 107 * The adapter will make the XMLReader act like a SAX1 108 * Parser.</p> 109 * 110 * @param xmlReader The SAX2 XMLReader to wrap. 111 * @exception java.lang.NullPointerException If the argument is null. 112 */ 113 public XMLReaderAdapter (XMLReader xmlReader) 114 { 115 setup(xmlReader); 116 } 117 118 119 120 /** 121 * Internal setup. 122 * 123 * @param xmlReader The embedded XMLReader. 124 */ 125 private void setup (XMLReader xmlReader) 126 { 127 if (xmlReader == null) { 128 throw new NullPointerException("XMLReader must not be null"); 129 } 130 this.xmlReader = xmlReader; 131 qAtts = new AttributesAdapter(); 132 } 133 134 135 136 //////////////////////////////////////////////////////////////////// 137 // Implementation of org.xml.sax.Parser. 138 //////////////////////////////////////////////////////////////////// 139 140 141 /** 142 * Set the locale for error reporting. 143 * 144 * <p>This is not supported in SAX2, and will always throw 145 * an exception.</p> 146 * 147 * @param locale the locale for error reporting. 148 * @see org.xml.sax.Parser#setLocale 149 * @exception org.xml.sax.SAXException Thrown unless overridden. 150 */ 151 public void setLocale (Locale locale) 152 throws SAXException 153 { 154 throw new SAXNotSupportedException("setLocale not supported"); 155 } 156 157 158 /** 159 * Register the entity resolver. 160 * 161 * @param resolver The new resolver. 162 * @see org.xml.sax.Parser#setEntityResolver 163 */ 164 public void setEntityResolver (EntityResolver resolver) 165 { 166 xmlReader.setEntityResolver(resolver); 167 } 168 169 170 /** 171 * Register the DTD event handler. 172 * 173 * @param handler The new DTD event handler. 174 * @see org.xml.sax.Parser#setDTDHandler 175 */ 176 public void setDTDHandler (DTDHandler handler) 177 { 178 xmlReader.setDTDHandler(handler); 179 } 180 181 182 /** 183 * Register the SAX1 document event handler. 184 * 185 * <p>Note that the SAX1 document handler has no Namespace 186 * support.</p> 187 * 188 * @param handler The new SAX1 document event handler. 189 * @see org.xml.sax.Parser#setDocumentHandler 190 */ 191 public void setDocumentHandler (DocumentHandler handler) 192 { 193 documentHandler = handler; 194 } 195 196 197 /** 198 * Register the error event handler. 199 * 200 * @param handler The new error event handler. 201 * @see org.xml.sax.Parser#setErrorHandler 202 */ 203 public void setErrorHandler (ErrorHandler handler) 204 { 205 xmlReader.setErrorHandler(handler); 206 } 207 208 209 /** 210 * Parse the document. 211 * 212 * <p>This method will throw an exception if the embedded 213 * XMLReader does not support the 214 * http://xml.org/sax/features/namespace-prefixes property.</p> 215 * 216 * @param systemId The absolute URL of the document. 217 * @exception java.io.IOException If there is a problem reading 218 * the raw content of the document. 219 * @exception org.xml.sax.SAXException If there is a problem 220 * processing the document. 221 * @see #parse(org.xml.sax.InputSource) 222 * @see org.xml.sax.Parser#parse(java.lang.String) 223 */ 224 public void parse (String systemId) 225 throws IOException, SAXException 226 { 227 parse(new InputSource(systemId)); 228 } 229 230 231 /** 232 * Parse the document. 233 * 234 * <p>This method will throw an exception if the embedded 235 * XMLReader does not support the 236 * http://xml.org/sax/features/namespace-prefixes property.</p> 237 * 238 * @param input An input source for the document. 239 * @exception java.io.IOException If there is a problem reading 240 * the raw content of the document. 241 * @exception org.xml.sax.SAXException If there is a problem 242 * processing the document. 243 * @see #parse(java.lang.String) 244 * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource) 245 */ 246 public void parse (InputSource input) 247 throws IOException, SAXException 248 { 249 setupXMLReader(); 250 xmlReader.parse(input); 251 } 252 253 254 /** 255 * Set up the XML reader. 256 */ 257 private void setupXMLReader () 258 throws SAXException 259 { 260 xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true); 261 try { 262 xmlReader.setFeature("http://xml.org/sax/features/namespaces", 263 false); 264 } catch (SAXException e) { 265 // NO OP: it's just extra information, and we can ignore it 266 } 267 xmlReader.setContentHandler(this); 268 } 269 270 271 272 //////////////////////////////////////////////////////////////////// 273 // Implementation of org.xml.sax.ContentHandler. 274 //////////////////////////////////////////////////////////////////// 275 276 277 /** 278 * Set a document locator. 279 * 280 * @param locator The document locator. 281 * @see org.xml.sax.ContentHandler#setDocumentLocator 282 */ 283 public void setDocumentLocator (Locator locator) 284 { 285 if (documentHandler != null) 286 documentHandler.setDocumentLocator(locator); 287 } 288 289 290 /** 291 * Start document event. 292 * 293 * @exception org.xml.sax.SAXException The client may raise a 294 * processing exception. 295 * @see org.xml.sax.ContentHandler#startDocument 296 */ 297 public void startDocument () 298 throws SAXException 299 { 300 if (documentHandler != null) 301 documentHandler.startDocument(); 302 } 303 304 305 /** 306 * End document event. 307 * 308 * @exception org.xml.sax.SAXException The client may raise a 309 * processing exception. 310 * @see org.xml.sax.ContentHandler#endDocument 311 */ 312 public void endDocument () 313 throws SAXException 314 { 315 if (documentHandler != null) 316 documentHandler.endDocument(); 317 } 318 319 320 /** 321 * Adapt a SAX2 start prefix mapping event. 322 * 323 * @param prefix The prefix being mapped. 324 * @param uri The Namespace URI being mapped to. 325 * @see org.xml.sax.ContentHandler#startPrefixMapping 326 */ 327 public void startPrefixMapping (String prefix, String uri) 328 { 329 } 330 331 332 /** 333 * Adapt a SAX2 end prefix mapping event. 334 * 335 * @param prefix The prefix being mapped. 336 * @see org.xml.sax.ContentHandler#endPrefixMapping 337 */ 338 public void endPrefixMapping (String prefix) 339 { 340 } 341 342 343 /** 344 * Adapt a SAX2 start element event. 345 * 346 * @param uri The Namespace URI. 347 * @param localName The Namespace local name. 348 * @param qName The qualified (prefixed) name. 349 * @param atts The SAX2 attributes. 350 * @exception org.xml.sax.SAXException The client may raise a 351 * processing exception. 352 * @see org.xml.sax.ContentHandler#endDocument 353 */ 354 public void startElement (String uri, String localName, 355 String qName, Attributes atts) 356 throws SAXException 357 { 358 if (documentHandler != null) { 359 qAtts.setAttributes(atts); 360 documentHandler.startElement(qName, qAtts); 361 } 362 } 363 364 365 /** 366 * Adapt a SAX2 end element event. 367 * 368 * @param uri The Namespace URI. 369 * @param localName The Namespace local name. 370 * @param qName The qualified (prefixed) name. 371 * @exception org.xml.sax.SAXException The client may raise a 372 * processing exception. 373 * @see org.xml.sax.ContentHandler#endElement 374 */ 375 public void endElement (String uri, String localName, 376 String qName) 377 throws SAXException 378 { 379 if (documentHandler != null) 380 documentHandler.endElement(qName); 381 } 382 383 384 /** 385 * Adapt a SAX2 characters event. 386 * 387 * @param ch An array of characters. 388 * @param start The starting position in the array. 389 * @param length The number of characters to use. 390 * @exception org.xml.sax.SAXException The client may raise a 391 * processing exception. 392 * @see org.xml.sax.ContentHandler#characters 393 */ 394 public void characters (char ch[], int start, int length) 395 throws SAXException 396 { 397 if (documentHandler != null) 398 documentHandler.characters(ch, start, length); 399 } 400 401 402 /** 403 * Adapt a SAX2 ignorable whitespace event. 404 * 405 * @param ch An array of characters. 406 * @param start The starting position in the array. 407 * @param length The number of characters to use. 408 * @exception org.xml.sax.SAXException The client may raise a 409 * processing exception. 410 * @see org.xml.sax.ContentHandler#ignorableWhitespace 411 */ 412 public void ignorableWhitespace (char ch[], int start, int length) 413 throws SAXException 414 { 415 if (documentHandler != null) 416 documentHandler.ignorableWhitespace(ch, start, length); 417 } 418 419 420 /** 421 * Adapt a SAX2 processing instruction event. 422 * 423 * @param target The processing instruction target. 424 * @param data The remainder of the processing instruction 425 * @exception org.xml.sax.SAXException The client may raise a 426 * processing exception. 427 * @see org.xml.sax.ContentHandler#processingInstruction 428 */ 429 public void processingInstruction (String target, String data) 430 throws SAXException 431 { 432 if (documentHandler != null) 433 documentHandler.processingInstruction(target, data); 434 } 435 436 437 /** 438 * Adapt a SAX2 skipped entity event. 439 * 440 * @param name The name of the skipped entity. 441 * @see org.xml.sax.ContentHandler#skippedEntity 442 * @exception org.xml.sax.SAXException Throwable by subclasses. 443 */ 444 public void skippedEntity (String name) 445 throws SAXException 446 { 447 } 448 449 450 451 //////////////////////////////////////////////////////////////////// 452 // Internal state. 453 //////////////////////////////////////////////////////////////////// 454 455 XMLReader xmlReader; 456 DocumentHandler documentHandler; 457 AttributesAdapter qAtts; 458 459 460 461 //////////////////////////////////////////////////////////////////// 462 // Internal class. 463 //////////////////////////////////////////////////////////////////// 464 465 466 /** 467 * Internal class to wrap a SAX2 Attributes object for SAX1. 468 */ 469 final class AttributesAdapter implements AttributeList 470 { 471 AttributesAdapter () 472 { 473 } 474 475 476 /** 477 * Set the embedded Attributes object. 478 * 479 * @param The embedded SAX2 Attributes. 480 */ 481 void setAttributes (Attributes attributes) 482 { 483 this.attributes = attributes; 484 } 485 486 487 /** 488 * Return the number of attributes. 489 * 490 * @return The length of the attribute list. 491 * @see org.xml.sax.AttributeList#getLength 492 */ 493 public int getLength () 494 { 495 return attributes.getLength(); 496 } 497 498 499 /** 500 * Return the qualified (prefixed) name of an attribute by position. 501 * 502 * @return The qualified name. 503 * @see org.xml.sax.AttributeList#getName 504 */ 505 public String getName (int i) 506 { 507 return attributes.getQName(i); 508 } 509 510 511 /** 512 * Return the type of an attribute by position. 513 * 514 * @return The type. 515 * @see org.xml.sax.AttributeList#getType(int) 516 */ 517 public String getType (int i) 518 { 519 return attributes.getType(i); 520 } 521 522 523 /** 524 * Return the value of an attribute by position. 525 * 526 * @return The value. 527 * @see org.xml.sax.AttributeList#getValue(int) 528 */ 529 public String getValue (int i) 530 { 531 return attributes.getValue(i); 532 } 533 534 535 /** 536 * Return the type of an attribute by qualified (prefixed) name. 537 * 538 * @return The type. 539 * @see org.xml.sax.AttributeList#getType(java.lang.String) 540 */ 541 public String getType (String qName) 542 { 543 return attributes.getType(qName); 544 } 545 546 547 /** 548 * Return the value of an attribute by qualified (prefixed) name. 549 * 550 * @return The value. 551 * @see org.xml.sax.AttributeList#getValue(java.lang.String) 552 */ 553 public String getValue (String qName) 554 { 555 return attributes.getValue(qName); 556 } 557 558 private Attributes attributes; 559 } 560 561 } 562 563 // end of XMLReaderAdapter.java