001: /*
002: * $Id: StAXContentHandler.java,v 1.3 2004/04/27 20:04:42 cniles Exp $
003: *
004: * Copyright (c) 2004, Christian Niles, Unit12
005: * All rights reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions are met:
009: *
010: * * Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * * Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: *
017: * * Neither the name of Christian Niles, Unit12, nor the names of its
018: * contributors may be used to endorse or promote products derived from
019: * this software without specific prior written permission.
020: *
021: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
022: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
023: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
024: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
025: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
026: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
027: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
028: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
029: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
030: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
031: * POSSIBILITY OF SUCH DAMAGE.
032: *
033: */
034: package javanet.staxutils;
035:
036: import javax.xml.stream.Location;
037: import javax.xml.stream.XMLReporter;
038: import javax.xml.stream.XMLStreamException;
039:
040: import org.xml.sax.Attributes;
041: import org.xml.sax.Locator;
042: import org.xml.sax.SAXException;
043: import org.xml.sax.SAXParseException;
044: import org.xml.sax.ext.LexicalHandler;
045: import org.xml.sax.helpers.DefaultHandler;
046:
047: /**
048: * Base class for SAX-to-STAX bridge classes that provides common
049: * functionality.
050: *
051: * @author Christian Niles
052: * @version $Revision: 1.3 $
053: */
054: public abstract class StAXContentHandler extends DefaultHandler
055: implements LexicalHandler {
056:
057: /**
058: * Whether the parser is currently within a CDATA section.
059: */
060: protected boolean isCDATA;
061:
062: /**
063: * Buffer containing text read within the current CDATA section.
064: */
065: protected StringBuffer CDATABuffer;
066:
067: /**
068: * Stack used to store declared namespaces.
069: */
070: protected SimpleNamespaceContext namespaces;
071:
072: /**
073: * The SAX {@link Locator}provided to the handler.
074: */
075: protected Locator docLocator;
076:
077: /**
078: * The STAX {@link XMLReporter}registered to receive notifications.
079: */
080: protected XMLReporter reporter;
081:
082: public StAXContentHandler() {
083:
084: }
085:
086: public StAXContentHandler(XMLReporter reporter) {
087:
088: this .reporter = reporter;
089:
090: }
091:
092: /**
093: * Sets the {@link XMLReporter}to which warning and error messages will be
094: * sent.
095: *
096: * @param reporter The {@link XMLReporter}to notify of errors.
097: */
098: public void setXMLReporter(XMLReporter reporter) {
099:
100: this .reporter = reporter;
101:
102: }
103:
104: public void setDocumentLocator(Locator locator) {
105:
106: this .docLocator = locator;
107:
108: }
109:
110: /**
111: * Calculates the STAX {@link Location}from the SAX {@link Locator}
112: * registered with this handler. If no {@link Locator}was provided, then
113: * this method will return <code>null</code>.
114: */
115: public Location getCurrentLocation() {
116:
117: if (docLocator != null) {
118:
119: return new SAXLocation(docLocator);
120:
121: } else {
122:
123: return null;
124:
125: }
126:
127: }
128:
129: public void error(SAXParseException e) throws SAXException {
130:
131: reportException("ERROR", e);
132:
133: }
134:
135: public void fatalError(SAXParseException e) throws SAXException {
136:
137: reportException("FATAL", e);
138:
139: }
140:
141: public void warning(SAXParseException e) throws SAXException {
142:
143: reportException("WARNING", e);
144:
145: }
146:
147: public void startDocument() throws SAXException {
148:
149: namespaces = new SimpleNamespaceContext();
150:
151: }
152:
153: public void endDocument() throws SAXException {
154:
155: namespaces = null;
156:
157: }
158:
159: public void startElement(String uri, String localName,
160: String qName, Attributes attributes) throws SAXException {
161:
162: namespaces = null;
163:
164: }
165:
166: public void endElement(String uri, String localName, String qName)
167: throws SAXException {
168:
169: namespaces = null;
170:
171: }
172:
173: public void startPrefixMapping(String prefix, String uri)
174: throws SAXException {
175:
176: if (prefix == null) {
177:
178: prefix = "";
179:
180: } else if (prefix.equals("xml")) {
181:
182: return;
183:
184: }
185:
186: if (namespaces == null) {
187:
188: namespaces = new SimpleNamespaceContext();
189:
190: }
191: namespaces.setPrefix(prefix, uri);
192:
193: }
194:
195: public void endPrefixMapping(String prefix) throws SAXException {
196:
197: }
198:
199: public void startCDATA() throws SAXException {
200:
201: isCDATA = true;
202: if (CDATABuffer == null) {
203:
204: CDATABuffer = new StringBuffer();
205:
206: } else {
207:
208: CDATABuffer.setLength(0);
209:
210: }
211:
212: }
213:
214: public void characters(char[] ch, int start, int length)
215: throws SAXException {
216:
217: if (isCDATA) {
218:
219: CDATABuffer.append(ch, start, length);
220:
221: }
222:
223: }
224:
225: public void endCDATA() throws SAXException {
226:
227: isCDATA = false;
228: CDATABuffer.setLength(0);
229:
230: }
231:
232: public void comment(char[] ch, int start, int length)
233: throws SAXException {
234:
235: }
236:
237: public void endDTD() throws SAXException {
238:
239: }
240:
241: public void endEntity(String name) throws SAXException {
242:
243: }
244:
245: public void startDTD(String name, String publicId, String systemId)
246: throws SAXException {
247:
248: }
249:
250: public void startEntity(String name) throws SAXException {
251:
252: }
253:
254: /**
255: * Used to report a {@link SAXException}to the {@link XMLReporter}
256: * registered with this handler.
257: */
258: protected void reportException(String type, SAXException e)
259: throws SAXException {
260:
261: if (reporter != null) {
262:
263: try {
264:
265: reporter.report(e.getMessage(), type, e,
266: getCurrentLocation());
267:
268: } catch (XMLStreamException e1) {
269:
270: throw new SAXException(e1);
271:
272: }
273:
274: }
275:
276: }
277:
278: /**
279: * Parses an XML qualified name, and places the resulting prefix and local
280: * name in the provided String array.
281: *
282: * @param qName The qualified name to parse.
283: * @param results An array where parse results will be placed. The prefix
284: * will be placed at <code>results[0]</code>, and the local
285: * part at <code>results[1]</code>
286: */
287: public static final void parseQName(String qName, String[] results) {
288:
289: String prefix, local;
290: int idx = qName.indexOf(':');
291: if (idx >= 0) {
292:
293: prefix = qName.substring(0, idx);
294: local = qName.substring(idx + 1);
295:
296: } else {
297:
298: prefix = "";
299: local = qName;
300:
301: }
302:
303: results[0] = prefix;
304: results[1] = local;
305:
306: }
307:
308: /**
309: * {@Link Location}implementation used to expose details from a SAX
310: * {@link Locator}.
311: *
312: * @author christian
313: * @version $Revision: 1.3 $
314: */
315: private static final class SAXLocation implements Location {
316:
317: private int lineNumber;
318:
319: private int columnNumber;
320:
321: private String publicId;
322:
323: private String systemId;
324:
325: private SAXLocation(Locator locator) {
326:
327: lineNumber = locator.getLineNumber();
328: columnNumber = locator.getColumnNumber();
329: publicId = locator.getPublicId();
330: systemId = locator.getSystemId();
331:
332: }
333:
334: public int getLineNumber() {
335:
336: return lineNumber;
337:
338: }
339:
340: public int getColumnNumber() {
341:
342: return columnNumber;
343:
344: }
345:
346: public int getCharacterOffset() {
347:
348: return -1;
349:
350: }
351:
352: public String getPublicId() {
353:
354: return publicId;
355:
356: }
357:
358: public String getSystemId() {
359:
360: return systemId;
361:
362: }
363:
364: }
365:
366: }
|