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