1 /* 2 * Copyright (c) 2000, 2005, 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 public class XMLReaderAdapter implements Parser, ContentHandler 77 { 78 79 80 //////////////////////////////////////////////////////////////////// 81 // Constructor. 82 //////////////////////////////////////////////////////////////////// 83 84 85 /** 86 * Create a new adapter. 87 * 88 * <p>Use the "org.xml.sax.driver" property to locate the SAX2 89 * driver to embed.</p> 90 * 91 * @exception org.xml.sax.SAXException If the embedded driver 92 * cannot be instantiated or if the 93 * org.xml.sax.driver property is not specified. 94 */ 95 public XMLReaderAdapter () 96 throws SAXException 97 { 98 setup(XMLReaderFactory.createXMLReader()); 99 } 100 101 102 /** 103 * Create a new adapter. 104 * 105 * <p>Create a new adapter, wrapped around a SAX2 XMLReader. 106 * The adapter will make the XMLReader act like a SAX1 107 * Parser.</p> 108 * 109 * @param xmlReader The SAX2 XMLReader to wrap. 110 * @exception java.lang.NullPointerException If the argument is null. 111 */ 112 public XMLReaderAdapter (XMLReader xmlReader) 113 { 114 setup(xmlReader); 115 } 116 117 118 119 /** 120 * Internal setup. 121 * 122 * @param xmlReader The embedded XMLReader. 123 */ 124 private void setup (XMLReader xmlReader) 125 { 126 if (xmlReader == null) { 127 throw new NullPointerException("XMLReader must not be null"); 128 } 129 this.xmlReader = xmlReader; 130 qAtts = new AttributesAdapter(); 131 } 132 133 134 135 //////////////////////////////////////////////////////////////////// 136 // Implementation of org.xml.sax.Parser. 137 //////////////////////////////////////////////////////////////////// 138 139 140 /** 141 * Set the locale for error reporting. 142 * 143 * <p>This is not supported in SAX2, and will always throw 144 * an exception.</p> 145 * 146 * @param locale the locale for error reporting. 147 * @see org.xml.sax.Parser#setLocale 148 * @exception org.xml.sax.SAXException Thrown unless overridden. 149 */ 150 public void setLocale (Locale locale) 151 throws SAXException 152 { 153 throw new SAXNotSupportedException("setLocale not supported"); 154 } 155 156 157 /** 158 * Register the entity resolver. 159 * 160 * @param resolver The new resolver. 161 * @see org.xml.sax.Parser#setEntityResolver 162 */ 163 public void setEntityResolver (EntityResolver resolver) 164 { 165 xmlReader.setEntityResolver(resolver); 166 } 167 168 169 /** 170 * Register the DTD event handler. 171 * 172 * @param handler The new DTD event handler. 173 * @see org.xml.sax.Parser#setDTDHandler 174 */ 175 public void setDTDHandler (DTDHandler handler) 176 { 177 xmlReader.setDTDHandler(handler); 178 } 179 180 181 /** 182 * Register the SAX1 document event handler. 183 * 184 * <p>Note that the SAX1 document handler has no Namespace 185 * support.</p> 186 * 187 * @param handler The new SAX1 document event handler. 188 * @see org.xml.sax.Parser#setDocumentHandler 189 */ 190 public void setDocumentHandler (DocumentHandler handler) 191 { 192 documentHandler = handler; 193 } 194 195 196 /** 197 * Register the error event handler. 198 * 199 * @param handler The new error event handler. 200 * @see org.xml.sax.Parser#setErrorHandler 201 */ 202 public void setErrorHandler (ErrorHandler handler) 203 { 204 xmlReader.setErrorHandler(handler); 205 } 206 207 208 /** 209 * Parse the document. 210 * 211 * <p>This method will throw an exception if the embedded 212 * XMLReader does not support the 213 * http://xml.org/sax/features/namespace-prefixes property.</p> 214 * 215 * @param systemId The absolute URL of the document. 216 * @exception java.io.IOException If there is a problem reading 217 * the raw content of the document. 218 * @exception org.xml.sax.SAXException If there is a problem 219 * processing the document. 220 * @see #parse(org.xml.sax.InputSource) 221 * @see org.xml.sax.Parser#parse(java.lang.String) 222 */ 223 public void parse (String systemId) 224 throws IOException, SAXException 225 { 226 parse(new InputSource(systemId)); 227 } 228 229 230 /** 231 * Parse the document. 232 * 233 * <p>This method will throw an exception if the embedded 234 * XMLReader does not support the 235 * http://xml.org/sax/features/namespace-prefixes property.</p> 236 * 237 * @param input An input source for the document. 238 * @exception java.io.IOException If there is a problem reading 239 * the raw content of the document. 240 * @exception org.xml.sax.SAXException If there is a problem 241 * processing the document. 242 * @see #parse(java.lang.String) 243 * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource) 244 */ 245 public void parse (InputSource input) 246 throws IOException, SAXException 247 { 248 setupXMLReader(); 249 xmlReader.parse(input); 250 } 251 252 253 /** 254 * Set up the XML reader. 255 */ 256 private void setupXMLReader () 257 throws SAXException 258 { 259 xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true); 260 try { 261 xmlReader.setFeature("http://xml.org/sax/features/namespaces", 262 false); 263 } catch (SAXException e) { 264 // NO OP: it's just extra information, and we can ignore it 265 } 266 xmlReader.setContentHandler(this); 267 } 268 269 270 271 //////////////////////////////////////////////////////////////////// 272 // Implementation of org.xml.sax.ContentHandler. 273 //////////////////////////////////////////////////////////////////// 274 275 276 /** 277 * Set a document locator. 278 * 279 * @param locator The document locator. 280 * @see org.xml.sax.ContentHandler#setDocumentLocator 281 */ 282 public void setDocumentLocator (Locator locator) 283 { 284 if (documentHandler != null) 285 documentHandler.setDocumentLocator(locator); 286 } 287 288 289 /** 290 * Start document event. 291 * 292 * @exception org.xml.sax.SAXException The client may raise a 293 * processing exception. 294 * @see org.xml.sax.ContentHandler#startDocument 295 */ 296 public void startDocument () 297 throws SAXException 298 { 299 if (documentHandler != null) 300 documentHandler.startDocument(); 301 } 302 303 304 /** 305 * End document event. 306 * 307 * @exception org.xml.sax.SAXException The client may raise a 308 * processing exception. 309 * @see org.xml.sax.ContentHandler#endDocument 310 */ 311 public void endDocument () 312 throws SAXException 313 { 314 if (documentHandler != null) 315 documentHandler.endDocument(); 316 } 317 318 319 /** 320 * Adapt a SAX2 start prefix mapping event. 321 * 322 * @param prefix The prefix being mapped. 323 * @param uri The Namespace URI being mapped to. 324 * @see org.xml.sax.ContentHandler#startPrefixMapping 325 */ 326 public void startPrefixMapping (String prefix, String uri) 327 { 328 } 329 330 331 /** 332 * Adapt a SAX2 end prefix mapping event. 333 * 334 * @param prefix The prefix being mapped. 335 * @see org.xml.sax.ContentHandler#endPrefixMapping 336 */ 337 public void endPrefixMapping (String prefix) 338 { 339 } 340 341 342 /** 343 * Adapt a SAX2 start element event. 344 * 345 * @param uri The Namespace URI. 346 * @param localName The Namespace local name. 347 * @param qName The qualified (prefixed) name. 348 * @param atts The SAX2 attributes. 349 * @exception org.xml.sax.SAXException The client may raise a 350 * processing exception. 351 * @see org.xml.sax.ContentHandler#endDocument 352 */ 353 public void startElement (String uri, String localName, 354 String qName, Attributes atts) 355 throws SAXException 356 { 357 if (documentHandler != null) { 358 qAtts.setAttributes(atts); 359 documentHandler.startElement(qName, qAtts); 360 } 361 } 362 363 364 /** 365 * Adapt a SAX2 end element event. 366 * 367 * @param uri The Namespace URI. 368 * @param localName The Namespace local name. 369 * @param qName The qualified (prefixed) name. 370 * @exception org.xml.sax.SAXException The client may raise a 371 * processing exception. 372 * @see org.xml.sax.ContentHandler#endElement 373 */ 374 public void endElement (String uri, String localName, 375 String qName) 376 throws SAXException 377 { 378 if (documentHandler != null) 379 documentHandler.endElement(qName); 380 } 381 382 383 /** 384 * Adapt a SAX2 characters event. 385 * 386 * @param ch An array of characters. 387 * @param start The starting position in the array. 388 * @param length The number of characters to use. 389 * @exception org.xml.sax.SAXException The client may raise a 390 * processing exception. 391 * @see org.xml.sax.ContentHandler#characters 392 */ 393 public void characters (char ch[], int start, int length) 394 throws SAXException 395 { 396 if (documentHandler != null) 397 documentHandler.characters(ch, start, length); 398 } 399 400 401 /** 402 * Adapt a SAX2 ignorable whitespace event. 403 * 404 * @param ch An array of characters. 405 * @param start The starting position in the array. 406 * @param length The number of characters to use. 407 * @exception org.xml.sax.SAXException The client may raise a 408 * processing exception. 409 * @see org.xml.sax.ContentHandler#ignorableWhitespace 410 */ 411 public void ignorableWhitespace (char ch[], int start, int length) 412 throws SAXException 413 { 414 if (documentHandler != null) 415 documentHandler.ignorableWhitespace(ch, start, length); 416 } 417 418 419 /** 420 * Adapt a SAX2 processing instruction event. 421 * 422 * @param target The processing instruction target. 423 * @param data The remainder of the processing instruction 424 * @exception org.xml.sax.SAXException The client may raise a 425 * processing exception. 426 * @see org.xml.sax.ContentHandler#processingInstruction 427 */ 428 public void processingInstruction (String target, String data) 429 throws SAXException 430 { 431 if (documentHandler != null) 432 documentHandler.processingInstruction(target, data); 433 } 434 435 436 /** 437 * Adapt a SAX2 skipped entity event. 438 * 439 * @param name The name of the skipped entity. 440 * @see org.xml.sax.ContentHandler#skippedEntity 441 * @exception org.xml.sax.SAXException Throwable by subclasses. 442 */ 443 public void skippedEntity (String name) 444 throws SAXException 445 { 446 } 447 448 449 450 //////////////////////////////////////////////////////////////////// 451 // Internal state. 452 //////////////////////////////////////////////////////////////////// 453 454 XMLReader xmlReader; 455 DocumentHandler documentHandler; 456 AttributesAdapter qAtts; 457 458 459 460 //////////////////////////////////////////////////////////////////// 461 // Internal class. 462 //////////////////////////////////////////////////////////////////// 463 464 465 /** 466 * Internal class to wrap a SAX2 Attributes object for SAX1. 467 */ 468 final class AttributesAdapter implements AttributeList 469 { 470 AttributesAdapter () 471 { 472 } 473 474 475 /** 476 * Set the embedded Attributes object. 477 * 478 * @param The embedded SAX2 Attributes. 479 */ 480 void setAttributes (Attributes attributes) 481 { 482 this.attributes = attributes; 483 } 484 485 486 /** 487 * Return the number of attributes. 488 * 489 * @return The length of the attribute list. 490 * @see org.xml.sax.AttributeList#getLength 491 */ 492 public int getLength () 493 { 494 return attributes.getLength(); 495 } 496 497 498 /** 499 * Return the qualified (prefixed) name of an attribute by position. 500 * 501 * @return The qualified name. 502 * @see org.xml.sax.AttributeList#getName 503 */ 504 public String getName (int i) 505 { 506 return attributes.getQName(i); 507 } 508 509 510 /** 511 * Return the type of an attribute by position. 512 * 513 * @return The type. 514 * @see org.xml.sax.AttributeList#getType(int) 515 */ 516 public String getType (int i) 517 { 518 return attributes.getType(i); 519 } 520 521 522 /** 523 * Return the value of an attribute by position. 524 * 525 * @return The value. 526 * @see org.xml.sax.AttributeList#getValue(int) 527 */ 528 public String getValue (int i) 529 { 530 return attributes.getValue(i); 531 } 532 533 534 /** 535 * Return the type of an attribute by qualified (prefixed) name. 536 * 537 * @return The type. 538 * @see org.xml.sax.AttributeList#getType(java.lang.String) 539 */ 540 public String getType (String qName) 541 { 542 return attributes.getType(qName); 543 } 544 545 546 /** 547 * Return the value of an attribute by qualified (prefixed) name. 548 * 549 * @return The value. 550 * @see org.xml.sax.AttributeList#getValue(java.lang.String) 551 */ 552 public String getValue (String qName) 553 { 554 return attributes.getValue(qName); 555 } 556 557 private Attributes attributes; 558 } 559 560 } 561 562 // end of XMLReaderAdapter.java