0001: /*
0002: * This file is part of the WfMOpen project.
0003: * Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
0004: * All rights reserved.
0005: *
0006: * This program is free software; you can redistribute it and/or modify
0007: * it under the terms of the GNU General Public License as published by
0008: * the Free Software Foundation; either version 2 of the License, or
0009: * (at your option) any later version.
0010: *
0011: * This program is distributed in the hope that it will be useful,
0012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0014: * GNU General Public License for more details.
0015: *
0016: * You should have received a copy of the GNU General Public License
0017: * along with this program; if not, write to the Free Software
0018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0019: *
0020: * $Id: SAXContentBuffer.java,v 1.4 2007/03/27 21:59:43 mlipp Exp $
0021: *
0022: * $Log: SAXContentBuffer.java,v $
0023: * Revision 1.4 2007/03/27 21:59:43 mlipp
0024: * Fixed lots of checkstyle warnings.
0025: *
0026: * Revision 1.3 2006/09/29 12:32:11 drmlipp
0027: * Consistently using WfMOpen as projct name now.
0028: *
0029: * Revision 1.2 2006/03/08 14:46:43 drmlipp
0030: * Synchronized with 1.3.3p5.
0031: *
0032: * Revision 1.1.1.3.6.2 2006/03/02 15:29:51 drmlipp
0033: * Added toW3cDom().
0034: *
0035: * Revision 1.1.1.3.6.1 2005/12/05 12:12:50 drmlipp
0036: * Added toString() to SAXContentBuffer.
0037: *
0038: * Revision 1.1.1.3 2004/08/18 15:17:35 drmlipp
0039: * Update to 1.2
0040: *
0041: * Revision 1.15 2004/06/30 20:52:37 lipp
0042: * Fixed null pointer exception.
0043: *
0044: * Revision 1.14 2004/06/25 14:51:33 lipp
0045: * Minimal implementation of XMLStreamReader.
0046: *
0047: * Revision 1.13 2004/06/24 20:15:27 lipp
0048: * Started pull API for SAXContentBuffer.
0049: *
0050: * Revision 1.12 2004/05/09 18:41:43 lipp
0051: * Added support for content > 32k.
0052: *
0053: * Revision 1.11 2003/10/18 09:22:23 lipp
0054: * Made emit multi-thread capable.
0055: *
0056: * Revision 1.10 2003/06/27 08:51:46 lipp
0057: * Fixed copyright/license information.
0058: *
0059: * Revision 1.9 2003/04/24 19:47:50 lipp
0060: * Removed dependency between general util and workflow api.
0061: *
0062: * Revision 1.8 2003/04/22 16:35:48 lipp
0063: * Implements SAXEventBuffer now.
0064: *
0065: * Revision 1.7 2003/04/22 11:13:11 lipp
0066: * Improved bufer length handling.
0067: *
0068: * Revision 1.6 2003/04/21 21:26:09 lipp
0069: * Temporary fix for buffer length error.
0070: *
0071: * Revision 1.5 2003/04/18 18:40:17 lipp
0072: * Better performing implementation of SAXContentBuffer.
0073: *
0074: * Revision 1.4 2002/08/26 20:23:13 lipp
0075: * Lots of method renames.
0076: *
0077: * Revision 1.3 2002/08/25 17:56:09 lipp
0078: * Making copy of attributes in SAXContentbuffer anr re-introduced
0079: * attrs.clear(). (Usage of SAXContentBuffer should be transparent.)
0080: *
0081: * Revision 1.2 2002/07/30 08:00:55 huaiyang
0082: * Implements the method of characters.
0083: *
0084: * Revision 1.1 2002/07/29 21:58:53 lipp
0085: * Moved SAXContentBuffer to sax package.
0086: *
0087: * Revision 1.3 2002/07/24 12:32:14 huaiyang
0088: * Implements the defined methods.
0089: *
0090: * Revision 1.2 2002/07/24 05:48:16 huaiyang
0091: * javadocs added.
0092: *
0093: * Revision 1.1 2002/07/17 15:23:51 lipp
0094: * Design definition, to be implemented.
0095: *
0096: */
0097: package de.danet.an.util.sax;
0098:
0099: import java.io.InputStream;
0100: import java.io.Serializable;
0101: import java.io.StringWriter;
0102:
0103: import java.util.ArrayList;
0104: import java.util.HashMap;
0105: import java.util.List;
0106: import java.util.Map;
0107: import java.util.NoSuchElementException;
0108:
0109: import java.text.ParsePosition;
0110:
0111: import javax.xml.namespace.NamespaceContext;
0112: import javax.xml.namespace.QName;
0113: import javax.xml.stream.Location;
0114: import javax.xml.stream.XMLStreamConstants;
0115: import javax.xml.stream.XMLStreamException;
0116: import javax.xml.stream.XMLStreamReader;
0117: import javax.xml.transform.OutputKeys;
0118: import javax.xml.transform.Templates;
0119: import javax.xml.transform.TransformerFactory;
0120: import javax.xml.transform.dom.DOMResult;
0121: import javax.xml.transform.sax.SAXTransformerFactory;
0122: import javax.xml.transform.sax.TransformerHandler;
0123: import javax.xml.transform.stream.StreamResult;
0124: import javax.xml.transform.stream.StreamSource;
0125:
0126: import org.w3c.dom.Node;
0127: import org.xml.sax.Attributes;
0128: import org.xml.sax.ContentHandler;
0129: import org.xml.sax.Locator;
0130: import org.xml.sax.SAXException;
0131: import org.xml.sax.ext.LexicalHandler;
0132: import org.xml.sax.helpers.AttributesImpl;
0133: import org.xml.sax.helpers.LocatorImpl;
0134:
0135: /**
0136: * This class provides a buffer for SAX content events. The events
0137: * reported to an instance of this class are internally
0138: * recorded. After recording, the events may be played back an
0139: * arbitrary number of times.<P>
0140: *
0141: * The class implements {@link Serializable
0142: * <code>Serializable</code>}. An instance of this class may thus be
0143: * transferred to another process and the SAX events may be replayed
0144: * there.<P>
0145: *
0146: * This implementation uses code from Apache's XMLByteStreamCompiler
0147: * and associated interpreter.
0148: *
0149: * @author <a href="mailto:lipp@danet.de"></a>
0150: * @version $Revision: 1.4 $
0151: */
0152: public class SAXContentBuffer implements ContentHandler,
0153: LexicalHandler, Serializable {
0154:
0155: /** Version id for serialization. */
0156: static final long serialVersionUID = 8913598909630773323L;
0157:
0158: private static final int START_DOCUMENT = 0;
0159: private static final int END_DOCUMENT = 1;
0160: private static final int START_PREFIX_MAPPING = 2;
0161: private static final int END_PREFIX_MAPPING = 3;
0162: private static final int START_ELEMENT = 4;
0163: private static final int END_ELEMENT = 5;
0164: private static final int CHARACTERS = 6;
0165: private static final int IGNORABLE_WHITESPACE = 7;
0166: private static final int PROCESSING_INSTRUCTION = 8;
0167: private static final int COMMENT = 9;
0168: private static final int LOCATOR = 10;
0169: private static final int START_DTD = 11;
0170: private static final int END_DTD = 12;
0171: private static final int START_CDATA = 13;
0172: private static final int END_CDATA = 14;
0173: private static final int SKIPPED_ENTITY = 15;
0174: private static final int START_ENTITY = 16;
0175: private static final int END_ENTITY = 17;
0176:
0177: private static Templates toStringTemplates = null;
0178:
0179: private transient Map map = new HashMap();
0180: private transient int count = 0;
0181:
0182: /** The buffer for the compile xml byte stream. */
0183: private byte[] buf = new byte[2000];
0184:
0185: /** The number of valid bytes in the buffer. */
0186: private int bufPos = 0;
0187:
0188: /** The current depth of the tree being recorded. */
0189: private int depth = 0;
0190:
0191: /**
0192: * Creates an instance of <code>SAXContentBuffer</code>
0193: * with all attributes initialized to default values.
0194: */
0195: public SAXContentBuffer() {
0196: }
0197:
0198: /**
0199: * Receive an object for locating the origin of SAX document events.
0200: *
0201: * @param locator An object that can return the location of any
0202: * SAX document event.
0203: * @see org.xml.sax.Locator
0204: */
0205: public void setDocumentLocator(Locator locator) {
0206: if (locator == null) {
0207: return;
0208: }
0209: try {
0210: writeEvent(LOCATOR);
0211: String publicId = locator.getPublicId();
0212: String systemId = locator.getSystemId();
0213: writeString(publicId != null ? publicId : "");
0214: writeString(systemId != null ? systemId : "");
0215: write(locator.getLineNumber());
0216: write(locator.getColumnNumber());
0217: } catch (Exception e) {
0218: throw new IllegalStateException(
0219: "Cannot write locator info: " + e.getMessage());
0220: }
0221: }
0222:
0223: /**
0224: * Receive notification of the beginning of a document.
0225: *
0226: * @throws SAXException Any SAX exception, possibly
0227: * wrapping another exception.
0228: * @see #endDocument
0229: */
0230: public void startDocument() throws SAXException {
0231: writeEvent(START_DOCUMENT);
0232: }
0233:
0234: /**
0235: * Receive notification of the end of a document.
0236: *
0237: * @throws SAXException Any SAX exception, possibly
0238: * wrapping another exception.
0239: * @see #startDocument
0240: */
0241: public void endDocument() throws SAXException {
0242: writeEvent(END_DOCUMENT);
0243: pack();
0244: }
0245:
0246: /**
0247: * Begin the scope of a prefix-URI Namespace mapping.
0248: *
0249: * @param prefix The Namespace prefix being declared.
0250: * @param uri The Namespace URI the prefix is mapped to.
0251: * @throws SAXException The client may throw an
0252: * exception during processing.
0253: * @see #endPrefixMapping
0254: * @see #startElement
0255: */
0256: public void startPrefixMapping(String prefix, String uri)
0257: throws SAXException {
0258: writeEvent(START_PREFIX_MAPPING);
0259: writeString(prefix);
0260: writeString(uri);
0261: }
0262:
0263: /**
0264: * End the scope of a prefix-URI mapping.
0265: *
0266: * @param prefix The prefix that was being mapping.
0267: * @throws SAXException The client may throw
0268: * an exception during processing.
0269: * @see #startPrefixMapping
0270: * @see #endElement
0271: */
0272: public void endPrefixMapping(String prefix) throws SAXException {
0273: writeEvent(END_PREFIX_MAPPING);
0274: writeString(prefix);
0275: }
0276:
0277: /**
0278: * Receive notification of the beginning of an element.
0279: *
0280: * @param namespaceURI The Namespace URI, or the empty string if the
0281: * element has no Namespace URI or if Namespace
0282: * processing is not being performed.
0283: * @param localName The local name (without prefix), or the
0284: * empty string if Namespace processing is not being
0285: * performed.
0286: * @param qName The qualified name (with prefix), or the
0287: * empty string if qualified names are not available.
0288: * @param atts The attributes attached to the element. If
0289: * there are no attributes, it shall be an empty
0290: * Attributes object.
0291: * @throws SAXException Any SAX exception, possibly
0292: * wrapping another exception.
0293: * @see #endElement
0294: * @see org.xml.sax.Attributes
0295: */
0296: public void startElement(String namespaceURI, String localName,
0297: String qName, Attributes atts) throws SAXException {
0298: depth += 1;
0299: int length = atts.getLength();
0300: writeEvent(START_ELEMENT);
0301: writeAttributes(length);
0302: for (int i = 0; i < length; i++) {
0303: writeString(atts.getURI(i));
0304: writeString(atts.getLocalName(i));
0305: writeString(atts.getQName(i));
0306: writeString(atts.getType(i));
0307: writeString(atts.getValue(i));
0308: }
0309: writeString((namespaceURI == null ? "" : namespaceURI));
0310: writeString(localName);
0311: writeString(qName);
0312: }
0313:
0314: /**
0315: * Receive notification of the end of an element.
0316: *
0317: * @param namespaceURI The Namespace URI, or the empty string if the
0318: * element has no Namespace URI or if Namespace
0319: * processing is not being performed.
0320: * @param localName The local name (without prefix), or the
0321: * empty string if Namespace processing is not being
0322: * performed.
0323: * @param qName The qualified XML 1.0 name (with prefix), or the
0324: * empty string if qualified names are not available.
0325: * @throws SAXException Any SAX exception, possibly
0326: * wrapping another exception.
0327: */
0328: public void endElement(String namespaceURI, String localName,
0329: String qName) throws SAXException {
0330: writeEvent(END_ELEMENT);
0331: writeString((namespaceURI == null ? "" : namespaceURI));
0332: writeString(localName);
0333: writeString(qName);
0334: depth -= 1;
0335: }
0336:
0337: /**
0338: * Receive notification of character data.
0339: *
0340: * @param ch The characters from the XML document.
0341: * @param start The start position in the array.
0342: * @param length The number of characters to read from the array.
0343: * @throws SAXException Any SAX exception, possibly
0344: * wrapping another exception.
0345: * @see #ignorableWhitespace
0346: * @see org.xml.sax.Locator
0347: */
0348: public void characters(char[] ch, int start, int length)
0349: throws SAXException {
0350: writeEvent(CHARACTERS);
0351: writeChars(ch, start, length, false);
0352: }
0353:
0354: /**
0355: * Receive notification of ignorable whitespace in element content.
0356: *
0357: * @param ch The characters from the XML document.
0358: * @param start The start position in the array.
0359: * @param length The number of characters to read from the array.
0360: * @throws SAXException Any SAX exception, possibly
0361: * wrapping another exception.
0362: * @see #characters
0363: */
0364: public void ignorableWhitespace(char[] ch, int start, int length)
0365: throws SAXException {
0366: writeEvent(IGNORABLE_WHITESPACE);
0367: writeChars(ch, start, length, false);
0368: }
0369:
0370: /**
0371: * Receive notification of a processing instruction.
0372: *
0373: * @param target The processing instruction target.
0374: * @param data The processing instruction data, or null if
0375: * none was supplied. The data does not include any
0376: * whitespace separating it from the target.
0377: * @throws SAXException Any SAX exception, possibly
0378: * wrapping another exception.
0379: */
0380: public void processingInstruction(String target, String data)
0381: throws SAXException {
0382: writeEvent(PROCESSING_INSTRUCTION);
0383: writeString(target);
0384: writeString(data);
0385: }
0386:
0387: /**
0388: * Receive notification of a skipped entity.
0389: *
0390: * @param name The name of the skipped entity. If it is a
0391: * parameter entity, the name will begin with '%', and if it is
0392: * the external DTD subset, it will be the string "[dtd]".
0393: * @throws SAXException Any SAX exception, possibly
0394: * wrapping another exception.
0395: */
0396: public void skippedEntity(String name) throws SAXException {
0397: writeEvent(SKIPPED_ENTITY);
0398: writeString(name);
0399: }
0400:
0401: /**
0402: * Report the start of DTD declarations, if any.
0403: *
0404: * @param name The document type name.
0405: * @param publicId The declared public identifier for the external DTD
0406: * subset, or null if none was declared.
0407: * @param systemId The declared system identifier for the external DTD
0408: * subset, or null if none was declared.
0409: * @throws SAXException not thrown.
0410: */
0411: public void startDTD(String name, String publicId, String systemId)
0412: throws SAXException {
0413: writeEvent(START_DTD);
0414: writeString(name);
0415: writeString(publicId != null ? publicId : "");
0416: writeString(systemId != null ? systemId : "");
0417: }
0418:
0419: /**
0420: * Report the end of DTD declarations.
0421: * @throws SAXException not thrown.
0422: */
0423: public void endDTD() throws SAXException {
0424: writeEvent(END_DTD);
0425: }
0426:
0427: /**
0428: * Report the beginning of an entity.
0429: *
0430: * @param name The name of the entity. If it is a parameter entity, the
0431: * name will begin with '%'.
0432: * @throws SAXException not thrown.
0433: */
0434: public void startEntity(String name) throws SAXException {
0435: writeEvent(START_ENTITY);
0436: writeString(name);
0437: }
0438:
0439: /**
0440: * Report the end of an entity.
0441: *
0442: * @param name The name of the entity that is ending.
0443: * @throws SAXException not thrown.
0444: */
0445: public void endEntity(String name) throws SAXException {
0446: writeEvent(END_ENTITY);
0447: writeString(name);
0448: }
0449:
0450: /**
0451: * Report the start of a CDATA section.
0452: * @throws SAXException not thrown.
0453: */
0454: public void startCDATA() throws SAXException {
0455: writeEvent(START_CDATA);
0456: }
0457:
0458: /**
0459: * Report the end of a CDATA section.
0460: * @throws SAXException not thrown.
0461: */
0462: public void endCDATA() throws SAXException {
0463: writeEvent(END_CDATA);
0464: }
0465:
0466: /**
0467: * Report an XML comment anywhere in the document.
0468: *
0469: * @param ary An array holding the characters in the comment.
0470: * @param start The starting position in the array.
0471: * @param length The number of characters to use from the array.
0472: * @throws SAXException not thrown.
0473: */
0474: public void comment(char[] ary, int start, int length)
0475: throws SAXException {
0476: try {
0477: writeEvent(COMMENT);
0478: writeChars(ary, start, length, false);
0479: } catch (Exception e) {
0480: throw new SAXException(e);
0481: }
0482: }
0483:
0484: private final void writeEvent(int event) throws SAXException {
0485: write(event);
0486: }
0487:
0488: private final void writeAttributes(int attributes)
0489: throws SAXException {
0490: write((attributes >>> 8) & 0xFF);
0491: write((attributes >>> 0) & 0xFF);
0492: }
0493:
0494: private final void writeString(String str) throws SAXException {
0495: Integer index = (Integer) map.get(str);
0496: if (index == null) {
0497: int length = str.length();
0498: map.put(str, new Integer(count++));
0499: writeChars(str.toCharArray(), 0, length, true);
0500: } else {
0501: int i = index.intValue();
0502: write(((i >>> 8) & 0xFF) | 0x80);
0503: write((i >>> 0) & 0xFF);
0504: }
0505: }
0506:
0507: private final void writeChars(char[] ch, int start, int length,
0508: boolean limitLength) throws SAXException {
0509: int utflen = 0;
0510: int c, count = 0;
0511:
0512: for (int i = 0; i < length; i++) {
0513: c = ch[i + start];
0514: if ((c >= 0x0001) && (c <= 0x007F)) {
0515: utflen++;
0516: } else if (c > 0x07FF) {
0517: utflen += 3;
0518: } else {
0519: utflen += 2;
0520: }
0521: }
0522:
0523: byte[] bytearr = null;
0524: if (utflen > 0x00007FFF) {
0525: if (limitLength) {
0526: throw new SAXException("UTFDataFormatException: "
0527: + "String cannot be longer than 32k.");
0528: }
0529: bytearr = new byte[utflen + 6];
0530: bytearr[count++] = (byte) (0xFF);
0531: bytearr[count++] = (byte) (0xFF);
0532: bytearr[count++] = (byte) ((utflen >>> 24) & 0xFF);
0533: bytearr[count++] = (byte) ((utflen >>> 16) & 0xFF);
0534: bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
0535: bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
0536: } else {
0537: bytearr = new byte[utflen + 2];
0538: bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
0539: bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
0540: }
0541: for (int i = 0; i < length; i++) {
0542: c = ch[i + start];
0543: if ((c >= 0x0001) && (c <= 0x007F)) {
0544: bytearr[count++] = (byte) c;
0545: } else if (c > 0x07FF) {
0546: bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
0547: bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
0548: bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
0549: } else {
0550: bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
0551: bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
0552: }
0553: }
0554:
0555: write(bytearr);
0556: }
0557:
0558: private void write(byte[] b) {
0559: int len = b.length;
0560: if (len == 0) {
0561: return;
0562: }
0563: int newcount = bufPos + len;
0564: if (newcount > buf.length) {
0565: byte[] newbuf = new byte[Math.max(
0566: (depth > 0 ? buf.length << 1 : 100), newcount)];
0567: System.arraycopy(buf, 0, newbuf, 0, bufPos);
0568: buf = newbuf;
0569: }
0570: System.arraycopy(b, 0, buf, bufPos, len);
0571: bufPos = newcount;
0572: }
0573:
0574: private void write(int b) {
0575: int newcount = bufPos + 1;
0576: if (newcount > buf.length) {
0577: byte[] newbuf = new byte[Math.max(
0578: (depth > 0 ? buf.length << 1 : 100), newcount)];
0579: System.arraycopy(buf, 0, newbuf, 0, bufPos);
0580: buf = newbuf;
0581: }
0582: buf[bufPos] = (byte) b;
0583: bufPos = newcount;
0584: }
0585:
0586: /**
0587: * The internal buffer used to record events is enlarged in
0588: * chunks. So some space may be left after the last event has been
0589: * recorded. This method resizes the buffer to the minimum.<P>
0590: *
0591: * This method is called by {@link #endDocument
0592: * <code>endDocument</code>} automatically. However, if only an
0593: * XML fragment is recorded, there may never be an
0594: * <code>endDocument</code> event and the mothod should be called
0595: * manually.
0596: */
0597: public void pack() {
0598: if (buf.length == bufPos) {
0599: return;
0600: }
0601: byte[] newbuf = new byte[bufPos];
0602: System.arraycopy(buf, 0, newbuf, 0, bufPos);
0603: buf = newbuf;
0604: }
0605:
0606: /**
0607: * Emits the events to the given <code>ContentHandler</code> and
0608: * <code>LexicalHandler</code>.
0609: *
0610: * @param contentHandler the content handler that is to receive
0611: * the events.
0612: * @param lexicalHandler the lexical handler that is to receive
0613: * the events (may be <code>null</code>).
0614: * @throws SAXException Any SAX exception, possibly wrapping
0615: * another exception.
0616: */
0617: public void emit(ContentHandler contentHandler,
0618: LexicalHandler lexicalHandler) throws SAXException {
0619: List st = new ArrayList();
0620: ParsePosition curPos = new ParsePosition(0);
0621: while (curPos.getIndex() < bufPos) {
0622: switch (readEvent(curPos)) {
0623: case START_DOCUMENT:
0624: contentHandler.startDocument();
0625: break;
0626: case END_DOCUMENT:
0627: contentHandler.endDocument();
0628: break;
0629: case START_PREFIX_MAPPING:
0630: contentHandler.startPrefixMapping(
0631: readString(curPos, st), readString(curPos, st));
0632: break;
0633: case END_PREFIX_MAPPING:
0634: contentHandler.endPrefixMapping(readString(curPos, st));
0635: break;
0636: case START_ELEMENT:
0637: int attributes = readAttributes(curPos);
0638: AttributesImpl atts = new AttributesImpl();
0639: for (int i = 0; i < attributes; i++) {
0640: atts.addAttribute(readString(curPos, st),
0641: readString(curPos, st), readString(curPos,
0642: st), readString(curPos, st),
0643: readString(curPos, st));
0644: }
0645: contentHandler.startElement(readString(curPos, st),
0646: readString(curPos, st), readString(curPos, st),
0647: atts);
0648: break;
0649: case END_ELEMENT:
0650: contentHandler.endElement(readString(curPos, st),
0651: readString(curPos, st), readString(curPos, st));
0652: break;
0653: case CHARACTERS:
0654: char[] chars = readChars(curPos);
0655: int len = chars.length;
0656: while (len > 0 && chars[len - 1] == 0) {
0657: len--;
0658: }
0659: if (len > 0) {
0660: contentHandler.characters(chars, 0, len);
0661: }
0662: break;
0663: case IGNORABLE_WHITESPACE:
0664: char[] spaces = readChars(curPos);
0665: len = spaces.length;
0666: while (len > 0 && spaces[len - 1] == 0) {
0667: len--;
0668: }
0669: if (len > 0) {
0670: contentHandler.characters(spaces, 0, len);
0671: }
0672: break;
0673: case PROCESSING_INSTRUCTION:
0674: contentHandler.processingInstruction(readString(curPos,
0675: st), readString(curPos, st));
0676: break;
0677: case COMMENT:
0678: chars = readChars(curPos);
0679: if (lexicalHandler != null) {
0680: len = chars.length;
0681: while (len > 0 && chars[len - 1] == 0) {
0682: len--;
0683: }
0684: if (len > 0) {
0685: lexicalHandler.comment(chars, 0, len);
0686: }
0687: }
0688: break;
0689: case LOCATOR: {
0690: String publicId = readString(curPos, st);
0691: String systemId = readString(curPos, st);
0692: int lineNumber = read(curPos);
0693: int columnNumber = read(curPos);
0694: LocatorImpl locator = new LocatorImpl();
0695: locator.setPublicId(publicId);
0696: locator.setSystemId(systemId);
0697: locator.setLineNumber(lineNumber);
0698: locator.setColumnNumber(columnNumber);
0699: contentHandler.setDocumentLocator(locator);
0700: }
0701: break;
0702: case START_DTD:
0703: String name = readString(curPos, st);
0704: String publicId = readString(curPos, st);
0705: String systemId = readString(curPos, st);
0706: if (lexicalHandler != null) {
0707: lexicalHandler.startDTD(name, publicId, systemId);
0708: }
0709: break;
0710: case END_DTD:
0711: if (lexicalHandler != null) {
0712: lexicalHandler.endDTD();
0713: }
0714: break;
0715: case START_CDATA:
0716: if (lexicalHandler != null) {
0717: lexicalHandler.startCDATA();
0718: }
0719: break;
0720: case END_CDATA:
0721: if (lexicalHandler != null) {
0722: lexicalHandler.endCDATA();
0723: }
0724: break;
0725: case SKIPPED_ENTITY:
0726: contentHandler.skippedEntity(readString(curPos, st));
0727: break;
0728: case START_ENTITY: {
0729: String entity = readString(curPos, st);
0730: if (lexicalHandler != null) {
0731: lexicalHandler.startEntity(entity);
0732: }
0733: break;
0734: }
0735: case END_ENTITY: {
0736: String entity = readString(curPos, st);
0737: if (lexicalHandler != null) {
0738: lexicalHandler.endEntity(entity);
0739: }
0740: break;
0741: }
0742: default:
0743: throw new SAXException(
0744: "parsing error: event not supported.");
0745: }
0746: }
0747: }
0748:
0749: /**
0750: * Emits the events to the given <code>ContentHandler</code>.
0751: *
0752: * @param contentHandler the content handler that is to receive
0753: * the events.
0754: * @throws SAXException Any SAX exception, possibly wrapping
0755: * another exception.
0756: */
0757: public void emit(ContentHandler contentHandler) throws SAXException {
0758: emit(contentHandler, null);
0759: }
0760:
0761: private int readEvent(ParsePosition curPos) throws SAXException {
0762: return read(curPos);
0763: }
0764:
0765: private int readAttributes(ParsePosition curPos)
0766: throws SAXException {
0767: int ch1 = read(curPos);
0768: int ch2 = read(curPos);
0769: return ((ch1 << 8) + (ch2 << 0));
0770: }
0771:
0772: private String readString(ParsePosition curPos, List stringTab)
0773: throws SAXException {
0774: int length = readLength(curPos);
0775: int index = length & 0x00007FFF;
0776: if (length >= 0x00008000) {
0777: return (String) stringTab.get(index);
0778: } else {
0779: char[] chars = readChars(curPos, index);
0780: int len = chars.length;
0781: if (len > 0) {
0782: while (chars[len - 1] == 0) {
0783: len--;
0784: }
0785: }
0786: String str;
0787: if (len == 0) {
0788: str = "";
0789: } else {
0790: str = new String(chars, 0, len);
0791: }
0792: stringTab.add(str);
0793: return str;
0794: }
0795: }
0796:
0797: /**
0798: * The returned char array might contain any number of zero bytes
0799: * at the end
0800: */
0801: private char[] readChars(ParsePosition curPos) throws SAXException {
0802: int length = readLength(curPos);
0803: if (length == 0xFFFF) {
0804: int ch1 = read(curPos);
0805: int ch2 = read(curPos);
0806: int ch3 = read(curPos);
0807: int ch4 = read(curPos);
0808: length = ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
0809: }
0810: return readChars(curPos, length);
0811: }
0812:
0813: private int read(ParsePosition curPos) throws SAXException {
0814: if (curPos.getIndex() >= buf.length) {
0815: throw new SAXException("Reached end of input.");
0816: }
0817: int res = buf[curPos.getIndex()] & 0xff;
0818: curPos.setIndex(curPos.getIndex() + 1);
0819: return res;
0820: }
0821:
0822: /**
0823: * The returned char array might contain any number of zero bytes
0824: * at the end
0825: */
0826: private char[] readChars(ParsePosition curPos, int len)
0827: throws SAXException {
0828: char[] str = new char[len];
0829: byte[] bytearr = new byte[len];
0830: int c, char2, char3;
0831: int count = 0;
0832: int i = 0;
0833:
0834: readBytes(bytearr, curPos);
0835:
0836: while (count < len) {
0837: c = (int) bytearr[count] & 0xff;
0838: switch (c >> 4) {
0839: case 0:
0840: case 1:
0841: case 2:
0842: case 3:
0843: case 4:
0844: case 5:
0845: case 6:
0846: case 7:
0847: // 0xxxxxxx
0848: count++;
0849: str[i++] = (char) c;
0850: break;
0851: case 12:
0852: case 13:
0853: // 110x xxxx 10xx xxxx
0854: count += 2;
0855: char2 = (int) bytearr[count - 1];
0856: str[i++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
0857: break;
0858: case 14:
0859: // 1110 xxxx 10xx xxxx 10xx xxxx
0860: count += 3;
0861: char2 = (int) bytearr[count - 2];
0862: char3 = (int) bytearr[count - 1];
0863: str[i++] = ((char) (((c & 0x0F) << 12)
0864: | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)));
0865: break;
0866: default:
0867: // 10xx xxxx, 1111 xxxx
0868: throw new SAXException("UTFDataFormatException");
0869: }
0870: }
0871:
0872: return str;
0873: }
0874:
0875: private void readBytes(byte[] b, ParsePosition curPos)
0876: throws SAXException {
0877: if (curPos.getIndex() + b.length > buf.length) {
0878: // TC:
0879: // >= prevents getting the last byte
0880: // 0 1 2 3 4 input.length = 5
0881: // |_ bufPos = 2
0882: // b.length = 3
0883: // 2 + 3 > 5 ok
0884: // 2 + 3 >= 5 wrong
0885: // why has this worked before?
0886: throw new SAXException("End of input reached.");
0887: }
0888: System.arraycopy(buf, curPos.getIndex(), b, 0, b.length);
0889: curPos.setIndex(curPos.getIndex() + b.length);
0890: }
0891:
0892: private int readLength(ParsePosition curPos) throws SAXException {
0893: int ch1 = read(curPos);
0894: int ch2 = read(curPos);
0895: return ((ch1 << 8) + (ch2 << 0));
0896: }
0897:
0898: /**
0899: * Create a new <code>XMLEventReader</code> for this SAX content.
0900: * Note that the implementation of the <code>XMLEventReader</code>
0901: * is currently incomplete and provides only very basic functions.
0902: *
0903: * @return the event reader
0904: */
0905: public XMLStreamReader createXMLStreamReader() {
0906: return new SAXBufferStreamReader();
0907: }
0908:
0909: /**
0910: * An XML stream reader backed up by the
0911: * <code>SAXContentBuffer</code>.
0912: */
0913: public class SAXBufferStreamReader implements Serializable,
0914: XMLStreamReader {
0915:
0916: private ParsePosition curPos = new ParsePosition(0);
0917: private List st = new ArrayList();
0918: private AttributesImpl atts = null;
0919: private int attsIndex = 0;
0920:
0921: private String namespaceURI = null;
0922: private String localName = null;
0923: private String qName = null;
0924:
0925: // Implementation of javax.xml.stream.XMLStreamReader
0926:
0927: /**
0928: * Get the value of a feature/property from the underlying
0929: * implementation.
0930: *
0931: * @param string the name of the property, may not be null
0932: * @return the value of the property
0933: * @exception IllegalArgumentException if the property is not
0934: * supported
0935: */
0936: public Object getProperty(String string)
0937: throws IllegalArgumentException {
0938: throw new IllegalArgumentException("No such property: "
0939: + string);
0940: }
0941:
0942: /**
0943: * Returns a <code>QName</code> for the current
0944: * <codeSTART_ELEMENT</code> or <code>END_ELEMENT</code>
0945: * event.
0946: *
0947: * @return a <code>QName</code> value
0948: * @throws IllegalStateException if this is not a
0949: * <code>START_ELEMENT</code> or <code>END_ELEMENT</code>
0950: */
0951: public QName getName() throws IllegalStateException {
0952: throw new UnsupportedOperationException();
0953: }
0954:
0955: /**
0956: * Returns the next parsing event
0957: * @return the next parsing event
0958: * @throws NoSuchElementException if this is called when
0959: * <code>hasNext()</code> returns false
0960: * @exception XMLStreamException if there is an error
0961: * processing the underlying XML source
0962: */
0963: public int next() throws XMLStreamException,
0964: NoSuchElementException {
0965: namespaceURI = null;
0966: localName = null;
0967: qName = null;
0968:
0969: // Are there pending attribute events?
0970: if (atts != null) {
0971: attsIndex += 1;
0972: if (attsIndex < atts.getLength()) {
0973: return XMLStreamConstants.ATTRIBUTE;
0974: }
0975: atts = null;
0976: }
0977: try {
0978: // Process events until we find something to return
0979: while (curPos.getIndex() < bufPos) {
0980: // Read next event from buffer
0981: switch (readEvent(curPos)) {
0982: case SAXContentBuffer.START_DOCUMENT: {
0983: return XMLStreamConstants.START_DOCUMENT;
0984: }
0985: case SAXContentBuffer.END_DOCUMENT: {
0986: curPos.setIndex(bufPos);
0987: return XMLStreamConstants.END_DOCUMENT;
0988: }
0989: case SAXContentBuffer.START_PREFIX_MAPPING: {
0990: String prefix = readString(curPos, st);
0991: String uri = readString(curPos, st);
0992: break;
0993: }
0994: case SAXContentBuffer.END_PREFIX_MAPPING: {
0995: String prefix = readString(curPos, st);
0996: break;
0997: }
0998: case SAXContentBuffer.START_ELEMENT: {
0999: int attributes = readAttributes(curPos);
1000: atts = new AttributesImpl();
1001: for (int i = 0; i < attributes; i++) {
1002: atts.addAttribute(readString(curPos, st),
1003: readString(curPos, st), readString(
1004: curPos, st), readString(
1005: curPos, st), readString(
1006: curPos, st));
1007: }
1008: attsIndex = -1;
1009: namespaceURI = readString(curPos, st);
1010: localName = readString(curPos, st);
1011: qName = readString(curPos, st);
1012: return XMLStreamConstants.START_ELEMENT;
1013: }
1014: case SAXContentBuffer.END_ELEMENT: {
1015: namespaceURI = readString(curPos, st);
1016: localName = readString(curPos, st);
1017: qName = readString(curPos, st);
1018: return XMLStreamConstants.END_ELEMENT;
1019: }
1020: case SAXContentBuffer.CHARACTERS: {
1021: char[] chars = readChars(curPos);
1022: int len = chars.length;
1023: while (len > 0 && chars[len - 1] == 0) {
1024: len--;
1025: }
1026: if (len > 0) {
1027: return XMLStreamConstants.CHARACTERS;
1028: }
1029: break;
1030: }
1031: case SAXContentBuffer.IGNORABLE_WHITESPACE: {
1032: char[] chars = readChars(curPos);
1033: int len = chars.length;
1034: while (len > 0 && chars[len - 1] == 0) {
1035: len--;
1036: }
1037: if (len > 0) {
1038: }
1039: break;
1040: }
1041: case SAXContentBuffer.PROCESSING_INSTRUCTION: {
1042: String target = readString(curPos, st);
1043: String data = readString(curPos, st);
1044: return XMLStreamConstants.PROCESSING_INSTRUCTION;
1045: }
1046: case SAXContentBuffer.COMMENT: {
1047: char[] chars = readChars(curPos);
1048: int len = chars.length;
1049: while (len > 0 && chars[len - 1] == 0) {
1050: len--;
1051: }
1052: if (len > 0) {
1053: }
1054: return XMLStreamConstants.COMMENT;
1055: }
1056: case SAXContentBuffer.LOCATOR: {
1057: String publicId = readString(curPos, st);
1058: String systemId = readString(curPos, st);
1059: int lineNumber = read(curPos);
1060: int columnNumber = read(curPos);
1061: break;
1062: }
1063: case SAXContentBuffer.START_DTD: {
1064: String name = readString(curPos, st);
1065: String publicId = readString(curPos, st);
1066: String systemId = readString(curPos, st);
1067: break;
1068: }
1069: case SAXContentBuffer.END_DTD: {
1070: return XMLStreamConstants.DTD;
1071: }
1072: case SAXContentBuffer.START_CDATA: {
1073: break;
1074: }
1075: case SAXContentBuffer.END_CDATA: {
1076: return XMLStreamConstants.CDATA;
1077: }
1078: case SAXContentBuffer.SKIPPED_ENTITY: {
1079: String skippedEntity = readString(curPos, st);
1080: break;
1081: }
1082: case SAXContentBuffer.START_ENTITY: {
1083: String entity = readString(curPos, st);
1084: break;
1085: }
1086: case SAXContentBuffer.END_ENTITY: {
1087: String entity = readString(curPos, st);
1088: return XMLStreamConstants.ENTITY_DECLARATION;
1089: }
1090: default: {
1091: throw new XMLStreamException(
1092: "parsing error: event not supported.");
1093: }
1094: }
1095: }
1096: throw new XMLStreamException("No more events");
1097: } catch (SAXException e) {
1098: throw (XMLStreamException) (new XMLStreamException(e
1099: .getMessage())).initCause(e);
1100: }
1101: }
1102:
1103: /**
1104: * Returns <code>true</code> if there are more parsing events
1105: * and <code>false</code> if there are no more events. This
1106: * method will return <code>false</code> if the current state of the
1107: * XMLStreamReader is <code>END_DOCUMENT</code>
1108: *
1109: * @return a <code>boolean</code> value
1110: * @exception XMLStreamException if an error occurs
1111: */
1112: public boolean hasNext() throws XMLStreamException {
1113: return curPos.getIndex() < bufPos;
1114: }
1115:
1116: /**
1117: * Frees any resources associated with this Reader.
1118: *
1119: * @exception XMLStreamException if an error occurs
1120: */
1121: public void close() throws XMLStreamException {
1122: }
1123:
1124: /**
1125: * Returns <code>null</code> as the encoding is unknown.
1126: *
1127: * @return a <code>String</code> value
1128: */
1129: public String getEncoding() {
1130: return null;
1131: }
1132:
1133: /**
1134: * Return the current location of the processor. If the
1135: * Location is unknown the processor should return an
1136: * implementation of Location that returns -1 for the location
1137: * and null for the publicId and systemId. The location
1138: * information is only valid until next() is called.
1139: *
1140: * @return a <code>Location</code> value
1141: */
1142: public Location getLocation() {
1143: throw new UnsupportedOperationException();
1144: }
1145:
1146: /**
1147: * Get the xml version declared on the xml declaration. Returns
1148: * <code>null</code> if none was declared.
1149: *
1150: * @return a <code>String</code> value
1151: */
1152: public String getVersion() {
1153: return null;
1154: }
1155:
1156: /**
1157: * Returns the current value of the parse event as a string,
1158: * this returns the string value of a <code>CHARACTERS</code>
1159: * event, returns the value of a <code>COMMENT</code>, the
1160: * replacement value for an <code>ENTITY_REFERENCE</code>, the
1161: * string value of a <code>CDATA</code> section, the string
1162: * value for a <code>SPACE</code> event, or the String value
1163: * of the internal subset of the DTD. If an
1164: * <code>ENTITY_REFERENCE</code> has been resolved, any
1165: * character data will be reported as <code>CHARACTERS</code>
1166: * events.
1167: *
1168: * @return a <code>String</code> value
1169: */
1170: public String getText() {
1171: throw new UnsupportedOperationException();
1172: }
1173:
1174: /**
1175: * Returns the character encoding declared on the xml
1176: * declaration. Returns <code>null</code> if none was declared.
1177: *
1178: * @return a <code>String</code> value
1179: */
1180: public String getCharacterEncodingScheme() {
1181: return null;
1182: }
1183:
1184: /**
1185: * Get the standalone declaration from the xml declaration.
1186: *
1187: * @return a <code>boolean</code> value
1188: */
1189: public boolean isStandalone() {
1190: throw new UnsupportedOperationException();
1191: }
1192:
1193: /**
1194: * Checks if standalone was set in the document.
1195: *
1196: * @return a <code>boolean</code> value
1197: */
1198: public boolean standaloneSet() {
1199: throw new UnsupportedOperationException();
1200: }
1201:
1202: /**
1203: * Returns an integer code that indicates the type of the
1204: * event the cursor is pointing to.
1205: *
1206: * @return an <code>int</code> value
1207: */
1208: public int getEventType() {
1209: throw new UnsupportedOperationException();
1210: }
1211:
1212: /**
1213: * Returns <code>true</code> if the cursor points to a start
1214: * tag (otherwise <code>false</code>).
1215: *
1216: * @return a <code>boolean</code> value
1217: */
1218: public boolean isStartElement() {
1219: return getEventType() == START_ELEMENT;
1220: }
1221:
1222: /**
1223: * Returns <code>true</code> if the cursor points to an end
1224: * tag (otherwise <code>false</code>).
1225: *
1226: * @return a <code>boolean</code> value
1227: */
1228: public boolean isEndElement() {
1229: return getEventType() == END_ELEMENT;
1230: }
1231:
1232: /**
1233: * Returns <code>true</code> if the cursor points to a
1234: * character data event.
1235: *
1236: * @return a <code>boolean</code> value
1237: */
1238: public boolean isCharacters() {
1239: return getEventType() == CHARACTERS;
1240: }
1241:
1242: /**
1243: * Returns a read only namespace context for the current
1244: * position. The context is transient and only valid until a
1245: * call to <code>next()</code> changes the state of the
1246: * reader.
1247: *
1248: * @return a <code>NamespaceContext</code> value
1249: */
1250: public NamespaceContext getNamespaceContext() {
1251: throw new UnsupportedOperationException();
1252: }
1253:
1254: /**
1255: * If the current event is a <code>START_ELEMENT</code> or
1256: * <code>END_ELEMENT</code> this method returns the URI of the
1257: * prefix or the default namespace. Returns <code>null</code>
1258: * if the event does not have a prefix.
1259: *
1260: * @param string a <code>String</code> value
1261: * @return a <code>String</code> value
1262: */
1263: public String getNamespaceURI(String string) {
1264: throw new UnsupportedOperationException();
1265: }
1266:
1267: /**
1268: * Returns the uri for the namespace declared at the index.
1269: *
1270: * @param n the position of the namespace declaration
1271: * @return a <code>String</code> value
1272: */
1273: public String getNamespaceURI(int n) {
1274: throw new UnsupportedOperationException();
1275: }
1276:
1277: /**
1278: * If the current event is a <code>START_ELEMENT</code> or
1279: * <code>END_ELEMENT</code> this method returns the URI of the
1280: * prefix or the default namespace. Returns null if the event
1281: * does not have a prefix.
1282: *
1283: * @return a <code>String</code> value
1284: */
1285: public String getNamespaceURI() {
1286: return namespaceURI;
1287: }
1288:
1289: /**
1290: * Returns true if the cursor points to a character data event
1291: * that consists of all whitespace.
1292: *
1293: * @return a <code>boolean</code> value
1294: */
1295: public boolean isWhiteSpace() {
1296: throw new UnsupportedOperationException();
1297: }
1298:
1299: /**
1300: * Returns the prefix of the current event or
1301: * <code>null</code> if the event does not have a prefix.
1302: *
1303: * @return a <code>String</code> value
1304: */
1305: public String getPrefix() {
1306: throw new UnsupportedOperationException();
1307: }
1308:
1309: /**
1310: * Test if the current event is of the given type and if the
1311: * namespace and name match the current namespace and name of
1312: * the current event. If the namespaceURI is <code>null</code>
1313: * it is not checked for equality, if the localName is
1314: * <code>null</code> it is not checked for equality.
1315: *
1316: * @param type an <code>int</code> value
1317: * @param namespaceURI a <code>String</code> value
1318: * @param localName a <code>String</code> value
1319: * @exception XMLStreamException if an error occurs
1320: */
1321: public void require(int type, String namespaceURI,
1322: String localName) throws XMLStreamException {
1323: throw new UnsupportedOperationException();
1324: }
1325:
1326: /**
1327: * Reads the content of a text-only element, an exception is
1328: * thrown if this is not a text-only element. Regardless of
1329: * value of javax.xml.stream.isCoalescing this method always
1330: * returns coalesced content.
1331: *
1332: * @return a <code>String</code> value
1333: * @exception XMLStreamException if an error occurs
1334: */
1335: public String getElementText() throws XMLStreamException {
1336: throw new UnsupportedOperationException();
1337: }
1338:
1339: /**
1340: * Skips any white space (<code>isWhiteSpace()</code> returns
1341: * <code>true</code>), <code>COMMENT</code>, or
1342: * <code>PROCESSING_INSTRUCTION</code>, until a
1343: * <code>START_ELEMENT</code> or <code>END_ELEMENT</code> is
1344: * reached. If other than white space characters,
1345: * <code>COMMENT</code>, <code>PROCESSING_INSTRUCTION</code>,
1346: * <code>START_ELEMENT</code>, <code>END_ELEMENT</code> are
1347: * encountered, an exception is thrown. This method should be
1348: * used when processing element-only content seperated by
1349: * white space.
1350: *
1351: * @return an <code>int</code> value
1352: * @exception XMLStreamException if an error occurs
1353: */
1354: public int nextTag() throws XMLStreamException {
1355: throw new UnsupportedOperationException();
1356: }
1357:
1358: /**
1359: * Returns the normalized attribute value of the attribute
1360: * with the namespace and localName If the namespaceURI is
1361: * null the namespace is not checked for equality
1362: *
1363: * @param namespaceURI a <code>String</code> value
1364: * @param localName a <code>String</code> value
1365: * @return a <code>String</code> value
1366: */
1367: public String getAttributeValue(String namespaceURI,
1368: String localName) {
1369: throw new UnsupportedOperationException();
1370: }
1371:
1372: /**
1373: * Returns the value of the attribute at the index.
1374: *
1375: * @param index an <code>int</code> value
1376: * @return a <code>String</code> value
1377: */
1378: public String getAttributeValue(int index) {
1379: throw new UnsupportedOperationException();
1380: }
1381:
1382: /**
1383: * Returns the count of attributes on this
1384: * <code>START_ELEMENT</code>, this method is only valid on a
1385: * <code>START_ELEMENT</code> or <code>ATTRIBUTE</code>. This
1386: * count excludes namespace definitions. Attribute indices are
1387: * zero-based.
1388: *
1389: * @return an <code>int</code> value
1390: */
1391: public int getAttributeCount() {
1392: throw new UnsupportedOperationException();
1393: }
1394:
1395: /**
1396: * Returns the qname of the attribute at the provided index.
1397: *
1398: * @param index an <code>int</code> value
1399: * @return a <code>QName</code> value
1400: */
1401: public QName getAttributeName(int index) {
1402: throw new UnsupportedOperationException();
1403: }
1404:
1405: /**
1406: * Returns the namespace of the attribute at the provided index.
1407: *
1408: * @param index an <code>int</code> value
1409: * @return a <code>String</code> value
1410: */
1411: public String getAttributeNamespace(int index) {
1412: throw new UnsupportedOperationException();
1413: }
1414:
1415: /**
1416: * Returns the localName of the attribute at the provided index.
1417: *
1418: * @param index an <code>int</code> value
1419: * @return a <code>String</code> value
1420: */
1421: public String getAttributeLocalName(int index) {
1422: throw new UnsupportedOperationException();
1423: }
1424:
1425: /**
1426: * Returns the prefix of this attribute at the provided index.
1427: *
1428: * @param index an <code>int</code> value
1429: * @return a <code>String</code> value
1430: */
1431: public String getAttributePrefix(int index) {
1432: throw new UnsupportedOperationException();
1433: }
1434:
1435: /**
1436: * Returns the XML type of the attribute at the provided index.
1437: *
1438: * @param index an <code>int</code> value
1439: * @return a <code>String</code> value
1440: */
1441: public String getAttributeType(int index) {
1442: throw new UnsupportedOperationException();
1443: }
1444:
1445: /**
1446: * Returns a boolean which indicates if this attribute was
1447: * created by default.
1448: *
1449: * @param index an <code>int</code> value
1450: * @return a <code>boolean</code> value
1451: */
1452: public boolean isAttributeSpecified(int index) {
1453: throw new UnsupportedOperationException();
1454: }
1455:
1456: /**
1457: * Returns the count of namespaces declared on this
1458: * <code>START_ELEMENT</code> or <code>END_ELEMENT</code>,
1459: * this method is only valid on a <code>START_ELEMENT</code>,
1460: * <code>END_ELEMENT</code> or <code>NAMESPACE</code>. On an
1461: * <code>END_ELEMENT</code> the count is of the namespaces
1462: * that are about to go out of scope. This is the equivalent
1463: * of the information reported by SAX callback for an end
1464: * element event.
1465: *
1466: * @return an <code>int</code> value
1467: */
1468: public int getNamespaceCount() {
1469: throw new UnsupportedOperationException();
1470: }
1471:
1472: /**
1473: * Returns the prefix for the namespace declared at the
1474: * index. Returns null if this is the default namespace
1475: * declaration
1476: *
1477: * @param index an <code>int</code> value
1478: * @return a <code>String</code> value
1479: */
1480: public String getNamespacePrefix(int index) {
1481: throw new UnsupportedOperationException();
1482: }
1483:
1484: /**
1485: * Returns an array which contains the characters from this
1486: * event. This array should be treated as read-only and
1487: * transient. I.e. the array will contain the text characters
1488: * until the XMLStreamReader moves on to the next
1489: * event. Attempts to hold onto the character array beyond
1490: * that time or modify the contents of the array are breaches
1491: * of the contract for this interface.
1492: *
1493: * @return a <code>char[]</code> value
1494: */
1495: public char[] getTextCharacters() {
1496: throw new UnsupportedOperationException();
1497: }
1498:
1499: /**
1500: * Gets the the text associated with a
1501: * <code>CHARACTERS</code>, <code>SPACE</code> or
1502: * <code>CDATA</code> event.
1503: *
1504: * @param sourceStart an <code>int</code> value
1505: * @param target a <code>char[]</code> value
1506: * @param targetStart an <code>int</code> value
1507: * @param length an <code>int</code> value
1508: * @return an <code>int</code> value
1509: * @exception XMLStreamException if an error occurs
1510: */
1511: public int getTextCharacters(int sourceStart, char[] target,
1512: int targetStart, int length) throws XMLStreamException {
1513: throw new UnsupportedOperationException();
1514: }
1515:
1516: /**
1517: * Returns the offset into the text character array where the
1518: * first character (of this text event) is stored.
1519: *
1520: * @return an <code>int</code> value
1521: */
1522: public int getTextStart() {
1523: throw new UnsupportedOperationException();
1524: }
1525:
1526: /**
1527: * Returns the length of the sequence of characters for this
1528: * Text event within the text character array.
1529: *
1530: * @return an <code>int</code> value
1531: */
1532: public int getTextLength() {
1533: throw new UnsupportedOperationException();
1534: }
1535:
1536: /**
1537: * Return <code>true</code> if the current event has text,
1538: * <code>false</code> otherwise. The following events have
1539: * text: <code>CHARACTERS</code>, <code>DTD</code>,
1540: * <code>ENTITY_REFERENCE</code>, <code>COMMENT</code>,
1541: * <code>SPACE</code>.
1542: *
1543: * @return a <code>boolean</code> value
1544: */
1545: public boolean hasText() {
1546: int t = getEventType();
1547: return t == XMLStreamConstants.CHARACTERS
1548: || t == XMLStreamConstants.DTD
1549: || t == XMLStreamConstants.ENTITY_REFERENCE
1550: || t == XMLStreamConstants.COMMENT
1551: || t == XMLStreamConstants.SPACE;
1552: }
1553:
1554: /**
1555: * Returns the (local) name of the current event. For
1556: * <code>START_ELEMENT</code> or <code>END_ELEMENT</code>
1557: * returns the (local) name of the current element. For
1558: * <code>ENTITY_REFERENCE</code> it returns entity name. The
1559: * current event must be <code>START_ELEMENT</code> or
1560: * <code>END_ELEMENT</code>, or <code>ENTITY_REFERENCE</code>
1561: *
1562: * @return a <code>String</code> value
1563: * @throws IllegalStateException if this not a
1564: * <code>START_ELEMENT</code>, <code>END_ELEMENT</code> or
1565: * <code>ENTITY_REFERENCE</code>
1566: */
1567: public String getLocalName() throws IllegalStateException {
1568: if (localName == null) {
1569: throw new IllegalStateException();
1570: }
1571: return localName;
1572: }
1573:
1574: /**
1575: * returns <code>true</code> if the current event has a name
1576: * (is a <code>START_ELEMENT</code> or
1577: * <code>END_ELEMENT<(code>) returns <code>false</code>
1578: * otherwise.
1579: *
1580: * @return a <code>boolean</code> value
1581: */
1582: public boolean hasName() {
1583: int t = getEventType();
1584: return t == XMLStreamConstants.START_ELEMENT
1585: || t == XMLStreamConstants.END_ELEMENT;
1586: }
1587:
1588: /**
1589: * Get the target of a processing instruction.
1590: *
1591: * @return a <code>String</code> value
1592: */
1593: public String getPITarget() {
1594: throw new UnsupportedOperationException();
1595: }
1596:
1597: /**
1598: * Get the data section of a processing instruction.
1599: *
1600: * @return a <code>String</code> value
1601: */
1602: public String getPIData() {
1603: throw new UnsupportedOperationException();
1604: }
1605:
1606: }
1607:
1608: /**
1609: * Returns a string representation of the buffer's content. Note
1610: * that this method should not be used to generate XML as charcode
1611: * handling is partially undefined (dependant on the platform
1612: * configuration).
1613: * @return a terse (unindented) XML representation
1614: */
1615: public String toString() {
1616: return toString(false);
1617: }
1618:
1619: /**
1620: * Returns a string representation of the buffer's content. Note
1621: * that this method should not be used to generate XML as charcode
1622: * handling is partially undefined (dependant on the platform
1623: * configuration).
1624: * @param pretty if <code>true</code> output will be formated
1625: * using line breaks and indentation, thus improving readability
1626: * @return the XML representation
1627: */
1628: public String toString(boolean pretty) {
1629: try {
1630: SAXTransformerFactory stf = (SAXTransformerFactory) TransformerFactory
1631: .newInstance();
1632: TransformerHandler serializer = null;
1633: if (pretty) {
1634: serializer = stf.newTransformerHandler();
1635: } else {
1636: if (toStringTemplates == null) {
1637: InputStream xslIn = SAXContentBuffer.class
1638: .getResourceAsStream("/de/danet/an/util/sax/remove-whitespace.xsl");
1639: toStringTemplates = stf
1640: .newTemplates(new StreamSource(xslIn));
1641: }
1642: serializer = stf
1643: .newTransformerHandler(toStringTemplates);
1644: }
1645: serializer.getTransformer().setOutputProperty(
1646: OutputKeys.INDENT, pretty ? "yes" : "no");
1647: serializer.getTransformer().setOutputProperty(
1648: OutputKeys.OMIT_XML_DECLARATION, "yes");
1649: StringWriter res = new StringWriter();
1650: serializer.setResult(new StreamResult(res));
1651: emit(serializer);
1652: return res.toString();
1653: } catch (Exception e) {
1654: return super .toString();
1655: }
1656: }
1657:
1658: /**
1659: * Returns a W3C DOM representation of the buffer's content.
1660: * @return the DOM representation
1661: */
1662: public Node toW3cDom() {
1663: try {
1664: SAXTransformerFactory stf = (SAXTransformerFactory) TransformerFactory
1665: .newInstance();
1666: TransformerHandler serializer = stf.newTransformerHandler();
1667: DOMResult res = new DOMResult();
1668: serializer.setResult(res);
1669: emit(serializer);
1670: return res.getNode();
1671: } catch (Exception e) {
1672: throw (IllegalStateException) (new IllegalStateException())
1673: .initCause(e);
1674: }
1675: }
1676:
1677: }
|