001: // XMLReaderAdapter.java - adapt an SAX2 XMLReader to a SAX1 Parser
002: // http://www.saxproject.org
003: // Written by David Megginson
004: // NO WARRANTY! This class is in the public domain.
005: // $Id: XMLReaderAdapter.java,v 1.7 2002/02/01 20:06:20 db Exp $
006:
007: package org.xml.sax.helpers;
008:
009: import java.io.IOException;
010: import java.util.Locale;
011:
012: import org.xml.sax.Parser; // deprecated
013: import org.xml.sax.Locator;
014: import org.xml.sax.InputSource;
015: import org.xml.sax.AttributeList; // deprecated
016: import org.xml.sax.EntityResolver;
017: import org.xml.sax.DTDHandler;
018: import org.xml.sax.DocumentHandler; // deprecated
019: import org.xml.sax.ErrorHandler;
020: import org.xml.sax.SAXException;
021:
022: import org.xml.sax.XMLReader;
023: import org.xml.sax.Attributes;
024: import org.xml.sax.ContentHandler;
025: import org.xml.sax.SAXNotSupportedException;
026:
027: /**
028: * Adapt a SAX2 XMLReader as a SAX1 Parser.
029: *
030: * <blockquote>
031: * <em>This module, both source code and documentation, is in the
032: * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
033: * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
034: * for further information.
035: * </blockquote>
036: *
037: * <p>This class wraps a SAX2 {@link org.xml.sax.XMLReader XMLReader}
038: * and makes it act as a SAX1 {@link org.xml.sax.Parser Parser}. The XMLReader
039: * must support a true value for the
040: * http://xml.org/sax/features/namespace-prefixes property or parsing will fail
041: * with a {@link org.xml.sax.SAXException SAXException}; if the XMLReader
042: * supports a false value for the http://xml.org/sax/features/namespaces
043: * property, that will also be used to improve efficiency.</p>
044: *
045: * @since SAX 2.0
046: * @author David Megginson
047: * @version 2.0.1 (sax2r2)
048: * @see org.xml.sax.Parser
049: * @see org.xml.sax.XMLReader
050: */
051: public class XMLReaderAdapter implements Parser, ContentHandler {
052:
053: ////////////////////////////////////////////////////////////////////
054: // Constructor.
055: ////////////////////////////////////////////////////////////////////
056:
057: /**
058: * Create a new adapter.
059: *
060: * <p>Use the "org.xml.sax.driver" property to locate the SAX2
061: * driver to embed.</p>
062: *
063: * @exception org.xml.sax.SAXException If the embedded driver
064: * cannot be instantiated or if the
065: * org.xml.sax.driver property is not specified.
066: */
067: public XMLReaderAdapter() throws SAXException {
068: setup(XMLReaderFactory.createXMLReader());
069: }
070:
071: /**
072: * Create a new adapter.
073: *
074: * <p>Create a new adapter, wrapped around a SAX2 XMLReader.
075: * The adapter will make the XMLReader act like a SAX1
076: * Parser.</p>
077: *
078: * @param xmlReader The SAX2 XMLReader to wrap.
079: * @exception java.lang.NullPointerException If the argument is null.
080: */
081: public XMLReaderAdapter(XMLReader xmlReader) {
082: setup(xmlReader);
083: }
084:
085: /**
086: * Internal setup.
087: *
088: * @param xmlReader The embedded XMLReader.
089: */
090: private void setup(XMLReader xmlReader) {
091: if (xmlReader == null) {
092: throw new NullPointerException("XMLReader must not be null");
093: }
094: this .xmlReader = xmlReader;
095: qAtts = new AttributesAdapter();
096: }
097:
098: ////////////////////////////////////////////////////////////////////
099: // Implementation of org.xml.sax.Parser.
100: ////////////////////////////////////////////////////////////////////
101:
102: /**
103: * Set the locale for error reporting.
104: *
105: * <p>This is not supported in SAX2, and will always throw
106: * an exception.</p>
107: *
108: * @param The locale for error reporting.
109: * @see org.xml.sax.Parser#setLocale
110: * @exception org.xml.sax.SAXException Thrown unless overridden.
111: */
112: public void setLocale(Locale locale) throws SAXException {
113: throw new SAXNotSupportedException("setLocale not supported");
114: }
115:
116: /**
117: * Register the entity resolver.
118: *
119: * @param resolver The new resolver.
120: * @see org.xml.sax.Parser#setEntityResolver
121: */
122: public void setEntityResolver(EntityResolver resolver) {
123: xmlReader.setEntityResolver(resolver);
124: }
125:
126: /**
127: * Register the DTD event handler.
128: *
129: * @param handler The new DTD event handler.
130: * @see org.xml.sax.Parser#setDTDHandler
131: */
132: public void setDTDHandler(DTDHandler handler) {
133: xmlReader.setDTDHandler(handler);
134: }
135:
136: /**
137: * Register the SAX1 document event handler.
138: *
139: * <p>Note that the SAX1 document handler has no Namespace
140: * support.</p>
141: *
142: * @param handler The new SAX1 document event handler.
143: * @see org.xml.sax.Parser#setDocumentHandler
144: */
145: public void setDocumentHandler(DocumentHandler handler) {
146: documentHandler = handler;
147: }
148:
149: /**
150: * Register the error event handler.
151: *
152: * @param handler The new error event handler.
153: * @see org.xml.sax.Parser#setErrorHandler
154: */
155: public void setErrorHandler(ErrorHandler handler) {
156: xmlReader.setErrorHandler(handler);
157: }
158:
159: /**
160: * Parse the document.
161: *
162: * <p>This method will throw an exception if the embedded
163: * XMLReader does not support the
164: * http://xml.org/sax/features/namespace-prefixes property.</p>
165: *
166: * @param systemId The absolute URL of the document.
167: * @exception java.io.IOException If there is a problem reading
168: * the raw content of the document.
169: * @exception org.xml.sax.SAXException If there is a problem
170: * processing the document.
171: * @see #parse(org.xml.sax.InputSource)
172: * @see org.xml.sax.Parser#parse(java.lang.String)
173: */
174: public void parse(String systemId) throws IOException, SAXException {
175: parse(new InputSource(systemId));
176: }
177:
178: /**
179: * Parse the document.
180: *
181: * <p>This method will throw an exception if the embedded
182: * XMLReader does not support the
183: * http://xml.org/sax/features/namespace-prefixes property.</p>
184: *
185: * @param input An input source for the document.
186: * @exception java.io.IOException If there is a problem reading
187: * the raw content of the document.
188: * @exception org.xml.sax.SAXException If there is a problem
189: * processing the document.
190: * @see #parse(java.lang.String)
191: * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource)
192: */
193: public void parse(InputSource input) throws IOException,
194: SAXException {
195: setupXMLReader();
196: xmlReader.parse(input);
197: }
198:
199: /**
200: * Set up the XML reader.
201: */
202: private void setupXMLReader() throws SAXException {
203: xmlReader.setFeature(
204: "http://xml.org/sax/features/namespace-prefixes", true);
205: try {
206: xmlReader.setFeature(
207: "http://xml.org/sax/features/namespaces", false);
208: } catch (SAXException e) {
209: // NO OP: it's just extra information, and we can ignore it
210: }
211: xmlReader.setContentHandler(this );
212: }
213:
214: ////////////////////////////////////////////////////////////////////
215: // Implementation of org.xml.sax.ContentHandler.
216: ////////////////////////////////////////////////////////////////////
217:
218: /**
219: * Set a document locator.
220: *
221: * @param locator The document locator.
222: * @see org.xml.sax.ContentHandler#setDocumentLocator
223: */
224: public void setDocumentLocator(Locator locator) {
225: if (documentHandler != null)
226: documentHandler.setDocumentLocator(locator);
227: }
228:
229: /**
230: * Start document event.
231: *
232: * @exception org.xml.sax.SAXException The client may raise a
233: * processing exception.
234: * @see org.xml.sax.ContentHandler#startDocument
235: */
236: public void startDocument() throws SAXException {
237: if (documentHandler != null)
238: documentHandler.startDocument();
239: }
240:
241: /**
242: * End document event.
243: *
244: * @exception org.xml.sax.SAXException The client may raise a
245: * processing exception.
246: * @see org.xml.sax.ContentHandler#endDocument
247: */
248: public void endDocument() throws SAXException {
249: if (documentHandler != null)
250: documentHandler.endDocument();
251: }
252:
253: /**
254: * Adapt a SAX2 start prefix mapping event.
255: *
256: * @param prefix The prefix being mapped.
257: * @param uri The Namespace URI being mapped to.
258: * @see org.xml.sax.ContentHandler#startPrefixMapping
259: */
260: public void startPrefixMapping(String prefix, String uri) {
261: }
262:
263: /**
264: * Adapt a SAX2 end prefix mapping event.
265: *
266: * @param prefix The prefix being mapped.
267: * @see org.xml.sax.ContentHandler#endPrefixMapping
268: */
269: public void endPrefixMapping(String prefix) {
270: }
271:
272: /**
273: * Adapt a SAX2 start element event.
274: *
275: * @param uri The Namespace URI.
276: * @param localName The Namespace local name.
277: * @param qName The qualified (prefixed) name.
278: * @param atts The SAX2 attributes.
279: * @exception org.xml.sax.SAXException The client may raise a
280: * processing exception.
281: * @see org.xml.sax.ContentHandler#endDocument
282: */
283: public void startElement(String uri, String localName,
284: String qName, Attributes atts) throws SAXException {
285: if (documentHandler != null) {
286: qAtts.setAttributes(atts);
287: documentHandler.startElement(qName, qAtts);
288: }
289: }
290:
291: /**
292: * Adapt a SAX2 end element event.
293: *
294: * @param uri The Namespace URI.
295: * @param localName The Namespace local name.
296: * @param qName The qualified (prefixed) name.
297: * @exception org.xml.sax.SAXException The client may raise a
298: * processing exception.
299: * @see org.xml.sax.ContentHandler#endElement
300: */
301: public void endElement(String uri, String localName, String qName)
302: throws SAXException {
303: if (documentHandler != null)
304: documentHandler.endElement(qName);
305: }
306:
307: /**
308: * Adapt a SAX2 characters event.
309: *
310: * @param ch An array of characters.
311: * @param start The starting position in the array.
312: * @param length The number of characters to use.
313: * @exception org.xml.sax.SAXException The client may raise a
314: * processing exception.
315: * @see org.xml.sax.ContentHandler#characters
316: */
317: public void characters(char ch[], int start, int length)
318: throws SAXException {
319: if (documentHandler != null)
320: documentHandler.characters(ch, start, length);
321: }
322:
323: /**
324: * Adapt a SAX2 ignorable whitespace event.
325: *
326: * @param ch An array of characters.
327: * @param start The starting position in the array.
328: * @param length The number of characters to use.
329: * @exception org.xml.sax.SAXException The client may raise a
330: * processing exception.
331: * @see org.xml.sax.ContentHandler#ignorableWhitespace
332: */
333: public void ignorableWhitespace(char ch[], int start, int length)
334: throws SAXException {
335: if (documentHandler != null)
336: documentHandler.ignorableWhitespace(ch, start, length);
337: }
338:
339: /**
340: * Adapt a SAX2 processing instruction event.
341: *
342: * @param target The processing instruction target.
343: * @param data The remainder of the processing instruction
344: * @exception org.xml.sax.SAXException The client may raise a
345: * processing exception.
346: * @see org.xml.sax.ContentHandler#processingInstruction
347: */
348: public void processingInstruction(String target, String data)
349: throws SAXException {
350: if (documentHandler != null)
351: documentHandler.processingInstruction(target, data);
352: }
353:
354: /**
355: * Adapt a SAX2 skipped entity event.
356: *
357: * @param name The name of the skipped entity.
358: * @see org.xml.sax.ContentHandler#skippedEntity
359: * @exception org.xml.sax.SAXException Throwable by subclasses.
360: */
361: public void skippedEntity(String name) throws SAXException {
362: }
363:
364: ////////////////////////////////////////////////////////////////////
365: // Internal state.
366: ////////////////////////////////////////////////////////////////////
367:
368: XMLReader xmlReader;
369: DocumentHandler documentHandler;
370: AttributesAdapter qAtts;
371:
372: ////////////////////////////////////////////////////////////////////
373: // Internal class.
374: ////////////////////////////////////////////////////////////////////
375:
376: /**
377: * Internal class to wrap a SAX2 Attributes object for SAX1.
378: */
379: final class AttributesAdapter implements AttributeList {
380: AttributesAdapter() {
381: }
382:
383: /**
384: * Set the embedded Attributes object.
385: *
386: * @param The embedded SAX2 Attributes.
387: */
388: void setAttributes(Attributes attributes) {
389: this .attributes = attributes;
390: }
391:
392: /**
393: * Return the number of attributes.
394: *
395: * @return The length of the attribute list.
396: * @see org.xml.sax.AttributeList#getLength
397: */
398: public int getLength() {
399: return attributes.getLength();
400: }
401:
402: /**
403: * Return the qualified (prefixed) name of an attribute by position.
404: *
405: * @return The qualified name.
406: * @see org.xml.sax.AttributeList#getName
407: */
408: public String getName(int i) {
409: return attributes.getQName(i);
410: }
411:
412: /**
413: * Return the type of an attribute by position.
414: *
415: * @return The type.
416: * @see org.xml.sax.AttributeList#getType(int)
417: */
418: public String getType(int i) {
419: return attributes.getType(i);
420: }
421:
422: /**
423: * Return the value of an attribute by position.
424: *
425: * @return The value.
426: * @see org.xml.sax.AttributeList#getValue(int)
427: */
428: public String getValue(int i) {
429: return attributes.getValue(i);
430: }
431:
432: /**
433: * Return the type of an attribute by qualified (prefixed) name.
434: *
435: * @return The type.
436: * @see org.xml.sax.AttributeList#getType(java.lang.String)
437: */
438: public String getType(String qName) {
439: return attributes.getType(qName);
440: }
441:
442: /**
443: * Return the value of an attribute by qualified (prefixed) name.
444: *
445: * @return The value.
446: * @see org.xml.sax.AttributeList#getValue(java.lang.String)
447: */
448: public String getValue(String qName) {
449: return attributes.getValue(qName);
450: }
451:
452: private Attributes attributes;
453: }
454:
455: }
456:
457: // end of XMLReaderAdapter.java
|