1. // ParserAdapter.java - adapt a SAX1 Parser to a SAX2 XMLReader.
  2. // Written by David Megginson, sax@megginson.com
  3. // NO WARRANTY! This class is in the public domain.
  4. // $Id: ParserAdapter.java,v 1.2 2001/08/01 06:43:19 tcng Exp $
  5. package org.xml.sax.helpers;
  6. import java.io.IOException;
  7. import java.util.Enumeration;
  8. import org.xml.sax.Parser; // deprecated
  9. import org.xml.sax.InputSource;
  10. import org.xml.sax.Locator;
  11. import org.xml.sax.AttributeList; // deprecated
  12. import org.xml.sax.EntityResolver;
  13. import org.xml.sax.DTDHandler;
  14. import org.xml.sax.DocumentHandler; // deprecated
  15. import org.xml.sax.ErrorHandler;
  16. import org.xml.sax.SAXException;
  17. import org.xml.sax.SAXParseException;
  18. import org.xml.sax.XMLReader;
  19. import org.xml.sax.Attributes;
  20. import org.xml.sax.ContentHandler;
  21. import org.xml.sax.SAXNotRecognizedException;
  22. import org.xml.sax.SAXNotSupportedException;
  23. /**
  24. * Adapt a SAX1 Parser as a SAX2 XMLReader.
  25. *
  26. * <blockquote>
  27. * <em>This module, both source code and documentation, is in the
  28. * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
  29. * </blockquote>
  30. *
  31. * <p>This class wraps a SAX1 {@link org.xml.sax.Parser Parser}
  32. * and makes it act as a SAX2 {@link org.xml.sax.XMLReader XMLReader},
  33. * with feature, property, and Namespace support. Note
  34. * that it is not possible to report {@link org.xml.sax.ContentHandler#skippedEntity
  35. * skippedEntity} events, since SAX1 does not make that information available.</p>
  36. *
  37. * <p>This adapter does not test for duplicate Namespace-qualified
  38. * attribute names.</p>
  39. *
  40. * @since SAX 2.0
  41. * @author David Megginson,
  42. * <a href="mailto:sax@megginson.com">sax@megginson.com</a>
  43. * @version 2.0
  44. * @see org.xml.sax.helpers.XMLReaderAdapter
  45. * @see org.xml.sax.XMLReader
  46. * @see org.xml.sax.Parser
  47. */
  48. public class ParserAdapter implements XMLReader, DocumentHandler
  49. {
  50. ////////////////////////////////////////////////////////////////////
  51. // Constructors.
  52. ////////////////////////////////////////////////////////////////////
  53. /**
  54. * Construct a new parser adapter.
  55. *
  56. * <p>Use the "org.xml.sax.parser" property to locate the
  57. * embedded SAX1 driver.</p>
  58. *
  59. * @exception org.xml.sax.SAXException If the embedded driver
  60. * cannot be instantiated or if the
  61. * org.xml.sax.parser property is not specified.
  62. */
  63. public ParserAdapter ()
  64. throws SAXException
  65. {
  66. super();
  67. String driver = System.getProperty("org.xml.sax.parser");
  68. try {
  69. setup(ParserFactory.makeParser());
  70. } catch (ClassNotFoundException e1) {
  71. throw new
  72. SAXException("Cannot find SAX1 driver class " +
  73. driver, e1);
  74. } catch (IllegalAccessException e2) {
  75. throw new
  76. SAXException("SAX1 driver class " +
  77. driver +
  78. " found but cannot be loaded", e2);
  79. } catch (InstantiationException e3) {
  80. throw new
  81. SAXException("SAX1 driver class " +
  82. driver +
  83. " loaded but cannot be instantiated", e3);
  84. } catch (ClassCastException e4) {
  85. throw new
  86. SAXException("SAX1 driver class " +
  87. driver +
  88. " does not implement org.xml.sax.Parser");
  89. } catch (NullPointerException e5) {
  90. throw new
  91. SAXException("System property org.xml.sax.parser not specified");
  92. }
  93. }
  94. /**
  95. * Construct a new parser adapter.
  96. *
  97. * <p>Note that the embedded parser cannot be changed once the
  98. * adapter is created; to embed a different parser, allocate
  99. * a new ParserAdapter.</p>
  100. *
  101. * @param parser The SAX1 parser to embed.
  102. * @exception java.lang.NullPointerException If the parser parameter
  103. * is null.
  104. */
  105. public ParserAdapter (Parser parser)
  106. {
  107. super();
  108. setup(parser);
  109. }
  110. /**
  111. * Internal setup method.
  112. *
  113. * @param parser The embedded parser.
  114. * @exception java.lang.NullPointerException If the parser parameter
  115. * is null.
  116. */
  117. private void setup (Parser parser)
  118. {
  119. if (parser == null) {
  120. throw new
  121. NullPointerException("Parser argument must not be null");
  122. }
  123. this.parser = parser;
  124. atts = new AttributesImpl();
  125. nsSupport = new NamespaceSupport();
  126. attAdapter = new AttributeListAdapter();
  127. }
  128. ////////////////////////////////////////////////////////////////////
  129. // Implementation of org.xml.sax.XMLReader.
  130. ////////////////////////////////////////////////////////////////////
  131. //
  132. // Internal constants for the sake of convenience.
  133. //
  134. private final static String FEATURES = "http://xml.org/sax/features/";
  135. private final static String NAMESPACES = FEATURES + "namespaces";
  136. private final static String NAMESPACE_PREFIXES = FEATURES + "namespace-prefixes";
  137. private final static String VALIDATION = FEATURES + "validation";
  138. private final static String EXTERNAL_GENERAL =
  139. FEATURES + "external-general-entities";
  140. private final static String EXTERNAL_PARAMETER =
  141. FEATURES + "external-parameter-entities";
  142. /**
  143. * Set a feature for the parser.
  144. *
  145. * <p>The only features supported are namespaces and
  146. * namespace-prefixes.</p>
  147. *
  148. * @param name The feature name, as a complete URI.
  149. * @param state The requested feature state.
  150. * @exception org.xml.sax.SAXNotRecognizedException If the feature
  151. * name is not known.
  152. * @exception org.xml.sax.SAXNotSupportedException If the feature
  153. * state is not supported.
  154. * @see org.xml.sax.XMLReader#setFeature
  155. */
  156. public void setFeature (String name, boolean state)
  157. throws SAXNotRecognizedException, SAXNotSupportedException
  158. {
  159. if (name.equals(NAMESPACES)) {
  160. checkNotParsing("feature", name);
  161. namespaces = state;
  162. if (!namespaces && !prefixes) {
  163. prefixes = true;
  164. }
  165. } else if (name.equals(NAMESPACE_PREFIXES)) {
  166. checkNotParsing("feature", name);
  167. prefixes = state;
  168. if (!prefixes && !namespaces) {
  169. namespaces = true;
  170. }
  171. } else if (name.equals(VALIDATION) ||
  172. name.equals(EXTERNAL_GENERAL) ||
  173. name.equals(EXTERNAL_PARAMETER)) {
  174. throw new SAXNotSupportedException("Feature: " + name);
  175. } else {
  176. throw new SAXNotRecognizedException("Feature: " + name);
  177. }
  178. }
  179. /**
  180. * Check a parser feature.
  181. *
  182. * <p>The only features supported are namespaces and
  183. * namespace-prefixes.</p>
  184. *
  185. * @param name The feature name, as a complete URI.
  186. * @return The current feature state.
  187. * @exception org.xml.sax.SAXNotRecognizedException If the feature
  188. * name is not known.
  189. * @exception org.xml.sax.SAXNotSupportedException If querying the
  190. * feature state is not supported.
  191. * @see org.xml.sax.XMLReader#setFeature
  192. */
  193. public boolean getFeature (String name)
  194. throws SAXNotRecognizedException, SAXNotSupportedException
  195. {
  196. if (name.equals(NAMESPACES)) {
  197. return namespaces;
  198. } else if (name.equals(NAMESPACE_PREFIXES)) {
  199. return prefixes;
  200. } else if (name.equals(VALIDATION) ||
  201. name.equals(EXTERNAL_GENERAL) ||
  202. name.equals(EXTERNAL_PARAMETER)) {
  203. throw new SAXNotSupportedException("Feature: " + name);
  204. } else {
  205. throw new SAXNotRecognizedException("Feature: " + name);
  206. }
  207. }
  208. /**
  209. * Set a parser property.
  210. *
  211. * <p>No special properties are currently supported.</p>
  212. *
  213. * @param name The property name.
  214. * @param value The property value.
  215. * @exception org.xml.sax.SAXNotRecognizedException If the feature
  216. * name is not known.
  217. * @exception org.xml.sax.SAXNotSupportedException If the feature
  218. * state is not supported.
  219. * @see org.xml.sax.XMLReader#setProperty
  220. */
  221. public void setProperty (String name, Object value)
  222. throws SAXNotRecognizedException, SAXNotSupportedException
  223. {
  224. throw new SAXNotRecognizedException("Property: " + name);
  225. }
  226. /**
  227. * Get a parser property.
  228. *
  229. * <p>No special properties are currently supported.</p>
  230. *
  231. * @param name The property name.
  232. * @return The property value.
  233. * @exception org.xml.sax.SAXNotRecognizedException If the feature
  234. * name is not known.
  235. * @exception org.xml.sax.SAXNotSupportedException If the feature
  236. * state is not supported.
  237. * @see org.xml.sax.XMLReader#getProperty
  238. */
  239. public Object getProperty (String name)
  240. throws SAXNotRecognizedException, SAXNotSupportedException
  241. {
  242. throw new SAXNotRecognizedException("Property: " + name);
  243. }
  244. /**
  245. * Set the entity resolver.
  246. *
  247. * @param resolver The new entity resolver.
  248. * @exception java.lang.NullPointerException If the entity resolver
  249. * parameter is null.
  250. * @see org.xml.sax.XMLReader#setEntityResolver
  251. */
  252. public void setEntityResolver (EntityResolver resolver)
  253. {
  254. if (resolver == null) {
  255. throw new NullPointerException("Null entity resolver");
  256. }
  257. entityResolver = resolver;
  258. }
  259. /**
  260. * Return the current entity resolver.
  261. *
  262. * @return The current entity resolver, or null if none was supplied.
  263. * @see org.xml.sax.XMLReader#getEntityResolver
  264. */
  265. public EntityResolver getEntityResolver ()
  266. {
  267. return entityResolver;
  268. }
  269. /**
  270. * Set the DTD handler.
  271. *
  272. * @param resolver The new DTD handler.
  273. * @exception java.lang.NullPointerException If the DTD handler
  274. * parameter is null.
  275. * @see org.xml.sax.XMLReader#setEntityResolver
  276. */
  277. public void setDTDHandler (DTDHandler handler)
  278. {
  279. if (handler == null) {
  280. throw new NullPointerException("Null DTD handler");
  281. }
  282. dtdHandler = handler;
  283. }
  284. /**
  285. * Return the current DTD handler.
  286. *
  287. * @return The current DTD handler, or null if none was supplied.
  288. * @see org.xml.sax.XMLReader#getEntityResolver
  289. */
  290. public DTDHandler getDTDHandler ()
  291. {
  292. return dtdHandler;
  293. }
  294. /**
  295. * Set the content handler.
  296. *
  297. * @param resolver The new content handler.
  298. * @exception java.lang.NullPointerException If the content handler
  299. * parameter is null.
  300. * @see org.xml.sax.XMLReader#setEntityResolver
  301. */
  302. public void setContentHandler (ContentHandler handler)
  303. {
  304. if (handler == null) {
  305. throw new NullPointerException("Null content handler");
  306. }
  307. contentHandler = handler;
  308. }
  309. /**
  310. * Return the current content handler.
  311. *
  312. * @return The current content handler, or null if none was supplied.
  313. * @see org.xml.sax.XMLReader#getEntityResolver
  314. */
  315. public ContentHandler getContentHandler ()
  316. {
  317. return contentHandler;
  318. }
  319. /**
  320. * Set the error handler.
  321. *
  322. * @param resolver The new error handler.
  323. * @exception java.lang.NullPointerException If the error handler
  324. * parameter is null.
  325. * @see org.xml.sax.XMLReader#setEntityResolver
  326. */
  327. public void setErrorHandler (ErrorHandler handler)
  328. {
  329. if (handler == null) {
  330. throw new NullPointerException("Null error handler");
  331. }
  332. errorHandler = handler;
  333. }
  334. /**
  335. * Return the current error handler.
  336. *
  337. * @return The current error handler, or null if none was supplied.
  338. * @see org.xml.sax.XMLReader#getEntityResolver
  339. */
  340. public ErrorHandler getErrorHandler ()
  341. {
  342. return errorHandler;
  343. }
  344. /**
  345. * Parse an XML document.
  346. *
  347. * @param systemId The absolute URL of the document.
  348. * @exception java.io.IOException If there is a problem reading
  349. * the raw content of the document.
  350. * @exception org.xml.sax.SAXException If there is a problem
  351. * processing the document.
  352. * @see #parse(org.xml.sax.InputSource)
  353. * @see org.xml.sax.Parser#parse(java.lang.String)
  354. */
  355. public void parse (String systemId)
  356. throws IOException, SAXException
  357. {
  358. parse(new InputSource(systemId));
  359. }
  360. /**
  361. * Parse an XML document.
  362. *
  363. * @param input An input source for the document.
  364. * @exception java.io.IOException If there is a problem reading
  365. * the raw content of the document.
  366. * @exception org.xml.sax.SAXException If there is a problem
  367. * processing the document.
  368. * @see #parse(java.lang.String)
  369. * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource)
  370. */
  371. public void parse (InputSource input)
  372. throws IOException, SAXException
  373. {
  374. if (parsing) {
  375. throw new SAXException("Parser is already in use");
  376. }
  377. setupParser();
  378. parsing = true;
  379. try {
  380. parser.parse(input);
  381. } finally {
  382. parsing = false;
  383. }
  384. parsing = false;
  385. }
  386. ////////////////////////////////////////////////////////////////////
  387. // Implementation of org.xml.sax.DocumentHandler.
  388. ////////////////////////////////////////////////////////////////////
  389. /**
  390. * Adapt a SAX1 document locator event.
  391. *
  392. * @param locator A document locator.
  393. * @see org.xml.sax.ContentHandler#setDocumentLocator
  394. */
  395. public void setDocumentLocator (Locator locator)
  396. {
  397. this.locator = locator;
  398. if (contentHandler != null) {
  399. contentHandler.setDocumentLocator(locator);
  400. }
  401. }
  402. /**
  403. * Adapt a SAX1 start document event.
  404. *
  405. * @exception org.xml.sax.SAXException The client may raise a
  406. * processing exception.
  407. * @see org.xml.sax.DocumentHandler#startDocument
  408. */
  409. public void startDocument ()
  410. throws SAXException
  411. {
  412. if (contentHandler != null) {
  413. contentHandler.startDocument();
  414. }
  415. }
  416. /**
  417. * Adapt a SAX1 end document event.
  418. *
  419. * @exception org.xml.sax.SAXException The client may raise a
  420. * processing exception.
  421. * @see org.xml.sax.DocumentHandler#endDocument
  422. */
  423. public void endDocument ()
  424. throws SAXException
  425. {
  426. if (contentHandler != null) {
  427. contentHandler.endDocument();
  428. }
  429. }
  430. /**
  431. * Adapt a SAX1 startElement event.
  432. *
  433. * <p>If necessary, perform Namespace processing.</p>
  434. *
  435. * @param qName The qualified (prefixed) name.
  436. * @param qAtts The XML 1.0 attribute list (with qnames).
  437. */
  438. public void startElement (String qName, AttributeList qAtts)
  439. throws SAXException
  440. {
  441. // If we're not doing Namespace
  442. // processing, dispatch this quickly.
  443. if (!namespaces) {
  444. if (contentHandler != null) {
  445. attAdapter.setAttributeList(qAtts);
  446. contentHandler.startElement("", "", qName.intern(),
  447. attAdapter);
  448. }
  449. return;
  450. }
  451. // OK, we're doing Namespace processing.
  452. nsSupport.pushContext();
  453. boolean seenDecl = false;
  454. atts.clear();
  455. // Take a first pass and copy all
  456. // attributes into the SAX2 attribute
  457. // list, noting any Namespace
  458. // declarations.
  459. int length = qAtts.getLength();
  460. for (int i = 0; i < length; i++) {
  461. String attQName = qAtts.getName(i);
  462. String type = qAtts.getType(i);
  463. String value = qAtts.getValue(i);
  464. // Found a declaration...
  465. if (attQName.startsWith("xmlns")) {
  466. String prefix;
  467. int n = attQName.indexOf(':');
  468. if (n == -1) {
  469. prefix = "";
  470. } else {
  471. prefix = attQName.substring(n+1);
  472. }
  473. if (!nsSupport.declarePrefix(prefix, value)) {
  474. reportError("Illegal Namespace prefix: " + prefix);
  475. }
  476. if (contentHandler != null) {
  477. contentHandler.startPrefixMapping(prefix, value);
  478. }
  479. // We may still have to add this to
  480. // the list.
  481. if (prefixes) {
  482. atts.addAttribute("", "", attQName.intern(),
  483. type, value);
  484. }
  485. seenDecl = true;
  486. // This isn't a declaration.
  487. } else {
  488. String attName[] = processName(attQName, true);
  489. atts.addAttribute(attName[0], attName[1], attName[2],
  490. type, value);
  491. }
  492. }
  493. // If there was a Namespace declaration,
  494. // we have to make a second pass just
  495. // to be safe -- this will happen very
  496. // rarely, possibly only once for each
  497. // document.
  498. if (seenDecl) {
  499. length = atts.getLength();
  500. for (int i = 0; i < length; i++) {
  501. String attQName = atts.getQName(i);
  502. if (!attQName.startsWith("xmlns")) {
  503. String attName[] = processName(attQName, true);
  504. atts.setURI(i, attName[0]);
  505. atts.setLocalName(i, attName[1]);
  506. }
  507. }
  508. }
  509. // OK, finally report the event.
  510. if (contentHandler != null) {
  511. String name[] = processName(qName, false);
  512. contentHandler.startElement(name[0], name[1], name[2], atts);
  513. }
  514. }
  515. /**
  516. * Adapt a SAX1 end element event.
  517. *
  518. * @param qName The qualified (prefixed) name.
  519. * @exception org.xml.sax.SAXException The client may raise a
  520. * processing exception.
  521. * @see org.xml.sax.DocumentHandler#endElement
  522. */
  523. public void endElement (String qName)
  524. throws SAXException
  525. {
  526. // If we're not doing Namespace
  527. // processing, dispatch this quickly.
  528. if (!namespaces) {
  529. if (contentHandler != null) {
  530. contentHandler.endElement("", "", qName.intern());
  531. }
  532. return;
  533. }
  534. // Split the name.
  535. String names[] = processName(qName, false);
  536. if (contentHandler != null) {
  537. contentHandler.endElement(names[0], names[1], names[2]);
  538. Enumeration prefixes = nsSupport.getDeclaredPrefixes();
  539. while (prefixes.hasMoreElements()) {
  540. String prefix = (String)prefixes.nextElement();
  541. contentHandler.endPrefixMapping(prefix);
  542. }
  543. }
  544. nsSupport.popContext();
  545. }
  546. /**
  547. * Adapt a SAX1 characters event.
  548. *
  549. * @param ch An array of characters.
  550. * @param start The starting position in the array.
  551. * @param length The number of characters to use.
  552. * @exception org.xml.sax.SAXException The client may raise a
  553. * processing exception.
  554. * @see org.xml.sax.DocumentHandler#characters
  555. */
  556. public void characters (char ch[], int start, int length)
  557. throws SAXException
  558. {
  559. if (contentHandler != null) {
  560. contentHandler.characters(ch, start, length);
  561. }
  562. }
  563. /**
  564. * Adapt a SAX1 ignorable whitespace event.
  565. *
  566. * @param ch An array of characters.
  567. * @param start The starting position in the array.
  568. * @param length The number of characters to use.
  569. * @exception org.xml.sax.SAXException The client may raise a
  570. * processing exception.
  571. * @see org.xml.sax.DocumentHandler#ignorableWhitespace
  572. */
  573. public void ignorableWhitespace (char ch[], int start, int length)
  574. throws SAXException
  575. {
  576. if (contentHandler != null) {
  577. contentHandler.ignorableWhitespace(ch, start, length);
  578. }
  579. }
  580. /**
  581. * Adapt a SAX1 processing instruction event.
  582. *
  583. * @param target The processing instruction target.
  584. * @param data The remainder of the processing instruction
  585. * @exception org.xml.sax.SAXException The client may raise a
  586. * processing exception.
  587. * @see org.xml.sax.DocumentHandler#processingInstruction
  588. */
  589. public void processingInstruction (String target, String data)
  590. throws SAXException
  591. {
  592. if (contentHandler != null) {
  593. contentHandler.processingInstruction(target, data);
  594. }
  595. }
  596. ////////////////////////////////////////////////////////////////////
  597. // Internal utility methods.
  598. ////////////////////////////////////////////////////////////////////
  599. /**
  600. * Initialize the parser before each run.
  601. */
  602. private void setupParser ()
  603. {
  604. nsSupport.reset();
  605. if (entityResolver != null) {
  606. parser.setEntityResolver(entityResolver);
  607. }
  608. if (dtdHandler != null) {
  609. parser.setDTDHandler(dtdHandler);
  610. }
  611. if (errorHandler != null) {
  612. parser.setErrorHandler(errorHandler);
  613. }
  614. parser.setDocumentHandler(this);
  615. locator = null;
  616. }
  617. /**
  618. * Process a qualified (prefixed) name.
  619. *
  620. * <p>If the name has an undeclared prefix, use only the qname
  621. * and make an ErrorHandler.error callback in case the app is
  622. * interested.</p>
  623. *
  624. * @param qName The qualified (prefixed) name.
  625. * @param isAttribute true if this is an attribute name.
  626. * @return The name split into three parts.
  627. * @exception org.xml.sax.SAXException The client may throw
  628. * an exception if there is an error callback.
  629. */
  630. private String [] processName (String qName, boolean isAttribute)
  631. throws SAXException
  632. {
  633. String parts[] = nsSupport.processName(qName, nameParts,
  634. isAttribute);
  635. if (parts == null) {
  636. parts = new String[3];
  637. parts[2] = qName.intern();
  638. reportError("Undeclared prefix: " + qName);
  639. }
  640. return parts;
  641. }
  642. /**
  643. * Report a non-fatal error.
  644. *
  645. * @param message The error message.
  646. * @exception org.xml.sax.SAXException The client may throw
  647. * an exception.
  648. */
  649. void reportError (String message)
  650. throws SAXException
  651. {
  652. if (errorHandler == null) {
  653. return;
  654. }
  655. SAXParseException e;
  656. if (locator != null) {
  657. e = new SAXParseException(message, locator);
  658. } else {
  659. e = new SAXParseException(message, null, null, -1, -1);
  660. }
  661. errorHandler.error(e);
  662. }
  663. /**
  664. * Throw an exception if we are parsing.
  665. *
  666. * <p>Use this method to detect illegal feature or
  667. * property changes.</p>
  668. *
  669. * @param type The type of thing (feature or property).
  670. * @param name The feature or property name.
  671. * @exception org.xml.sax.SAXNotSupportedException If a
  672. * document is currently being parsed.
  673. */
  674. private void checkNotParsing (String type, String name)
  675. throws SAXNotSupportedException
  676. {
  677. if (parsing) {
  678. throw new SAXNotSupportedException("Cannot change " +
  679. type + ' ' +
  680. name + " while parsing");
  681. }
  682. }
  683. ////////////////////////////////////////////////////////////////////
  684. // Internal state.
  685. ////////////////////////////////////////////////////////////////////
  686. private NamespaceSupport nsSupport;
  687. private AttributeListAdapter attAdapter;
  688. private boolean parsing = false;
  689. private String nameParts[] = new String[3];
  690. private Parser parser = null;
  691. private AttributesImpl atts = null;
  692. // Features
  693. private boolean namespaces = true;
  694. private boolean prefixes = false;
  695. // Properties
  696. // Handlers
  697. Locator locator;
  698. EntityResolver entityResolver = null;
  699. DTDHandler dtdHandler = null;
  700. ContentHandler contentHandler = null;
  701. ErrorHandler errorHandler = null;
  702. ////////////////////////////////////////////////////////////////////
  703. // Inner class to wrap an AttributeList when not doing NS proc.
  704. ////////////////////////////////////////////////////////////////////
  705. /**
  706. * Adapt a SAX1 AttributeList as a SAX2 Attributes object.
  707. *
  708. * <p>This class is in the Public Domain, and comes with NO
  709. * WARRANTY of any kind.</p>
  710. *
  711. * <p>This wrapper class is used only when Namespace support
  712. * is disabled -- it provides pretty much a direct mapping
  713. * from SAX1 to SAX2, except that names and types are
  714. * interned whenever requested.</p>
  715. */
  716. final class AttributeListAdapter implements Attributes
  717. {
  718. /**
  719. * Construct a new adapter.
  720. */
  721. AttributeListAdapter ()
  722. {
  723. }
  724. /**
  725. * Set the embedded AttributeList.
  726. *
  727. * <p>This method must be invoked before any of the others
  728. * can be used.</p>
  729. *
  730. * @param The SAX1 attribute list (with qnames).
  731. */
  732. void setAttributeList (AttributeList qAtts)
  733. {
  734. this.qAtts = qAtts;
  735. }
  736. /**
  737. * Return the length of the attribute list.
  738. *
  739. * @return The number of attributes in the list.
  740. * @see org.xml.sax.Attributes#getLength
  741. */
  742. public int getLength ()
  743. {
  744. return qAtts.getLength();
  745. }
  746. /**
  747. * Return the Namespace URI of the specified attribute.
  748. *
  749. * @param The attribute's index.
  750. * @return Always the empty string.
  751. * @see org.xml.sax.Attributes#getURI
  752. */
  753. public String getURI (int i)
  754. {
  755. return "";
  756. }
  757. /**
  758. * Return the local name of the specified attribute.
  759. *
  760. * @param The attribute's index.
  761. * @return Always the empty string.
  762. * @see org.xml.sax.Attributes#getLocalName
  763. */
  764. public String getLocalName (int i)
  765. {
  766. return "";
  767. }
  768. /**
  769. * Return the qualified (prefixed) name of the specified attribute.
  770. *
  771. * @param The attribute's index.
  772. * @return The attribute's qualified name, internalized.
  773. */
  774. public String getQName (int i)
  775. {
  776. return qAtts.getName(i).intern();
  777. }
  778. /**
  779. * Return the type of the specified attribute.
  780. *
  781. * @param The attribute's index.
  782. * @return The attribute's type as an internalized string.
  783. */
  784. public String getType (int i)
  785. {
  786. return qAtts.getType(i).intern();
  787. }
  788. /**
  789. * Return the value of the specified attribute.
  790. *
  791. * @param The attribute's index.
  792. * @return The attribute's value.
  793. */
  794. public String getValue (int i)
  795. {
  796. return qAtts.getValue(i);
  797. }
  798. /**
  799. * Look up an attribute index by Namespace name.
  800. *
  801. * @param uri The Namespace URI or the empty string.
  802. * @param localName The local name.
  803. * @return The attributes index, or -1 if none was found.
  804. * @see org.xml.sax.Attributes#getIndex(java.lang.String,java.lang.String)
  805. */
  806. public int getIndex (String uri, String localName)
  807. {
  808. return -1;
  809. }
  810. /**
  811. * Look up an attribute index by qualified (prefixed) name.
  812. *
  813. * @param qName The qualified name.
  814. * @return The attributes index, or -1 if none was found.
  815. * @see org.xml.sax.Attributes#getIndex(java.lang.String)
  816. */
  817. public int getIndex (String qName)
  818. {
  819. int max = atts.getLength();
  820. for (int i = 0; i < max; i++) {
  821. if (qAtts.getName(i).equals(qName)) {
  822. return i;
  823. }
  824. }
  825. return -1;
  826. }
  827. /**
  828. * Look up the type of an attribute by Namespace name.
  829. *
  830. * @param uri The Namespace URI
  831. * @param localName The local name.
  832. * @return The attribute's type as an internalized string.
  833. */
  834. public String getType (String uri, String localName)
  835. {
  836. return null;
  837. }
  838. /**
  839. * Look up the type of an attribute by qualified (prefixed) name.
  840. *
  841. * @param qName The qualified name.
  842. * @return The attribute's type as an internalized string.
  843. */
  844. public String getType (String qName)
  845. {
  846. return qAtts.getType(qName).intern();
  847. }
  848. /**
  849. * Look up the value of an attribute by Namespace name.
  850. *
  851. * @param uri The Namespace URI
  852. * @param localName The local name.
  853. * @return The attribute's value.
  854. */
  855. public String getValue (String uri, String localName)
  856. {
  857. return null;
  858. }
  859. /**
  860. * Look up the value of an attribute by qualified (prefixed) name.
  861. *
  862. * @param qName The qualified name.
  863. * @return The attribute's value.
  864. */
  865. public String getValue (String qName)
  866. {
  867. return qAtts.getValue(qName);
  868. }
  869. private AttributeList qAtts;
  870. }
  871. }
  872. // end of ParserAdapter.java