summaryrefslogtreecommitdiff
path: root/libjava/classpath/gnu/xml/stream
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/gnu/xml/stream
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'libjava/classpath/gnu/xml/stream')
-rw-r--r--libjava/classpath/gnu/xml/stream/AttributeImpl.java123
-rw-r--r--libjava/classpath/gnu/xml/stream/BufferedReader.java198
-rw-r--r--libjava/classpath/gnu/xml/stream/CRLFReader.java180
-rw-r--r--libjava/classpath/gnu/xml/stream/CharactersImpl.java119
-rw-r--r--libjava/classpath/gnu/xml/stream/CommentImpl.java91
-rw-r--r--libjava/classpath/gnu/xml/stream/DTDImpl.java114
-rw-r--r--libjava/classpath/gnu/xml/stream/EndDocumentImpl.java70
-rw-r--r--libjava/classpath/gnu/xml/stream/EndElementImpl.java107
-rw-r--r--libjava/classpath/gnu/xml/stream/EntityDeclarationImpl.java163
-rw-r--r--libjava/classpath/gnu/xml/stream/EntityReferenceImpl.java101
-rw-r--r--libjava/classpath/gnu/xml/stream/FilteredEventReader.java114
-rw-r--r--libjava/classpath/gnu/xml/stream/FilteredStreamReader.java90
-rw-r--r--libjava/classpath/gnu/xml/stream/NamespaceImpl.java137
-rw-r--r--libjava/classpath/gnu/xml/stream/NotationDeclarationImpl.java125
-rw-r--r--libjava/classpath/gnu/xml/stream/ProcessingInstructionImpl.java104
-rw-r--r--libjava/classpath/gnu/xml/stream/SAXParser.java1041
-rw-r--r--libjava/classpath/gnu/xml/stream/SAXParserFactory.java104
-rw-r--r--libjava/classpath/gnu/xml/stream/StartDocumentImpl.java143
-rw-r--r--libjava/classpath/gnu/xml/stream/StartElementImpl.java152
-rw-r--r--libjava/classpath/gnu/xml/stream/UnicodeReader.java205
-rw-r--r--libjava/classpath/gnu/xml/stream/XIncludeFilter.java931
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLEventAllocatorImpl.java204
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLEventFactoryImpl.java269
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLEventImpl.java198
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLEventReaderImpl.java157
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLEventWriterImpl.java190
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java397
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLOutputFactoryImpl.java187
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLParser.java5434
-rw-r--r--libjava/classpath/gnu/xml/stream/XMLStreamWriterImpl.java1016
30 files changed, 12464 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/xml/stream/AttributeImpl.java b/libjava/classpath/gnu/xml/stream/AttributeImpl.java
new file mode 100644
index 000000000..58a0dbe21
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/AttributeImpl.java
@@ -0,0 +1,123 @@
+/* AttributeImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Writer;
+import javax.xml.namespace.QName;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+
+/**
+ * An attribute event.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class AttributeImpl
+ extends XMLEventImpl
+ implements Attribute
+{
+
+ protected final QName name;
+ protected final String value;
+ protected final String type;
+ protected final boolean specified;
+
+ protected AttributeImpl(Location location,
+ QName name, String value, String type,
+ boolean specified)
+ {
+ super(location);
+ this.name = name;
+ this.value = value;
+ this.type = type;
+ this.specified = specified;
+ }
+
+ public int getEventType()
+ {
+ return ATTRIBUTE;
+ }
+
+ public QName getName()
+ {
+ return name;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+
+ public String getDTDType()
+ {
+ return type;
+ }
+
+ public boolean isSpecified()
+ {
+ return specified;
+ }
+
+ public void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException
+ {
+ try
+ {
+ String prefix = name.getPrefix();
+ if (prefix != null && !"".equals(prefix))
+ {
+ writer.write(prefix);
+ writer.write(':');
+ }
+ writer.write(name.getLocalPart());
+ writer.write('=');
+ writer.write('"');
+ writer.write(encode(value, true));
+ writer.write('"');
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/BufferedReader.java b/libjava/classpath/gnu/xml/stream/BufferedReader.java
new file mode 100644
index 000000000..dc69fb34b
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/BufferedReader.java
@@ -0,0 +1,198 @@
+/* BufferedReader.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * A mark-capable buffered reader.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class BufferedReader
+ extends Reader
+{
+
+ static final int DEFAULT_BUFFER_SIZE = 4096;
+
+ final Reader in;
+ char[] buf;
+ int pos, count, markpos, marklimit, bufferSize;
+
+ BufferedReader(Reader in)
+ {
+ this(in, DEFAULT_BUFFER_SIZE);
+ }
+
+ BufferedReader(Reader in, int bufferSize)
+ {
+ if (bufferSize < 1)
+ throw new IllegalArgumentException();
+ this.in = in;
+ this.bufferSize = bufferSize;
+ buf = new char[bufferSize];
+ pos = count = bufferSize;
+ }
+
+ public void close()
+ throws IOException
+ {
+ buf = null;
+ pos = count = 0;
+ markpos = -1;
+ in.close();
+ }
+
+ public void mark(int readlimit)
+ throws IOException
+ {
+ marklimit = readlimit;
+ markpos = pos;
+ }
+
+ public boolean markSupported()
+ {
+ return true;
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (pos >= count && !refill())
+ return -1;
+ return (int) buf[pos++];
+ }
+
+ public int read(char[] b)
+ throws IOException
+ {
+ return read(b, 0, b.length);
+ }
+
+ public int read(char[] b, int off, int len)
+ throws IOException
+ {
+ if (off < 0 || len < 0 || b.length - off < len)
+ throw new IndexOutOfBoundsException();
+
+ if (len == 0)
+ return 0;
+
+ if (pos >= count && !refill())
+ return -1;
+
+ int ret = Math.min(count - pos, len);
+ System.arraycopy(buf, pos, b, off, ret);
+ pos += ret;
+ off += ret;
+ len -= ret;
+
+ while (len > 0 && refill())
+ {
+ int remain = Math.min(count - pos, len);
+ System.arraycopy(buf, pos, b, off, remain);
+ pos += remain;
+ off += remain;
+ len -= remain;
+ ret += remain;
+ }
+
+ return ret;
+ }
+
+ public void reset()
+ throws IOException
+ {
+ if (markpos == -1)
+ throw new IOException(buf == null ? "Stream closed." : "Invalid mark.");
+ pos = markpos;
+ }
+
+ public long skip(long n)
+ throws IOException
+ {
+ if (buf == null)
+ throw new IOException("Stream closed.");
+ final long origN = n;
+ while (n > 0L)
+ {
+ if (pos >= count && !refill())
+ break;
+ int numread = (int) Math.min((long) (count - pos), n);
+ pos += numread;
+ n -= numread;
+ }
+ return origN - n;
+ }
+
+ private boolean refill()
+ throws IOException
+ {
+ if (buf == null)
+ throw new IOException("Stream closed.");
+
+ int markcount = count - markpos;
+ if (markpos == -1 || markcount >= marklimit)
+ {
+ markpos = -1;
+ pos = count = 0;
+ }
+ else
+ {
+ char[] newbuf = buf;
+ if (markpos < bufferSize)
+ {
+ newbuf = new char[count - markpos + bufferSize];
+ }
+ System.arraycopy(buf, markpos, newbuf, 0, markcount);
+ buf = newbuf;
+ count = markcount;
+ pos -= markpos;
+ markpos = 0;
+ }
+
+ int numread = in.read(buf, count, bufferSize);
+ if (numread <= 0)
+ return false;
+
+ count += numread;
+ return true;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/CRLFReader.java b/libjava/classpath/gnu/xml/stream/CRLFReader.java
new file mode 100644
index 000000000..7f3cf4d74
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/CRLFReader.java
@@ -0,0 +1,180 @@
+/* CRLFReader.java --
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * Filtered reader that normalizes CRLF pairs into LFs.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class CRLFReader
+ extends Reader
+{
+
+ /**
+ * The CR octet.
+ */
+ public static final int CR = 13;
+
+ /**
+ * The LF octet.
+ */
+ public static final int LF = 10;
+
+ private boolean doReset;
+
+ protected Reader in;
+
+ /**
+ * Constructor.
+ */
+ protected CRLFReader(Reader in)
+ {
+ if (!in.markSupported())
+ in = new BufferedReader(in);
+ this.in = in;
+ }
+
+ public int read()
+ throws IOException
+ {
+ int c = in.read();
+ if (c == 13) // CR
+ {
+ in.mark(1);
+ int d = in.read();
+ if (d == 10) // LF
+ c = d;
+ else
+ in.reset();
+ }
+ return c;
+ }
+
+ public int read(char[] b)
+ throws IOException
+ {
+ return read(b, 0, b.length);
+ }
+
+ public int read(char[] b, int off, int len)
+ throws IOException
+ {
+ in.mark(len + 1);
+ int l = in.read(b, off, len);
+ if (l > 0)
+ {
+ int i = indexOfCRLF(b, off, l);
+ if (doReset)
+ {
+ in.reset();
+ if (i != -1)
+ {
+ l = in.read(b, off, (i + 1) - off); // read to CR
+ in.read(); // skip LF
+ b[i] = '\n'; // fix CR as LF
+ }
+ else
+ l = in.read(b, off, len); // CR(s) but no LF
+ }
+ }
+ return l;
+ }
+
+ public boolean markSupported()
+ {
+ return in.markSupported();
+ }
+
+ public void mark(int limit)
+ throws IOException
+ {
+ in.mark(limit);
+ }
+
+ public void reset()
+ throws IOException
+ {
+ in.reset();
+ }
+
+ public long skip(long n)
+ throws IOException
+ {
+ return in.skip(n);
+ }
+
+ public void close()
+ throws IOException
+ {
+ in.close();
+ }
+
+ private int indexOfCRLF(char[] b, int off, int len)
+ throws IOException
+ {
+ doReset = false;
+ int end = off + len;
+ int em1 = end - 1;
+ for (int i = off; i < end; i++)
+ {
+ if (b[i] == '\r') // CR
+ {
+ int d;
+ if (i == em1)
+ {
+ d = in.read();
+ doReset = true;
+ }
+ else
+ d = b[i + 1];
+ if (d == '\n') // LF
+ {
+ doReset = true;
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/CharactersImpl.java b/libjava/classpath/gnu/xml/stream/CharactersImpl.java
new file mode 100644
index 000000000..2107a5a6d
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/CharactersImpl.java
@@ -0,0 +1,119 @@
+/* CharactersImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Writer;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Characters;
+
+/**
+ * A character data (text) event.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class CharactersImpl
+ extends XMLEventImpl
+ implements Characters
+{
+
+ protected final String data;
+ protected final boolean whitespace;
+ protected final boolean cdata;
+ protected final boolean ignorableWhitespace;
+
+ protected CharactersImpl(Location location,
+ String data, boolean whitespace, boolean cdata,
+ boolean ignorableWhitespace)
+ {
+ super(location);
+ this.data = data;
+ this.whitespace = whitespace;
+ this.cdata = cdata;
+ this.ignorableWhitespace = ignorableWhitespace;
+ }
+
+ public int getEventType()
+ {
+ return cdata ? CDATA : whitespace ? SPACE : CHARACTERS;
+ }
+
+ public String getData()
+ {
+ return data;
+ }
+
+ public boolean isWhiteSpace()
+ {
+ return whitespace;
+ }
+
+ public boolean isCData()
+ {
+ return cdata;
+ }
+
+ public boolean isIgnorableWhiteSpace()
+ {
+ return ignorableWhitespace;
+ }
+
+ public void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException
+ {
+ try
+ {
+ if (cdata)
+ {
+ writer.write("<![CDATA[");
+ writer.write(data);
+ writer.write("]]>");
+ }
+ else
+ writer.write(encode(data, false));
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/CommentImpl.java b/libjava/classpath/gnu/xml/stream/CommentImpl.java
new file mode 100644
index 000000000..118ac7a57
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/CommentImpl.java
@@ -0,0 +1,91 @@
+/* CommentImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Writer;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Comment;
+
+/**
+ * A comment event.
+ *
+ * @author <a href'mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class CommentImpl
+ extends XMLEventImpl
+ implements Comment
+{
+
+ protected final String text;
+
+ protected CommentImpl(Location location, String text)
+ {
+ super(location);
+ this.text = text;
+ }
+
+ public int getEventType()
+ {
+ return COMMENT;
+ }
+
+ public String getText()
+ {
+ return text;
+ }
+
+ public void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException
+ {
+ try
+ {
+ writer.write("<!--");
+ writer.write(encode(text, false));
+ writer.write("-->");
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/DTDImpl.java b/libjava/classpath/gnu/xml/stream/DTDImpl.java
new file mode 100644
index 000000000..cf049d362
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/DTDImpl.java
@@ -0,0 +1,114 @@
+/* DTDImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.DTD;
+
+/**
+ * A DOCTYPE declaration event.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class DTDImpl
+ extends XMLEventImpl
+ implements DTD
+{
+
+ protected final String body;
+ protected final Object impl;
+ protected final List notations;
+ protected final List entities;
+
+ protected DTDImpl(Location location,
+ String body, Object impl, List notations, List entities)
+ {
+ super(location);
+ this.body = body;
+ this.impl = impl;
+ this.notations = notations;
+ this.entities = entities;
+ }
+
+ public int getEventType()
+ {
+ return DTD;
+ }
+
+ public String getDocumentTypeDeclaration()
+ {
+ return body;
+ }
+
+ public Object getProcessedDTD()
+ {
+ return impl;
+ }
+
+ public List getNotations()
+ {
+ return notations;
+ }
+
+ public List getEntities()
+ {
+ return entities;
+ }
+
+ public void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException
+ {
+ try
+ {
+ writer.write("<!DOCTYPE ");
+ writer.write(body);
+ writer.write(">");
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/EndDocumentImpl.java b/libjava/classpath/gnu/xml/stream/EndDocumentImpl.java
new file mode 100644
index 000000000..13877c5c9
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/EndDocumentImpl.java
@@ -0,0 +1,70 @@
+/* EndDocumentImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.Writer;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.EndDocument;
+
+/**
+ * An end-document event.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class EndDocumentImpl
+ extends XMLEventImpl
+ implements EndDocument
+{
+
+ protected EndDocumentImpl(Location location)
+ {
+ super(location);
+ }
+
+ public int getEventType()
+ {
+ return END_DOCUMENT;
+ }
+
+ public void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException
+ {
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/EndElementImpl.java b/libjava/classpath/gnu/xml/stream/EndElementImpl.java
new file mode 100644
index 000000000..71f6aa0bc
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/EndElementImpl.java
@@ -0,0 +1,107 @@
+/* EndElementImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.EndElement;
+
+/**
+ * An end-element event.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class EndElementImpl
+ extends XMLEventImpl
+ implements EndElement
+{
+
+ protected final QName name;
+ protected final List namespaces;
+
+ protected EndElementImpl(Location location, QName name, List namespaces)
+ {
+ super(location);
+ this.name = name;
+ this.namespaces = namespaces;
+ }
+
+ public int getEventType()
+ {
+ return END_ELEMENT;
+ }
+
+ public QName getName()
+ {
+ return name;
+ }
+
+ public Iterator getNamespaces()
+ {
+ return namespaces.iterator();
+ }
+
+ public void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException
+ {
+ try
+ {
+ writer.write("</");
+ String prefix = name.getPrefix();
+ if (prefix != null && !"".equals(prefix))
+ {
+ writer.write(prefix);
+ writer.write(':');
+ }
+ writer.write(name.getLocalPart());
+ writer.write(">");
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/EntityDeclarationImpl.java b/libjava/classpath/gnu/xml/stream/EntityDeclarationImpl.java
new file mode 100644
index 000000000..b6e33e8d2
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/EntityDeclarationImpl.java
@@ -0,0 +1,163 @@
+/* EntityDeclarationImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Writer;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.EntityDeclaration;
+
+/**
+ * An entity declaration event.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class EntityDeclarationImpl
+ extends XMLEventImpl
+ implements EntityDeclaration
+{
+
+ protected final String publicId;
+ protected final String systemId;
+ protected final String name;
+ protected final String notationName;
+ protected final String replacementText;
+ protected final String baseUri;
+
+ protected EntityDeclarationImpl(Location location,
+ String publicId, String systemId,
+ String name, String notationName,
+ String replacementText, String baseUri)
+ {
+ super(location);
+ this.publicId = publicId;
+ this.systemId = systemId;
+ this.name = name;
+ this.notationName = notationName;
+ this.replacementText = replacementText;
+ this.baseUri = baseUri;
+ }
+
+ public int getEventType()
+ {
+ return ENTITY_DECLARATION;
+ }
+
+ public String getPublicId()
+ {
+ return publicId;
+ }
+
+ public String getSystemId()
+ {
+ return systemId;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String getNotationName()
+ {
+ return notationName;
+ }
+
+ public String getReplacementText()
+ {
+ return replacementText;
+ }
+
+ public String getBaseURI()
+ {
+ return baseUri;
+ }
+
+ public void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException
+ {
+ try
+ {
+ writer.write("<!ENTITY ");
+ writer.write(name);
+ writer.write(' ');
+ if (systemId != null)
+ {
+ if (publicId != null)
+ {
+ writer.write(" PUBLIC ");
+ writer.write('"');
+ writer.write(publicId);
+ writer.write('"');
+ writer.write(' ');
+ writer.write('"');
+ writer.write(systemId);
+ writer.write('"');
+ }
+ else
+ {
+ writer.write(" SYSTEM ");
+ writer.write('"');
+ writer.write(systemId);
+ writer.write('"');
+ }
+ if (notationName != null)
+ {
+ writer.write(" NDATA ");
+ writer.write(notationName);
+ }
+ }
+ else
+ {
+ writer.write('"');
+ if (replacementText != null)
+ writer.write(replacementText);
+ writer.write('"');
+ }
+ writer.write(">");
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/EntityReferenceImpl.java b/libjava/classpath/gnu/xml/stream/EntityReferenceImpl.java
new file mode 100644
index 000000000..6f8a11c80
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/EntityReferenceImpl.java
@@ -0,0 +1,101 @@
+/* EntityReferenceImpl.java --
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Writer;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.EntityDeclaration;
+import javax.xml.stream.events.EntityReference;
+
+/**
+ * An entity reference event.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class EntityReferenceImpl
+ extends XMLEventImpl
+ implements EntityReference
+{
+
+ protected final EntityDeclaration decl;
+ protected final String name;
+
+ protected EntityReferenceImpl(Location location,
+ EntityDeclaration decl,
+ String name)
+ {
+ super(location);
+ this.decl = decl;
+ this.name = name;
+ }
+
+ public int getEventType()
+ {
+ return ENTITY_REFERENCE;
+ }
+
+ public EntityDeclaration getDeclaration()
+ {
+ return decl;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException
+ {
+ try
+ {
+ writer.write('&');
+ writer.write(name);
+ writer.write(';');
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/FilteredEventReader.java b/libjava/classpath/gnu/xml/stream/FilteredEventReader.java
new file mode 100644
index 000000000..1ddb469df
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/FilteredEventReader.java
@@ -0,0 +1,114 @@
+/* FilteredEventReader.java --
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import javax.xml.stream.EventFilter;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.XMLEvent;
+import javax.xml.stream.util.EventReaderDelegate;
+
+class FilteredEventReader
+ extends EventReaderDelegate
+{
+
+ final EventFilter filter;
+
+ FilteredEventReader(XMLEventReader reader, EventFilter filter)
+ {
+ super(reader);
+ this.filter = filter;
+ }
+
+ public boolean hasNext()
+ {
+ // XXX ???
+ return super.hasNext();
+ }
+
+ public XMLEvent nextEvent()
+ throws XMLStreamException
+ {
+ XMLEvent ret;
+ do
+ {
+ ret = super.nextEvent();
+ }
+ while (!filter.accept(ret));
+ return ret;
+ }
+
+ public Object next()
+ {
+ try
+ {
+ return nextEvent();
+ }
+ catch (XMLStreamException e)
+ {
+ RuntimeException e2 = new RuntimeException();
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public XMLEvent peek()
+ throws XMLStreamException
+ {
+ XMLEvent ret;
+ do
+ {
+ ret = super.peek();
+ }
+ while (!filter.accept(ret));
+ return ret;
+ }
+
+ public XMLEvent nextTag()
+ throws XMLStreamException
+ {
+ XMLEvent ret;
+ do
+ {
+ ret = super.nextTag();
+ }
+ while (!filter.accept(ret));
+ return ret;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/FilteredStreamReader.java b/libjava/classpath/gnu/xml/stream/FilteredStreamReader.java
new file mode 100644
index 000000000..62d96488e
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/FilteredStreamReader.java
@@ -0,0 +1,90 @@
+/* FilteredStreamReader.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import javax.xml.stream.StreamFilter;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.util.StreamReaderDelegate;
+
+class FilteredStreamReader
+ extends StreamReaderDelegate
+{
+
+ final XMLStreamReader reader;
+ final StreamFilter filter;
+
+ FilteredStreamReader(XMLStreamReader reader, StreamFilter filter)
+ {
+ super(reader);
+ this.reader = reader;
+ this.filter = filter;
+ }
+
+ public boolean hasNext()
+ throws XMLStreamException
+ {
+ // XXX ???
+ return super.hasNext();
+ }
+
+ public int next()
+ throws XMLStreamException
+ {
+ int ret;
+ do
+ {
+ ret = super.next();
+ }
+ while (!filter.accept(reader));
+ return ret;
+ }
+
+ public int nextTag()
+ throws XMLStreamException
+ {
+ int ret;
+ do
+ {
+ ret = super.nextTag();
+ }
+ while (!filter.accept(reader));
+ return ret;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/NamespaceImpl.java b/libjava/classpath/gnu/xml/stream/NamespaceImpl.java
new file mode 100644
index 000000000..241f980b6
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/NamespaceImpl.java
@@ -0,0 +1,137 @@
+/* NamespaceImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Writer;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Namespace;
+
+/**
+ * A namespace declaration event.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class NamespaceImpl
+ extends XMLEventImpl
+ implements Namespace
+{
+
+ protected final String prefix;
+ protected final String uri;
+ protected final boolean specified;
+
+ protected NamespaceImpl(Location location, String prefix, String uri,
+ boolean specified)
+ {
+ super(location);
+ this.prefix = prefix;
+ this.uri = uri;
+ this.specified = specified;
+ }
+
+ public int getEventType()
+ {
+ return NAMESPACE;
+ }
+
+ public String getPrefix()
+ {
+ return prefix;
+ }
+
+ public String getNamespaceURI()
+ {
+ return uri;
+ }
+
+ public boolean isSpecified()
+ {
+ return specified;
+ }
+
+ public QName getName()
+ {
+ if (isDefaultNamespaceDeclaration())
+ return new QName("", "xmlns", null);
+ else
+ return new QName("", prefix, "xmlns");
+ }
+
+ public String getDTDType()
+ {
+ return "CDATA";
+ }
+
+ public String getValue()
+ {
+ return uri;
+ }
+
+ public boolean isDefaultNamespaceDeclaration()
+ {
+ return (prefix == null || "".equals(prefix));
+ }
+
+ public void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException
+ {
+ try
+ {
+ writer.write("xmlns");
+ if (prefix != null && !"".equals(prefix))
+ {
+ writer.write(':');
+ writer.write(prefix);
+ }
+ writer.write('=');
+ writer.write('"');
+ writer.write(encode(uri, true));
+ writer.write('"');
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/NotationDeclarationImpl.java b/libjava/classpath/gnu/xml/stream/NotationDeclarationImpl.java
new file mode 100644
index 000000000..a338237ee
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/NotationDeclarationImpl.java
@@ -0,0 +1,125 @@
+/* NotationDeclarationImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Writer;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.NotationDeclaration;
+
+/**
+ * A notation declaration event.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class NotationDeclarationImpl
+ extends XMLEventImpl
+ implements NotationDeclaration
+{
+
+ protected final String name;
+ protected final String publicId;
+ protected final String systemId;
+
+ protected NotationDeclarationImpl(Location location,
+ String name, String publicId,
+ String systemId)
+ {
+ super(location);
+ this.name = name;
+ this.publicId = publicId;
+ this.systemId = systemId;
+ }
+
+ public int getEventType()
+ {
+ return NOTATION_DECLARATION;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String getPublicId()
+ {
+ return publicId;
+ }
+
+ public String getSystemId()
+ {
+ return systemId;
+ }
+
+ public void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException
+ {
+ try
+ {
+ writer.write("<!NOTATION ");
+ writer.write(name);
+ if (publicId != null)
+ {
+ writer.write(" PUBLIC ");
+ writer.write('"');
+ writer.write(publicId);
+ writer.write('"');
+ writer.write(' ');
+ writer.write('"');
+ writer.write(systemId);
+ writer.write('"');
+ }
+ else
+ {
+ writer.write(" SYSTEM ");
+ writer.write('"');
+ writer.write(systemId);
+ writer.write('"');
+ }
+ writer.write('>');
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/ProcessingInstructionImpl.java b/libjava/classpath/gnu/xml/stream/ProcessingInstructionImpl.java
new file mode 100644
index 000000000..4ce0badc8
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/ProcessingInstructionImpl.java
@@ -0,0 +1,104 @@
+/* ProcessingInstructionImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Writer;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.ProcessingInstruction;
+
+/**
+ * A processing instruction event.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class ProcessingInstructionImpl
+ extends XMLEventImpl
+ implements ProcessingInstruction
+{
+
+ protected final String target;
+ protected final String data;
+
+ protected ProcessingInstructionImpl(Location location,
+ String target, String data)
+ {
+ super(location);
+ this.target = target;
+ this.data = data;
+ }
+
+ public int getEventType()
+ {
+ return PROCESSING_INSTRUCTION;
+ }
+
+ public String getTarget()
+ {
+ return target;
+ }
+
+ public String getData()
+ {
+ return data;
+ }
+
+ public void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException
+ {
+ try
+ {
+ writer.write("<?");
+ writer.write(target);
+ if (data != null)
+ {
+ writer.write(' ');
+ writer.write(data);
+ }
+ writer.write("?>");
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/SAXParser.java b/libjava/classpath/gnu/xml/stream/SAXParser.java
new file mode 100644
index 000000000..b71d98ed3
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/SAXParser.java
@@ -0,0 +1,1041 @@
+/* SAXParser.java --
+ Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.Map;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLReporter;
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Parser;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.Attributes2;
+import org.xml.sax.ext.DeclHandler;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.ext.Locator2;
+
+/**
+ * JAXP SAX parser using an underlying StAX parser.
+ * This parser supports the following additional SAX features and
+ * properties:
+ * <table>
+ * <tr><th colspan='4'>Features</th></tr>
+ * <tr><td>http://gnu.org/sax/features/xml-base</td>
+ * <td colspan='2'>read/write</td>
+ * <td>Indicates or sets whether XML Base processing is enabled</td></tr>
+ * <tr><th colspan='4'>Properties</th></tr>
+ * <tr><td>http://gnu.org/sax/properties/base-uri</td>
+ * <td>read-only</td><td>String</td>
+ * <td>Returns the base URI of the current event</td></tr>
+ * <tr><td>http://gnu.org/sax/properties/document-xml-encoding</td>
+ * <td>read-only</td><td>String</td>
+ * <td>Returns the encoding specified in the XML declaration</td></tr>
+ * </table>
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class SAXParser
+ extends javax.xml.parsers.SAXParser
+ implements XMLReader, Attributes2, Locator2, XMLReporter, XMLResolver
+{
+
+ ContentHandler contentHandler;
+ DeclHandler declHandler;
+ DTDHandler dtdHandler;
+ EntityResolver entityResolver;
+ ErrorHandler errorHandler;
+ LexicalHandler lexicalHandler;
+
+ boolean validating = false;
+ boolean namespaceAware = true;
+ boolean xIncludeAware = false;
+ boolean stringInterning = true;
+ boolean coalescing = true;
+ boolean replaceERefs = true;
+ boolean externalEntities = true;
+ boolean supportDTD = true;
+ boolean baseAware = true;
+
+ XMLParser parser;
+ XMLStreamReader reader;
+ String encoding;
+ String xmlVersion;
+ boolean xmlStandalone;
+ String xmlEncoding;
+ String baseURI;
+
+ public SAXParser()
+ {
+ }
+
+ SAXParser(boolean validating, boolean namespaceAware, boolean xIncludeAware)
+ {
+ this.validating = validating;
+ this.namespaceAware = namespaceAware;
+ this.xIncludeAware = xIncludeAware;
+ }
+
+ // -- SAXParser --
+
+ public Parser getParser()
+ throws SAXException
+ {
+ return null;
+ }
+
+ public XMLReader getXMLReader()
+ throws SAXException
+ {
+ return this;
+ }
+
+ public boolean isNamespaceAware()
+ {
+ return namespaceAware;
+ }
+
+ public boolean isValidating()
+ {
+ return validating;
+ }
+
+ public void setProperty(String name, Object value)
+ throws SAXNotRecognizedException, SAXNotSupportedException
+ {
+ if (parser != null)
+ throw new IllegalStateException("parsing in progress");
+ final String FEATURES = "http://xml.org/sax/features/";
+ final String PROPERTIES = "http://xml.org/sax/properties/";
+ final String GNU_FEATURES = "http://gnu.org/sax/features/";
+ if ((FEATURES + "namespaces").equals(name))
+ namespaceAware = Boolean.TRUE.equals(value);
+ else if ((FEATURES + "namespace-prefixes").equals(name))
+ {
+ // NOOP
+ }
+ else if ((FEATURES + "string-interning").equals(name))
+ stringInterning = Boolean.TRUE.equals(value);
+ else if ((FEATURES + "use-attributes2").equals(name))
+ {
+ // NOOP
+ }
+ else if ((FEATURES + "validation").equals(name))
+ validating = Boolean.TRUE.equals(value);
+ else if ((FEATURES + "external-general-entities").equals(name))
+ externalEntities = Boolean.TRUE.equals(value);
+ else if ((FEATURES + "external-parameter-entities").equals(name))
+ externalEntities = Boolean.TRUE.equals(value);
+ else if ((PROPERTIES + "declaration-handler").equals(name))
+ declHandler = (DeclHandler) value;
+ else if ((PROPERTIES + "lexical-handler").equals(name))
+ lexicalHandler = (LexicalHandler) value;
+ else if ((GNU_FEATURES + "xml-base").equals(name))
+ baseAware = Boolean.TRUE.equals(value);
+ else if ((GNU_FEATURES + "coalescing").equals(name))
+ coalescing = Boolean.TRUE.equals(value);
+ else
+ throw new SAXNotSupportedException(name);
+ }
+
+ public Object getProperty(String name)
+ throws SAXNotRecognizedException, SAXNotSupportedException
+ {
+ final String FEATURES = "http://xml.org/sax/features/";
+ final String PROPERTIES = "http://xml.org/sax/properties/";
+ final String GNU_FEATURES = "http://gnu.org/sax/features/";
+ final String GNU_PROPERTIES = "http://gnu.org/sax/properties/";
+ if ((GNU_FEATURES + "base-uri").equals(name))
+ return baseURI;
+ if ((FEATURES + "is-standalone").equals(name))
+ return xmlStandalone ? Boolean.TRUE : Boolean.FALSE;
+ if ((FEATURES + "namespaces").equals(name))
+ return namespaceAware ? Boolean.TRUE : Boolean.FALSE;
+ if ((FEATURES + "namespace-prefixes").equals(name))
+ return Boolean.TRUE;
+ if ((FEATURES + "string-interning").equals(name))
+ return stringInterning ? Boolean.TRUE : Boolean.FALSE;
+ if ((FEATURES + "use-attributes2").equals(name))
+ return Boolean.TRUE;
+ if ((FEATURES + "use-locator2").equals(name))
+ return Boolean.TRUE;
+ if ((FEATURES + "use-entity-resolver2").equals(name))
+ return Boolean.FALSE;
+ if ((FEATURES + "validation").equals(name))
+ return validating ? Boolean.TRUE : Boolean.FALSE;
+ if ((FEATURES + "external-general-entities").equals(name))
+ return externalEntities ? Boolean.TRUE : Boolean.FALSE;
+ if ((FEATURES + "external-parameter-entities").equals(name))
+ return externalEntities ? Boolean.TRUE : Boolean.FALSE;
+ if ((FEATURES + "xml-1.1").equals(name))
+ return Boolean.TRUE;
+ if ((PROPERTIES + "declaration-handler").equals(name))
+ return declHandler;
+ if ((PROPERTIES + "document-xml-version").equals(name))
+ return xmlVersion;
+ if ((PROPERTIES + "lexical-handler").equals(name))
+ return lexicalHandler;
+ if ((GNU_FEATURES + "xml-base").equals(name))
+ return baseAware ? Boolean.TRUE : Boolean.FALSE;
+ if ((GNU_PROPERTIES + "document-xml-encoding").equals(name))
+ return xmlEncoding;
+ throw new SAXNotRecognizedException(name);
+ }
+
+ public boolean isXIncludeAware()
+ {
+ return xIncludeAware;
+ }
+
+ public void reset()
+ {
+ parser = null;
+ encoding = null;
+ xmlVersion = null;
+ xmlStandalone = false;
+ }
+
+ // -- XMLReader --
+
+ public boolean getFeature(String name)
+ throws SAXNotRecognizedException, SAXNotSupportedException
+ {
+ Object ret = getProperty(name);
+ if (ret instanceof Boolean)
+ return ((Boolean) ret).booleanValue();
+ throw new SAXNotSupportedException(name);
+ }
+
+ public void setFeature(String name, boolean value)
+ throws SAXNotRecognizedException, SAXNotSupportedException
+ {
+ setProperty(name, value ? Boolean.TRUE : Boolean.FALSE);
+ }
+
+ public void setEntityResolver(EntityResolver resolver)
+ {
+ entityResolver = resolver;
+ }
+
+ public EntityResolver getEntityResolver()
+ {
+ return entityResolver;
+ }
+
+ public void setDTDHandler(DTDHandler handler)
+ {
+ dtdHandler = handler;
+ }
+
+ public DTDHandler getDTDHandler()
+ {
+ return dtdHandler;
+ }
+
+ public void setContentHandler(ContentHandler handler)
+ {
+ contentHandler = handler;
+ }
+
+ public ContentHandler getContentHandler()
+ {
+ return contentHandler;
+ }
+
+ public void setErrorHandler(ErrorHandler handler)
+ {
+ errorHandler = handler;
+ }
+
+ public ErrorHandler getErrorHandler()
+ {
+ return errorHandler;
+ }
+
+ public synchronized void parse(InputSource input)
+ throws IOException, SAXException
+ {
+ reset();
+ String systemId = input.getSystemId();
+ InputStream in = input.getByteStream();
+ boolean opened = false;
+ if (in != null)
+ parser = new XMLParser(in, systemId,
+ validating,
+ namespaceAware,
+ coalescing,
+ replaceERefs,
+ externalEntities,
+ supportDTD,
+ baseAware,
+ stringInterning,
+ true,
+ this,
+ this);
+ else
+ {
+ Reader r = input.getCharacterStream();
+ if (r != null)
+ parser = new XMLParser(r, systemId,
+ validating,
+ namespaceAware,
+ coalescing,
+ replaceERefs,
+ externalEntities,
+ supportDTD,
+ baseAware,
+ stringInterning,
+ true,
+ this,
+ this);
+ }
+ if (parser == null)
+ {
+ if (systemId == null)
+ throw new SAXException("No stream or system ID specified");
+ systemId = XMLParser.absolutize(null, systemId);
+ in = new URL(systemId).openStream();
+ opened = true;
+ parser = new XMLParser(in, systemId,
+ validating,
+ namespaceAware,
+ coalescing,
+ replaceERefs,
+ externalEntities,
+ supportDTD,
+ baseAware,
+ stringInterning,
+ true,
+ this,
+ this);
+ }
+ reader = parser;
+ baseURI = systemId;
+
+ if (xIncludeAware)
+ reader = new XIncludeFilter(parser, systemId, namespaceAware,
+ validating, true);
+
+ if (contentHandler != null)
+ contentHandler.setDocumentLocator(this);
+ boolean startDocumentDone = false;
+ try
+ {
+ while (parser.hasNext())
+ {
+ int event = parser.next();
+ if (baseAware)
+ baseURI = parser.getXMLBase();
+ switch (event)
+ {
+ case XMLStreamConstants.CHARACTERS:
+ if (contentHandler != null)
+ {
+ char[] b = reader.getTextCharacters();
+ contentHandler.characters(b, 0, b.length);
+ }
+ break;
+ case XMLStreamConstants.SPACE:
+ if (contentHandler != null)
+ {
+ char[] b = reader.getTextCharacters();
+ if (isIgnorableWhitespace(parser, b, false))
+ contentHandler.ignorableWhitespace(b, 0, b.length);
+ else
+ contentHandler.characters(b, 0, b.length);
+ }
+ break;
+ case XMLStreamConstants.CDATA:
+ if (lexicalHandler != null)
+ lexicalHandler.startCDATA();
+ if (contentHandler != null)
+ {
+ char[] b = reader.getTextCharacters();
+ if (isIgnorableWhitespace(parser, b, true))
+ contentHandler.ignorableWhitespace(b, 0, b.length);
+ else
+ contentHandler.characters(b, 0, b.length);
+ }
+ if (lexicalHandler != null)
+ lexicalHandler.endCDATA();
+ break;
+ case XMLStreamConstants.START_ELEMENT:
+ if (contentHandler != null)
+ {
+ QName name = reader.getName();
+ String uri = name.getNamespaceURI();
+ String localName = name.getLocalPart();
+ String prefix = name.getPrefix();
+ String qName = localName;
+ if (!"".equals(prefix))
+ qName = prefix + ":" + localName;
+ if (!namespaceAware)
+ {
+ uri = "";
+ localName = "";
+ }
+ else
+ {
+ int nc = reader.getNamespaceCount();
+ for (int i = 0; i < nc; i++)
+ {
+ String nsuri = reader.getNamespaceURI(i);
+ String nsprefix = reader.getNamespacePrefix(i);
+ if ("xml".equals(nsprefix))
+ continue;
+ contentHandler.startPrefixMapping(nsprefix, nsuri);
+ }
+ }
+ contentHandler.startElement(uri, localName, qName, this);
+ }
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ if (contentHandler != null)
+ {
+ QName name = reader.getName();
+ String uri = name.getNamespaceURI();
+ String localName = name.getLocalPart();
+ String prefix = name.getPrefix();
+ String qName = localName;
+ if (!"".equals(prefix))
+ qName = prefix + ":" + localName;
+ if (!namespaceAware)
+ {
+ uri = "";
+ localName = "";
+ }
+ contentHandler.endElement(uri, localName, qName);
+ if (namespaceAware)
+ {
+ int nc = reader.getNamespaceCount();
+ for (int i = 0; i < nc; i++)
+ {
+ String nsprefix = reader.getNamespacePrefix(i);
+ if ("xml".equals(nsprefix))
+ continue;
+ contentHandler.endPrefixMapping(nsprefix);
+ }
+ }
+ }
+ break;
+ case XMLStreamConstants.COMMENT:
+ if (lexicalHandler != null)
+ {
+ char[] b = reader.getTextCharacters();
+ lexicalHandler.comment(b, 0, b.length);
+ }
+ break;
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ if (contentHandler != null)
+ {
+ String target = reader.getPITarget();
+ String data = reader.getPIData();
+ if (data == null)
+ data = "";
+ contentHandler.processingInstruction(target, data);
+ }
+ break;
+ case XMLParser.START_ENTITY:
+ if (lexicalHandler != null)
+ {
+ String name = reader.getText();
+ lexicalHandler.startEntity(name);
+ }
+ break;
+ case XMLParser.END_ENTITY:
+ if (lexicalHandler != null)
+ {
+ String name = reader.getText();
+ lexicalHandler.endEntity(name);
+ }
+ break;
+ case XMLStreamConstants.START_DOCUMENT:
+ encoding = reader.getEncoding();
+ xmlVersion = reader.getVersion();
+ xmlStandalone = reader.isStandalone();
+ xmlEncoding = reader.getCharacterEncodingScheme();
+ if (contentHandler != null)
+ contentHandler.startDocument();
+ startDocumentDone = true;
+ break;
+ case XMLStreamConstants.END_DOCUMENT:
+ if (contentHandler != null)
+ contentHandler.endDocument();
+ break;
+ case XMLStreamConstants.DTD:
+ XMLParser.Doctype doctype = parser.doctype;
+ if (lexicalHandler != null)
+ {
+ String rootName = doctype.rootName;
+ String publicId = doctype.publicId;
+ String systemId2 = doctype.systemId;
+ lexicalHandler.startDTD(rootName, publicId, systemId2);
+ }
+ for (Iterator i = doctype.entryIterator(); i.hasNext(); )
+ {
+ String entry = (String) i.next();
+ char c = entry.charAt(0);
+ String name = entry.substring(1);
+ if ('E' == c)
+ {
+ // Element decl
+ if (declHandler != null)
+ {
+ XMLParser.ContentModel model =
+ doctype.getElementModel(name);
+ declHandler.elementDecl(name, model.text);
+ }
+ }
+ else if ('A' == c)
+ {
+ // Attlist decl
+ if (declHandler != null)
+ {
+ for (Iterator j = doctype.attlistIterator(name);
+ j.hasNext(); )
+ {
+ Map.Entry att = (Map.Entry) j.next();
+ String aname = (String) att.getKey();
+ XMLParser.AttributeDecl decl =
+ (XMLParser.AttributeDecl) att.getValue();
+ String type = decl.type;
+ String value = decl.value;
+ String mode = null;
+ switch (decl.valueType)
+ {
+ case XMLParser.ATTRIBUTE_DEFAULT_FIXED:
+ mode = "#FIXED";
+ break;
+ case XMLParser.ATTRIBUTE_DEFAULT_REQUIRED:
+ mode = "#REQUIRED";
+ break;
+ case XMLParser.ATTRIBUTE_DEFAULT_IMPLIED:
+ mode = "#IMPLIED";
+ break;
+ }
+ declHandler.attributeDecl(name, aname,
+ type, mode, value);
+ }
+ }
+ }
+ else if ('e' == c)
+ {
+ // Entity decl
+ Object entity = doctype.getEntity(name);
+ if (entity instanceof String)
+ {
+ if (declHandler != null)
+ declHandler.internalEntityDecl(name,
+ (String) entity);
+ }
+ else
+ {
+ XMLParser.ExternalIds ids =
+ (XMLParser.ExternalIds) entity;
+ if (ids.notationName != null)
+ {
+ if (dtdHandler != null)
+ {
+ String pub = ids.publicId;
+ String url = ids.systemId;
+ String not = ids.notationName;
+ dtdHandler.unparsedEntityDecl(name,
+ pub,
+ url,
+ not);
+ }
+ }
+ else
+ {
+ if (declHandler != null)
+ {
+ String pub = ids.publicId;
+ String url = ids.systemId;
+ declHandler.externalEntityDecl(name,
+ pub,
+ url);
+ }
+ }
+ }
+ }
+ else if ('n' == c)
+ {
+ // Notation decl
+ if (dtdHandler != null)
+ {
+ XMLParser.ExternalIds ids =
+ doctype.getNotation(name);
+ String pub = ids.publicId;
+ String url = ids.systemId;
+ dtdHandler.notationDecl(name, pub, url);
+ }
+ }
+ else if ('c' == c)
+ {
+ // Comment
+ if (lexicalHandler != null)
+ {
+ String comment = doctype.getComment(name);
+ char[] b = comment.toCharArray();
+ lexicalHandler.comment(b, 0, b.length);
+ }
+ }
+ else if ('p' == c)
+ {
+ // Processing instruction
+ if (contentHandler != null)
+ {
+ String[] pi = doctype.getPI(name);
+ String target = pi[0];
+ String data = pi[1];
+ if (data == null)
+ data = "";
+ contentHandler.processingInstruction(target, data);
+ }
+ }
+ }
+ if (lexicalHandler != null)
+ lexicalHandler.endDTD();
+ }
+ }
+ reset();
+ if (opened)
+ in.close();
+ }
+ catch (Exception e)
+ {
+ SAXParseException e2 = new SAXParseException(e.getMessage(), this);
+ e2.initCause(e);
+ try
+ {
+ if (!startDocumentDone && contentHandler != null)
+ contentHandler.startDocument();
+ if (errorHandler != null)
+ errorHandler.fatalError(e2);
+ if (contentHandler != null)
+ contentHandler.endDocument();
+ }
+ catch (SAXException sex)
+ {
+ // Ignored, we will rethrow the original exception.
+ }
+ reset();
+ if (opened)
+ in.close();
+ if (e instanceof SAXException)
+ throw (SAXException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ else
+ throw e2;
+ }
+ }
+
+ /**
+ * Indicates whether the specified characters are ignorable whitespace.
+ */
+ private boolean isIgnorableWhitespace(XMLParser reader, char[] b,
+ boolean testCharacters)
+ throws XMLStreamException
+ {
+ XMLParser.Doctype doctype = reader.doctype;
+ if (doctype == null)
+ return false;
+ String currentElement = reader.getCurrentElement();
+ // check for xml:space
+ int ac = reader.getAttributeCount();
+ for (int i = 0; i < ac; i++)
+ {
+ QName aname = reader.getAttributeName(i);
+ if ("space".equals(aname.getLocalPart()) &&
+ XMLConstants.XML_NS_URI.equals(aname.getNamespaceURI()))
+ {
+ if ("preserve".equals(reader.getAttributeValue(i)))
+ return false;
+ }
+ }
+ XMLParser.ContentModel model = doctype.getElementModel(currentElement);
+ if (model == null || model.type != XMLParser.ContentModel.ELEMENT)
+ return false;
+ if (model.external && xmlStandalone)
+ return false;
+ boolean white = true;
+ if (testCharacters)
+ {
+ for (int i = 0; i < b.length; i++)
+ {
+ if (b[i] != ' ' && b[i] != '\t' && b[i] != '\n' && b[i] != '\r')
+ {
+ white = false;
+ break;
+ }
+ }
+ }
+ return white;
+ }
+
+ public void parse(String systemId)
+ throws IOException, SAXException
+ {
+ parse(new InputSource(systemId));
+ }
+
+ // -- Attributes2 --
+
+ public int getIndex(String qName)
+ {
+ int len = reader.getAttributeCount();
+ for (int i = 0; i < len; i++)
+ {
+ QName q = reader.getAttributeName(i);
+ String localName = q.getLocalPart();
+ String prefix = q.getPrefix();
+ String qn = ("".equals(prefix)) ? localName : prefix + ":" + localName;
+ if (qName.equals(qn))
+ return i;
+ }
+ return -1;
+ }
+
+ public int getIndex(String uri, String localName)
+ {
+ int len = reader.getAttributeCount();
+ for (int i = 0; i < len; i++)
+ {
+ QName q = reader.getAttributeName(i);
+ String ln = q.getLocalPart();
+ String u = q.getNamespaceURI();
+ if (u == null && uri != null)
+ continue;
+ if (u != null && !u.equals(uri))
+ continue;
+ if (ln.equals(localName))
+ return i;
+ }
+ return -1;
+ }
+
+ public int getLength()
+ {
+ return reader.getAttributeCount();
+ }
+
+ public String getLocalName(int index)
+ {
+ return reader.getAttributeLocalName(index);
+ }
+
+ public String getQName(int index)
+ {
+ QName q = reader.getAttributeName(index);
+ String localName = q.getLocalPart();
+ String prefix = q.getPrefix();
+ return ("".equals(prefix)) ? localName : prefix + ":" + localName;
+ }
+
+ public String getType(int index)
+ {
+ String ret = reader.getAttributeType(index);
+ // SAX doesn't permit ENUMERATION?
+ return ("ENUMERATION".equals(ret)) ? "NMTOKEN" : ret;
+ }
+
+ public String getType(String qName)
+ {
+ int index = getIndex(qName);
+ return (index == -1) ? null : getType(index);
+ }
+
+ public String getType(String uri, String localName)
+ {
+ int index = getIndex(uri, localName);
+ return (index == -1) ? null : getType(index);
+ }
+
+ public String getURI(int index)
+ {
+ String ret = reader.getAttributeNamespace(index);
+ return (ret == null) ? "" : ret;
+ }
+
+ public String getValue(int index)
+ {
+ return reader.getAttributeValue(index);
+ }
+
+ public String getValue(String qName)
+ {
+ int index = getIndex(qName);
+ return (index == -1) ? null : getValue(index);
+ }
+
+ public String getValue(String uri, String localName)
+ {
+ int index = getIndex(uri, localName);
+ return (index == -1) ? null : getValue(index);
+ }
+
+ public boolean isDeclared(int index)
+ {
+ return parser.isAttributeDeclared(index);
+ }
+
+ public boolean isDeclared(String qName)
+ {
+ int index = getIndex(qName);
+ return (index == -1) ? false : isDeclared(index);
+ }
+
+ public boolean isDeclared(String uri, String localName)
+ {
+ int index = getIndex(uri, localName);
+ return (index == -1) ? false : isDeclared(index);
+ }
+
+ public boolean isSpecified(int index)
+ {
+ return reader.isAttributeSpecified(index);
+ }
+
+ public boolean isSpecified(String qName)
+ {
+ int index = getIndex(qName);
+ return (index == -1) ? false : isSpecified(index);
+ }
+
+ public boolean isSpecified(String uri, String localName)
+ {
+ int index = getIndex(uri, localName);
+ return (index == -1) ? false : isSpecified(index);
+ }
+
+ // -- Locator2 --
+
+ public int getColumnNumber()
+ {
+ Location l = reader.getLocation();
+ return l.getColumnNumber();
+ }
+
+ public int getLineNumber()
+ {
+ Location l = reader.getLocation();
+ return l.getLineNumber();
+ }
+
+ public String getPublicId()
+ {
+ Location l = reader.getLocation();
+ return l.getPublicId();
+ }
+
+ public String getSystemId()
+ {
+ Location l = reader.getLocation();
+ return l.getSystemId();
+ }
+
+ public String getEncoding()
+ {
+ return encoding;
+ }
+
+ public String getXMLVersion()
+ {
+ return xmlVersion;
+ }
+
+ // -- XMLResolver --
+
+ public Object resolveEntity(String publicId, String systemId,
+ String baseURI, String namespace)
+ throws XMLStreamException
+ {
+ if (entityResolver != null)
+ {
+ try
+ {
+ InputSource input =
+ entityResolver.resolveEntity(publicId, systemId);
+ if (input != null)
+ {
+ InputStream in = input.getByteStream();
+ if (in == null)
+ {
+ String newSystemId = input.getSystemId();
+ if (newSystemId != null && !newSystemId.equals(systemId))
+ in = XMLParser.resolve(newSystemId);
+ }
+ return in;
+ }
+ }
+ catch (SAXException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+ return null;
+ }
+
+ public XMLEventReader resolveAsXMLEventReader(String uri)
+ throws XMLStreamException
+ {
+ // unused
+ return null;
+ }
+
+ public XMLStreamReader resolveAsXMLStreamReader(String uri)
+ throws XMLStreamException
+ {
+ // unused
+ return null;
+ }
+
+ // -- XMLReporter --
+
+ public void report(String message, String errorType,
+ Object relatedInformation, Location location)
+ throws XMLStreamException
+ {
+ if (errorHandler != null)
+ {
+ try
+ {
+ errorHandler.warning(new SAXParseException(message, this));
+ }
+ catch (SAXException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+ }
+
+ public static void main(String[] args)
+ throws Exception
+ {
+ boolean validating = false;
+ boolean namespaceAware = false;
+ boolean xIncludeAware = false;
+ boolean expectCallbackClass = false;
+ String callbackClass = null;
+ int pos = 0;
+ while (pos < args.length && (args[pos].startsWith("-") || expectCallbackClass))
+ {
+ if ("-x".equals(args[pos]))
+ xIncludeAware = true;
+ else if ("-v".equals(args[pos]))
+ validating = true;
+ else if ("-n".equals(args[pos]))
+ namespaceAware = true;
+ else if ("-c".equals(args[pos]))
+ expectCallbackClass = true;
+ else if (expectCallbackClass)
+ {
+ callbackClass = args[pos];
+ expectCallbackClass = false;
+ }
+ pos++;
+ }
+ if (pos >= args.length || expectCallbackClass)
+ {
+ System.out.println("Syntax: SAXParser [-n] [-v] [-x] [-c <class>] <file> [<file2> [...]]");
+ System.out.println("\t-n: use namespace aware mode");
+ System.out.println("\t-v: use validating parser");
+ System.out.println("\t-x: use XInclude aware mode");
+ System.out.println("\t-c <class>: use specified class as callback handler (must have a no-arg public constructor)");
+ System.exit(2);
+ }
+ while (pos < args.length)
+ {
+ ContentHandler handler = null;
+ if (callbackClass != null)
+ {
+ Class t = Class.forName(callbackClass);
+ handler = (ContentHandler) t.newInstance();
+ }
+ else
+ handler = new org.xml.sax.helpers.DefaultHandler();
+ SAXParser parser = new SAXParser(validating, namespaceAware,
+ xIncludeAware);
+ InputSource input = new InputSource(args[pos]);
+ java.io.FileReader fr = new java.io.FileReader(args[pos]);
+ input.setCharacterStream(fr);
+ try
+ {
+ XMLReader reader = parser.getXMLReader();
+ reader.setContentHandler(handler);
+ reader.parse(input);
+ }
+ finally
+ {
+ fr.close();
+ }
+ pos++;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/SAXParserFactory.java b/libjava/classpath/gnu/xml/stream/SAXParserFactory.java
new file mode 100644
index 000000000..ebaeb3cb2
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/SAXParserFactory.java
@@ -0,0 +1,104 @@
+/* SAXParserFactory.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+/**
+ * SAX parser factory providing a SAX compatibility layer on top of StAX.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class SAXParserFactory
+ extends javax.xml.parsers.SAXParserFactory
+{
+
+ static final Set FEATURE_NAMES = new HashSet();
+ static
+ {
+ FEATURE_NAMES.add("http://xml.org/sax/features/namespaces");
+ FEATURE_NAMES.add("http://xml.org/sax/features/string-interning");
+ FEATURE_NAMES.add("http://xml.org/sax/features/validation");
+ }
+
+ Map features = new HashMap();
+
+ public javax.xml.parsers.SAXParser newSAXParser()
+ throws ParserConfigurationException, SAXException
+ {
+ boolean validating = isValidating();
+ boolean namespaceAware = isNamespaceAware();
+ boolean xIncludeAware = isXIncludeAware();
+ SAXParser ret = new SAXParser(validating, namespaceAware, xIncludeAware);
+ for (Iterator i = features.entrySet().iterator(); i.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ String name = (String) entry.getKey();
+ Boolean value = (Boolean) entry.getValue();
+ ret.setFeature(name, value.booleanValue());
+ }
+ return ret;
+ }
+
+ public void setFeature(String name, boolean value)
+ throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException
+ {
+ if (!FEATURE_NAMES.contains(name))
+ throw new SAXNotSupportedException(name);
+ features.put(name, value ? Boolean.TRUE : Boolean.FALSE);
+ }
+
+ public boolean getFeature(String name)
+ throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException
+ {
+ if (!FEATURE_NAMES.contains(name))
+ throw new SAXNotSupportedException(name);
+ Boolean value = (Boolean) features.get(name);
+ return (value == null) ? false : value.booleanValue();
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/StartDocumentImpl.java b/libjava/classpath/gnu/xml/stream/StartDocumentImpl.java
new file mode 100644
index 000000000..d2e590cfc
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/StartDocumentImpl.java
@@ -0,0 +1,143 @@
+/* StartDocumentImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Writer;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartDocument;
+
+/**
+ * A start-document event.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class StartDocumentImpl
+ extends XMLEventImpl
+ implements StartDocument
+{
+
+ protected final String systemId;
+ protected final String encoding;
+ protected final String xmlVersion;
+ protected final boolean xmlStandalone;
+ protected final boolean standaloneDeclared;
+ protected final boolean encodingDeclared;
+
+ protected StartDocumentImpl(Location location,
+ String systemId, String encoding,
+ String xmlVersion, boolean xmlStandalone,
+ boolean standaloneDeclared,
+ boolean encodingDeclared)
+ {
+ super(location);
+ this.systemId = systemId;
+ this.encoding = encoding;
+ this.xmlVersion = xmlVersion;
+ this.xmlStandalone = xmlStandalone;
+ this.standaloneDeclared = standaloneDeclared;
+ this.encodingDeclared = encodingDeclared;
+ }
+
+ public int getEventType()
+ {
+ return START_DOCUMENT;
+ }
+
+ public String getSystemId()
+ {
+ return systemId;
+ }
+
+ public String getCharacterEncodingScheme()
+ {
+ return encoding;
+ }
+
+ public boolean encodingSet()
+ {
+ return encodingDeclared;
+ }
+
+ public boolean isStandalone()
+ {
+ return xmlStandalone;
+ }
+
+ public boolean standaloneSet()
+ {
+ return standaloneDeclared;
+ }
+
+ public String getVersion()
+ {
+ return xmlVersion;
+ }
+
+ public void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException
+ {
+ try
+ {
+ writer.write("<?xml version='");
+ writer.write(xmlVersion);
+ writer.write('\'');
+ if (standaloneDeclared)
+ {
+ writer.write(" standalone='");
+ writer.write(xmlStandalone ? "yes" : "no");
+ writer.write('\'');
+ }
+ if (encodingDeclared)
+ {
+ writer.write(" encoding='");
+ writer.write(encoding);
+ writer.write('\'');
+ }
+ writer.write("?>");
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/StartElementImpl.java b/libjava/classpath/gnu/xml/stream/StartElementImpl.java
new file mode 100644
index 000000000..66e68d560
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/StartElementImpl.java
@@ -0,0 +1,152 @@
+/* StartElementImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.Namespace;
+import javax.xml.stream.events.StartElement;
+
+/**
+ * A start-element event.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class StartElementImpl
+ extends XMLEventImpl
+ implements StartElement
+{
+
+ protected final QName name;
+ protected final List attributes;
+ protected final List namespaces;
+ protected final NamespaceContext namespaceContext;
+
+ protected StartElementImpl(Location location,
+ QName name, List attributes, List namespaces,
+ NamespaceContext namespaceContext)
+ {
+ super(location);
+ this.name = name;
+ this.attributes = attributes;
+ this.namespaces = namespaces;
+ this.namespaceContext = namespaceContext;
+ }
+
+ public int getEventType()
+ {
+ return START_ELEMENT;
+ }
+
+ public QName getName()
+ {
+ return name;
+ }
+
+ public Iterator getAttributes()
+ {
+ return attributes.iterator();
+ }
+
+ public Iterator getNamespaces()
+ {
+ return namespaces.iterator();
+ }
+
+ public Attribute getAttributeByName(QName name)
+ {
+ for (Iterator i = attributes.iterator(); i.hasNext(); )
+ {
+ Attribute attr = (Attribute) i.next();
+ if (name.equals(attr.getName()))
+ return attr;
+ }
+ return null;
+ }
+
+ public NamespaceContext getNamespaceContext()
+ {
+ return namespaceContext;
+ }
+
+ public String getNamespaceURI(String prefix)
+ {
+ return namespaceContext.getNamespaceURI(prefix);
+ }
+
+ public void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException
+ {
+ try
+ {
+ writer.write('<');
+ String prefix = name.getPrefix();
+ if (prefix != null && !"".equals(prefix))
+ {
+ writer.write(prefix);
+ writer.write(':');
+ }
+ writer.write(name.getLocalPart());
+ for (Iterator i = namespaces.iterator(); i.hasNext(); )
+ {
+ writer.write(' ');
+ ((Namespace) i.next()).writeAsEncodedUnicode(writer);
+ }
+ for (Iterator i = attributes.iterator(); i.hasNext(); )
+ {
+ writer.write(' ');
+ ((Attribute) i.next()).writeAsEncodedUnicode(writer);
+ }
+ writer.write('>');
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/UnicodeReader.java b/libjava/classpath/gnu/xml/stream/UnicodeReader.java
new file mode 100644
index 000000000..aa2a95422
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/UnicodeReader.java
@@ -0,0 +1,205 @@
+/* UnicodeReader.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * A reader that converts UTF-16 characters to Unicode code points.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class UnicodeReader
+{
+
+ final Reader in;
+
+ UnicodeReader(Reader in)
+ {
+ this.in = in;
+ }
+
+ public void mark(int limit)
+ throws IOException
+ {
+ in.mark(limit * 2);
+ }
+
+ public void reset()
+ throws IOException
+ {
+ in.reset();
+ }
+
+ public int read()
+ throws IOException
+ {
+ int ret = in.read();
+ if (ret == -1)
+ return ret;
+ if (ret >= 0xd800 && ret < 0xdc00)
+ {
+ // Unicode surrogate?
+ int low = in.read();
+ if (low >= 0xdc00 && low < 0xe000)
+ ret = Character.toCodePoint((char) ret, (char) low);
+ else
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(ret));
+ }
+ else if (ret >= 0xdc00 && ret < 0xe000)
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(ret));
+ return ret;
+ }
+
+ public int read(int[] buf, int off, int len)
+ throws IOException
+ {
+ if (len == 0)
+ return 0;
+ char[] b2 = new char[len];
+ int ret = in.read(b2, 0, len);
+ if (ret <= 0)
+ return ret;
+ int l = ret - 1;
+ int i = 0, j = off;
+ for (; i < l; i++)
+ {
+ char c = b2[i];
+ if (c >= 0xd800 && c < 0xdc00)
+ {
+ // Unicode surrogate?
+ char d = b2[i + 1];
+ if (d >= 0xdc00 && d < 0xe000)
+ {
+ buf[j++] = Character.toCodePoint(c, d);
+ i++;
+ continue;
+ }
+ else
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(c));
+ }
+ else if (c >= 0xdc00 && c < 0xe000)
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(c));
+ buf[j++] = (int) c;
+ }
+ if (i == l)
+ {
+ // last char
+ char c = b2[l];
+ if (c >= 0xd800 && c < 0xdc00)
+ {
+ int low = in.read();
+ if (low >= 0xdc00 && low < 0xe000)
+ {
+ buf[j++] = Character.toCodePoint(c, (char) low);
+ return j;
+ }
+ else
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(c));
+ }
+ else if (c >= 0xdc00 && c < 0xe000)
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(c));
+ buf[j++] = (int) c;
+ }
+ return j;
+ }
+
+ public void close()
+ throws IOException
+ {
+ in.close();
+ }
+
+ /**
+ * Returns the specified UTF-16 char array as an array of Unicode code
+ * points.
+ */
+ public static int[] toCodePointArray(String text)
+ throws IOException
+ {
+ char[] b2 = text.toCharArray();
+ int[] buf = new int[b2.length];
+ if (b2.length > 0)
+ {
+ int l = b2.length - 1;
+ int i = 0, j = 0;
+ for (; i < l; i++)
+ {
+ char c = b2[i];
+ if (c >= 0xd800 && c < 0xdc00)
+ {
+ // Unicode surrogate?
+ char d = b2[i + 1];
+ if (d >= 0xdc00 && d < 0xe000)
+ {
+ buf[j++] = Character.toCodePoint(c, d);
+ i++;
+ continue;
+ }
+ else
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(c));
+ }
+ else if (c >= 0xdc00 && c < 0xe000)
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(c));
+ buf[j++] = (int) c;
+ }
+ if (i == l)
+ {
+ // last char
+ buf[j++] = (int) b2[l];
+ if (j < buf.length)
+ {
+ int[] buf2 = new int[j];
+ System.arraycopy(buf, 0, buf2, 0, j);
+ buf = buf2;
+ }
+ }
+ }
+ return buf;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/XIncludeFilter.java b/libjava/classpath/gnu/xml/stream/XIncludeFilter.java
new file mode 100644
index 000000000..6d955c492
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/XIncludeFilter.java
@@ -0,0 +1,931 @@
+/* XIncludeFilter.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashSet;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.util.StreamReaderDelegate;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.TypeInfo;
+import org.w3c.dom.traversal.DocumentTraversal;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.TreeWalker;
+import org.w3c.dom.xpath.XPathEvaluator;
+import org.w3c.dom.xpath.XPathNSResolver;
+import org.w3c.dom.xpath.XPathResult;
+import org.xml.sax.SAXException;
+
+/**
+ * StAX filter for performing XInclude processing.
+ *
+ * @see http://www.w3.org/TR/xinclude/
+ * @see http://www.w3.org/TR/xptr-framework/
+ * @see http://www.w3.org/TR/xptr-element/
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class XIncludeFilter
+ extends StreamReaderDelegate
+{
+
+ static final String XINCLUDE_NS_URI = "http://www.w3.org/2001/XInclude";
+ static final int SHOW_FLAGS =
+ NodeFilter.SHOW_CDATA_SECTION |
+ NodeFilter.SHOW_COMMENT |
+ NodeFilter.SHOW_ELEMENT |
+ NodeFilter.SHOW_ENTITY_REFERENCE |
+ NodeFilter.SHOW_PROCESSING_INSTRUCTION |
+ NodeFilter.SHOW_TEXT;
+
+ final String systemId;
+ final boolean namespaceAware;
+ final boolean validating;
+ final boolean expandERefs;
+ String href;
+ int event;
+ boolean included;
+ XPathResult result;
+ int snapshotIndex;
+ Node current;
+ TreeWalker walker;
+ HashSet seen = new HashSet();
+ boolean backtracking;
+ boolean lookahead;
+
+ Reader includedText;
+ char[] buf;
+ int len = -1;
+ boolean inInclude, inFallback, seenFallback;
+
+ DocumentBuilder builder;
+
+ XIncludeFilter(XMLStreamReader reader, String systemId,
+ boolean namespaceAware, boolean validating,
+ boolean expandERefs)
+ {
+ super(reader);
+ this.systemId = XMLParser.absolutize(null, systemId);
+ this.namespaceAware = namespaceAware;
+ this.validating = validating;
+ this.expandERefs = expandERefs;
+ }
+
+ public int getAttributeCount()
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ return (attrs == null) ? 0 : attrs.getLength();
+ }
+ return super.getAttributeCount();
+ }
+
+ public String getAttributeLocalName(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Node attr = attrs.item(index);
+ return attr.getLocalName();
+ }
+ return super.getAttributeLocalName(index);
+ }
+
+ public String getAttributeNamespace(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Node attr = attrs.item(index);
+ return attr.getNamespaceURI();
+ }
+ return super.getAttributeNamespace(index);
+ }
+
+ public String getAttributePrefix(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Node attr = attrs.item(index);
+ return attr.getPrefix();
+ }
+ return super.getAttributePrefix(index);
+ }
+
+ public QName getAttributeName(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Node attr = attrs.item(index);
+ String localName = attr.getLocalName();
+ String uri = attr.getNamespaceURI();
+ String prefix = attr.getPrefix();
+ return new QName(uri, localName, prefix);
+ }
+ return super.getAttributeName(index);
+ }
+
+ public String getAttributeType(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Attr attr = (Attr) attrs.item(index);
+ TypeInfo ti = attr.getSchemaTypeInfo();
+ return (ti == null) ? "CDATA" : ti.getTypeName();
+ }
+ return super.getAttributeType(index);
+ }
+
+ public boolean isAttributeSpecified(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return false;
+ Attr attr = (Attr) attrs.item(index);
+ return attr.getSpecified();
+ }
+ return super.isAttributeSpecified(index);
+ }
+
+ public String getAttributeValue(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Node attr = attrs.item(index);
+ return attr.getNodeValue();
+ }
+ return super.getAttributeValue(index);
+ }
+
+ public String getAttributeValue(String uri, String localName)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Node attr = attrs.getNamedItemNS(uri, localName);
+ return (attr == null) ? null : attr.getNodeValue();
+ }
+ return super.getAttributeValue(uri, localName);
+ }
+
+ public String getElementText()
+ throws XMLStreamException
+ {
+ if (current != null)
+ return current.getTextContent();
+ return super.getElementText();
+ }
+
+ public int getEventType()
+ {
+ return event;
+ }
+
+ public String getLocalName()
+ {
+ if (current != null)
+ return current.getLocalName();
+ return super.getLocalName();
+ }
+
+ public QName getName()
+ {
+ if (current != null)
+ {
+ String localName = current.getLocalName();
+ String uri = current.getNamespaceURI();
+ String prefix = current.getPrefix();
+ return new QName(uri, localName, prefix);
+ }
+ return super.getName();
+ }
+
+ public String getNamespaceURI()
+ {
+ if (current != null)
+ return current.getNamespaceURI();
+ return super.getNamespaceURI();
+ }
+
+ // TODO namespaces
+
+ public String getPIData()
+ {
+ if (current != null)
+ return ((ProcessingInstruction) current).getData();
+ return super.getPIData();
+ }
+
+ public String getPITarget()
+ {
+ if (current != null)
+ return ((ProcessingInstruction) current).getTarget();
+ return super.getPITarget();
+ }
+
+ public String getPrefix()
+ {
+ if (current != null)
+ return current.getPrefix();
+ return super.getPrefix();
+ }
+
+ public String getText()
+ {
+ if (current != null)
+ return current.getNodeValue();
+ if (walker != null)
+ {
+ Node n = walker.getCurrentNode();
+ if (n != null)
+ return n.getTextContent();
+ }
+ if (buf != null)
+ return new String(buf, 0, len);
+ return super.getText();
+ }
+
+ public char[] getTextCharacters()
+ {
+ if (current != null)
+ {
+ buf = current.getNodeValue().toCharArray();
+ len = buf.length;
+ }
+ if (buf != null)
+ return buf;
+ return super.getTextCharacters();
+ }
+
+ public int getTextCharacters(int sourceStart, char[] target,
+ int targetStart, int length)
+ throws XMLStreamException
+ {
+ if (current != null)
+ {
+ buf = current.getNodeValue().toCharArray();
+ len = buf.length;
+ }
+ if (buf != null)
+ {
+ int max = Math.min(len - sourceStart, length);
+ if (max > 0)
+ System.arraycopy(buf, sourceStart, target, targetStart, max);
+ return max;
+ }
+ return super.getTextCharacters(sourceStart, target, targetStart, length);
+ }
+
+ public int getTextLength()
+ {
+ if (current != null)
+ {
+ buf = current.getNodeValue().toCharArray();
+ len = buf.length;
+ }
+ if (buf != null)
+ return len;
+ return super.getTextLength();
+ }
+
+ public int getTextStart()
+ {
+ if (current != null)
+ {
+ buf = current.getNodeValue().toCharArray();
+ len = buf.length;
+ }
+ if (buf != null)
+ return 0;
+ return super.getTextStart();
+ }
+
+ public boolean hasNext()
+ throws XMLStreamException
+ {
+ if (!lookahead)
+ {
+ try
+ {
+ next();
+ }
+ catch (NoSuchElementException e)
+ {
+ event = -1;
+ }
+ lookahead = true;
+ }
+ return (event != -1);
+ }
+
+ public int next()
+ throws XMLStreamException
+ {
+ if (lookahead)
+ {
+ lookahead = false;
+ return event;
+ }
+ buf = null;
+ len = 0;
+ if (walker != null)
+ {
+ Node c = walker.getCurrentNode();
+ Node n = null;
+ if (c.getNodeType() == Node.ELEMENT_NODE)
+ {
+ boolean isStartElement = !seen.contains(c);
+ if (isStartElement)
+ {
+ seen.add(c);
+ current = c;
+ event = XMLStreamConstants.START_ELEMENT;
+ return event;
+ }
+ else if (backtracking)
+ {
+ n = walker.nextSibling();
+ if (n != null)
+ backtracking = false;
+ }
+ else
+ {
+ n = walker.firstChild();
+ if (n == null)
+ n = walker.nextSibling();
+ }
+ }
+ else
+ {
+ n = walker.firstChild();
+ if (n == null)
+ n = walker.nextSibling();
+ }
+ if (n == null)
+ {
+ current = walker.parentNode();
+ if (current != null && current.getNodeType() == Node.ELEMENT_NODE)
+ {
+ // end-element
+ backtracking = true;
+ event = XMLStreamConstants.END_ELEMENT;
+ return event;
+ }
+ else
+ {
+ walker = null;
+ current = null;
+ }
+ }
+ else
+ {
+ current = n;
+ switch (n.getNodeType())
+ {
+ case Node.ELEMENT_NODE:
+ return next();
+ case Node.TEXT_NODE:
+ String text = n.getNodeValue();
+ buf = text.toCharArray();
+ len = buf.length;
+ event = isSpace(buf, len) ?
+ XMLStreamConstants.SPACE :
+ XMLStreamConstants.CHARACTERS;
+ return event;
+ case Node.CDATA_SECTION_NODE:
+ event = XMLStreamConstants.CDATA;
+ return event;
+ case Node.COMMENT_NODE:
+ event = XMLStreamConstants.COMMENT;
+ return event;
+ case Node.PROCESSING_INSTRUCTION_NODE:
+ event = XMLStreamConstants.PROCESSING_INSTRUCTION;
+ return event;
+ case Node.ENTITY_REFERENCE_NODE:
+ event = XMLStreamConstants.ENTITY_REFERENCE;
+ return event;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ }
+ if (result != null)
+ {
+ switch (result.getResultType())
+ {
+ case XPathResult.BOOLEAN_TYPE:
+ boolean bval = result.getBooleanValue();
+ String btext = bval ? "true" : "false";
+ buf = btext.toCharArray();
+ len = buf.length;
+ result = null;
+ event = XMLStreamConstants.CHARACTERS;
+ return event;
+ case XPathResult.NUMBER_TYPE:
+ double nval = result.getNumberValue();
+ String ntext = Double.toString(nval);
+ buf = ntext.toCharArray();
+ len = buf.length;
+ result = null;
+ event = XMLStreamConstants.CHARACTERS;
+ return event;
+ case XPathResult.STRING_TYPE:
+ String stext = result.getStringValue();
+ buf = stext.toCharArray();
+ len = buf.length;
+ result = null;
+ event = isSpace(buf, len) ?
+ XMLStreamConstants.SPACE :
+ XMLStreamConstants.CHARACTERS;
+ return event;
+ case XPathResult.ANY_UNORDERED_NODE_TYPE:
+ case XPathResult.FIRST_ORDERED_NODE_TYPE:
+ Node n1 = result.getSingleNodeValue();
+ Document d1 = getDocument(n1);
+ walker = getDocumentTraversal(d1)
+ .createTreeWalker(n1, SHOW_FLAGS, null, expandERefs);
+ result = null;
+ return next();
+ case XPathResult.ORDERED_NODE_ITERATOR_TYPE:
+ case XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
+ Node n2 = result.iterateNext();
+ if (n2 == null)
+ {
+ result = null;
+ return next();
+ }
+ Document d2 = getDocument(n2);
+ walker = getDocumentTraversal(d2)
+ .createTreeWalker(n2, SHOW_FLAGS, null, expandERefs);
+ return next();
+ case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE:
+ case XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE:
+ Node n3 = result.snapshotItem(snapshotIndex++);
+ if (n3 == null)
+ {
+ result = null;
+ return next();
+ }
+ Document d3 = getDocument(n3);
+ walker = getDocumentTraversal(d3)
+ .createTreeWalker(n3, SHOW_FLAGS, null, expandERefs);
+ return next();
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ if (includedText != null)
+ {
+ // fill buffer
+ if (buf == null)
+ buf = new char[2048];
+ try
+ {
+ len = includedText.read(buf, 0, buf.length);
+ if (len == -1)
+ {
+ includedText = null;
+ buf = null;
+ return next();
+ }
+ // chars or space?
+ return (event = isSpace(buf, len) ?
+ XMLStreamConstants.SPACE :
+ XMLStreamConstants.CHARACTERS);
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+ event = super.next();
+ switch (event)
+ {
+ case XMLStreamConstants.START_ELEMENT:
+ String uri = getNamespaceURI();
+ if (XINCLUDE_NS_URI.equals(uri))
+ {
+ String localName = getLocalName();
+ if ("include".equals(localName))
+ {
+ href = getAttributeValue(null, "href");
+ String parse = getAttributeValue(null, "parse");
+ String xpointer = getAttributeValue(null, "xpointer");
+ String encoding = getAttributeValue(null, "encoding");
+ String accept = getAttributeValue(null, "accept");
+ String acceptLanguage = getAttributeValue(null,
+ "accept-language");
+ if (includeResource(href, parse, xpointer, encoding,
+ accept, acceptLanguage))
+ {
+ // Skip to xi:include end-element event
+ int depth = 0;
+ while (depth >= 0)
+ {
+ event = super.next();
+ switch (event)
+ {
+ case XMLStreamConstants.START_ELEMENT:
+ depth++;
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ depth--;
+ }
+ }
+ }
+ else
+ inInclude = true;
+ }
+ else if (inInclude && "fallback".equals(localName))
+ {
+ if (!seenFallback)
+ inFallback = seenFallback = true;
+ else
+ throw new XMLStreamException("duplicate xi:fallback element");
+ }
+ else if (inInclude)
+ {
+ throw new XMLStreamException("illegal xi element '" +
+ localName + "'");
+ }
+ return next();
+ }
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ String uri2 = getNamespaceURI();
+ if (XINCLUDE_NS_URI.equals(uri2))
+ {
+ String localName = getLocalName();
+ if ("include".equals(localName))
+ {
+ if (!seenFallback && included)
+ {
+ String msg = "Unable to read " + href +
+ " and no xi:fallback element present";
+ throw new XMLStreamException(msg);
+ }
+ included = false;
+ href = null;
+ inInclude = inFallback = seenFallback = false;
+ }
+ else if ("fallback".equals(localName))
+ inFallback = false;
+ return next();
+ }
+ break;
+ }
+ if (inInclude && !inFallback)
+ return next();
+ return event;
+ }
+
+ boolean isSpace(char[] text, int len)
+ {
+ boolean space = true;
+ for (int i = 0; i < len; i++)
+ {
+ char c = text[i];
+ if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
+ {
+ space = false;
+ break;
+ }
+ }
+ return space;
+ }
+
+ String getBaseURI()
+ {
+ String base = (String) getParent().getProperty("gnu.xml.stream.baseURI");
+ return (base == null) ? systemId : base;
+ }
+
+ boolean includeResource(String href, String parse, String xpointer,
+ String encoding, String accept,
+ String acceptLanguage)
+ {
+ included = false;
+ try
+ {
+ if (xpointer != null)
+ throw new XMLStreamException("xpointer attribute not yet supported");
+ String base = getBaseURI();
+ if (href == null || "".equals(href))
+ href = base;
+ else
+ href = XMLParser.absolutize(base, href);
+ if (parse == null || "xml".equals(parse))
+ {
+ seen.clear();
+ result = null;
+ snapshotIndex = 0;
+ walker = null;
+ current = null;
+ backtracking = false;
+
+ URLConnection connection = getURLConnection(href, accept,
+ acceptLanguage);
+ InputStream in = connection.getInputStream();
+ Document doc = getDocumentBuilder().parse(in, href);
+ DocumentTraversal dt = getDocumentTraversal(doc);
+ if (xpointer == null)
+ {
+ result = null;
+ Node item = doc.getDocumentElement();
+ walker = dt.createTreeWalker(item, SHOW_FLAGS, null,
+ expandERefs);
+ }
+ else
+ {
+ result = null;
+ snapshotIndex = 0;
+ walker = null;
+ // shorthand or scheme-based?
+ int lpi = xpointer.indexOf('(');
+ int rpi = xpointer.indexOf(')', lpi);
+ if (lpi != -1 && rpi != -1)
+ {
+ String scheme = xpointer.substring(0, lpi);
+ if ("element".equals(scheme))
+ {
+ // element() scheme
+ String elementSchemeData =
+ xpointer.substring(lpi + 1, rpi);
+ Node item = doc;
+ int si = elementSchemeData.indexOf('/');
+ if (si == -1)
+ {
+ if (elementSchemeData.length() > 0)
+ item = doc.getElementById(elementSchemeData);
+ }
+ else
+ {
+ if (si > 0)
+ {
+ String context =
+ elementSchemeData.substring(0, si);
+ item = doc.getElementById(context);
+ elementSchemeData =
+ elementSchemeData.substring(si + 1);
+ }
+ StringTokenizer st =
+ new StringTokenizer(elementSchemeData, "/");
+ while (st.hasMoreTokens() && item != null)
+ {
+ int n = Integer.parseInt(st.nextToken());
+ Node ctx = item.getFirstChild();
+ int count = 1;
+ while (ctx != null && count++ < n)
+ ctx = ctx.getNextSibling();
+ item = ctx;
+ }
+ }
+ walker = dt.createTreeWalker(item, SHOW_FLAGS, null,
+ expandERefs);
+ included = true;
+ }
+ else if ("xpointer".equals(scheme))
+ {
+ xpointer = xpointer.substring(lpi + 1, rpi);
+ XPathEvaluator eval = getXPathEvaluator(doc);
+ XPathNSResolver resolver = eval.createNSResolver(doc);
+ result =
+ (XPathResult) eval.evaluate(xpointer, doc,
+ resolver,
+ XPathResult.ANY_TYPE,
+ null);
+ // TODO xpointer() scheme functions
+ included = true;
+ }
+ else
+ {
+ String msg = "Unknown XPointer scheme: " + scheme;
+ throw new XMLStreamException(msg);
+ }
+ }
+ else
+ {
+ Node item = doc.getElementById(xpointer);
+ walker = dt.createTreeWalker(item, SHOW_FLAGS, null,
+ expandERefs);
+ included = true;
+ }
+ }
+ }
+ else if ("text".equals(parse))
+ {
+ URLConnection connection = getURLConnection(href, accept,
+ acceptLanguage);
+ InputStream in = connection.getInputStream();
+ if (encoding == null)
+ {
+ encoding = connection.getContentEncoding();
+ if (encoding == null)
+ {
+ String contentType = connection.getContentType();
+ if (contentType != null)
+ encoding = getParameter(contentType, "charset");
+ }
+ }
+ if (encoding == null)
+ includedText = new InputStreamReader(in, "UTF-8");
+ else
+ includedText = new InputStreamReader(in, encoding);
+ included = true;
+ }
+ else
+ throw new XMLStreamException("value of 'parse' attribute must be "+
+ "'xml' or 'text'");
+ return true;
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
+ catch (XMLStreamException e)
+ {
+ return false;
+ }
+ catch (SAXException e)
+ {
+ return false;
+ }
+ }
+
+ URLConnection getURLConnection(String href, String accept,
+ String acceptLanguage)
+ throws IOException
+ {
+ URL url = new URL(href);
+ URLConnection connection = url.openConnection();
+ if (connection instanceof HttpURLConnection)
+ {
+ HttpURLConnection http = (HttpURLConnection) connection;
+ http.setInstanceFollowRedirects(true);
+ if (accept != null)
+ http.setRequestProperty("Accept", accept);
+ if (acceptLanguage != null)
+ http.setRequestProperty("Accept-Language", acceptLanguage);
+ }
+ return connection;
+ }
+
+ Document getDocument(Node node)
+ {
+ if (node.getNodeType() == Node.DOCUMENT_NODE)
+ return (Document) node;
+ return node.getOwnerDocument();
+ }
+
+ DocumentBuilder getDocumentBuilder()
+ throws XMLStreamException
+ {
+ if (builder == null)
+ {
+ try
+ {
+ DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
+ f.setXIncludeAware(true);
+ f.setNamespaceAware(namespaceAware);
+ f.setValidating(validating);
+ builder = f.newDocumentBuilder();
+ }
+ catch (ParserConfigurationException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+ builder.reset();
+ return builder;
+ }
+
+ DocumentTraversal getDocumentTraversal(Document doc)
+ throws XMLStreamException
+ {
+ DOMImplementation dom = doc.getImplementation();
+ if (!dom.hasFeature("Traversal", "2.0"))
+ throw new XMLStreamException("Traversal not supported");
+ return (DocumentTraversal) doc;
+ }
+
+ XPathEvaluator getXPathEvaluator(Document doc)
+ throws XMLStreamException
+ {
+ DOMImplementation dom = doc.getImplementation();
+ if (!dom.hasFeature("XPath", "3.0"))
+ throw new XMLStreamException("XPath not supported");
+ return (XPathEvaluator) doc;
+ }
+
+ static String getParameter(String contentType, String name)
+ {
+ StringTokenizer st = new StringTokenizer(contentType, " ;");
+ if (st.hasMoreTokens())
+ st.nextToken();
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ int ei = token.indexOf('=');
+ if (ei != -1)
+ {
+ String key = token.substring(0, ei);
+ if (key.equals(name))
+ {
+ String value = token.substring(ei + 1);
+ int len = value.length();
+ if (len > 1 &&
+ value.charAt(0) == '"' &&
+ value.charAt(len - 1) == '"')
+ value = value.substring(1, len - 1);
+ else if (len > 1 &&
+ value.charAt(0) == '\'' &&
+ value.charAt(len - 1) == '\'')
+ value = value.substring(1, len - 1);
+ return value;
+ }
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/XMLEventAllocatorImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventAllocatorImpl.java
new file mode 100644
index 000000000..a1824bfc5
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/XMLEventAllocatorImpl.java
@@ -0,0 +1,204 @@
+/* XMLEventAllocatorImpl.java --
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.events.EntityDeclaration;
+import javax.xml.stream.events.XMLEvent;
+import javax.xml.stream.util.XMLEventAllocator;
+import javax.xml.stream.util.XMLEventConsumer;
+
+/**
+ * Allocator for creating XML events based on a reader state.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class XMLEventAllocatorImpl
+ implements XMLEventAllocator
+{
+
+ protected Map entityDeclarations;
+
+ protected XMLEventAllocatorImpl()
+ {
+ entityDeclarations = new HashMap();
+ }
+
+ public XMLEvent allocate(XMLStreamReader reader)
+ throws XMLStreamException
+ {
+ String text;
+ boolean whitespace;
+ boolean ignorableWhitespace;
+ int len;
+ List namespaces;
+ int eventType = reader.getEventType();
+ Location location = reader.getLocation();
+ switch (eventType)
+ {
+ case XMLStreamConstants.CDATA:
+ text = reader.getText();
+ whitespace = isWhitespace(text);
+ // TODO ignorableWhitespace
+ ignorableWhitespace = whitespace && false;
+ return new CharactersImpl(location, text,
+ whitespace, true, ignorableWhitespace);
+ case XMLStreamConstants.CHARACTERS:
+ text = reader.getText();
+ whitespace = false;
+ // TODO ignorableWhitespace
+ ignorableWhitespace = whitespace && false;
+ return new CharactersImpl(location, text,
+ whitespace, false, ignorableWhitespace);
+ case XMLStreamConstants.COMMENT:
+ text = reader.getText();
+ return new CommentImpl(location, text);
+ case XMLStreamConstants.DTD:
+ text = reader.getText();
+ List notations = new LinkedList();
+ List entities = new LinkedList();
+ // TODO readDTDBody(notations, entities);
+ return new DTDImpl(location, text, null, notations, entities);
+ case XMLStreamConstants.END_DOCUMENT:
+ return new EndDocumentImpl(location);
+ case XMLStreamConstants.END_ELEMENT:
+ len = reader.getNamespaceCount();
+ namespaces = new LinkedList();
+ for (int i = 0; i < len; i++)
+ namespaces.add(new NamespaceImpl(location,
+ reader.getNamespacePrefix(i),
+ reader.getNamespaceURI(i),
+ false));
+ return new EndElementImpl(location,
+ reader.getName(),
+ namespaces);
+ case XMLStreamConstants.ENTITY_REFERENCE:
+ String name = reader.getLocalName();
+ EntityDeclaration decl =
+ (EntityDeclaration) entityDeclarations.get(name);
+ return new EntityReferenceImpl(location, decl, name);
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ return new ProcessingInstructionImpl(location,
+ reader.getPITarget(),
+ reader.getPIData());
+ case XMLStreamConstants.SPACE:
+ text = reader.getText();
+ whitespace = true;
+ // TODO ignorableWhitespace
+ ignorableWhitespace = whitespace && false;
+ return new CharactersImpl(location, text,
+ whitespace, false, ignorableWhitespace);
+ case XMLStreamConstants.START_DOCUMENT:
+ String systemId = location.getSystemId();
+ String encoding = reader.getCharacterEncodingScheme();
+ boolean encodingDeclared = encoding != null;
+ if (encoding == null)
+ {
+ encoding = reader.getEncoding();
+ if (encoding == null)
+ encoding = "UTF-8";
+ }
+ String xmlVersion = reader.getVersion();
+ if (xmlVersion == null)
+ xmlVersion = "1.0";
+ boolean xmlStandalone = reader.isStandalone();
+ boolean standaloneDeclared = reader.standaloneSet();
+ return new StartDocumentImpl(location,
+ systemId,
+ encoding,
+ xmlVersion,
+ xmlStandalone,
+ standaloneDeclared,
+ encodingDeclared);
+ case XMLStreamConstants.START_ELEMENT:
+ len = reader.getNamespaceCount();
+ namespaces = new LinkedList();
+ for (int i = 0; i < len; i++)
+ namespaces.add(new NamespaceImpl(location,
+ reader.getNamespacePrefix(i),
+ reader.getNamespaceURI(i),
+ false));
+ len = reader.getAttributeCount();
+ List attributes = new LinkedList();
+ for (int i = 0; i < len; i++)
+ attributes.add(new AttributeImpl(location,
+ reader.getAttributeName(i),
+ reader.getAttributeValue(i),
+ reader.getAttributeType(i),
+ reader.isAttributeSpecified(i)));
+ return new StartElementImpl(location,
+ reader.getName(),
+ attributes, namespaces,
+ reader.getNamespaceContext());
+ default:
+ throw new XMLStreamException("Unknown event type: " + eventType);
+ }
+ }
+
+ public void allocate(XMLStreamReader reader, XMLEventConsumer consumer)
+ throws XMLStreamException
+ {
+ consumer.add(allocate(reader));
+ }
+
+ public XMLEventAllocator newInstance()
+ {
+ return new XMLEventAllocatorImpl();
+ }
+
+ protected boolean isWhitespace(String text)
+ {
+ int len = text.length();
+ for (int i = 0; i < len; i++)
+ {
+ char c = text.charAt(i);
+ if (c != 0x20 && c != 0x09 && c != 0x0a && c != 0x0d)
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/XMLEventFactoryImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventFactoryImpl.java
new file mode 100644
index 000000000..12f7f2c79
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/XMLEventFactoryImpl.java
@@ -0,0 +1,269 @@
+/* XMLEventFactoryImpl.java --
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLEventFactory;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.Characters;
+import javax.xml.stream.events.Comment;
+import javax.xml.stream.events.DTD;
+import javax.xml.stream.events.EndDocument;
+import javax.xml.stream.events.EndElement;
+import javax.xml.stream.events.EntityDeclaration;
+import javax.xml.stream.events.EntityReference;
+import javax.xml.stream.events.Namespace;
+import javax.xml.stream.events.ProcessingInstruction;
+import javax.xml.stream.events.StartDocument;
+import javax.xml.stream.events.StartElement;
+
+/**
+ * Factory for XML events.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class XMLEventFactoryImpl
+ extends XMLEventFactory
+{
+
+ protected Location location;
+
+ public void setLocation(Location location)
+ {
+ this.location = location;
+ }
+
+ public Attribute createAttribute(String prefix, String namespaceURI,
+ String localName, String value)
+ {
+ return new AttributeImpl(location,
+ new QName(namespaceURI, localName, prefix),
+ value, "CDATA", true);
+ }
+
+ public Attribute createAttribute(String localName, String value)
+ {
+ return new AttributeImpl(location,
+ new QName(localName),
+ value, "CDATA", true);
+ }
+
+ public Attribute createAttribute(QName name, String value)
+ {
+ return new AttributeImpl(location, name, value,
+ "CDATA", true);
+ }
+
+ public Namespace createNamespace(String namespaceURI)
+ {
+ return new NamespaceImpl(location,
+ XMLConstants.DEFAULT_NS_PREFIX,
+ namespaceURI,
+ true);
+ }
+
+ public Namespace createNamespace(String prefix, String namespaceUri)
+ {
+ return new NamespaceImpl(location, prefix, namespaceUri, true);
+ }
+
+ public StartElement createStartElement(QName name,
+ Iterator attributes,
+ Iterator namespaces)
+ {
+ return new StartElementImpl(location, name,
+ createLinkedList(attributes),
+ createLinkedList(namespaces),
+ null);
+ }
+
+ public StartElement createStartElement(String prefix,
+ String namespaceUri,
+ String localName)
+ {
+ return new StartElementImpl(location,
+ new QName(namespaceUri, localName, prefix),
+ Collections.EMPTY_LIST,
+ Collections.EMPTY_LIST,
+ null);
+ }
+
+ public StartElement createStartElement(String prefix,
+ String namespaceUri,
+ String localName,
+ Iterator attributes,
+ Iterator namespaces)
+ {
+ return new StartElementImpl(location,
+ new QName(namespaceUri, localName, prefix),
+ createLinkedList(attributes),
+ createLinkedList(namespaces),
+ null);
+ }
+
+ public StartElement createStartElement(String prefix,
+ String namespaceUri,
+ String localName,
+ Iterator attributes,
+ Iterator namespaces,
+ NamespaceContext context)
+ {
+ return new StartElementImpl(location,
+ new QName(namespaceUri, localName, prefix),
+ createLinkedList(attributes),
+ createLinkedList(namespaces),
+ context);
+ }
+
+ public EndElement createEndElement(QName name,
+ Iterator namespaces)
+ {
+ return new EndElementImpl(location, name,
+ createLinkedList(namespaces));
+ }
+
+ public EndElement createEndElement(String prefix,
+ String namespaceUri,
+ String localName)
+ {
+ return new EndElementImpl(location,
+ new QName(namespaceUri, localName, prefix),
+ Collections.EMPTY_LIST);
+ }
+
+ public EndElement createEndElement(String prefix,
+ String namespaceUri,
+ String localName,
+ Iterator namespaces)
+ {
+ return new EndElementImpl(location,
+ new QName(namespaceUri, localName, prefix),
+ createLinkedList(namespaces));
+ }
+
+ public Characters createCharacters(String content)
+ {
+ return new CharactersImpl(location, content, false, false, false);
+ }
+
+ public Characters createCData(String content)
+ {
+ return new CharactersImpl(location, content, false, true, false);
+ }
+
+ public Characters createSpace(String content)
+ {
+ return new CharactersImpl(location, content, true, false, false);
+ }
+
+ public Characters createIgnorableSpace(String content)
+ {
+ return new CharactersImpl(location, content, true, false, true);
+ }
+
+ public StartDocument createStartDocument()
+ {
+ return new StartDocumentImpl(location, null, "UTF-8", "1.0",
+ false, false, false);
+ }
+
+ public StartDocument createStartDocument(String encoding,
+ String version,
+ boolean standalone)
+ {
+ return new StartDocumentImpl(location, null, encoding, version,
+ standalone, true, true);
+ }
+
+ public StartDocument createStartDocument(String encoding,
+ String version)
+ {
+ return new StartDocumentImpl(location, null, encoding, version,
+ false, false, true);
+ }
+
+ public StartDocument createStartDocument(String encoding)
+ {
+ return new StartDocumentImpl(location, null, encoding, "1.0",
+ false, false, true);
+ }
+
+ public EndDocument createEndDocument()
+ {
+ return new EndDocumentImpl(location);
+ }
+
+ public EntityReference createEntityReference(String name,
+ EntityDeclaration declaration)
+ {
+ return new EntityReferenceImpl(location, declaration, name);
+ }
+
+ public Comment createComment(String text)
+ {
+ return new CommentImpl(location, text);
+ }
+
+ public ProcessingInstruction createProcessingInstruction(String target,
+ String data)
+ {
+ return new ProcessingInstructionImpl(location, target, data);
+ }
+
+ public DTD createDTD(String dtd)
+ {
+ return new DTDImpl(location, dtd, null,
+ Collections.EMPTY_LIST,
+ Collections.EMPTY_LIST);
+ }
+
+ LinkedList createLinkedList(Iterator i)
+ {
+ LinkedList ret = new LinkedList();
+ while (i.hasNext())
+ ret.add(i.next());
+ return ret;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/XMLEventImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventImpl.java
new file mode 100644
index 000000000..2e650bf74
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/XMLEventImpl.java
@@ -0,0 +1,198 @@
+/* XMLEventImpl.java --
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.io.Writer;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Characters;
+import javax.xml.stream.events.EndElement;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+
+/**
+ * An XML stream event.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public abstract class XMLEventImpl
+ implements XMLEvent
+{
+
+ protected final Location location;
+
+ protected XMLEventImpl(Location location)
+ {
+ this.location = location;
+ }
+
+ public abstract int getEventType();
+
+ public Location getLocation()
+ {
+ return location;
+ }
+
+ public boolean isStartElement()
+ {
+ return getEventType() == START_ELEMENT;
+ }
+
+ public boolean isAttribute()
+ {
+ return getEventType() == ATTRIBUTE;
+ }
+
+ public boolean isNamespace()
+ {
+ return getEventType() == NAMESPACE;
+ }
+
+ public boolean isEndElement()
+ {
+ return getEventType() == END_ELEMENT;
+ }
+
+ public boolean isEntityReference()
+ {
+ return getEventType() == ENTITY_REFERENCE;
+ }
+
+ public boolean isProcessingInstruction()
+ {
+ return getEventType() == PROCESSING_INSTRUCTION;
+ }
+
+ public boolean isCharacters()
+ {
+ int et = getEventType();
+ return et == CHARACTERS || et == CDATA;
+ }
+
+ public boolean isStartDocument()
+ {
+ return getEventType() == START_DOCUMENT;
+ }
+
+ public boolean isEndDocument()
+ {
+ return getEventType() == END_DOCUMENT;
+ }
+
+ public StartElement asStartElement()
+ {
+ return (StartElement) this;
+ }
+
+ public EndElement asEndElement()
+ {
+ return (EndElement) this;
+ }
+
+ public Characters asCharacters()
+ {
+ return (Characters) this;
+ }
+
+ public QName getSchemaType()
+ {
+ return null;
+ }
+
+ public abstract void writeAsEncodedUnicode(Writer writer)
+ throws XMLStreamException;
+
+ protected String encode(String text, boolean inAttr)
+ {
+ int len = text.length();
+ CPStringBuilder buf = null;
+ for (int i = 0; i < len; i++)
+ {
+ char c = text.charAt(i);
+ if (c == '<')
+ {
+ if (buf == null)
+ {
+ buf = new CPStringBuilder(text.substring(0, i));
+ }
+ buf.append("&lt;");
+ }
+ else if (c == '>')
+ {
+ if (buf == null)
+ {
+ buf = new CPStringBuilder(text.substring(0, i));
+ }
+ buf.append("&gt;");
+ }
+ else if (c == '&')
+ {
+ if (buf == null)
+ {
+ buf = new CPStringBuilder(text.substring(0, i));
+ }
+ buf.append("&amp;");
+ }
+ else if (c == '\'' && inAttr)
+ {
+ if (buf == null)
+ {
+ buf = new CPStringBuilder(text.substring(0, i));
+ }
+ buf.append("&apos;");
+ }
+ else if (c == '"' && inAttr)
+ {
+ if (buf == null)
+ {
+ buf = new CPStringBuilder(text.substring(0, i));
+ }
+ buf.append("&quot;");
+ }
+ else if (buf != null)
+ {
+ buf.append(c);
+ }
+ }
+ return (buf == null) ? text : buf.toString();
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/XMLEventReaderImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventReaderImpl.java
new file mode 100644
index 000000000..bab6d9378
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/XMLEventReaderImpl.java
@@ -0,0 +1,157 @@
+/* XMLEventReaderImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.events.XMLEvent;
+import javax.xml.stream.util.XMLEventAllocator;
+
+/**
+ * Parser using XML events.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class XMLEventReaderImpl
+ implements XMLEventReader
+{
+
+ protected final XMLStreamReader reader;
+ protected final XMLEventAllocator allocator;
+ protected final String systemId;
+ protected XMLEvent peekEvent;
+
+ protected XMLEventReaderImpl(XMLStreamReader reader,
+ XMLEventAllocator allocator,
+ String systemId)
+ {
+ this.reader = reader;
+ this.allocator = allocator;
+ this.systemId = systemId;
+ }
+
+ public XMLEvent nextEvent()
+ throws XMLStreamException
+ {
+ XMLEvent ret = peek();
+ peekEvent = null;
+ return ret;
+ }
+
+ public Object next()
+ {
+ try
+ {
+ return nextEvent();
+ }
+ catch (XMLStreamException e)
+ {
+ RuntimeException e2 = new RuntimeException();
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public boolean hasNext()
+ {
+ if (peekEvent != null)
+ return true;
+ try
+ {
+ return reader.hasNext();
+ }
+ catch (XMLStreamException e)
+ {
+ return false;
+ }
+ }
+
+ public XMLEvent peek()
+ throws XMLStreamException
+ {
+ if (peekEvent != null)
+ return peekEvent;
+ if (!reader.hasNext())
+ return null;
+ reader.next();
+ peekEvent = allocator.allocate(reader);
+ return peekEvent;
+ }
+
+ public String getElementText()
+ throws XMLStreamException
+ {
+ return reader.getElementText();
+ }
+
+ public XMLEvent nextTag()
+ throws XMLStreamException
+ {
+ if (peekEvent != null)
+ {
+ int eventType = peekEvent.getEventType();
+ if (eventType == XMLStreamConstants.START_ELEMENT ||
+ eventType == XMLStreamConstants.END_ELEMENT)
+ return peekEvent;
+ else
+ peekEvent = null;
+ }
+ reader.nextTag();
+ return allocator.allocate(reader);
+ }
+
+ public Object getProperty(String name)
+ throws IllegalArgumentException
+ {
+ return reader.getProperty(name);
+ }
+
+ public void close()
+ throws XMLStreamException
+ {
+ reader.close();
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/XMLEventWriterImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventWriterImpl.java
new file mode 100644
index 000000000..33b1dce31
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/XMLEventWriterImpl.java
@@ -0,0 +1,190 @@
+/* XMLEventWriterImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.Characters;
+import javax.xml.stream.events.Comment;
+import javax.xml.stream.events.DTD;
+import javax.xml.stream.events.Namespace;
+import javax.xml.stream.events.ProcessingInstruction;
+import javax.xml.stream.events.StartDocument;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+
+/**
+ * Writer to write events to an underlying XML stream writer.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class XMLEventWriterImpl
+ implements XMLEventWriter
+{
+
+ protected final XMLStreamWriter writer;
+
+ protected XMLEventWriterImpl(XMLStreamWriter writer)
+ {
+ this.writer = writer;
+ }
+
+ public void flush()
+ throws XMLStreamException
+ {
+ writer.flush();
+ }
+
+ public void close()
+ throws XMLStreamException
+ {
+ writer.close();
+ }
+
+ public void add(XMLEvent event)
+ throws XMLStreamException
+ {
+ QName name;
+ String uri;
+ switch (event.getEventType())
+ {
+ case XMLStreamConstants.START_ELEMENT:
+ StartElement startElement = event.asStartElement();
+ name = startElement.getName();
+ uri = name.getNamespaceURI();
+ if (uri != null && !"".equals(uri))
+ writer.writeStartElement(name.getPrefix(), name.getLocalPart(), uri);
+ else
+ writer.writeStartElement(name.getLocalPart());
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ writer.writeEndElement();
+ break;
+ case XMLStreamConstants.ATTRIBUTE:
+ Attribute attribute = (Attribute) event;
+ name = attribute.getName();
+ uri = name.getNamespaceURI();
+ if (uri != null && !"".equals(uri))
+ writer.writeAttribute(name.getPrefix(), uri, name.getLocalPart(),
+ attribute.getValue());
+ else
+ writer.writeAttribute(name.getLocalPart(), attribute.getValue());
+ break;
+ case XMLStreamConstants.NAMESPACE:
+ Namespace namespace = (Namespace) event;
+ uri = namespace.getNamespaceURI();
+ writer.writeNamespace(namespace.getPrefix(), uri);
+ break;
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ ProcessingInstruction pi = (ProcessingInstruction) event;
+ String data = pi.getData();
+ if (data == null)
+ writer.writeProcessingInstruction(pi.getTarget());
+ else
+ writer.writeProcessingInstruction(pi.getTarget(), data);
+ break;
+ case XMLStreamConstants.COMMENT:
+ Comment comment = (Comment) event;
+ writer.writeComment(comment.getText());
+ break;
+ case XMLStreamConstants.START_DOCUMENT:
+ StartDocument startDocument = (StartDocument) event;
+ writer.writeStartDocument(startDocument.getVersion());
+ break;
+ case XMLStreamConstants.END_DOCUMENT:
+ writer.writeEndDocument();
+ break;
+ case XMLStreamConstants.DTD:
+ DTD dtd = (DTD) event;
+ writer.writeDTD(dtd.getDocumentTypeDeclaration());
+ break;
+ case XMLStreamConstants.CHARACTERS:
+ case XMLStreamConstants.SPACE:
+ Characters characters = event.asCharacters();
+ writer.writeCharacters(characters.getData());
+ break;
+ case XMLStreamConstants.CDATA:
+ Characters cdata = event.asCharacters();
+ writer.writeCData(cdata.getData());
+ break;
+ }
+ }
+
+ public void add(XMLEventReader reader)
+ throws XMLStreamException
+ {
+ while (reader.hasNext())
+ add(reader.nextEvent());
+ }
+
+ public String getPrefix(String uri)
+ throws XMLStreamException
+ {
+ return writer.getPrefix(uri);
+ }
+
+ public void setPrefix(String prefix, String uri)
+ throws XMLStreamException
+ {
+ writer.setPrefix(prefix, uri);
+ }
+
+ public void setDefaultNamespace(String uri)
+ throws XMLStreamException
+ {
+ writer.setDefaultNamespace(uri);
+ }
+
+ public void setNamespaceContext(NamespaceContext context)
+ throws XMLStreamException
+ {
+ writer.setNamespaceContext(context);
+ }
+
+ public NamespaceContext getNamespaceContext()
+ {
+ return writer.getNamespaceContext();
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java b/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java
new file mode 100644
index 000000000..87aa32107
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java
@@ -0,0 +1,397 @@
+/* XMLInputFactoryImpl.java --
+ Copyright (C) 2005,2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.stream.EventFilter;
+import javax.xml.stream.StreamFilter;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLReporter;
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.util.XMLEventAllocator;
+
+/**
+ * Factory for creating parsers from various kinds of XML source.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class XMLInputFactoryImpl
+ extends XMLInputFactory
+{
+
+ protected XMLResolver resolver;
+ protected XMLReporter reporter;
+ protected XMLEventAllocator allocator;
+
+ protected boolean validating;
+ protected boolean namespaceAware = true;
+ protected boolean coalescing;
+ protected boolean replacingEntityReferences = true;
+ protected boolean externalEntities = true;
+ protected boolean supportDTD = true;
+ protected boolean xIncludeAware = false;
+ protected boolean baseAware = true;
+ protected boolean stringInterning = true;
+
+ public XMLInputFactoryImpl()
+ {
+ allocator = new XMLEventAllocatorImpl();
+ }
+
+ public XMLStreamReader createXMLStreamReader(Reader reader)
+ throws XMLStreamException
+ {
+ return createXMLStreamReader(null, reader);
+ }
+
+ public XMLStreamReader createXMLStreamReader(Source source)
+ throws XMLStreamException
+ {
+ String systemId = source.getSystemId();
+ InputStream in = getInputStream(source);
+ XMLParser ret = new XMLParser(in, systemId,
+ validating,
+ namespaceAware,
+ coalescing,
+ replacingEntityReferences,
+ externalEntities,
+ supportDTD,
+ baseAware,
+ stringInterning,
+ false,
+ reporter,
+ resolver);
+ if (xIncludeAware)
+ return new XIncludeFilter(ret, systemId, namespaceAware, validating,
+ replacingEntityReferences);
+ return ret;
+ }
+
+ public XMLStreamReader createXMLStreamReader(InputStream in)
+ throws XMLStreamException
+ {
+ return createXMLStreamReader(null, in);
+ }
+
+ public XMLStreamReader createXMLStreamReader(InputStream in, String encoding)
+ throws XMLStreamException
+ {
+ return createXMLStreamReader(in);
+ }
+
+ public XMLStreamReader createXMLStreamReader(String systemId, InputStream in)
+ throws XMLStreamException
+ {
+ XMLParser ret = new XMLParser(in, systemId,
+ validating,
+ namespaceAware,
+ coalescing,
+ replacingEntityReferences,
+ externalEntities,
+ supportDTD,
+ baseAware,
+ stringInterning,
+ false,
+ reporter,
+ resolver);
+ if (xIncludeAware)
+ return new XIncludeFilter(ret, null, namespaceAware, validating,
+ replacingEntityReferences);
+ return ret;
+ }
+
+ public XMLStreamReader createXMLStreamReader(String systemId, Reader reader)
+ throws XMLStreamException
+ {
+ XMLParser ret = new XMLParser(reader, systemId,
+ validating,
+ namespaceAware,
+ coalescing,
+ replacingEntityReferences,
+ externalEntities,
+ supportDTD,
+ baseAware,
+ stringInterning,
+ false,
+ reporter,
+ resolver);
+ if (xIncludeAware)
+ return new XIncludeFilter(ret, null, namespaceAware, validating,
+ replacingEntityReferences);
+ return ret;
+ }
+
+ public XMLEventReader createXMLEventReader(Reader reader)
+ throws XMLStreamException
+ {
+ XMLStreamReader sr = createXMLStreamReader(reader);
+ return new XMLEventReaderImpl(sr, allocator, null);
+ }
+
+ public XMLEventReader createXMLEventReader(String systemId, Reader reader)
+ throws XMLStreamException
+ {
+ XMLStreamReader sr = createXMLStreamReader(systemId, reader);
+ return new XMLEventReaderImpl(sr, allocator, null);
+ }
+
+ public XMLEventReader createXMLEventReader(XMLStreamReader reader)
+ throws XMLStreamException
+ {
+ return new XMLEventReaderImpl(reader, allocator, null);
+ }
+
+ public XMLEventReader createXMLEventReader(Source source)
+ throws XMLStreamException
+ {
+ XMLStreamReader sr = createXMLStreamReader(source);
+ return new XMLEventReaderImpl(sr, allocator, null);
+ }
+
+ public XMLEventReader createXMLEventReader(InputStream in)
+ throws XMLStreamException
+ {
+ XMLStreamReader sr = createXMLStreamReader(in);
+ return new XMLEventReaderImpl(sr, allocator, null);
+ }
+
+ public XMLEventReader createXMLEventReader(InputStream in, String encoding)
+ throws XMLStreamException
+ {
+ XMLStreamReader sr = createXMLStreamReader(in, encoding);
+ return new XMLEventReaderImpl(sr, allocator, null);
+ }
+
+ public XMLEventReader createXMLEventReader(String systemId, InputStream in)
+ throws XMLStreamException
+ {
+ XMLStreamReader sr = createXMLStreamReader(systemId, in);
+ return new XMLEventReaderImpl(sr, allocator, null);
+ }
+
+ public XMLStreamReader createFilteredReader(XMLStreamReader reader,
+ StreamFilter filter)
+ throws XMLStreamException
+ {
+ return new FilteredStreamReader(reader, filter);
+ }
+
+ public XMLEventReader createFilteredReader(XMLEventReader reader,
+ EventFilter filter)
+ throws XMLStreamException
+ {
+ return new FilteredEventReader(reader, filter);
+ }
+
+ public XMLResolver getXMLResolver()
+ {
+ return resolver;
+ }
+
+ public void setXMLResolver(XMLResolver resolver)
+ {
+ this.resolver = resolver;
+ }
+
+ public XMLReporter getXMLReporter()
+ {
+ return reporter;
+ }
+
+ public void setXMLReporter(XMLReporter reporter)
+ {
+ this.reporter = reporter;
+ }
+
+ public void setProperty(String name, Object value)
+ throws IllegalArgumentException
+ {
+ if (name.equals(IS_NAMESPACE_AWARE))
+ namespaceAware = ((Boolean) value).booleanValue();
+ else if (name.equals(IS_VALIDATING))
+ validating = ((Boolean) value).booleanValue();
+ else if (name.equals(IS_COALESCING))
+ coalescing = ((Boolean) value).booleanValue();
+ else if (name.equals(IS_REPLACING_ENTITY_REFERENCES))
+ replacingEntityReferences = ((Boolean) value).booleanValue();
+ else if (name.equals(IS_SUPPORTING_EXTERNAL_ENTITIES))
+ externalEntities = ((Boolean) value).booleanValue();
+ else if (name.equals(SUPPORT_DTD))
+ supportDTD = ((Boolean) value).booleanValue();
+ else if (name.equals(REPORTER))
+ reporter = (XMLReporter) value;
+ else if (name.equals(RESOLVER))
+ resolver = (XMLResolver) value;
+ else if (name.equals(ALLOCATOR))
+ allocator = (XMLEventAllocator) value;
+ else if (name.equals("gnu.xml.stream.stringInterning"))
+ stringInterning = ((Boolean) value).booleanValue();
+ else if (name.equals("gnu.xml.stream.baseAware"))
+ baseAware = ((Boolean) value).booleanValue();
+ else if (name.equals("gnu.xml.stream.xIncludeAware"))
+ xIncludeAware = ((Boolean) value).booleanValue();
+ else
+ throw new IllegalArgumentException(name);
+ }
+
+ public Object getProperty(String name)
+ throws IllegalArgumentException
+ {
+ if (name.equals(IS_NAMESPACE_AWARE))
+ return namespaceAware ? Boolean.TRUE : Boolean.FALSE;
+ if (name.equals(IS_VALIDATING))
+ return validating ? Boolean.TRUE : Boolean.FALSE;
+ if (name.equals(IS_COALESCING))
+ return coalescing ? Boolean.TRUE : Boolean.FALSE;
+ if (name.equals(IS_REPLACING_ENTITY_REFERENCES))
+ return replacingEntityReferences ? Boolean.TRUE : Boolean.FALSE;
+ if (name.equals(IS_SUPPORTING_EXTERNAL_ENTITIES))
+ return externalEntities ? Boolean.TRUE : Boolean.FALSE;
+ if (name.equals(SUPPORT_DTD))
+ return supportDTD ? Boolean.TRUE : Boolean.FALSE;
+ if (name.equals(REPORTER))
+ return reporter;
+ if (name.equals(RESOLVER))
+ return resolver;
+ if (name.equals(ALLOCATOR))
+ return allocator;
+ if (name.equals("gnu.xml.stream.stringInterning"))
+ return stringInterning ? Boolean.TRUE : Boolean.FALSE;
+ if (name.equals("gnu.xml.stream.baseAware"))
+ return baseAware ? Boolean.TRUE : Boolean.FALSE;
+ if (name.equals("gnu.xml.stream.xIncludeAware"))
+ return xIncludeAware ? Boolean.TRUE : Boolean.FALSE;
+ throw new IllegalArgumentException(name);
+ }
+
+ public boolean isPropertySupported(String name)
+ {
+ return name.equals(IS_NAMESPACE_AWARE) ||
+ name.equals(IS_VALIDATING) ||
+ name.equals(IS_COALESCING) ||
+ name.equals(IS_REPLACING_ENTITY_REFERENCES) ||
+ name.equals(IS_SUPPORTING_EXTERNAL_ENTITIES) ||
+ name.equals(SUPPORT_DTD) ||
+ name.equals(REPORTER) ||
+ name.equals(RESOLVER) ||
+ name.equals(ALLOCATOR) ||
+ name.equals("gnu.xml.stream.stringInterning") ||
+ name.equals("gnu.xml.stream.baseAware") ||
+ name.equals("gnu.xml.stream.xIncludeAware");
+ }
+
+ public void setEventAllocator(XMLEventAllocator allocator)
+ {
+ this.allocator = allocator;
+ }
+
+ public XMLEventAllocator getEventAllocator()
+ {
+ return allocator;
+ }
+
+ public void setCoalescing(boolean coalescing)
+ {
+ this.coalescing = coalescing;
+ }
+
+ public boolean isCoalescing()
+ {
+ return coalescing;
+ }
+
+ protected InputStream getInputStream(Source source)
+ throws XMLStreamException
+ {
+ InputStream in = null;
+ if (source instanceof StreamSource)
+ {
+ StreamSource streamSource = (StreamSource) source;
+ in = streamSource.getInputStream();
+ }
+ if (in == null)
+ {
+ String systemId = source.getSystemId();
+ try
+ {
+ URL url = new URL(systemId);
+ try
+ {
+ in = url.openStream();
+ }
+ catch (IOException e2)
+ {
+ XMLStreamException e3 = new XMLStreamException(e2);
+ e3.initCause(e2);
+ throw e3;
+ }
+ }
+ catch (MalformedURLException e)
+ {
+ // Fall back to relative file
+ if (File.separatorChar != '/')
+ systemId = systemId.replace('/', File.separatorChar);
+ try
+ {
+ in = new FileInputStream(systemId);
+ }
+ catch (FileNotFoundException e2)
+ {
+ XMLStreamException e3 = new XMLStreamException(e2);
+ e3.initCause(e2);
+ throw e3;
+ }
+ }
+ }
+ return in;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/XMLOutputFactoryImpl.java b/libjava/classpath/gnu/xml/stream/XMLOutputFactoryImpl.java
new file mode 100644
index 000000000..d849e8ba5
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/XMLOutputFactoryImpl.java
@@ -0,0 +1,187 @@
+/* XMLOutputFactoryImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.io.UnsupportedEncodingException;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+/**
+ * Standard output factory.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class XMLOutputFactoryImpl
+ extends XMLOutputFactory
+{
+
+ protected boolean prefixDefaulting = false;
+
+ public XMLOutputFactoryImpl()
+ {
+ }
+
+ public XMLStreamWriter createXMLStreamWriter(Writer stream)
+ throws XMLStreamException
+ {
+ // XXX try to determine character encoding of writer?
+ return new XMLStreamWriterImpl(stream, null, prefixDefaulting);
+ }
+
+ public XMLStreamWriter createXMLStreamWriter(OutputStream stream)
+ throws XMLStreamException
+ {
+ return createXMLStreamWriter(stream, "UTF-8");
+ }
+
+ public XMLStreamWriter createXMLStreamWriter(OutputStream stream,
+ String encoding)
+ throws XMLStreamException
+ {
+ if (encoding == null)
+ encoding = "UTF-8";
+ try
+ {
+ Writer writer = new OutputStreamWriter(stream, encoding);
+ return new XMLStreamWriterImpl(writer, encoding, prefixDefaulting);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public XMLStreamWriter createXMLStreamWriter(Result result)
+ throws XMLStreamException
+ {
+ if (result instanceof StreamResult)
+ {
+ StreamResult sr = (StreamResult) result;
+ OutputStream out = sr.getOutputStream();
+ if (out != null)
+ return createXMLStreamWriter(out);
+ Writer writer = sr.getWriter();
+ if (writer != null)
+ return createXMLStreamWriter(writer);
+ }
+ throw new UnsupportedOperationException();
+ }
+
+ public XMLEventWriter createXMLEventWriter(OutputStream stream)
+ throws XMLStreamException
+ {
+ XMLStreamWriter writer = createXMLStreamWriter(stream);
+ return new XMLEventWriterImpl(writer);
+ }
+
+ public XMLEventWriter createXMLEventWriter(OutputStream stream,
+ String encoding)
+ throws XMLStreamException
+ {
+ XMLStreamWriter writer = createXMLStreamWriter(stream, encoding);
+ return new XMLEventWriterImpl(writer);
+ }
+
+ public XMLEventWriter createXMLEventWriter(Writer stream)
+ throws XMLStreamException
+ {
+ XMLStreamWriter writer = createXMLStreamWriter(stream);
+ return new XMLEventWriterImpl(writer);
+ }
+
+ public XMLEventWriter createXMLEventWriter(Result result)
+ throws XMLStreamException
+ {
+ if (result instanceof StreamResult)
+ {
+ StreamResult sr = (StreamResult) result;
+ OutputStream out = sr.getOutputStream();
+ if (out != null)
+ return createXMLEventWriter(out);
+ Writer writer = sr.getWriter();
+ if (writer != null)
+ return createXMLEventWriter(writer);
+ }
+ throw new UnsupportedOperationException();
+ }
+
+ public void setProperty(String name, Object value)
+ throws IllegalArgumentException
+ {
+ if (IS_REPAIRING_NAMESPACES.equals(name))
+ prefixDefaulting = ((Boolean) value).booleanValue();
+ else
+ throw new IllegalArgumentException(name);
+ }
+
+ public Object getProperty(String name)
+ throws IllegalArgumentException
+ {
+ if (IS_REPAIRING_NAMESPACES.equals(name))
+ return new Boolean(prefixDefaulting);
+ throw new IllegalArgumentException(name);
+ }
+
+ public boolean isPropertySupported(String name)
+ {
+ if (IS_REPAIRING_NAMESPACES.equals(name))
+ return true;
+ return false;
+ }
+
+ public boolean isPrefixDefaulting()
+ {
+ return prefixDefaulting;
+ }
+
+ public void setPrefixDefaulting(boolean value)
+ {
+ prefixDefaulting = value;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/XMLParser.java b/libjava/classpath/gnu/xml/stream/XMLParser.java
new file mode 100644
index 000000000..71e876569
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/XMLParser.java
@@ -0,0 +1,5434 @@
+/* XMLParser.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+
+Partly derived from code which carried the following notice:
+
+ Copyright (c) 1997, 1998 by Microstar Software Ltd.
+
+ AElfred is free for both commercial and non-commercial use and
+ redistribution, provided that Microstar's copyright and disclaimer are
+ retained intact. You are free to modify AElfred for your own use and
+ to redistribute AElfred with your modifications, provided that the
+ modifications are clearly documented.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ merchantability or fitness for a particular purpose. Please use it AT
+ YOUR OWN RISK.
+*/
+
+package gnu.xml.stream;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.io.BufferedInputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLReporter;
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import gnu.java.net.CRLFInputStream;
+import gnu.classpath.debug.TeeInputStream;
+import gnu.classpath.debug.TeeReader;
+
+/**
+ * An XML parser.
+ * This parser supports the following additional StAX properties:
+ * <table>
+ * <tr><td>gnu.xml.stream.stringInterning</td>
+ * <td>Boolean</td>
+ * <td>Indicates whether markup strings will be interned</td></tr>
+ * <tr><td>gnu.xml.stream.xmlBase</td>
+ * <td>Boolean</td>
+ * <td>Indicates whether XML Base processing will be performed</td></tr>
+ * <tr><td>gnu.xml.stream.baseURI</td>
+ * <td>String</td>
+ * <td>Returns the base URI of the current event</td></tr>
+ * </table>
+ *
+ * @see http://www.w3.org/TR/REC-xml/
+ * @see http://www.w3.org/TR/xml11/
+ * @see http://www.w3.org/TR/REC-xml-names
+ * @see http://www.w3.org/TR/xml-names11
+ * @see http://www.w3.org/TR/xmlbase/
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class XMLParser
+ implements XMLStreamReader, NamespaceContext
+{
+
+ // -- parser state machine states --
+ private static final int INIT = 0; // start state
+ private static final int PROLOG = 1; // in prolog
+ private static final int CONTENT = 2; // in content
+ private static final int EMPTY_ELEMENT = 3; // empty element state
+ private static final int MISC = 4; // in Misc (after root element)
+
+ // -- parameters for parsing literals --
+ private final static int LIT_ENTITY_REF = 2;
+ private final static int LIT_NORMALIZE = 4;
+ private final static int LIT_ATTRIBUTE = 8;
+ private final static int LIT_DISABLE_PE = 16;
+ private final static int LIT_DISABLE_CREF = 32;
+ private final static int LIT_DISABLE_EREF = 64;
+ private final static int LIT_PUBID = 256;
+
+ // -- types of attribute values --
+ final static int ATTRIBUTE_DEFAULT_UNDECLARED = 30;
+ final static int ATTRIBUTE_DEFAULT_SPECIFIED = 31;
+ final static int ATTRIBUTE_DEFAULT_IMPLIED = 32;
+ final static int ATTRIBUTE_DEFAULT_REQUIRED = 33;
+ final static int ATTRIBUTE_DEFAULT_FIXED = 34;
+
+ // -- additional event types --
+ final static int START_ENTITY = 50;
+ final static int END_ENTITY = 51;
+
+ /**
+ * The current input.
+ */
+ private Input input;
+
+ /**
+ * Stack of inputs representing XML general entities.
+ * The input representing the XML input stream or reader is always the
+ * first element in this stack.
+ */
+ private LinkedList inputStack = new LinkedList();
+
+ /**
+ * Stack of start-entity events to be reported.
+ */
+ private LinkedList startEntityStack = new LinkedList();
+
+ /**
+ * Stack of end-entity events to be reported.
+ */
+ private LinkedList endEntityStack = new LinkedList();
+
+ /**
+ * Current parser state within the main state machine.
+ */
+ private int state = INIT;
+
+ /**
+ * The (type of the) current event.
+ */
+ private int event;
+
+ /**
+ * The element name stack. The first element in this stack will be the
+ * root element.
+ */
+ private LinkedList stack = new LinkedList();
+
+ /**
+ * Stack of namespace contexts. These are maps specifying prefix-to-URI
+ * mappings. The first element in this stack is the most recent namespace
+ * context (i.e. the other way around from the element name stack).
+ */
+ private LinkedList namespaces = new LinkedList();
+
+ /**
+ * The base-URI stack. This holds the base URI context for each element.
+ * The first element in this stack is the most recent context (i.e. the
+ * other way around from the element name stack).
+ */
+ private LinkedList bases = new LinkedList();
+
+ /**
+ * The list of attributes for the current element, in the order defined in
+ * the XML stream.
+ */
+ private ArrayList attrs = new ArrayList();
+
+ /**
+ * Buffer for text and character data.
+ */
+ private StringBuffer buf = new StringBuffer();
+
+ /**
+ * Buffer for NMTOKEN strings (markup).
+ */
+ private StringBuffer nmtokenBuf = new StringBuffer();
+
+ /**
+ * Buffer for string literals. (e.g. attribute values)
+ */
+ private StringBuffer literalBuf = new StringBuffer();
+
+ /**
+ * Temporary Unicode character buffer used during character data reads.
+ */
+ private int[] tmpBuf = new int[1024];
+
+ /**
+ * The element content model for the current element.
+ */
+ private ContentModel currentContentModel;
+
+ /**
+ * The validation stack. This holds lists of the elements seen for each
+ * element, in order to determine whether the names and order of these
+ * elements match the content model for the element. The last entry in
+ * this stack represents the current element.
+ */
+ private LinkedList validationStack;
+
+ /**
+ * These sets contain the IDs and the IDREFs seen in the document, to
+ * ensure that IDs are unique and that each IDREF refers to an ID in the
+ * document.
+ */
+ private HashSet ids, idrefs;
+
+ /**
+ * The target and data associated with the current processing instruction
+ * event.
+ */
+ private String piTarget, piData;
+
+ /**
+ * The XML version declared in the XML declaration.
+ */
+ private String xmlVersion;
+
+ /**
+ * The encoding declared in the XML declaration.
+ */
+ private String xmlEncoding;
+
+ /**
+ * The standalone value declared in the XML declaration.
+ */
+ private Boolean xmlStandalone;
+
+ /**
+ * The document type definition.
+ */
+ Doctype doctype;
+
+ /**
+ * State variables for determining parameter-entity expansion.
+ */
+ private boolean expandPE, peIsError;
+
+ /**
+ * Whether this is a validating parser.
+ */
+ private final boolean validating;
+
+ /**
+ * Whether strings representing markup will be interned.
+ */
+ private final boolean stringInterning;
+
+ /**
+ * If true, CDATA sections will be merged with adjacent text nodes into a
+ * single event.
+ */
+ private final boolean coalescing;
+
+ /**
+ * Whether to replace general entity references with their replacement
+ * text automatically during parsing.
+ * Otherwise entity-reference events will be issued.
+ */
+ private final boolean replaceERefs;
+
+ /**
+ * Whether to support external entities.
+ */
+ private final boolean externalEntities;
+
+ /**
+ * Whether to support DTDs.
+ */
+ private final boolean supportDTD;
+
+ /**
+ * Whether to support XML namespaces. If true, namespace information will
+ * be available. Otherwise namespaces will simply be reported as ordinary
+ * attributes.
+ */
+ private final boolean namespaceAware;
+
+ /**
+ * Whether to support XML Base. If true, URIs specified in xml:base
+ * attributes will be honoured when resolving external entities.
+ */
+ private final boolean baseAware;
+
+ /**
+ * Whether to report extended event types (START_ENTITY and END_ENTITY)
+ * in addition to the standard event types. Used by the SAX parser.
+ */
+ private final boolean extendedEventTypes;
+
+ /**
+ * The reporter to receive parsing warnings.
+ */
+ final XMLReporter reporter;
+
+ /**
+ * Callback interface for resolving external entities.
+ */
+ final XMLResolver resolver;
+
+ // -- Constants for testing the next kind of markup event --
+ private static final String TEST_START_ELEMENT = "<";
+ private static final String TEST_END_ELEMENT = "</";
+ private static final String TEST_COMMENT = "<!--";
+ private static final String TEST_PI = "<?";
+ private static final String TEST_CDATA = "<![CDATA[";
+ private static final String TEST_XML_DECL = "<?xml";
+ private static final String TEST_DOCTYPE_DECL = "<!DOCTYPE";
+ private static final String TEST_ELEMENT_DECL = "<!ELEMENT";
+ private static final String TEST_ATTLIST_DECL = "<!ATTLIST";
+ private static final String TEST_ENTITY_DECL = "<!ENTITY";
+ private static final String TEST_NOTATION_DECL = "<!NOTATION";
+ private static final String TEST_KET = ">";
+ private static final String TEST_END_COMMENT = "--";
+ private static final String TEST_END_PI = "?>";
+ private static final String TEST_END_CDATA = "]]>";
+
+ /**
+ * The general entities predefined by the XML specification.
+ */
+ private static final LinkedHashMap PREDEFINED_ENTITIES = new LinkedHashMap();
+ static
+ {
+ PREDEFINED_ENTITIES.put("amp", "&");
+ PREDEFINED_ENTITIES.put("lt", "<");
+ PREDEFINED_ENTITIES.put("gt", ">");
+ PREDEFINED_ENTITIES.put("apos", "'");
+ PREDEFINED_ENTITIES.put("quot", "\"");
+ }
+
+ /**
+ * Creates a new XML parser for the given input stream.
+ * This constructor should be used where possible, as it allows the
+ * encoding of the XML data to be correctly determined from the stream.
+ * @param in the input stream
+ * @param systemId the URL from which the input stream was retrieved
+ * (necessary if there are external entities to be resolved)
+ * @param validating if the parser is to be a validating parser
+ * @param namespaceAware if the parser should support XML Namespaces
+ * @param coalescing if CDATA sections should be merged into adjacent text
+ * nodes
+ * @param replaceERefs if entity references should be automatically
+ * replaced by their replacement text (otherwise they will be reported as
+ * entity-reference events)
+ * @param externalEntities if external entities should be loaded
+ * @param supportDTD if support for the XML DTD should be enabled
+ * @param baseAware if the parser should support XML Base to resolve
+ * external entities
+ * @param stringInterning whether strings will be interned during parsing
+ * @param reporter the reporter to receive warnings during processing
+ * @param resolver the callback interface used to resolve external
+ * entities
+ */
+ public XMLParser(InputStream in, String systemId,
+ boolean validating,
+ boolean namespaceAware,
+ boolean coalescing,
+ boolean replaceERefs,
+ boolean externalEntities,
+ boolean supportDTD,
+ boolean baseAware,
+ boolean stringInterning,
+ boolean extendedEventTypes,
+ XMLReporter reporter,
+ XMLResolver resolver)
+ {
+ this.validating = validating;
+ this.namespaceAware = namespaceAware;
+ this.coalescing = coalescing;
+ this.replaceERefs = replaceERefs;
+ this.externalEntities = externalEntities;
+ this.supportDTD = supportDTD;
+ this.baseAware = baseAware;
+ this.stringInterning = stringInterning;
+ this.extendedEventTypes = extendedEventTypes;
+ this.reporter = reporter;
+ this.resolver = resolver;
+ if (validating)
+ {
+ validationStack = new LinkedList();
+ ids = new HashSet();
+ idrefs = new HashSet();
+ }
+ String debug = System.getProperty("gnu.xml.debug.input");
+ if (debug != null)
+ {
+ try
+ {
+ File file = File.createTempFile(debug, ".xml");
+ in = new TeeInputStream(in, new FileOutputStream(file));
+ }
+ catch (IOException e)
+ {
+ RuntimeException e2 = new RuntimeException();
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+ systemId = canonicalize(systemId);
+ pushInput(new Input(in, null, null, systemId, null, null, false, true));
+ }
+
+ /**
+ * Creates a new XML parser for the given character stream.
+ * This constructor is only available for compatibility with the JAXP
+ * APIs, which permit XML to be parsed from a character stream. Because
+ * the encoding specified by the character stream may conflict with that
+ * specified in the XML declaration, this method should be avoided where
+ * possible.
+ * @param in the input stream
+ * @param systemId the URL from which the input stream was retrieved
+ * (necessary if there are external entities to be resolved)
+ * @param validating if the parser is to be a validating parser
+ * @param namespaceAware if the parser should support XML Namespaces
+ * @param coalescing if CDATA sections should be merged into adjacent text
+ * nodes
+ * @param replaceERefs if entity references should be automatically
+ * replaced by their replacement text (otherwise they will be reported as
+ * entity-reference events)
+ * @param externalEntities if external entities should be loaded
+ * @param supportDTD if support for the XML DTD should be enabled
+ * @param baseAware if the parser should support XML Base to resolve
+ * external entities
+ * @param stringInterning whether strings will be interned during parsing
+ * @param reporter the reporter to receive warnings during processing
+ * @param resolver the callback interface used to resolve external
+ * entities
+ */
+ public XMLParser(Reader reader, String systemId,
+ boolean validating,
+ boolean namespaceAware,
+ boolean coalescing,
+ boolean replaceERefs,
+ boolean externalEntities,
+ boolean supportDTD,
+ boolean baseAware,
+ boolean stringInterning,
+ boolean extendedEventTypes,
+ XMLReporter reporter,
+ XMLResolver resolver)
+ {
+ this.validating = validating;
+ this.namespaceAware = namespaceAware;
+ this.coalescing = coalescing;
+ this.replaceERefs = replaceERefs;
+ this.externalEntities = externalEntities;
+ this.supportDTD = supportDTD;
+ this.baseAware = baseAware;
+ this.stringInterning = stringInterning;
+ this.extendedEventTypes = extendedEventTypes;
+ this.reporter = reporter;
+ this.resolver = resolver;
+ if (validating)
+ {
+ validationStack = new LinkedList();
+ ids = new HashSet();
+ idrefs = new HashSet();
+ }
+ String debug = System.getProperty("gnu.xml.debug.input");
+ if (debug != null)
+ {
+ try
+ {
+ File file = File.createTempFile(debug, ".xml");
+ reader = new TeeReader(reader, new FileWriter(file));
+ }
+ catch (IOException e)
+ {
+ RuntimeException e2 = new RuntimeException();
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+ systemId = canonicalize(systemId);
+ pushInput(new Input(null, reader, null, systemId, null, null, false, true));
+ }
+
+ // -- NamespaceContext --
+
+ public String getNamespaceURI(String prefix)
+ {
+ if (XMLConstants.XML_NS_PREFIX.equals(prefix))
+ return XMLConstants.XML_NS_URI;
+ if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix))
+ return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
+ for (Iterator i = namespaces.iterator(); i.hasNext(); )
+ {
+ LinkedHashMap ctx = (LinkedHashMap) i.next();
+ String namespaceURI = (String) ctx.get(prefix);
+ if (namespaceURI != null)
+ return namespaceURI;
+ }
+ return null;
+ }
+
+ public String getPrefix(String namespaceURI)
+ {
+ if (XMLConstants.XML_NS_URI.equals(namespaceURI))
+ return XMLConstants.XML_NS_PREFIX;
+ if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI))
+ return XMLConstants.XMLNS_ATTRIBUTE;
+ for (Iterator i = namespaces.iterator(); i.hasNext(); )
+ {
+ LinkedHashMap ctx = (LinkedHashMap) i.next();
+ if (ctx.containsValue(namespaceURI))
+ {
+ for (Iterator j = ctx.entrySet().iterator(); j.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ String uri = (String) entry.getValue();
+ if (uri.equals(namespaceURI))
+ return (String) entry.getKey();
+ }
+ }
+ }
+ return null;
+ }
+
+ public Iterator getPrefixes(String namespaceURI)
+ {
+ if (XMLConstants.XML_NS_URI.equals(namespaceURI))
+ return Collections.singleton(XMLConstants.XML_NS_PREFIX).iterator();
+ if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI))
+ return Collections.singleton(XMLConstants.XMLNS_ATTRIBUTE).iterator();
+ LinkedList acc = new LinkedList();
+ for (Iterator i = namespaces.iterator(); i.hasNext(); )
+ {
+ LinkedHashMap ctx = (LinkedHashMap) i.next();
+ if (ctx.containsValue(namespaceURI))
+ {
+ for (Iterator j = ctx.entrySet().iterator(); j.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ String uri = (String) entry.getValue();
+ if (uri.equals(namespaceURI))
+ acc.add(entry.getKey());
+ }
+ }
+ }
+ return acc.iterator();
+ }
+
+ // -- XMLStreamReader --
+
+ public void close()
+ throws XMLStreamException
+ {
+ stack = null;
+ namespaces = null;
+ bases = null;
+ buf = null;
+ attrs = null;
+ doctype = null;
+
+ inputStack = null;
+ validationStack = null;
+ ids = null;
+ idrefs = null;
+ }
+
+ public NamespaceContext getNamespaceContext()
+ {
+ return this;
+ }
+
+ public int getAttributeCount()
+ {
+ return attrs.size();
+ }
+
+ public String getAttributeLocalName(int index)
+ {
+ Attribute a = (Attribute) attrs.get(index);
+ return a.localName;
+ }
+
+ public String getAttributeNamespace(int index)
+ {
+ String prefix = getAttributePrefix(index);
+ return getNamespaceURI(prefix);
+ }
+
+ public String getAttributePrefix(int index)
+ {
+ Attribute a = (Attribute) attrs.get(index);
+ return a.prefix;
+ }
+
+ public QName getAttributeName(int index)
+ {
+ Attribute a = (Attribute) attrs.get(index);
+ String namespaceURI = getNamespaceURI(a.prefix);
+ return new QName(namespaceURI, a.localName, a.prefix);
+ }
+
+ public String getAttributeType(int index)
+ {
+ Attribute a = (Attribute) attrs.get(index);
+ return a.type;
+ }
+
+ private String getAttributeType(String elementName, String attName)
+ {
+ if (doctype != null)
+ {
+ AttributeDecl att = doctype.getAttributeDecl(elementName, attName);
+ if (att != null)
+ return att.type;
+ }
+ return "CDATA";
+ }
+
+ public String getAttributeValue(int index)
+ {
+ Attribute a = (Attribute) attrs.get(index);
+ return a.value;
+ }
+
+ public String getAttributeValue(String namespaceURI, String localName)
+ {
+ for (Iterator i = attrs.iterator(); i.hasNext(); )
+ {
+ Attribute a = (Attribute) i.next();
+ if (a.localName.equals(localName))
+ {
+ String uri = getNamespaceURI(a.prefix);
+ if ((uri == null && namespaceURI == null) ||
+ (uri != null && uri.equals(namespaceURI)))
+ return a.value;
+ }
+ }
+ return null;
+ }
+
+ boolean isAttributeDeclared(int index)
+ {
+ if (doctype == null)
+ return false;
+ Attribute a = (Attribute) attrs.get(index);
+ String qn = ("".equals(a.prefix)) ? a.localName :
+ a.prefix + ":" + a.localName;
+ String elementName = buf.toString();
+ return doctype.isAttributeDeclared(elementName, qn);
+ }
+
+ public String getCharacterEncodingScheme()
+ {
+ return xmlEncoding;
+ }
+
+ public String getElementText()
+ throws XMLStreamException
+ {
+ if (event != XMLStreamConstants.START_ELEMENT)
+ throw new XMLStreamException("current event must be START_ELEMENT");
+ CPStringBuilder elementText = new CPStringBuilder();
+ int depth = stack.size();
+ while (event != XMLStreamConstants.END_ELEMENT || stack.size() > depth)
+ {
+ switch (next())
+ {
+ case XMLStreamConstants.CHARACTERS:
+ case XMLStreamConstants.SPACE:
+ elementText.append(buf.toString());
+ }
+ }
+ return elementText.toString();
+ }
+
+ public String getEncoding()
+ {
+ return (input.inputEncoding == null) ? "UTF-8" : input.inputEncoding;
+ }
+
+ public int getEventType()
+ {
+ return event;
+ }
+
+ public String getLocalName()
+ {
+ switch (event)
+ {
+ case XMLStreamConstants.START_ELEMENT:
+ case XMLStreamConstants.END_ELEMENT:
+ String qName = buf.toString();
+ int ci = qName.indexOf(':');
+ String localName = (ci == -1) ? qName : qName.substring(ci + 1);
+ if (stringInterning)
+ localName = localName.intern();
+ return localName;
+ default:
+ return null;
+ }
+ }
+
+ public Location getLocation()
+ {
+ return input;
+ }
+
+ public QName getName()
+ {
+ switch (event)
+ {
+ case XMLStreamConstants.START_ELEMENT:
+ case XMLStreamConstants.END_ELEMENT:
+ String qName = buf.toString();
+ int ci = qName.indexOf(':');
+ String localName = (ci == -1) ? qName : qName.substring(ci + 1);
+ if (stringInterning)
+ localName = localName.intern();
+ String prefix = (ci == -1) ?
+ (namespaceAware ? XMLConstants.DEFAULT_NS_PREFIX : null) :
+ qName.substring(0, ci);
+ if (stringInterning && prefix != null)
+ prefix = prefix.intern();
+ String namespaceURI = getNamespaceURI(prefix);
+ return new QName(namespaceURI, localName, prefix);
+ default:
+ return null;
+ }
+ }
+
+ public int getNamespaceCount()
+ {
+ if (!namespaceAware || namespaces.isEmpty())
+ return 0;
+ switch (event)
+ {
+ case XMLStreamConstants.START_ELEMENT:
+ case XMLStreamConstants.END_ELEMENT:
+ LinkedHashMap ctx = (LinkedHashMap) namespaces.getFirst();
+ return ctx.size();
+ default:
+ return 0;
+ }
+ }
+
+ public String getNamespacePrefix(int index)
+ {
+ LinkedHashMap ctx = (LinkedHashMap) namespaces.getFirst();
+ int count = 0;
+ for (Iterator i = ctx.keySet().iterator(); i.hasNext(); )
+ {
+ String prefix = (String) i.next();
+ if (count++ == index)
+ return prefix;
+ }
+ return null;
+ }
+
+ public String getNamespaceURI()
+ {
+ switch (event)
+ {
+ case XMLStreamConstants.START_ELEMENT:
+ case XMLStreamConstants.END_ELEMENT:
+ String qName = buf.toString();
+ int ci = qName.indexOf(':');
+ if (ci == -1)
+ return null;
+ String prefix = qName.substring(0, ci);
+ return getNamespaceURI(prefix);
+ default:
+ return null;
+ }
+ }
+
+ public String getNamespaceURI(int index)
+ {
+ LinkedHashMap ctx = (LinkedHashMap) namespaces.getFirst();
+ int count = 0;
+ for (Iterator i = ctx.values().iterator(); i.hasNext(); )
+ {
+ String uri = (String) i.next();
+ if (count++ == index)
+ return uri;
+ }
+ return null;
+ }
+
+ public String getPIData()
+ {
+ return piData;
+ }
+
+ public String getPITarget()
+ {
+ return piTarget;
+ }
+
+ public String getPrefix()
+ {
+ switch (event)
+ {
+ case XMLStreamConstants.START_ELEMENT:
+ case XMLStreamConstants.END_ELEMENT:
+ String qName = buf.toString();
+ int ci = qName.indexOf(':');
+ String prefix = (ci == -1) ?
+ (namespaceAware ? XMLConstants.DEFAULT_NS_PREFIX : null) :
+ qName.substring(0, ci);
+ if (stringInterning && prefix != null)
+ prefix = prefix.intern();
+ return prefix;
+ default:
+ return null;
+ }
+ }
+
+ public Object getProperty(String name)
+ throws IllegalArgumentException
+ {
+ if (name == null)
+ throw new IllegalArgumentException("name is null");
+ if (XMLInputFactory.ALLOCATOR.equals(name))
+ return null;
+ if (XMLInputFactory.IS_COALESCING.equals(name))
+ return coalescing ? Boolean.TRUE : Boolean.FALSE;
+ if (XMLInputFactory.IS_NAMESPACE_AWARE.equals(name))
+ return namespaceAware ? Boolean.TRUE : Boolean.FALSE;
+ if (XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES.equals(name))
+ return replaceERefs ? Boolean.TRUE : Boolean.FALSE;
+ if (XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES.equals(name))
+ return externalEntities ? Boolean.TRUE : Boolean.FALSE;
+ if (XMLInputFactory.IS_VALIDATING.equals(name))
+ return Boolean.FALSE;
+ if (XMLInputFactory.REPORTER.equals(name))
+ return reporter;
+ if (XMLInputFactory.RESOLVER.equals(name))
+ return resolver;
+ if (XMLInputFactory.SUPPORT_DTD.equals(name))
+ return supportDTD ? Boolean.TRUE : Boolean.FALSE;
+ if ("gnu.xml.stream.stringInterning".equals(name))
+ return stringInterning ? Boolean.TRUE : Boolean.FALSE;
+ if ("gnu.xml.stream.xmlBase".equals(name))
+ return baseAware ? Boolean.TRUE : Boolean.FALSE;
+ if ("gnu.xml.stream.baseURI".equals(name))
+ return getXMLBase();
+ return null;
+ }
+
+ public String getText()
+ {
+ return buf.toString();
+ }
+
+ public char[] getTextCharacters()
+ {
+ return buf.toString().toCharArray();
+ }
+
+ public int getTextCharacters(int sourceStart, char[] target,
+ int targetStart, int length)
+ throws XMLStreamException
+ {
+ length = Math.min(sourceStart + buf.length(), length);
+ int sourceEnd = sourceStart + length;
+ buf.getChars(sourceStart, sourceEnd, target, targetStart);
+ return length;
+ }
+
+ public int getTextLength()
+ {
+ return buf.length();
+ }
+
+ public int getTextStart()
+ {
+ return 0;
+ }
+
+ public String getVersion()
+ {
+ return (xmlVersion == null) ? "1.0" : xmlVersion;
+ }
+
+ public boolean hasName()
+ {
+ switch (event)
+ {
+ case XMLStreamConstants.START_ELEMENT:
+ case XMLStreamConstants.END_ELEMENT:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public boolean hasText()
+ {
+ switch (event)
+ {
+ case XMLStreamConstants.CHARACTERS:
+ case XMLStreamConstants.SPACE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public boolean isAttributeSpecified(int index)
+ {
+ Attribute a = (Attribute) attrs.get(index);
+ return a.specified;
+ }
+
+ public boolean isCharacters()
+ {
+ return (event == XMLStreamConstants.CHARACTERS);
+ }
+
+ public boolean isEndElement()
+ {
+ return (event == XMLStreamConstants.END_ELEMENT);
+ }
+
+ public boolean isStandalone()
+ {
+ return Boolean.TRUE.equals(xmlStandalone);
+ }
+
+ public boolean isStartElement()
+ {
+ return (event == XMLStreamConstants.START_ELEMENT);
+ }
+
+ public boolean isWhiteSpace()
+ {
+ return (event == XMLStreamConstants.SPACE);
+ }
+
+ public int nextTag()
+ throws XMLStreamException
+ {
+ do
+ {
+ switch (next())
+ {
+ case XMLStreamConstants.START_ELEMENT:
+ case XMLStreamConstants.END_ELEMENT:
+ case XMLStreamConstants.CHARACTERS:
+ case XMLStreamConstants.SPACE:
+ case XMLStreamConstants.COMMENT:
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ break;
+ default:
+ throw new XMLStreamException("Unexpected event type: " + event);
+ }
+ }
+ while (event != XMLStreamConstants.START_ELEMENT &&
+ event != XMLStreamConstants.END_ELEMENT);
+ return event;
+ }
+
+ public void require(int type, String namespaceURI, String localName)
+ throws XMLStreamException
+ {
+ if (event != type)
+ throw new XMLStreamException("Current event type is " + event);
+ if (event == XMLStreamConstants.START_ELEMENT ||
+ event == XMLStreamConstants.END_ELEMENT)
+ {
+ String ln = getLocalName();
+ if (!ln.equals(localName))
+ throw new XMLStreamException("Current local-name is " + ln);
+ String uri = getNamespaceURI();
+ if ((uri == null && namespaceURI != null) ||
+ (uri != null && !uri.equals(namespaceURI)))
+ throw new XMLStreamException("Current namespace URI is " + uri);
+ }
+ }
+
+ public boolean standaloneSet()
+ {
+ return (xmlStandalone != null);
+ }
+
+ public boolean hasNext()
+ throws XMLStreamException
+ {
+ return (event != XMLStreamConstants.END_DOCUMENT && event != -1);
+ }
+
+ public int next()
+ throws XMLStreamException
+ {
+ if (event == XMLStreamConstants.END_ELEMENT)
+ {
+ // Pop namespace context
+ if (namespaceAware && !namespaces.isEmpty())
+ namespaces.removeFirst();
+ // Pop base context
+ if (baseAware && !bases.isEmpty())
+ bases.removeFirst();
+ }
+ if (!startEntityStack.isEmpty())
+ {
+ String entityName = (String) startEntityStack.removeFirst();
+ buf.setLength(0);
+ buf.append(entityName);
+ event = START_ENTITY;
+ return extendedEventTypes ? event : next();
+ }
+ else if (!endEntityStack.isEmpty())
+ {
+ String entityName = (String) endEntityStack.removeFirst();
+ buf.setLength(0);
+ buf.append(entityName);
+ event = END_ENTITY;
+ return extendedEventTypes ? event : next();
+ }
+ try
+ {
+ if (!input.initialized)
+ input.init();
+ switch (state)
+ {
+ case CONTENT:
+ if (tryRead(TEST_END_ELEMENT))
+ {
+ readEndElement();
+ if (stack.isEmpty())
+ state = MISC;
+ event = XMLStreamConstants.END_ELEMENT;
+ }
+ else if (tryRead(TEST_COMMENT))
+ {
+ readComment(false);
+ event = XMLStreamConstants.COMMENT;
+ }
+ else if (tryRead(TEST_PI))
+ {
+ readPI(false);
+ event = XMLStreamConstants.PROCESSING_INSTRUCTION;
+ }
+ else if (tryRead(TEST_CDATA))
+ {
+ readCDSect();
+ event = XMLStreamConstants.CDATA;
+ }
+ else if (tryRead(TEST_START_ELEMENT))
+ {
+ state = readStartElement();
+ event = XMLStreamConstants.START_ELEMENT;
+ }
+ else
+ {
+ // Check for character reference or predefined entity
+ mark(8);
+ int c = readCh();
+ if (c == 0x26) // '&'
+ {
+ c = readCh();
+ if (c == 0x23) // '#'
+ {
+ reset();
+ event = readCharData(null);
+ }
+ else
+ {
+ // entity reference
+ reset();
+ readCh(); // &
+ readReference();
+ String ref = buf.toString();
+ String text = (String) PREDEFINED_ENTITIES.get(ref);
+ if (text != null)
+ {
+ event = readCharData(text);
+ }
+ else if (replaceERefs && !isUnparsedEntity(ref))
+ {
+ // this will report a start-entity event
+ boolean external = false;
+ if (doctype != null)
+ {
+ Object entity = doctype.getEntity(ref);
+ if (entity instanceof ExternalIds)
+ external = true;
+ }
+ expandEntity(ref, false, external);
+ event = next();
+ }
+ else
+ {
+ event = XMLStreamConstants.ENTITY_REFERENCE;
+ }
+ }
+ }
+ else
+ {
+ reset();
+ event = readCharData(null);
+ if (validating && doctype != null)
+ validatePCData(buf.toString());
+ }
+ }
+ break;
+ case EMPTY_ELEMENT:
+ String elementName = (String) stack.removeLast();
+ buf.setLength(0);
+ buf.append(elementName);
+ state = stack.isEmpty() ? MISC : CONTENT;
+ event = XMLStreamConstants.END_ELEMENT;
+ if (validating && doctype != null)
+ endElementValidationHook();
+ break;
+ case INIT: // XMLDecl?
+ if (tryRead(TEST_XML_DECL))
+ readXMLDecl();
+ input.finalizeEncoding();
+ event = XMLStreamConstants.START_DOCUMENT;
+ state = PROLOG;
+ break;
+ case PROLOG: // Misc* (doctypedecl Misc*)?
+ skipWhitespace();
+ if (doctype == null && tryRead(TEST_DOCTYPE_DECL))
+ {
+ readDoctypeDecl();
+ event = XMLStreamConstants.DTD;
+ }
+ else if (tryRead(TEST_COMMENT))
+ {
+ readComment(false);
+ event = XMLStreamConstants.COMMENT;
+ }
+ else if (tryRead(TEST_PI))
+ {
+ readPI(false);
+ event = XMLStreamConstants.PROCESSING_INSTRUCTION;
+ }
+ else if (tryRead(TEST_START_ELEMENT))
+ {
+ state = readStartElement();
+ event = XMLStreamConstants.START_ELEMENT;
+ }
+ else
+ {
+ int c = readCh();
+ error("no root element: U+" + Integer.toHexString(c));
+ }
+ break;
+ case MISC: // Comment | PI | S
+ skipWhitespace();
+ if (tryRead(TEST_COMMENT))
+ {
+ readComment(false);
+ event = XMLStreamConstants.COMMENT;
+ }
+ else if (tryRead(TEST_PI))
+ {
+ readPI(false);
+ event = XMLStreamConstants.PROCESSING_INSTRUCTION;
+ }
+ else
+ {
+ if (event == XMLStreamConstants.END_DOCUMENT)
+ throw new NoSuchElementException();
+ int c = readCh();
+ if (c != -1)
+ error("Only comments and PIs may appear after " +
+ "the root element");
+ event = XMLStreamConstants.END_DOCUMENT;
+ }
+ break;
+ default:
+ event = -1;
+ }
+ return event;
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException();
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ // package private
+
+ /**
+ * Returns the current element name.
+ */
+ String getCurrentElement()
+ {
+ return (String) stack.getLast();
+ }
+
+ // private
+
+ private void mark(int limit)
+ throws IOException
+ {
+ input.mark(limit);
+ }
+
+ private void reset()
+ throws IOException
+ {
+ input.reset();
+ }
+
+ private int read()
+ throws IOException
+ {
+ return input.read();
+ }
+
+ private int read(int[] b, int off, int len)
+ throws IOException
+ {
+ return input.read(b, off, len);
+ }
+
+ /**
+ * Parsed character read.
+ */
+ private int readCh()
+ throws IOException, XMLStreamException
+ {
+ int c = read();
+ if (expandPE && c == 0x25) // '%'
+ {
+ if (peIsError)
+ error("PE reference within decl in internal subset.");
+ expandPEReference();
+ return readCh();
+ }
+ return c;
+ }
+
+ /**
+ * Reads the next character, ensuring it is the character specified.
+ * @param delim the character to match
+ * @exception XMLStreamException if the next character is not the
+ * specified one
+ */
+ private void require(char delim)
+ throws IOException, XMLStreamException
+ {
+ mark(1);
+ int c = readCh();
+ if (delim != c)
+ {
+ reset();
+ error("required character (got U+" + Integer.toHexString(c) + ")",
+ new Character(delim));
+ }
+ }
+
+ /**
+ * Reads the next few characters, ensuring they match the string specified.
+ * @param delim the string to match
+ * @exception XMLStreamException if the next characters do not match the
+ * specified string
+ */
+ private void require(String delim)
+ throws IOException, XMLStreamException
+ {
+ char[] chars = delim.toCharArray();
+ int len = chars.length;
+ mark(len);
+ int off = 0;
+ do
+ {
+ int l2 = read(tmpBuf, off, len - off);
+ if (l2 == -1)
+ {
+ reset();
+ error("EOF before required string", delim);
+ }
+ off += l2;
+ }
+ while (off < len);
+ for (int i = 0; i < chars.length; i++)
+ {
+ if (chars[i] != tmpBuf[i])
+ {
+ reset();
+ error("required string", delim);
+ }
+ }
+ }
+
+ /**
+ * Try to read a single character. On failure, reset the stream.
+ * @param delim the character to test
+ * @return true if the character matched delim, false otherwise.
+ */
+ private boolean tryRead(char delim)
+ throws IOException, XMLStreamException
+ {
+ mark(1);
+ int c = readCh();
+ if (delim != c)
+ {
+ reset();
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Tries to read the specified characters.
+ * If successful, the stream is positioned after the last character,
+ * otherwise it is reset.
+ * @param test the string to test
+ * @return true if the characters matched the test string, false otherwise.
+ */
+ private boolean tryRead(String test)
+ throws IOException
+ {
+ char[] chars = test.toCharArray();
+ int len = chars.length;
+ mark(len);
+ int count = 0;
+ int l2 = read(tmpBuf, 0, len);
+ if (l2 == -1)
+ {
+ reset();
+ return false;
+ }
+ count += l2;
+ // check the characters we received first before doing additional reads
+ for (int i = 0; i < count; i++)
+ {
+ if (chars[i] != tmpBuf[i])
+ {
+ reset();
+ return false;
+ }
+ }
+ while (count < len)
+ {
+ // force read
+ int c = read();
+ if (c == -1)
+ {
+ reset();
+ return false;
+ }
+ tmpBuf[count] = (char) c;
+ // check each character as it is read
+ if (chars[count] != tmpBuf[count])
+ {
+ reset();
+ return false;
+ }
+ count++;
+ }
+ return true;
+ }
+
+ /**
+ * Reads characters until the specified test string is encountered.
+ * @param delim the string delimiting the end of the characters
+ */
+ private void readUntil(String delim)
+ throws IOException, XMLStreamException
+ {
+ int startLine = input.line;
+ try
+ {
+ while (!tryRead(delim))
+ {
+ int c = readCh();
+ if (c == -1)
+ throw new EOFException();
+ else if (input.xml11)
+ {
+ if (!isXML11Char(c) || isXML11RestrictedChar(c))
+ error("illegal XML 1.1 character",
+ "U+" + Integer.toHexString(c));
+ }
+ else if (!isChar(c))
+ error("illegal XML character",
+ "U+" + Integer.toHexString(c));
+ buf.append(Character.toChars(c));
+ }
+ }
+ catch (EOFException e)
+ {
+ error("end of input while looking for delimiter "+
+ "(started on line " + startLine + ')', delim);
+ }
+ }
+
+ /**
+ * Reads any whitespace characters.
+ * @return true if whitespace characters were read, false otherwise
+ */
+ private boolean tryWhitespace()
+ throws IOException, XMLStreamException
+ {
+ boolean white;
+ boolean ret = false;
+ do
+ {
+ mark(1);
+ int c = readCh();
+ while (c == -1 && inputStack.size() > 1)
+ {
+ popInput();
+ c = readCh();
+ }
+ white = (c == 0x20 || c == 0x09 || c == 0x0a || c == 0x0d);
+ if (white)
+ ret = true;
+ }
+ while (white);
+ reset();
+ return ret;
+ }
+
+ /**
+ * Skip over any whitespace characters.
+ */
+ private void skipWhitespace()
+ throws IOException, XMLStreamException
+ {
+ boolean white;
+ do
+ {
+ mark(1);
+ int c = readCh();
+ while (c == -1 && inputStack.size() > 1)
+ {
+ popInput();
+ c = readCh();
+ }
+ white = (c == 0x20 || c == 0x09 || c == 0x0a || c == 0x0d);
+ }
+ while (white);
+ reset();
+ }
+
+ /**
+ * Try to read as many whitespace characters as are available.
+ * @exception XMLStreamException if no whitespace characters were seen
+ */
+ private void requireWhitespace()
+ throws IOException, XMLStreamException
+ {
+ if (!tryWhitespace())
+ error("whitespace required");
+ }
+
+ /**
+ * Returns the current base URI for resolving external entities.
+ */
+ String getXMLBase()
+ {
+ if (baseAware)
+ {
+ for (Iterator i = bases.iterator(); i.hasNext(); )
+ {
+ String base = (String) i.next();
+ if (base != null)
+ return base;
+ }
+ }
+ return input.systemId;
+ }
+
+ /**
+ * Push the specified text input source.
+ */
+ private void pushInput(String name, String text, boolean report,
+ boolean normalize)
+ throws IOException, XMLStreamException
+ {
+ // Check for recursion
+ if (name != null && !"".equals(name))
+ {
+ for (Iterator i = inputStack.iterator(); i.hasNext(); )
+ {
+ Input ctx = (Input) i.next();
+ if (name.equals(ctx.name))
+ error("entities may not be self-recursive", name);
+ }
+ }
+ else
+ report = false;
+ pushInput(new Input(null, new StringReader(text), input.publicId,
+ input.systemId, name, input.inputEncoding, report,
+ normalize));
+ }
+
+ /**
+ * Push the specified external input source.
+ */
+ private void pushInput(String name, ExternalIds ids, boolean report,
+ boolean normalize)
+ throws IOException, XMLStreamException
+ {
+ if (!externalEntities)
+ return;
+ String url = canonicalize(absolutize(input.systemId, ids.systemId));
+ // Check for recursion
+ for (Iterator i = inputStack.iterator(); i.hasNext(); )
+ {
+ Input ctx = (Input) i.next();
+ if (url.equals(ctx.systemId))
+ error("entities may not be self-recursive", url);
+ if (name != null && !"".equals(name) && name.equals(ctx.name))
+ error("entities may not be self-recursive", name);
+ }
+ if (name == null || "".equals(name))
+ report = false;
+ InputStream in = null;
+ if (resolver != null)
+ {
+ Object obj = resolver.resolveEntity(ids.publicId, url, getXMLBase(),
+ null);
+ if (obj instanceof InputStream)
+ in = (InputStream) obj;
+ }
+ if (in == null)
+ in = resolve(url);
+ if (in == null)
+ error("unable to resolve external entity",
+ (ids.systemId != null) ? ids.systemId : ids.publicId);
+ pushInput(new Input(in, null, ids.publicId, url, name, null, report,
+ normalize));
+ input.init();
+ if (tryRead(TEST_XML_DECL))
+ readTextDecl();
+ input.finalizeEncoding();
+ }
+
+ /**
+ * Push the specified input source (general entity) onto the input stack.
+ */
+ private void pushInput(Input input)
+ {
+ if (input.report)
+ startEntityStack.addFirst(input.name);
+ inputStack.addLast(input);
+ if (this.input != null)
+ input.xml11 = this.input.xml11;
+ this.input = input;
+ }
+
+ /**
+ * Returns a canonicalized version of the specified URL.
+ * This is largely to work around a problem with the specification of
+ * file URLs.
+ */
+ static String canonicalize(String url)
+ {
+ if (url == null)
+ return null;
+ if (url.startsWith("file:") && !url.startsWith("file://"))
+ url = "file://" + url.substring(5);
+ return url;
+ }
+
+ /**
+ * "Absolutize" a URL. This resolves a relative URL into an absolute one.
+ * @param base the current base URL
+ * @param href the (absolute or relative) URL to resolve
+ */
+ public static String absolutize(String base, String href)
+ {
+ if (href == null)
+ return null;
+ int ci = href.indexOf(':');
+ if (ci > 1 && isURLScheme(href.substring(0, ci)))
+ {
+ // href is absolute already
+ return href;
+ }
+ if (base == null)
+ base = "";
+ else
+ {
+ int i = base.lastIndexOf('/');
+ if (i != -1)
+ base = base.substring(0, i + 1);
+ else
+ base = "";
+ }
+ if ("".equals(base))
+ {
+ // assume file URL relative to current directory
+ base = System.getProperty("user.dir");
+ if (base.charAt(0) == '/')
+ base = base.substring(1);
+ base = "file:///" + base.replace(File.separatorChar, '/');
+ if (!base.endsWith("/"))
+ base += "/";
+ }
+ // We can't use java.net.URL here to do the parsing, as it searches for
+ // a protocol handler. A protocol handler may not be registered for the
+ // URL scheme here. Do it manually.
+ //
+ // Set aside scheme and host portion of base URL
+ String basePrefix = null;
+ ci = base.indexOf(':');
+ if (ci > 1 && isURLScheme(base.substring(0, ci)))
+ {
+ if (base.length() > (ci + 3) &&
+ base.charAt(ci + 1) == '/' &&
+ base.charAt(ci + 2) == '/')
+ {
+ int si = base.indexOf('/', ci + 3);
+ if (si == -1)
+ base = null;
+ else
+ {
+ basePrefix = base.substring(0, si);
+ base = base.substring(si);
+ }
+ }
+ else
+ base = null;
+ }
+ if (base == null) // unknown or malformed base URL, use href
+ return href;
+ if (href.startsWith("/")) // absolute href pathname
+ return (basePrefix == null) ? href : basePrefix + href;
+ // relative href pathname
+ if (!base.endsWith("/"))
+ {
+ int lsi = base.lastIndexOf('/');
+ if (lsi == -1)
+ base = "/";
+ else
+ base = base.substring(0, lsi + 1);
+ }
+ while (href.startsWith("../") || href.startsWith("./"))
+ {
+ if (href.startsWith("../"))
+ {
+ // strip last path component from base
+ int lsi = base.lastIndexOf('/', base.length() - 2);
+ if (lsi > -1)
+ base = base.substring(0, lsi + 1);
+ href = href.substring(3); // strip ../ prefix
+ }
+ else
+ {
+ href = href.substring(2); // strip ./ prefix
+ }
+ }
+ return (basePrefix == null) ? base + href : basePrefix + base + href;
+ }
+
+ /**
+ * Indicates whether the specified characters match the scheme portion of
+ * a URL.
+ * @see RFC 1738 section 2.1
+ */
+ private static boolean isURLScheme(String text)
+ {
+ int len = text.length();
+ for (int i = 0; i < len; i++)
+ {
+ char c = text.charAt(i);
+ if (c == '+' || c == '.' || c == '-')
+ continue;
+ if (c < 65 || (c > 90 && c < 97) || c > 122)
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns an input stream for the given URL.
+ */
+ static InputStream resolve(String url)
+ throws IOException
+ {
+ try
+ {
+ return new URL(url).openStream();
+ }
+ catch (MalformedURLException e)
+ {
+ return null;
+ }
+ catch (IOException e)
+ {
+ IOException e2 = new IOException("error resolving " + url);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ /**
+ * Pops the current input source (general entity) off the stack.
+ */
+ private void popInput()
+ {
+ Input old = (Input) inputStack.removeLast();
+ if (old.report)
+ endEntityStack.addFirst(old.name);
+ input = (Input) inputStack.getLast();
+ }
+
+ /**
+ * Parse an entity text declaration.
+ */
+ private void readTextDecl()
+ throws IOException, XMLStreamException
+ {
+ final int flags = LIT_DISABLE_CREF | LIT_DISABLE_PE | LIT_DISABLE_EREF;
+ requireWhitespace();
+ if (tryRead("version"))
+ {
+ readEq();
+ String v = readLiteral(flags, false);
+ if ("1.0".equals(v))
+ input.xml11 = false;
+ else if ("1.1".equals(v))
+ {
+ Input i1 = (Input) inputStack.getFirst();
+ if (!i1.xml11)
+ error("external entity specifies later version number");
+ input.xml11 = true;
+ }
+ else
+ throw new XMLStreamException("illegal XML version: " + v);
+ requireWhitespace();
+ }
+ require("encoding");
+ readEq();
+ String enc = readLiteral(flags, false);
+ skipWhitespace();
+ require("?>");
+ input.setInputEncoding(enc);
+ }
+
+ /**
+ * Parse the XML declaration.
+ */
+ private void readXMLDecl()
+ throws IOException, XMLStreamException
+ {
+ final int flags = LIT_DISABLE_CREF | LIT_DISABLE_PE | LIT_DISABLE_EREF;
+
+ requireWhitespace();
+ require("version");
+ readEq();
+ xmlVersion = readLiteral(flags, false);
+ if ("1.0".equals(xmlVersion))
+ input.xml11 = false;
+ else if ("1.1".equals(xmlVersion))
+ input.xml11 = true;
+ else
+ throw new XMLStreamException("illegal XML version: " + xmlVersion);
+
+ boolean white = tryWhitespace();
+
+ if (tryRead("encoding"))
+ {
+ if (!white)
+ error("whitespace required before 'encoding='");
+ readEq();
+ xmlEncoding = readLiteral(flags, false);
+ white = tryWhitespace();
+ }
+
+ if (tryRead("standalone"))
+ {
+ if (!white)
+ error("whitespace required before 'standalone='");
+ readEq();
+ String standalone = readLiteral(flags, false);
+ if ("yes".equals(standalone))
+ xmlStandalone = Boolean.TRUE;
+ else if ("no".equals(standalone))
+ xmlStandalone = Boolean.FALSE;
+ else
+ error("standalone flag must be 'yes' or 'no'", standalone);
+ }
+
+ skipWhitespace();
+ require("?>");
+ if (xmlEncoding != null)
+ input.setInputEncoding(xmlEncoding);
+ }
+
+ /**
+ * Parse the DOCTYPE declaration.
+ */
+ private void readDoctypeDecl()
+ throws IOException, XMLStreamException
+ {
+ if (!supportDTD)
+ error("parser was configured not to support DTDs");
+ requireWhitespace();
+ String rootName = readNmtoken(true);
+ skipWhitespace();
+ ExternalIds ids = readExternalIds(false, true);
+ doctype =
+ this.new Doctype(rootName, ids.publicId, ids.systemId);
+
+ // Parse internal subset first
+ skipWhitespace();
+ if (tryRead('['))
+ {
+ while (true)
+ {
+ expandPE = true;
+ skipWhitespace();
+ expandPE = false;
+ if (tryRead(']'))
+ break;
+ else
+ readMarkupdecl(false);
+ }
+ }
+ skipWhitespace();
+ require('>');
+
+ // Parse external subset
+ if (ids.systemId != null && externalEntities)
+ {
+ pushInput("", ">", false, false);
+ pushInput("[dtd]", ids, true, true);
+ // loop until we get back to ">"
+ while (true)
+ {
+ expandPE = true;
+ skipWhitespace();
+ expandPE = false;
+ mark(1);
+ int c = readCh();
+ if (c == 0x3e) // '>'
+ break;
+ else if (c == -1)
+ popInput();
+ else
+ {
+ reset();
+ expandPE = true;
+ readMarkupdecl(true);
+ expandPE = true;
+ }
+ }
+ if (inputStack.size() != 2)
+ error("external subset has unmatched '>'");
+ popInput();
+ }
+ checkDoctype();
+ if (validating)
+ validateDoctype();
+
+ // Make rootName available for reading
+ buf.setLength(0);
+ buf.append(rootName);
+ }
+
+ /**
+ * Checks the well-formedness of the DTD.
+ */
+ private void checkDoctype()
+ throws XMLStreamException
+ {
+ // TODO check entity recursion
+ }
+
+ /**
+ * Parse the markupdecl production.
+ */
+ private void readMarkupdecl(boolean inExternalSubset)
+ throws IOException, XMLStreamException
+ {
+ boolean saved = expandPE;
+ mark(1);
+ require('<');
+ reset();
+ expandPE = false;
+ if (tryRead(TEST_ELEMENT_DECL))
+ {
+ expandPE = saved;
+ readElementDecl();
+ }
+ else if (tryRead(TEST_ATTLIST_DECL))
+ {
+ expandPE = saved;
+ readAttlistDecl();
+ }
+ else if (tryRead(TEST_ENTITY_DECL))
+ {
+ expandPE = saved;
+ readEntityDecl(inExternalSubset);
+ }
+ else if (tryRead(TEST_NOTATION_DECL))
+ {
+ expandPE = saved;
+ readNotationDecl(inExternalSubset);
+ }
+ else if (tryRead(TEST_PI))
+ {
+ readPI(true);
+ expandPE = saved;
+ }
+ else if (tryRead(TEST_COMMENT))
+ {
+ readComment(true);
+ expandPE = saved;
+ }
+ else if (tryRead("<!["))
+ {
+ // conditional section
+ expandPE = saved;
+ if (inputStack.size() < 2)
+ error("conditional sections illegal in internal subset");
+ skipWhitespace();
+ if (tryRead("INCLUDE"))
+ {
+ skipWhitespace();
+ require('[');
+ skipWhitespace();
+ while (!tryRead("]]>"))
+ {
+ readMarkupdecl(inExternalSubset);
+ skipWhitespace();
+ }
+ }
+ else if (tryRead("IGNORE"))
+ {
+ skipWhitespace();
+ require('[');
+ expandPE = false;
+ for (int nesting = 1; nesting > 0; )
+ {
+ int c = readCh();
+ switch (c)
+ {
+ case 0x3c: // '<'
+ if (tryRead("!["))
+ nesting++;
+ break;
+ case 0x5d: // ']'
+ if (tryRead("]>"))
+ nesting--;
+ break;
+ case -1:
+ throw new EOFException();
+ }
+ }
+ expandPE = saved;
+ }
+ else
+ error("conditional section must begin with INCLUDE or IGNORE");
+ }
+ else
+ error("expected markup declaration");
+ }
+
+ /**
+ * Parse the elementdecl production.
+ */
+ private void readElementDecl()
+ throws IOException, XMLStreamException
+ {
+ requireWhitespace();
+ boolean saved = expandPE;
+ expandPE = (inputStack.size() > 1);
+ String name = readNmtoken(true);
+ expandPE = saved;
+ requireWhitespace();
+ readContentspec(name);
+ skipWhitespace();
+ require('>');
+ }
+
+ /**
+ * Parse the contentspec production.
+ */
+ private void readContentspec(String elementName)
+ throws IOException, XMLStreamException
+ {
+ if (tryRead("EMPTY"))
+ doctype.addElementDecl(elementName, "EMPTY", new EmptyContentModel());
+ else if (tryRead("ANY"))
+ doctype.addElementDecl(elementName, "ANY", new AnyContentModel());
+ else
+ {
+ ContentModel model;
+ CPStringBuilder acc = new CPStringBuilder();
+ require('(');
+ acc.append('(');
+ skipWhitespace();
+ if (tryRead("#PCDATA"))
+ {
+ // mixed content
+ acc.append("#PCDATA");
+ MixedContentModel mm = new MixedContentModel();
+ model = mm;
+ skipWhitespace();
+ if (tryRead(')'))
+ {
+ acc.append(")");
+ if (tryRead('*'))
+ {
+ mm.min = 0;
+ mm.max = -1;
+ }
+ }
+ else
+ {
+ while (!tryRead(")"))
+ {
+ require('|');
+ acc.append('|');
+ skipWhitespace();
+ String name = readNmtoken(true);
+ acc.append(name);
+ mm.addName(name);
+ skipWhitespace();
+ }
+ require('*');
+ acc.append(")*");
+ mm.min = 0;
+ mm.max = -1;
+ }
+ }
+ else
+ model = readElements(acc);
+ doctype.addElementDecl(elementName, acc.toString(), model);
+ }
+ }
+
+ /**
+ * Parses an element content model.
+ */
+ private ElementContentModel readElements(CPStringBuilder acc)
+ throws IOException, XMLStreamException
+ {
+ int separator;
+ ElementContentModel model = new ElementContentModel();
+
+ // Parse first content particle
+ skipWhitespace();
+ model.addContentParticle(readContentParticle(acc));
+ // End or separator
+ skipWhitespace();
+ int c = readCh();
+ switch (c)
+ {
+ case 0x29: // ')'
+ acc.append(')');
+ mark(1);
+ c = readCh();
+ switch (c)
+ {
+ case 0x3f: // '?'
+ acc.append('?');
+ model.min = 0;
+ model.max = 1;
+ break;
+ case 0x2a: // '*'
+ acc.append('*');
+ model.min = 0;
+ model.max = -1;
+ break;
+ case 0x2b: // '+'
+ acc.append('+');
+ model.min = 1;
+ model.max = -1;
+ break;
+ default:
+ reset();
+ }
+ return model; // done
+ case 0x7c: // '|'
+ model.or = true;
+ // fall through
+ case 0x2c: // ','
+ separator = c;
+ acc.append(Character.toChars(c));
+ break;
+ default:
+ error("bad separator in content model",
+ "U+" + Integer.toHexString(c));
+ return model;
+ }
+ // Parse subsequent content particles
+ while (true)
+ {
+ skipWhitespace();
+ model.addContentParticle(readContentParticle(acc));
+ skipWhitespace();
+ c = readCh();
+ if (c == 0x29) // ')'
+ {
+ acc.append(')');
+ break;
+ }
+ else if (c != separator)
+ {
+ error("bad separator in content model",
+ "U+" + Integer.toHexString(c));
+ return model;
+ }
+ else
+ acc.append(c);
+ }
+ // Check for occurrence indicator
+ mark(1);
+ c = readCh();
+ switch (c)
+ {
+ case 0x3f: // '?'
+ acc.append('?');
+ model.min = 0;
+ model.max = 1;
+ break;
+ case 0x2a: // '*'
+ acc.append('*');
+ model.min = 0;
+ model.max = -1;
+ break;
+ case 0x2b: // '+'
+ acc.append('+');
+ model.min = 1;
+ model.max = -1;
+ break;
+ default:
+ reset();
+ }
+ return model;
+ }
+
+ /**
+ * Parse a cp production.
+ */
+ private ContentParticle readContentParticle(CPStringBuilder acc)
+ throws IOException, XMLStreamException
+ {
+ ContentParticle cp = new ContentParticle();
+ if (tryRead('('))
+ {
+ acc.append('(');
+ cp.content = readElements(acc);
+ }
+ else
+ {
+ String name = readNmtoken(true);
+ acc.append(name);
+ cp.content = name;
+ mark(1);
+ int c = readCh();
+ switch (c)
+ {
+ case 0x3f: // '?'
+ acc.append('?');
+ cp.min = 0;
+ cp.max = 1;
+ break;
+ case 0x2a: // '*'
+ acc.append('*');
+ cp.min = 0;
+ cp.max = -1;
+ break;
+ case 0x2b: // '+'
+ acc.append('+');
+ cp.min = 1;
+ cp.max = -1;
+ break;
+ default:
+ reset();
+ }
+ }
+ return cp;
+ }
+
+ /**
+ * Parse an attribute-list definition.
+ */
+ private void readAttlistDecl()
+ throws IOException, XMLStreamException
+ {
+ requireWhitespace();
+ boolean saved = expandPE;
+ expandPE = (inputStack.size() > 1);
+ String elementName = readNmtoken(true);
+ expandPE = saved;
+ boolean white = tryWhitespace();
+ while (!tryRead('>'))
+ {
+ if (!white)
+ error("whitespace required before attribute definition");
+ readAttDef(elementName);
+ white = tryWhitespace();
+ }
+ }
+
+ /**
+ * Parse a single attribute definition.
+ */
+ private void readAttDef(String elementName)
+ throws IOException, XMLStreamException
+ {
+ String name = readNmtoken(true);
+ requireWhitespace();
+ CPStringBuilder acc = new CPStringBuilder();
+ HashSet values = new HashSet();
+ String type = readAttType(acc, values);
+ if (validating)
+ {
+ if ("ID".equals(type))
+ {
+ // VC: One ID per Element Type
+ for (Iterator i = doctype.attlistIterator(elementName);
+ i.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ AttributeDecl decl = (AttributeDecl) entry.getValue();
+ if ("ID".equals(decl.type))
+ error("element types must not have more than one ID " +
+ "attribute");
+ }
+ }
+ else if ("NOTATION".equals(type))
+ {
+ // VC: One Notation Per Element Type
+ for (Iterator i = doctype.attlistIterator(elementName);
+ i.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ AttributeDecl decl = (AttributeDecl) entry.getValue();
+ if ("NOTATION".equals(decl.type))
+ error("element types must not have more than one NOTATION " +
+ "attribute");
+ }
+ // VC: No Notation on Empty Element
+ ContentModel model = doctype.getElementModel(elementName);
+ if (model != null && model.type == ContentModel.EMPTY)
+ error("attributes of type NOTATION must not be declared on an " +
+ "element declared EMPTY");
+ }
+ }
+ String enumer = null;
+ if ("ENUMERATION".equals(type) || "NOTATION".equals(type))
+ enumer = acc.toString();
+ else
+ values = null;
+ requireWhitespace();
+ readDefault(elementName, name, type, enumer, values);
+ }
+
+ /**
+ * Parse an attribute type.
+ */
+ private String readAttType(CPStringBuilder acc, HashSet values)
+ throws IOException, XMLStreamException
+ {
+ if (tryRead('('))
+ {
+ readEnumeration(false, acc, values);
+ return "ENUMERATION";
+ }
+ else
+ {
+ String typeString = readNmtoken(true);
+ if ("NOTATION".equals(typeString))
+ {
+ readNotationType(acc, values);
+ return typeString;
+ }
+ else if ("CDATA".equals(typeString) ||
+ "ID".equals(typeString) ||
+ "IDREF".equals(typeString) ||
+ "IDREFS".equals(typeString) ||
+ "ENTITY".equals(typeString) ||
+ "ENTITIES".equals(typeString) ||
+ "NMTOKEN".equals(typeString) ||
+ "NMTOKENS".equals(typeString))
+ return typeString;
+ else
+ {
+ error("illegal attribute type", typeString);
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Parse an enumeration.
+ */
+ private void readEnumeration(boolean isNames, CPStringBuilder acc,
+ HashSet values)
+ throws IOException, XMLStreamException
+ {
+ acc.append('(');
+ // first token
+ skipWhitespace();
+ String token = readNmtoken(isNames);
+ acc.append(token);
+ values.add(token);
+ // subsequent tokens
+ skipWhitespace();
+ while (!tryRead(')'))
+ {
+ require('|');
+ acc.append('|');
+ skipWhitespace();
+ token = readNmtoken(isNames);
+ // VC: No Duplicate Tokens
+ if (validating && values.contains(token))
+ error("duplicate token", token);
+ acc.append(token);
+ values.add(token);
+ skipWhitespace();
+ }
+ acc.append(')');
+ }
+
+ /**
+ * Parse a notation type for an attribute.
+ */
+ private void readNotationType(CPStringBuilder acc, HashSet values)
+ throws IOException, XMLStreamException
+ {
+ requireWhitespace();
+ require('(');
+ readEnumeration(true, acc, values);
+ }
+
+ /**
+ * Parse the default value for an attribute.
+ */
+ private void readDefault(String elementName, String name,
+ String type, String enumeration, HashSet values)
+ throws IOException, XMLStreamException
+ {
+ int valueType = ATTRIBUTE_DEFAULT_SPECIFIED;
+ int flags = LIT_ATTRIBUTE;
+ String value = null, defaultType = null;
+ boolean saved = expandPE;
+
+ if (!"CDATA".equals(type))
+ flags |= LIT_NORMALIZE;
+
+ expandPE = false;
+ if (tryRead('#'))
+ {
+ if (tryRead("FIXED"))
+ {
+ defaultType = "#FIXED";
+ valueType = ATTRIBUTE_DEFAULT_FIXED;
+ requireWhitespace();
+ value = readLiteral(flags, false);
+ }
+ else if (tryRead("REQUIRED"))
+ {
+ defaultType = "#REQUIRED";
+ valueType = ATTRIBUTE_DEFAULT_REQUIRED;
+ }
+ else if (tryRead("IMPLIED"))
+ {
+ defaultType = "#IMPLIED";
+ valueType = ATTRIBUTE_DEFAULT_IMPLIED;
+ }
+ else
+ error("illegal keyword for attribute default value");
+ }
+ else
+ value = readLiteral(flags, false);
+ expandPE = saved;
+ if (validating)
+ {
+ if ("ID".equals(type))
+ {
+ // VC: Attribute Default Value Syntactically Correct
+ if (value != null && !isNmtoken(value, true))
+ error("default value must match Name production", value);
+ // VC: ID Attribute Default
+ if (valueType != ATTRIBUTE_DEFAULT_REQUIRED &&
+ valueType != ATTRIBUTE_DEFAULT_IMPLIED)
+ error("ID attributes must have a declared default of " +
+ "#IMPLIED or #REQUIRED");
+ }
+ else if (value != null)
+ {
+ // VC: Attribute Default Value Syntactically Correct
+ if ("IDREF".equals(type) || "ENTITY".equals(type))
+ {
+ if (!isNmtoken(value, true))
+ error("default value must match Name production", value);
+ }
+ else if ("IDREFS".equals(type) || "ENTITIES".equals(type))
+ {
+ StringTokenizer st = new StringTokenizer(value);
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ if (!isNmtoken(token, true))
+ error("default value must match Name production", token);
+ }
+ }
+ else if ("NMTOKEN".equals(type) || "ENUMERATION".equals(type))
+ {
+ if (!isNmtoken(value, false))
+ error("default value must match Nmtoken production", value);
+ }
+ else if ("NMTOKENS".equals(type))
+ {
+ StringTokenizer st = new StringTokenizer(value);
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ if (!isNmtoken(token, false))
+ error("default value must match Nmtoken production",
+ token);
+ }
+ }
+ }
+ }
+ // Register attribute def
+ AttributeDecl attribute =
+ new AttributeDecl(type, value, valueType, enumeration, values,
+ inputStack.size() != 1);
+ doctype.addAttributeDecl(elementName, name, attribute);
+ }
+
+ /**
+ * Parse the EntityDecl production.
+ */
+ private void readEntityDecl(boolean inExternalSubset)
+ throws IOException, XMLStreamException
+ {
+ int flags = 0;
+ // Check if parameter entity
+ boolean peFlag = false;
+ expandPE = false;
+ requireWhitespace();
+ if (tryRead('%'))
+ {
+ peFlag = true;
+ requireWhitespace();
+ }
+ expandPE = true;
+ // Read entity name
+ String name = readNmtoken(true);
+ if (name.indexOf(':') != -1)
+ error("illegal character ':' in entity name", name);
+ if (peFlag)
+ name = "%" + name;
+ requireWhitespace();
+ mark(1);
+ int c = readCh();
+ reset();
+ if (c == 0x22 || c == 0x27) // " | '
+ {
+ // Internal entity replacement text
+ String value = readLiteral(flags | LIT_DISABLE_EREF, true);
+ int ai = value.indexOf('&');
+ while (ai != -1)
+ {
+ int sci = value.indexOf(';', ai);
+ if (sci == -1)
+ error("malformed reference in entity value", value);
+ String ref = value.substring(ai + 1, sci);
+ int[] cp = UnicodeReader.toCodePointArray(ref);
+ if (cp.length == 0)
+ error("malformed reference in entity value", value);
+ if (cp[0] == 0x23) // #
+ {
+ if (cp.length == 1)
+ error("malformed reference in entity value", value);
+ if (cp[1] == 0x78) // 'x'
+ {
+ if (cp.length == 2)
+ error("malformed reference in entity value", value);
+ for (int i = 2; i < cp.length; i++)
+ {
+ int x = cp[i];
+ if (x < 0x30 ||
+ (x > 0x39 && x < 0x41) ||
+ (x > 0x46 && x < 0x61) ||
+ x > 0x66)
+ error("malformed character reference in entity value",
+ value);
+ }
+ }
+ else
+ {
+ for (int i = 1; i < cp.length; i++)
+ {
+ int x = cp[i];
+ if (x < 0x30 || x > 0x39)
+ error("malformed character reference in entity value",
+ value);
+ }
+ }
+ }
+ else
+ {
+ if (!isNameStartCharacter(cp[0], input.xml11))
+ error("malformed reference in entity value", value);
+ for (int i = 1; i < cp.length; i++)
+ {
+ if (!isNameCharacter(cp[i], input.xml11))
+ error("malformed reference in entity value", value);
+ }
+ }
+ ai = value.indexOf('&', sci);
+ }
+ doctype.addEntityDecl(name, value, inExternalSubset);
+ }
+ else
+ {
+ ExternalIds ids = readExternalIds(false, false);
+ // Check for NDATA
+ boolean white = tryWhitespace();
+ if (!peFlag && tryRead("NDATA"))
+ {
+ if (!white)
+ error("whitespace required before NDATA");
+ requireWhitespace();
+ ids.notationName = readNmtoken(true);
+ }
+ doctype.addEntityDecl(name, ids, inExternalSubset);
+ }
+ // finish
+ skipWhitespace();
+ require('>');
+ }
+
+ /**
+ * Parse the NotationDecl production.
+ */
+ private void readNotationDecl(boolean inExternalSubset)
+ throws IOException, XMLStreamException
+ {
+ requireWhitespace();
+ String notationName = readNmtoken(true);
+ if (notationName.indexOf(':') != -1)
+ error("illegal character ':' in notation name", notationName);
+ if (validating)
+ {
+ // VC: Unique Notation Name
+ ExternalIds notation = doctype.getNotation(notationName);
+ if (notation != null)
+ error("duplicate notation name", notationName);
+ }
+ requireWhitespace();
+ ExternalIds ids = readExternalIds(true, false);
+ ids.notationName = notationName;
+ doctype.addNotationDecl(notationName, ids, inExternalSubset);
+ skipWhitespace();
+ require('>');
+ }
+
+ /**
+ * Returns a tuple {publicId, systemId}.
+ */
+ private ExternalIds readExternalIds(boolean inNotation, boolean isSubset)
+ throws IOException, XMLStreamException
+ {
+ int c;
+ int flags = LIT_DISABLE_CREF | LIT_DISABLE_PE | LIT_DISABLE_EREF;
+ ExternalIds ids = new ExternalIds();
+
+ if (tryRead("PUBLIC"))
+ {
+ requireWhitespace();
+ ids.publicId = readLiteral(LIT_NORMALIZE | LIT_PUBID | flags, false);
+ if (inNotation)
+ {
+ skipWhitespace();
+ mark(1);
+ c = readCh();
+ reset();
+ if (c == 0x22 || c == 0x27) // " | '
+ {
+ String href = readLiteral(flags, false);
+ ids.systemId = absolutize(input.systemId, href);
+ }
+ }
+ else
+ {
+ requireWhitespace();
+ String href = readLiteral(flags, false);
+ ids.systemId = absolutize(input.systemId, href);
+ }
+ // Check valid URI characters
+ for (int i = 0; i < ids.publicId.length(); i++)
+ {
+ char d = ids.publicId.charAt(i);
+ if (d >= 'a' && d <= 'z')
+ continue;
+ if (d >= 'A' && d <= 'Z')
+ continue;
+ if (" \r\n0123456789-' ()+,./:=?;!*#@$_%".indexOf(d) != -1)
+ continue;
+ error("illegal PUBLIC id character",
+ "U+" + Integer.toHexString(d));
+ }
+ }
+ else if (tryRead("SYSTEM"))
+ {
+ requireWhitespace();
+ String href = readLiteral(flags, false);
+ ids.systemId = absolutize(input.systemId, href);
+ }
+ else if (!isSubset)
+ {
+ error("missing SYSTEM or PUBLIC keyword");
+ }
+ if (ids.systemId != null && !inNotation)
+ {
+ if (ids.systemId.indexOf('#') != -1)
+ error("SYSTEM id has a URI fragment", ids.systemId);
+ }
+ return ids;
+ }
+
+ /**
+ * Parse the start of an element.
+ * @return the state of the parser afterwards (EMPTY_ELEMENT or CONTENT)
+ */
+ private int readStartElement()
+ throws IOException, XMLStreamException
+ {
+ // Read element name
+ String elementName = readNmtoken(true);
+ attrs.clear();
+ // Push namespace context
+ if (namespaceAware)
+ {
+ if (elementName.charAt(0) == ':' ||
+ elementName.charAt(elementName.length() - 1) == ':')
+ error("not a QName", elementName);
+ namespaces.addFirst(new LinkedHashMap());
+ }
+ // Read element content
+ boolean white = tryWhitespace();
+ mark(1);
+ int c = readCh();
+ while (c != 0x2f && c != 0x3e) // '/' | '>'
+ {
+ // Read attribute
+ reset();
+ if (!white)
+ error("need whitespace between attributes");
+ readAttribute(elementName);
+ white = tryWhitespace();
+ mark(1);
+ c = readCh();
+ }
+ // supply defaulted attributes
+ if (doctype != null)
+ {
+ for (Iterator i = doctype.attlistIterator(elementName); i.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ String attName = (String) entry.getKey();
+ AttributeDecl decl = (AttributeDecl) entry.getValue();
+ if (validating)
+ {
+ switch (decl.valueType)
+ {
+ case ATTRIBUTE_DEFAULT_REQUIRED:
+ // VC: Required Attribute
+ if (decl.value == null && !attributeSpecified(attName))
+ error("value for " + attName + " attribute is required");
+ break;
+ case ATTRIBUTE_DEFAULT_FIXED:
+ // VC: Fixed Attribute Default
+ for (Iterator j = attrs.iterator(); j.hasNext(); )
+ {
+ Attribute a = (Attribute) j.next();
+ if (attName.equals(a.name) &&
+ !decl.value.equals(a.value))
+ error("value for " + attName + " attribute must be " +
+ decl.value);
+ }
+ break;
+ }
+ }
+ if (namespaceAware && attName.equals("xmlns"))
+ {
+ LinkedHashMap ctx =
+ (LinkedHashMap) namespaces.getFirst();
+ if (ctx.containsKey(XMLConstants.DEFAULT_NS_PREFIX))
+ continue; // namespace was specified
+ }
+ else if (namespaceAware && attName.startsWith("xmlns:"))
+ {
+ LinkedHashMap ctx =
+ (LinkedHashMap) namespaces.getFirst();
+ if (ctx.containsKey(attName.substring(6)))
+ continue; // namespace was specified
+ }
+ else if (attributeSpecified(attName))
+ continue;
+ if (decl.value == null)
+ continue;
+ // VC: Standalone Document Declaration
+ if (validating && decl.external && xmlStandalone == Boolean.TRUE)
+ error("standalone must be 'no' if attributes inherit values " +
+ "from externally declared markup declarations");
+ Attribute attr =
+ new Attribute(attName, decl.type, false, decl.value);
+ if (namespaceAware)
+ {
+ if (!addNamespace(attr))
+ attrs.add(attr);
+ }
+ else
+ attrs.add(attr);
+ }
+ }
+ if (baseAware)
+ {
+ String uri = getAttributeValue(XMLConstants.XML_NS_URI, "base");
+ String base = getXMLBase();
+ bases.addFirst(absolutize(base, uri));
+ }
+ if (namespaceAware)
+ {
+ // check prefix bindings
+ int ci = elementName.indexOf(':');
+ if (ci != -1)
+ {
+ String prefix = elementName.substring(0, ci);
+ String uri = getNamespaceURI(prefix);
+ if (uri == null)
+ error("unbound element prefix", prefix);
+ else if (input.xml11 && "".equals(uri))
+ error("XML 1.1 unbound element prefix", prefix);
+ }
+ for (Iterator i = attrs.iterator(); i.hasNext(); )
+ {
+ Attribute attr = (Attribute) i.next();
+ if (attr.prefix != null &&
+ !XMLConstants.XMLNS_ATTRIBUTE.equals(attr.prefix))
+ {
+ String uri = getNamespaceURI(attr.prefix);
+ if (uri == null)
+ error("unbound attribute prefix", attr.prefix);
+ else if (input.xml11 && "".equals(uri))
+ error("XML 1.1 unbound attribute prefix", attr.prefix);
+ }
+ }
+ }
+ if (validating && doctype != null)
+ {
+ validateStartElement(elementName);
+ currentContentModel = doctype.getElementModel(elementName);
+ if (currentContentModel == null)
+ error("no element declaration", elementName);
+ validationStack.add(new LinkedList());
+ }
+ // make element name available for read
+ buf.setLength(0);
+ buf.append(elementName);
+ // push element onto stack
+ stack.addLast(elementName);
+ switch (c)
+ {
+ case 0x3e: // '>'
+ return CONTENT;
+ case 0x2f: // '/'
+ require('>');
+ return EMPTY_ELEMENT;
+ }
+ return -1; // to satisfy compiler
+ }
+
+ /**
+ * Indicates whether the specified attribute name was specified for the
+ * current element.
+ */
+ private boolean attributeSpecified(String attName)
+ {
+ for (Iterator j = attrs.iterator(); j.hasNext(); )
+ {
+ Attribute a = (Attribute) j.next();
+ if (attName.equals(a.name))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Parse an attribute.
+ */
+ private void readAttribute(String elementName)
+ throws IOException, XMLStreamException
+ {
+ // Read attribute name
+ String attributeName = readNmtoken(true);
+ String type = getAttributeType(elementName, attributeName);
+ readEq();
+ // Read literal
+ final int flags = LIT_ATTRIBUTE | LIT_ENTITY_REF;
+ String value = (type == null || "CDATA".equals(type)) ?
+ readLiteral(flags, false) : readLiteral(flags | LIT_NORMALIZE, false);
+ // add attribute event
+ Attribute attr = this.new Attribute(attributeName, type, true, value);
+ if (namespaceAware)
+ {
+ if (attributeName.charAt(0) == ':' ||
+ attributeName.charAt(attributeName.length() - 1) == ':')
+ error("not a QName", attributeName);
+ else if (attributeName.equals("xmlns"))
+ {
+ LinkedHashMap ctx = (LinkedHashMap) namespaces.getFirst();
+ if (ctx.containsKey(XMLConstants.DEFAULT_NS_PREFIX))
+ error("duplicate default namespace");
+ }
+ else if (attributeName.startsWith("xmlns:"))
+ {
+ LinkedHashMap ctx = (LinkedHashMap) namespaces.getFirst();
+ if (ctx.containsKey(attributeName.substring(6)))
+ error("duplicate namespace", attributeName.substring(6));
+ }
+ else if (attrs.contains(attr))
+ error("duplicate attribute", attributeName);
+ }
+ else if (attrs.contains(attr))
+ error("duplicate attribute", attributeName);
+ if (validating && doctype != null)
+ {
+ // VC: Attribute Value Type
+ AttributeDecl decl =
+ doctype.getAttributeDecl(elementName, attributeName);
+ if (decl == null)
+ error("attribute must be declared", attributeName);
+ if ("ENUMERATION".equals(decl.type))
+ {
+ // VC: Enumeration
+ if (!decl.values.contains(value))
+ error("value does not match enumeration " + decl.enumeration,
+ value);
+ }
+ else if ("ID".equals(decl.type))
+ {
+ // VC: ID
+ if (!isNmtoken(value, true))
+ error("ID values must match the Name production");
+ if (ids.contains(value))
+ error("Duplicate ID", value);
+ ids.add(value);
+ }
+ else if ("IDREF".equals(decl.type) || "IDREFS".equals(decl.type))
+ {
+ StringTokenizer st = new StringTokenizer(value);
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ // VC: IDREF
+ if (!isNmtoken(token, true))
+ error("IDREF values must match the Name production");
+ idrefs.add(token);
+ }
+ }
+ else if ("NMTOKEN".equals(decl.type) || "NMTOKENS".equals(decl.type))
+ {
+ StringTokenizer st = new StringTokenizer(value);
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ // VC: Name Token
+ if (!isNmtoken(token, false))
+ error("NMTOKEN values must match the Nmtoken production");
+ }
+ }
+ else if ("ENTITY".equals(decl.type))
+ {
+ // VC: Entity Name
+ if (!isNmtoken(value, true))
+ error("ENTITY values must match the Name production");
+ Object entity = doctype.getEntity(value);
+ if (entity == null || !(entity instanceof ExternalIds) ||
+ ((ExternalIds) entity).notationName == null)
+ error("ENTITY values must match the name of an unparsed " +
+ "entity declared in the DTD");
+ }
+ else if ("NOTATION".equals(decl.type))
+ {
+ if (!decl.values.contains(value))
+ error("NOTATION values must match a declared notation name",
+ value);
+ // VC: Notation Attributes
+ ExternalIds notation = doctype.getNotation(value);
+ if (notation == null)
+ error("NOTATION values must match the name of a notation " +
+ "declared in the DTD", value);
+ }
+ }
+ if (namespaceAware)
+ {
+ if (!addNamespace(attr))
+ attrs.add(attr);
+ }
+ else
+ attrs.add(attr);
+ }
+
+ /**
+ * Determines whether the specified attribute is a namespace declaration,
+ * and adds it to the current namespace context if so. Returns false if
+ * the attribute is an ordinary attribute.
+ */
+ private boolean addNamespace(Attribute attr)
+ throws XMLStreamException
+ {
+ if ("xmlns".equals(attr.name))
+ {
+ LinkedHashMap ctx = (LinkedHashMap) namespaces.getFirst();
+ if (ctx.get(XMLConstants.DEFAULT_NS_PREFIX) != null)
+ error("Duplicate default namespace declaration");
+ if (XMLConstants.XML_NS_URI.equals(attr.value))
+ error("can't bind XML namespace");
+ ctx.put(XMLConstants.DEFAULT_NS_PREFIX, attr.value);
+ return true;
+ }
+ else if ("xmlns".equals(attr.prefix))
+ {
+ LinkedHashMap ctx = (LinkedHashMap) namespaces.getFirst();
+ if (ctx.get(attr.localName) != null)
+ error("Duplicate namespace declaration for prefix",
+ attr.localName);
+ if (XMLConstants.XML_NS_PREFIX.equals(attr.localName))
+ {
+ if (!XMLConstants.XML_NS_URI.equals(attr.value))
+ error("can't redeclare xml prefix");
+ else
+ return false; // treat as attribute
+ }
+ if (XMLConstants.XML_NS_URI.equals(attr.value))
+ error("can't bind non-xml prefix to XML namespace");
+ if (XMLConstants.XMLNS_ATTRIBUTE.equals(attr.localName))
+ error("can't redeclare xmlns prefix");
+ if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(attr.value))
+ error("can't bind non-xmlns prefix to XML Namespace namespace");
+ if ("".equals(attr.value) && !input.xml11)
+ error("illegal use of 1.1-style prefix unbinding in 1.0 document");
+ ctx.put(attr.localName, attr.value);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Parse a closing tag.
+ */
+ private void readEndElement()
+ throws IOException, XMLStreamException
+ {
+ // pop element off stack
+ String expected = (String) stack.removeLast();
+ require(expected);
+ skipWhitespace();
+ require('>');
+ // Make element name available
+ buf.setLength(0);
+ buf.append(expected);
+ if (validating && doctype != null)
+ endElementValidationHook();
+ }
+
+ /**
+ * Validate the end of an element.
+ * Called on an end-element or empty element if validating.
+ */
+ private void endElementValidationHook()
+ throws XMLStreamException
+ {
+ validateEndElement();
+ validationStack.removeLast();
+ if (stack.isEmpty())
+ currentContentModel = null;
+ else
+ {
+ String parent = (String) stack.getLast();
+ currentContentModel = doctype.getElementModel(parent);
+ }
+ }
+
+ /**
+ * Parse a comment.
+ */
+ private void readComment(boolean inDTD)
+ throws IOException, XMLStreamException
+ {
+ boolean saved = expandPE;
+ expandPE = false;
+ buf.setLength(0);
+ readUntil(TEST_END_COMMENT);
+ require('>');
+ expandPE = saved;
+ if (inDTD)
+ doctype.addComment(buf.toString());
+ }
+
+ /**
+ * Parse a processing instruction.
+ */
+ private void readPI(boolean inDTD)
+ throws IOException, XMLStreamException
+ {
+ boolean saved = expandPE;
+ expandPE = false;
+ piTarget = readNmtoken(true);
+ if (piTarget.indexOf(':') != -1)
+ error("illegal character in PI target", new Character(':'));
+ if ("xml".equalsIgnoreCase(piTarget))
+ error("illegal PI target", piTarget);
+ if (tryRead(TEST_END_PI))
+ piData = null;
+ else
+ {
+ if (!tryWhitespace())
+ error("whitespace required between PI target and data");
+ buf.setLength(0);
+ readUntil(TEST_END_PI);
+ piData = buf.toString();
+ }
+ expandPE = saved;
+ if (inDTD)
+ doctype.addPI(piTarget, piData);
+ }
+
+ /**
+ * Parse an entity reference.
+ */
+ private void readReference()
+ throws IOException, XMLStreamException
+ {
+ buf.setLength(0);
+ String entityName = readNmtoken(true);
+ require(';');
+ buf.setLength(0);
+ buf.append(entityName);
+ }
+
+ /**
+ * Read an CDATA section.
+ */
+ private void readCDSect()
+ throws IOException, XMLStreamException
+ {
+ buf.setLength(0);
+ readUntil(TEST_END_CDATA);
+ }
+
+ /**
+ * Read character data.
+ * @return the type of text read (CHARACTERS or SPACE)
+ */
+ private int readCharData(String prefix)
+ throws IOException, XMLStreamException
+ {
+ boolean white = true;
+ buf.setLength(0);
+ if (prefix != null)
+ buf.append(prefix);
+ boolean done = false;
+ boolean entities = false;
+ while (!done)
+ {
+ // Block read
+ mark(tmpBuf.length);
+ int len = read(tmpBuf, 0, tmpBuf.length);
+ if (len == -1)
+ {
+ if (inputStack.size() > 1)
+ {
+ popInput();
+ // report end-entity
+ done = true;
+ }
+ else
+ throw new EOFException();
+ }
+ for (int i = 0; i < len && !done; i++)
+ {
+ int c = tmpBuf[i];
+ switch (c)
+ {
+ case 0x20:
+ case 0x09:
+ case 0x0a:
+ case 0x0d:
+ buf.append(Character.toChars(c));
+ break; // whitespace
+ case 0x26: // '&'
+ reset();
+ read(tmpBuf, 0, i);
+ // character reference?
+ mark(3);
+ c = readCh(); // &
+ c = readCh();
+ if (c == 0x23) // '#'
+ {
+ mark(1);
+ c = readCh();
+ boolean hex = (c == 0x78); // 'x'
+ if (!hex)
+ reset();
+ char[] ch = readCharacterRef(hex ? 16 : 10);
+ buf.append(ch, 0, ch.length);
+ for (int j = 0; j < ch.length; j++)
+ {
+ switch (ch[j])
+ {
+ case 0x20:
+ case 0x09:
+ case 0x0a:
+ case 0x0d:
+ break; // whitespace
+ default:
+ white = false;
+ }
+ }
+ }
+ else
+ {
+ // entity reference
+ reset();
+ c = readCh(); // &
+ String entityName = readNmtoken(true);
+ require(';');
+ String text =
+ (String) PREDEFINED_ENTITIES.get(entityName);
+ if (text != null)
+ buf.append(text);
+ else
+ {
+ pushInput("", "&" + entityName + ";", false, false);
+ done = true;
+ break;
+ }
+ }
+ // continue processing
+ i = -1;
+ mark(tmpBuf.length);
+ len = read(tmpBuf, 0, tmpBuf.length);
+ if (len == -1)
+ {
+ if (inputStack.size() > 1)
+ {
+ popInput();
+ done = true;
+ }
+ else
+ throw new EOFException();
+ }
+ entities = true;
+ break; // end of text sequence
+ case 0x3e: // '>'
+ int l = buf.length();
+ if (l > 1 &&
+ buf.charAt(l - 1) == ']' &&
+ buf.charAt(l - 2) == ']')
+ error("Character data may not contain unescaped ']]>'");
+ buf.append(Character.toChars(c));
+ break;
+ case 0x3c: // '<'
+ reset();
+ // read i characters
+ int count = 0, remaining = i;
+ do
+ {
+ int r = read(tmpBuf, 0, remaining);
+ count += r;
+ remaining -= r;
+ }
+ while (count < i);
+ i = len;
+ if (coalescing && tryRead(TEST_CDATA))
+ readUntil(TEST_END_CDATA); // read CDATA section into buf
+ else
+ done = true; // end of text sequence
+ break;
+ default:
+ if (input.xml11)
+ {
+ if (!isXML11Char(c) || isXML11RestrictedChar(c))
+ error("illegal XML 1.1 character",
+ "U+" + Integer.toHexString(c));
+ }
+ else if (!isChar(c))
+ error("illegal XML character",
+ "U+" + Integer.toHexString(c));
+ white = false;
+ buf.append(Character.toChars(c));
+ }
+ }
+ // if text buffer >= 2MB, return it as a chunk
+ // to avoid excessive memory use
+ if (buf.length() >= 2097152)
+ done = true;
+ }
+ if (entities)
+ normalizeCRLF(buf);
+ return white ? XMLStreamConstants.SPACE : XMLStreamConstants.CHARACTERS;
+ }
+
+ /**
+ * Expands the specified entity.
+ */
+ private void expandEntity(String name, boolean inAttr, boolean normalize)
+ throws IOException, XMLStreamException
+ {
+ if (doctype != null)
+ {
+ Object value = doctype.getEntity(name);
+ if (value != null)
+ {
+ if (xmlStandalone == Boolean.TRUE)
+ {
+ // VC: Standalone Document Declaration
+ if (doctype.isEntityExternal(name))
+ error("reference to external entity in standalone document");
+ else if (value instanceof ExternalIds)
+ {
+ ExternalIds ids = (ExternalIds) value;
+ if (ids.notationName != null &&
+ doctype.isNotationExternal(ids.notationName))
+ error("reference to external notation in " +
+ "standalone document");
+ }
+ }
+ if (value instanceof String)
+ {
+ String text = (String) value;
+ if (inAttr && text.indexOf('<') != -1)
+ error("< in attribute value");
+ pushInput(name, text, !inAttr, normalize);
+ }
+ else if (inAttr)
+ error("reference to external entity in attribute value", name);
+ else
+ pushInput(name, (ExternalIds) value, !inAttr, normalize);
+ return;
+ }
+ }
+ error("reference to undeclared entity", name);
+ }
+
+ /**
+ * Indicates whether the specified entity is unparsed.
+ */
+ private boolean isUnparsedEntity(String name)
+ {
+ if (doctype != null)
+ {
+ Object value = doctype.getEntity(name);
+ if (value != null && value instanceof ExternalIds)
+ return ((ExternalIds) value).notationName != null;
+ }
+ return false;
+ }
+
+ /**
+ * Read an equals sign.
+ */
+ private void readEq()
+ throws IOException, XMLStreamException
+ {
+ skipWhitespace();
+ require('=');
+ skipWhitespace();
+ }
+
+ /**
+ * Character read for reading literals.
+ * @param recognizePEs whether to recognize parameter-entity references
+ */
+ private int literalReadCh(boolean recognizePEs)
+ throws IOException, XMLStreamException
+ {
+ int c = recognizePEs ? readCh() : read();
+ while (c == -1)
+ {
+ if (inputStack.size() > 1)
+ {
+ inputStack.removeLast();
+ input = (Input) inputStack.getLast();
+ // Don't issue end-entity
+ c = recognizePEs ? readCh() : read();
+ }
+ else
+ throw new EOFException();
+ }
+ return c;
+ }
+
+ /**
+ * Read a string literal.
+ */
+ private String readLiteral(int flags, boolean recognizePEs)
+ throws IOException, XMLStreamException
+ {
+ boolean saved = expandPE;
+ int delim = readCh();
+ if (delim != 0x27 && delim != 0x22)
+ error("expected '\"' or \"'\"", "U+" + Integer.toHexString(delim));
+ literalBuf.setLength(0);
+ if ((flags & LIT_DISABLE_PE) != 0)
+ expandPE = false;
+ boolean entities = false;
+ int inputStackSize = inputStack.size();
+ do
+ {
+ int c = literalReadCh(recognizePEs);
+ if (c == delim && inputStackSize == inputStack.size())
+ break;
+ switch (c)
+ {
+ case 0x0a:
+ case 0x0d:
+ if ((flags & (LIT_ATTRIBUTE | LIT_PUBID)) != 0)
+ c = 0x20; // normalize to space
+ break;
+ case 0x09:
+ if ((flags & LIT_ATTRIBUTE) != 0)
+ c = 0x20; // normalize to space
+ break;
+ case 0x26: // '&'
+ mark(2);
+ c = readCh();
+ if (c == 0x23) // '#'
+ {
+ if ((flags & LIT_DISABLE_CREF) != 0)
+ {
+ reset();
+ c = 0x26; // '&'
+ }
+ else
+ {
+ mark(1);
+ c = readCh();
+ boolean hex = (c == 0x78); // 'x'
+ if (!hex)
+ reset();
+ char[] ref = readCharacterRef(hex ? 16 : 10);
+ for (int i = 0; i < ref.length; i++)
+ literalBuf.append(ref[i]);
+ entities = true;
+ continue;
+ }
+ }
+ else
+ {
+ if ((flags & LIT_DISABLE_EREF) != 0)
+ {
+ reset();
+ c = 0x26; // '&'
+ }
+ else
+ {
+ reset();
+ String entityName = readNmtoken(true);
+ require(';');
+ String text =
+ (String) PREDEFINED_ENTITIES.get(entityName);
+ if (text != null)
+ literalBuf.append(text);
+ else
+ expandEntity(entityName,
+ (flags & LIT_ATTRIBUTE) != 0,
+ true);
+ entities = true;
+ continue;
+ }
+ }
+ break;
+ case 0x3c: // '<'
+ if ((flags & LIT_ATTRIBUTE) != 0)
+ error("attribute values may not contain '<'");
+ break;
+ case -1:
+ if (inputStack.size() > 1)
+ {
+ popInput();
+ continue;
+ }
+ throw new EOFException();
+ default:
+ if ((c < 0x0020 || c > 0xfffd) ||
+ (c >= 0xd800 && c < 0xdc00) ||
+ (input.xml11 && (c >= 0x007f) &&
+ (c <= 0x009f) && (c != 0x0085)))
+ error("illegal character", "U+" + Integer.toHexString(c));
+ }
+ literalBuf.append(Character.toChars(c));
+ }
+ while (true);
+ expandPE = saved;
+ if (entities)
+ normalizeCRLF(literalBuf);
+ if ((flags & LIT_NORMALIZE) > 0)
+ literalBuf = normalize(literalBuf);
+ return literalBuf.toString();
+ }
+
+ /**
+ * Performs attribute-value normalization of the text buffer.
+ * This discards leading and trailing whitespace, and replaces sequences
+ * of whitespace with a single space.
+ */
+ private StringBuffer normalize(StringBuffer buf)
+ {
+ StringBuffer acc = new StringBuffer();
+ int len = buf.length();
+ int avState = 0;
+ for (int i = 0; i < len; i++)
+ {
+ char c = buf.charAt(i);
+ if (c == ' ')
+ avState = (avState == 0) ? 0 : 1;
+ else
+ {
+ if (avState == 1)
+ acc.append(' ');
+ acc.append(c);
+ avState = 2;
+ }
+ }
+ return acc;
+ }
+
+ /**
+ * Replace any CR/LF pairs in the buffer with LF.
+ * This may be necessary if combinations of CR or LF were declared as
+ * (character) entity references in the input.
+ */
+ private void normalizeCRLF(StringBuffer buf)
+ {
+ int len = buf.length() - 1;
+ for (int i = 0; i < len; i++)
+ {
+ char c = buf.charAt(i);
+ if (c == '\r' && buf.charAt(i + 1) == '\n')
+ {
+ buf.deleteCharAt(i--);
+ len--;
+ }
+ }
+ }
+
+ /**
+ * Parse and expand a parameter entity reference.
+ */
+ private void expandPEReference()
+ throws IOException, XMLStreamException
+ {
+ String name = readNmtoken(true, new StringBuffer());
+ require(';');
+ mark(1); // ensure we don't reset to before the semicolon
+ if (doctype != null)
+ {
+ String entityName = "%" + name;
+ Object entity = doctype.getEntity(entityName);
+ if (entity != null)
+ {
+ if (xmlStandalone == Boolean.TRUE)
+ {
+ if (doctype.isEntityExternal(entityName))
+ error("reference to external parameter entity in " +
+ "standalone document");
+ }
+ if (entity instanceof String)
+ {
+ pushInput(name, (String) entity, false, input.normalize);
+ //pushInput(name, " " + (String) entity + " ");
+ }
+ else
+ {
+ //pushInput("", " ");
+ pushInput(name, (ExternalIds) entity, false, input.normalize);
+ //pushInput("", " ");
+ }
+ }
+ else
+ error("reference to undeclared parameter entity", name);
+ }
+ else
+ error("reference to parameter entity without doctype", name);
+ }
+
+ /**
+ * Parse the digits in a character reference.
+ * @param base the base of the digits (10 or 16)
+ */
+ private char[] readCharacterRef(int base)
+ throws IOException, XMLStreamException
+ {
+ CPStringBuilder b = new CPStringBuilder();
+ for (int c = readCh(); c != 0x3b && c != -1; c = readCh())
+ b.append(Character.toChars(c));
+ try
+ {
+ int ord = Integer.parseInt(b.toString(), base);
+ if (input.xml11)
+ {
+ if (!isXML11Char(ord))
+ error("illegal XML 1.1 character reference " +
+ "U+" + Integer.toHexString(ord));
+ }
+ else
+ {
+ if ((ord < 0x20 && !(ord == 0x0a || ord == 0x09 || ord == 0x0d))
+ || (ord >= 0xd800 && ord <= 0xdfff)
+ || ord == 0xfffe || ord == 0xffff
+ || ord > 0x0010ffff)
+ error("illegal XML character reference " +
+ "U+" + Integer.toHexString(ord));
+ }
+ return Character.toChars(ord);
+ }
+ catch (NumberFormatException e)
+ {
+ error("illegal characters in character reference", b.toString());
+ return null;
+ }
+ }
+
+ /**
+ * Parses an NMTOKEN or Name production.
+ * @param isName if a Name, otherwise an NMTOKEN
+ */
+ private String readNmtoken(boolean isName)
+ throws IOException, XMLStreamException
+ {
+ return readNmtoken(isName, nmtokenBuf);
+ }
+
+ /**
+ * Parses an NMTOKEN or Name production using the specified buffer.
+ * @param isName if a Name, otherwise an NMTOKEN
+ * @param buf the character buffer to use
+ */
+ private String readNmtoken(boolean isName, StringBuffer buf)
+ throws IOException, XMLStreamException
+ {
+ buf.setLength(0);
+ int c = readCh();
+ if (isName)
+ {
+ if (!isNameStartCharacter(c, input.xml11))
+ error("not a name start character",
+ "U+" + Integer.toHexString(c));
+ }
+ else
+ {
+ if (!isNameCharacter(c, input.xml11))
+ error("not a name character",
+ "U+" + Integer.toHexString(c));
+ }
+ buf.append(Character.toChars(c));
+ do
+ {
+ mark(1);
+ c = readCh();
+ switch (c)
+ {
+ case 0x25: // '%'
+ case 0x3c: // '<'
+ case 0x3e: // '>'
+ case 0x26: // '&'
+ case 0x2c: // ','
+ case 0x7c: // '|'
+ case 0x2a: // '*'
+ case 0x2b: // '+'
+ case 0x3f: // '?'
+ case 0x29: // ')'
+ case 0x3d: // '='
+ case 0x27: // '\''
+ case 0x22: // '"'
+ case 0x5b: // '['
+ case 0x20: // ' '
+ case 0x09: // '\t'
+ case 0x0a: // '\n'
+ case 0x0d: // '\r'
+ case 0x3b: // ';'
+ case 0x2f: // '/'
+ case -1:
+ reset();
+ return intern(buf.toString());
+ default:
+ if (!isNameCharacter(c, input.xml11))
+ error("not a name character",
+ "U+" + Integer.toHexString(c));
+ else
+ buf.append(Character.toChars(c));
+ }
+ }
+ while (true);
+ }
+
+ /**
+ * Indicates whether the specified Unicode character is an XML 1.1 Char.
+ */
+ public static boolean isXML11Char(int c)
+ {
+ return ((c >= 0x0001 && c <= 0xD7FF) ||
+ (c >= 0xE000 && c < 0xFFFE) ||
+ (c >= 0x10000 && c <= 0x10FFFF));
+ }
+
+ /**
+ * Indicates whether the specified Unicode character is an XML 1.1
+ * RestrictedChar.
+ */
+ public static boolean isXML11RestrictedChar(int c)
+ {
+ return ((c >= 0x0001 && c <= 0x0008) ||
+ (c >= 0x000B && c <= 0x000C) ||
+ (c >= 0x000E && c <= 0x001F) ||
+ (c >= 0x007F && c <= 0x0084) ||
+ (c >= 0x0086 && c <= 0x009F));
+ }
+
+ /**
+ * Indicates whether the specified text matches the Name or Nmtoken
+ * production.
+ */
+ private boolean isNmtoken(String text, boolean isName)
+ {
+ try
+ {
+ int[] cp = UnicodeReader.toCodePointArray(text);
+ if (cp.length == 0)
+ return false;
+ if (isName)
+ {
+ if (!isNameStartCharacter(cp[0], input.xml11))
+ return false;
+ }
+ else
+ {
+ if (!isNameCharacter(cp[0], input.xml11))
+ return false;
+ }
+ for (int i = 1; i < cp.length; i++)
+ {
+ if (!isNameCharacter(cp[i], input.xml11))
+ return false;
+ }
+ return true;
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Indicates whether the specified Unicode character is a Name start
+ * character.
+ */
+ public static boolean isNameStartCharacter(int c, boolean xml11)
+ {
+ if (xml11)
+ return ((c >= 0x0041 && c <= 0x005a) ||
+ (c >= 0x0061 && c <= 0x007a) ||
+ c == 0x3a |
+ c == 0x5f |
+ (c >= 0xC0 && c <= 0xD6) ||
+ (c >= 0xD8 && c <= 0xF6) ||
+ (c >= 0xF8 && c <= 0x2FF) ||
+ (c >= 0x370 && c <= 0x37D) ||
+ (c >= 0x37F && c <= 0x1FFF) ||
+ (c >= 0x200C && c <= 0x200D) ||
+ (c >= 0x2070 && c <= 0x218F) ||
+ (c >= 0x2C00 && c <= 0x2FEF) ||
+ (c >= 0x3001 && c <= 0xD7FF) ||
+ (c >= 0xF900 && c <= 0xFDCF) ||
+ (c >= 0xFDF0 && c <= 0xFFFD) ||
+ (c >= 0x10000 && c <= 0xEFFFF));
+ else
+ return (c == 0x5f || c == 0x3a || isLetter(c));
+ }
+
+ /**
+ * Indicates whether the specified Unicode character is a Name non-initial
+ * character.
+ */
+ public static boolean isNameCharacter(int c, boolean xml11)
+ {
+ if (xml11)
+ return ((c >= 0x0041 && c <= 0x005a) ||
+ (c >= 0x0061 && c <= 0x007a) ||
+ (c >= 0x0030 && c <= 0x0039) ||
+ c == 0x3a |
+ c == 0x5f |
+ c == 0x2d |
+ c == 0x2e |
+ c == 0xB7 |
+ (c >= 0xC0 && c <= 0xD6) ||
+ (c >= 0xD8 && c <= 0xF6) ||
+ (c >= 0xF8 && c <= 0x2FF) ||
+ (c >= 0x300 && c <= 0x37D) ||
+ (c >= 0x37F && c <= 0x1FFF) ||
+ (c >= 0x200C && c <= 0x200D) ||
+ (c >= 0x203F && c <= 0x2040) ||
+ (c >= 0x2070 && c <= 0x218F) ||
+ (c >= 0x2C00 && c <= 0x2FEF) ||
+ (c >= 0x3001 && c <= 0xD7FF) ||
+ (c >= 0xF900 && c <= 0xFDCF) ||
+ (c >= 0xFDF0 && c <= 0xFFFD) ||
+ (c >= 0x10000 && c <= 0xEFFFF));
+ else
+ return (c == 0x2e || c == 0x2d || c == 0x5f || c == 0x3a ||
+ isLetter(c) || isDigit(c) ||
+ isCombiningChar(c) || isExtender(c));
+ }
+
+ /**
+ * Indicates whether the specified Unicode character matches the Letter
+ * production.
+ */
+ public static boolean isLetter(int c)
+ {
+ if ((c >= 0x0041 && c <= 0x005A) ||
+ (c >= 0x0061 && c <= 0x007A) ||
+ (c >= 0x00C0 && c <= 0x00D6) ||
+ (c >= 0x00D8 && c <= 0x00F6) ||
+ (c >= 0x00F8 && c <= 0x00FF) ||
+ (c >= 0x0100 && c <= 0x0131) ||
+ (c >= 0x0134 && c <= 0x013E) ||
+ (c >= 0x0141 && c <= 0x0148) ||
+ (c >= 0x014A && c <= 0x017E) ||
+ (c >= 0x0180 && c <= 0x01C3) ||
+ (c >= 0x01CD && c <= 0x01F0) ||
+ (c >= 0x01F4 && c <= 0x01F5) ||
+ (c >= 0x01FA && c <= 0x0217) ||
+ (c >= 0x0250 && c <= 0x02A8) ||
+ (c >= 0x02BB && c <= 0x02C1) ||
+ c == 0x0386 ||
+ (c >= 0x0388 && c <= 0x038A) ||
+ c == 0x038C ||
+ (c >= 0x038E && c <= 0x03A1) ||
+ (c >= 0x03A3 && c <= 0x03CE) ||
+ (c >= 0x03D0 && c <= 0x03D6) ||
+ c == 0x03DA ||
+ c == 0x03DC ||
+ c == 0x03DE ||
+ c == 0x03E0 ||
+ (c >= 0x03E2 && c <= 0x03F3) ||
+ (c >= 0x0401 && c <= 0x040C) ||
+ (c >= 0x040E && c <= 0x044F) ||
+ (c >= 0x0451 && c <= 0x045C) ||
+ (c >= 0x045E && c <= 0x0481) ||
+ (c >= 0x0490 && c <= 0x04C4) ||
+ (c >= 0x04C7 && c <= 0x04C8) ||
+ (c >= 0x04CB && c <= 0x04CC) ||
+ (c >= 0x04D0 && c <= 0x04EB) ||
+ (c >= 0x04EE && c <= 0x04F5) ||
+ (c >= 0x04F8 && c <= 0x04F9) ||
+ (c >= 0x0531 && c <= 0x0556) ||
+ c == 0x0559 ||
+ (c >= 0x0561 && c <= 0x0586) ||
+ (c >= 0x05D0 && c <= 0x05EA) ||
+ (c >= 0x05F0 && c <= 0x05F2) ||
+ (c >= 0x0621 && c <= 0x063A) ||
+ (c >= 0x0641 && c <= 0x064A) ||
+ (c >= 0x0671 && c <= 0x06B7) ||
+ (c >= 0x06BA && c <= 0x06BE) ||
+ (c >= 0x06C0 && c <= 0x06CE) ||
+ (c >= 0x06D0 && c <= 0x06D3) ||
+ c == 0x06D5 ||
+ (c >= 0x06E5 && c <= 0x06E6) ||
+ (c >= 0x0905 && c <= 0x0939) ||
+ c == 0x093D ||
+ (c >= 0x0958 && c <= 0x0961) ||
+ (c >= 0x0985 && c <= 0x098C) ||
+ (c >= 0x098F && c <= 0x0990) ||
+ (c >= 0x0993 && c <= 0x09A8) ||
+ (c >= 0x09AA && c <= 0x09B0) ||
+ c == 0x09B2 ||
+ (c >= 0x09B6 && c <= 0x09B9) ||
+ (c >= 0x09DC && c <= 0x09DD) ||
+ (c >= 0x09DF && c <= 0x09E1) ||
+ (c >= 0x09F0 && c <= 0x09F1) ||
+ (c >= 0x0A05 && c <= 0x0A0A) ||
+ (c >= 0x0A0F && c <= 0x0A10) ||
+ (c >= 0x0A13 && c <= 0x0A28) ||
+ (c >= 0x0A2A && c <= 0x0A30) ||
+ (c >= 0x0A32 && c <= 0x0A33) ||
+ (c >= 0x0A35 && c <= 0x0A36) ||
+ (c >= 0x0A38 && c <= 0x0A39) ||
+ (c >= 0x0A59 && c <= 0x0A5C) ||
+ c == 0x0A5E ||
+ (c >= 0x0A72 && c <= 0x0A74) ||
+ (c >= 0x0A85 && c <= 0x0A8B) ||
+ c == 0x0A8D ||
+ (c >= 0x0A8F && c <= 0x0A91) ||
+ (c >= 0x0A93 && c <= 0x0AA8) ||
+ (c >= 0x0AAA && c <= 0x0AB0) ||
+ (c >= 0x0AB2 && c <= 0x0AB3) ||
+ (c >= 0x0AB5 && c <= 0x0AB9) ||
+ c == 0x0ABD ||
+ c == 0x0AE0 ||
+ (c >= 0x0B05 && c <= 0x0B0C) ||
+ (c >= 0x0B0F && c <= 0x0B10) ||
+ (c >= 0x0B13 && c <= 0x0B28) ||
+ (c >= 0x0B2A && c <= 0x0B30) ||
+ (c >= 0x0B32 && c <= 0x0B33) ||
+ (c >= 0x0B36 && c <= 0x0B39) ||
+ c == 0x0B3D ||
+ (c >= 0x0B5C && c <= 0x0B5D) ||
+ (c >= 0x0B5F && c <= 0x0B61) ||
+ (c >= 0x0B85 && c <= 0x0B8A) ||
+ (c >= 0x0B8E && c <= 0x0B90) ||
+ (c >= 0x0B92 && c <= 0x0B95) ||
+ (c >= 0x0B99 && c <= 0x0B9A) ||
+ c == 0x0B9C ||
+ (c >= 0x0B9E && c <= 0x0B9F) ||
+ (c >= 0x0BA3 && c <= 0x0BA4) ||
+ (c >= 0x0BA8 && c <= 0x0BAA) ||
+ (c >= 0x0BAE && c <= 0x0BB5) ||
+ (c >= 0x0BB7 && c <= 0x0BB9) ||
+ (c >= 0x0C05 && c <= 0x0C0C) ||
+ (c >= 0x0C0E && c <= 0x0C10) ||
+ (c >= 0x0C12 && c <= 0x0C28) ||
+ (c >= 0x0C2A && c <= 0x0C33) ||
+ (c >= 0x0C35 && c <= 0x0C39) ||
+ (c >= 0x0C60 && c <= 0x0C61) ||
+ (c >= 0x0C85 && c <= 0x0C8C) ||
+ (c >= 0x0C8E && c <= 0x0C90) ||
+ (c >= 0x0C92 && c <= 0x0CA8) ||
+ (c >= 0x0CAA && c <= 0x0CB3) ||
+ (c >= 0x0CB5 && c <= 0x0CB9) ||
+ c == 0x0CDE ||
+ (c >= 0x0CE0 && c <= 0x0CE1) ||
+ (c >= 0x0D05 && c <= 0x0D0C) ||
+ (c >= 0x0D0E && c <= 0x0D10) ||
+ (c >= 0x0D12 && c <= 0x0D28) ||
+ (c >= 0x0D2A && c <= 0x0D39) ||
+ (c >= 0x0D60 && c <= 0x0D61) ||
+ (c >= 0x0E01 && c <= 0x0E2E) ||
+ c == 0x0E30 ||
+ (c >= 0x0E32 && c <= 0x0E33) ||
+ (c >= 0x0E40 && c <= 0x0E45) ||
+ (c >= 0x0E81 && c <= 0x0E82) ||
+ c == 0x0E84 ||
+ (c >= 0x0E87 && c <= 0x0E88) ||
+ c == 0x0E8A ||
+ c == 0x0E8D ||
+ (c >= 0x0E94 && c <= 0x0E97) ||
+ (c >= 0x0E99 && c <= 0x0E9F) ||
+ (c >= 0x0EA1 && c <= 0x0EA3) ||
+ c == 0x0EA5 ||
+ c == 0x0EA7 ||
+ (c >= 0x0EAA && c <= 0x0EAB) ||
+ (c >= 0x0EAD && c <= 0x0EAE) ||
+ c == 0x0EB0 ||
+ (c >= 0x0EB2 && c <= 0x0EB3) ||
+ c == 0x0EBD ||
+ (c >= 0x0EC0 && c <= 0x0EC4) ||
+ (c >= 0x0F40 && c <= 0x0F47) ||
+ (c >= 0x0F49 && c <= 0x0F69) ||
+ (c >= 0x10A0 && c <= 0x10C5) ||
+ (c >= 0x10D0 && c <= 0x10F6) ||
+ c == 0x1100 ||
+ (c >= 0x1102 && c <= 0x1103) ||
+ (c >= 0x1105 && c <= 0x1107) ||
+ c == 0x1109 ||
+ (c >= 0x110B && c <= 0x110C) ||
+ (c >= 0x110E && c <= 0x1112) ||
+ c == 0x113C ||
+ c == 0x113E ||
+ c == 0x1140 ||
+ c == 0x114C ||
+ c == 0x114E ||
+ c == 0x1150 ||
+ (c >= 0x1154 && c <= 0x1155) ||
+ c == 0x1159 ||
+ (c >= 0x115F && c <= 0x1161) ||
+ c == 0x1163 ||
+ c == 0x1165 ||
+ c == 0x1167 ||
+ c == 0x1169 ||
+ (c >= 0x116D && c <= 0x116E) ||
+ (c >= 0x1172 && c <= 0x1173) ||
+ c == 0x1175 ||
+ c == 0x119E ||
+ c == 0x11A8 ||
+ c == 0x11AB ||
+ (c >= 0x11AE && c <= 0x11AF) ||
+ (c >= 0x11B7 && c <= 0x11B8) ||
+ c == 0x11BA ||
+ (c >= 0x11BC && c <= 0x11C2) ||
+ c == 0x11EB ||
+ c == 0x11F0 ||
+ c == 0x11F9 ||
+ (c >= 0x1E00 && c <= 0x1E9B) ||
+ (c >= 0x1EA0 && c <= 0x1EF9) ||
+ (c >= 0x1F00 && c <= 0x1F15) ||
+ (c >= 0x1F18 && c <= 0x1F1D) ||
+ (c >= 0x1F20 && c <= 0x1F45) ||
+ (c >= 0x1F48 && c <= 0x1F4D) ||
+ (c >= 0x1F50 && c <= 0x1F57) ||
+ c == 0x1F59 ||
+ c == 0x1F5B ||
+ c == 0x1F5D ||
+ (c >= 0x1F5F && c <= 0x1F7D) ||
+ (c >= 0x1F80 && c <= 0x1FB4) ||
+ (c >= 0x1FB6 && c <= 0x1FBC) ||
+ c == 0x1FBE ||
+ (c >= 0x1FC2 && c <= 0x1FC4) ||
+ (c >= 0x1FC6 && c <= 0x1FCC) ||
+ (c >= 0x1FD0 && c <= 0x1FD3) ||
+ (c >= 0x1FD6 && c <= 0x1FDB) ||
+ (c >= 0x1FE0 && c <= 0x1FEC) ||
+ (c >= 0x1FF2 && c <= 0x1FF4) ||
+ (c >= 0x1FF6 && c <= 0x1FFC) ||
+ c == 0x2126 ||
+ (c >= 0x212A && c <= 0x212B) ||
+ c == 0x212E ||
+ (c >= 0x2180 && c <= 0x2182) ||
+ (c >= 0x3041 && c <= 0x3094) ||
+ (c >= 0x30A1 && c <= 0x30FA) ||
+ (c >= 0x3105 && c <= 0x312C) ||
+ (c >= 0xAC00 && c <= 0xD7A3))
+ return true; // BaseChar
+ if ((c >= 0x4e00 && c <= 0x9fa5) ||
+ c == 0x3007 ||
+ (c >= 0x3021 && c <= 0x3029))
+ return true; // Ideographic
+ return false;
+ }
+
+ /**
+ * Indicates whether the specified Unicode character matches the Digit
+ * production.
+ */
+ public static boolean isDigit(int c)
+ {
+ return ((c >= 0x0030 && c <= 0x0039) ||
+ (c >= 0x0660 && c <= 0x0669) ||
+ (c >= 0x06F0 && c <= 0x06F9) ||
+ (c >= 0x0966 && c <= 0x096F) ||
+ (c >= 0x09E6 && c <= 0x09EF) ||
+ (c >= 0x0A66 && c <= 0x0A6F) ||
+ (c >= 0x0AE6 && c <= 0x0AEF) ||
+ (c >= 0x0B66 && c <= 0x0B6F) ||
+ (c >= 0x0BE7 && c <= 0x0BEF) ||
+ (c >= 0x0C66 && c <= 0x0C6F) ||
+ (c >= 0x0CE6 && c <= 0x0CEF) ||
+ (c >= 0x0D66 && c <= 0x0D6F) ||
+ (c >= 0x0E50 && c <= 0x0E59) ||
+ (c >= 0x0ED0 && c <= 0x0ED9) ||
+ (c >= 0x0F20 && c <= 0x0F29));
+ }
+
+ /**
+ * Indicates whether the specified Unicode character matches the
+ * CombiningChar production.
+ */
+ public static boolean isCombiningChar(int c)
+ {
+ return ((c >= 0x0300 && c <= 0x0345) ||
+ (c >= 0x0360 && c <= 0x0361) ||
+ (c >= 0x0483 && c <= 0x0486) ||
+ (c >= 0x0591 && c <= 0x05A1) ||
+ (c >= 0x05A3 && c <= 0x05B9) ||
+ (c >= 0x05BB && c <= 0x05BD) ||
+ c == 0x05BF ||
+ (c >= 0x05C1 && c <= 0x05C2) ||
+ c == 0x05C4 ||
+ (c >= 0x064B && c <= 0x0652) ||
+ c == 0x0670 ||
+ (c >= 0x06D6 && c <= 0x06DC) ||
+ (c >= 0x06DD && c <= 0x06DF) ||
+ (c >= 0x06E0 && c <= 0x06E4) ||
+ (c >= 0x06E7 && c <= 0x06E8) ||
+ (c >= 0x06EA && c <= 0x06ED) ||
+ (c >= 0x0901 && c <= 0x0903) ||
+ c == 0x093C ||
+ (c >= 0x093E && c <= 0x094C) ||
+ c == 0x094D ||
+ (c >= 0x0951 && c <= 0x0954) ||
+ (c >= 0x0962 && c <= 0x0963) ||
+ (c >= 0x0981 && c <= 0x0983) ||
+ c == 0x09BC ||
+ c == 0x09BE ||
+ c == 0x09BF ||
+ (c >= 0x09C0 && c <= 0x09C4) ||
+ (c >= 0x09C7 && c <= 0x09C8) ||
+ (c >= 0x09CB && c <= 0x09CD) ||
+ c == 0x09D7 ||
+ (c >= 0x09E2 && c <= 0x09E3) ||
+ c == 0x0A02 ||
+ c == 0x0A3C ||
+ c == 0x0A3E ||
+ c == 0x0A3F ||
+ (c >= 0x0A40 && c <= 0x0A42) ||
+ (c >= 0x0A47 && c <= 0x0A48) ||
+ (c >= 0x0A4B && c <= 0x0A4D) ||
+ (c >= 0x0A70 && c <= 0x0A71) ||
+ (c >= 0x0A81 && c <= 0x0A83) ||
+ c == 0x0ABC ||
+ (c >= 0x0ABE && c <= 0x0AC5) ||
+ (c >= 0x0AC7 && c <= 0x0AC9) ||
+ (c >= 0x0ACB && c <= 0x0ACD) ||
+ (c >= 0x0B01 && c <= 0x0B03) ||
+ c == 0x0B3C ||
+ (c >= 0x0B3E && c <= 0x0B43) ||
+ (c >= 0x0B47 && c <= 0x0B48) ||
+ (c >= 0x0B4B && c <= 0x0B4D) ||
+ (c >= 0x0B56 && c <= 0x0B57) ||
+ (c >= 0x0B82 && c <= 0x0B83) ||
+ (c >= 0x0BBE && c <= 0x0BC2) ||
+ (c >= 0x0BC6 && c <= 0x0BC8) ||
+ (c >= 0x0BCA && c <= 0x0BCD) ||
+ c == 0x0BD7 ||
+ (c >= 0x0C01 && c <= 0x0C03) ||
+ (c >= 0x0C3E && c <= 0x0C44) ||
+ (c >= 0x0C46 && c <= 0x0C48) ||
+ (c >= 0x0C4A && c <= 0x0C4D) ||
+ (c >= 0x0C55 && c <= 0x0C56) ||
+ (c >= 0x0C82 && c <= 0x0C83) ||
+ (c >= 0x0CBE && c <= 0x0CC4) ||
+ (c >= 0x0CC6 && c <= 0x0CC8) ||
+ (c >= 0x0CCA && c <= 0x0CCD) ||
+ (c >= 0x0CD5 && c <= 0x0CD6) ||
+ (c >= 0x0D02 && c <= 0x0D03) ||
+ (c >= 0x0D3E && c <= 0x0D43) ||
+ (c >= 0x0D46 && c <= 0x0D48) ||
+ (c >= 0x0D4A && c <= 0x0D4D) ||
+ c == 0x0D57 ||
+ c == 0x0E31 ||
+ (c >= 0x0E34 && c <= 0x0E3A) ||
+ (c >= 0x0E47 && c <= 0x0E4E) ||
+ c == 0x0EB1 ||
+ (c >= 0x0EB4 && c <= 0x0EB9) ||
+ (c >= 0x0EBB && c <= 0x0EBC) ||
+ (c >= 0x0EC8 && c <= 0x0ECD) ||
+ (c >= 0x0F18 && c <= 0x0F19) ||
+ c == 0x0F35 ||
+ c == 0x0F37 ||
+ c == 0x0F39 ||
+ c == 0x0F3E ||
+ c == 0x0F3F ||
+ (c >= 0x0F71 && c <= 0x0F84) ||
+ (c >= 0x0F86 && c <= 0x0F8B) ||
+ (c >= 0x0F90 && c <= 0x0F95) ||
+ c == 0x0F97 ||
+ (c >= 0x0F99 && c <= 0x0FAD) ||
+ (c >= 0x0FB1 && c <= 0x0FB7) ||
+ c == 0x0FB9 ||
+ (c >= 0x20D0 && c <= 0x20DC) ||
+ c == 0x20E1 ||
+ (c >= 0x302A && c <= 0x302F) ||
+ c == 0x3099 ||
+ c == 0x309A);
+ }
+
+ /**
+ * Indicates whether the specified Unicode character matches the Extender
+ * production.
+ */
+ public static boolean isExtender(int c)
+ {
+ return (c == 0x00B7 ||
+ c == 0x02D0 ||
+ c == 0x02D1 ||
+ c == 0x0387 ||
+ c == 0x0640 ||
+ c == 0x0E46 ||
+ c == 0x0EC6 ||
+ c == 0x3005 ||
+ (c >= 0x3031 && c <= 0x3035) ||
+ (c >= 0x309D && c <= 0x309E) ||
+ (c >= 0x30FC && c <= 0x30FE));
+ }
+
+ /**
+ * Indicates whether the specified Unicode character matches the Char
+ * production.
+ */
+ public static boolean isChar(int c)
+ {
+ return (c >= 0x20 && c < 0xd800) ||
+ (c >= 0xe00 && c < 0xfffe) ||
+ (c >= 0x10000 && c < 0x110000) ||
+ c == 0xa || c == 0x9 || c == 0xd;
+ }
+
+ /**
+ * Interns the specified text or not, depending on the value of
+ * stringInterning.
+ */
+ private String intern(String text)
+ {
+ return stringInterning ? text.intern() : text;
+ }
+
+ /**
+ * Report a parsing error.
+ */
+ private void error(String message)
+ throws XMLStreamException
+ {
+ error(message, null);
+ }
+
+ /**
+ * Report a parsing error.
+ */
+ private void error(String message, Object info)
+ throws XMLStreamException
+ {
+ if (info != null)
+ {
+ if (info instanceof String)
+ message += ": \"" + ((String) info) + "\"";
+ else if (info instanceof Character)
+ message += ": '" + ((Character) info) + "'";
+ }
+ throw new XMLStreamException(message);
+ }
+
+ /**
+ * Perform validation of a start-element event.
+ */
+ private void validateStartElement(String elementName)
+ throws XMLStreamException
+ {
+ if (currentContentModel == null)
+ {
+ // root element
+ // VC: Root Element Type
+ if (!elementName.equals(doctype.rootName))
+ error("root element name must match name in DTD");
+ return;
+ }
+ // VC: Element Valid
+ switch (currentContentModel.type)
+ {
+ case ContentModel.EMPTY:
+ error("child element found in empty element", elementName);
+ break;
+ case ContentModel.ELEMENT:
+ LinkedList ctx = (LinkedList) validationStack.getLast();
+ ctx.add(elementName);
+ break;
+ case ContentModel.MIXED:
+ MixedContentModel mm = (MixedContentModel) currentContentModel;
+ if (!mm.containsName(elementName))
+ error("illegal element for content model", elementName);
+ break;
+ }
+ }
+
+ /**
+ * Perform validation of an end-element event.
+ */
+ private void validateEndElement()
+ throws XMLStreamException
+ {
+ if (currentContentModel == null)
+ {
+ // root element
+ // VC: IDREF
+ if (!idrefs.containsAll(ids))
+ error("IDREF values must match the value of some ID attribute");
+ return;
+ }
+ // VC: Element Valid
+ switch (currentContentModel.type)
+ {
+ case ContentModel.ELEMENT:
+ LinkedList ctx = (LinkedList) validationStack.getLast();
+ ElementContentModel ecm = (ElementContentModel) currentContentModel;
+ validateElementContent(ecm, ctx);
+ break;
+ }
+ }
+
+ /**
+ * Perform validation of character data.
+ */
+ private void validatePCData(String text)
+ throws XMLStreamException
+ {
+ // VC: Element Valid
+ switch (currentContentModel.type)
+ {
+ case ContentModel.EMPTY:
+ error("character data found in empty element", text);
+ break;
+ case ContentModel.ELEMENT:
+ boolean white = true;
+ int len = text.length();
+ for (int i = 0; i < len; i++)
+ {
+ char c = text.charAt(i);
+ if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
+ {
+ white = false;
+ break;
+ }
+ }
+ if (!white)
+ error("character data found in element with element content", text);
+ else if (xmlStandalone == Boolean.TRUE && currentContentModel.external)
+ // VC: Standalone Document Declaration
+ error("whitespace in element content of externally declared " +
+ "element in standalone document");
+ break;
+ }
+ }
+
+ /**
+ * Validates the specified validation context (list of child elements)
+ * against the element content model for the current element.
+ */
+ private void validateElementContent(ElementContentModel model,
+ LinkedList children)
+ throws XMLStreamException
+ {
+ // Use regular expression
+ CPStringBuilder buf = new CPStringBuilder();
+ for (Iterator i = children.iterator(); i.hasNext(); )
+ {
+ buf.append((String) i.next());
+ buf.append(' ');
+ }
+ String c = buf.toString();
+ String regex = createRegularExpression(model);
+ if (!c.matches(regex))
+ error("element content "+model.text+" does not match expression "+regex, c);
+ }
+
+ /**
+ * Creates the regular expression used to validate an element content
+ * model.
+ */
+ private String createRegularExpression(ElementContentModel model)
+ {
+ if (model.regex == null)
+ {
+ CPStringBuilder buf = new CPStringBuilder();
+ buf.append('(');
+ for (Iterator i = model.contentParticles.iterator(); i.hasNext(); )
+ {
+ ContentParticle cp = (ContentParticle) i.next();
+ if (cp.content instanceof String)
+ {
+ buf.append('(');
+ buf.append((String) cp.content);
+ buf.append(' ');
+ buf.append(')');
+ if (cp.max == -1)
+ {
+ if (cp.min == 0)
+ buf.append('*');
+ else
+ buf.append('+');
+ }
+ else if (cp.min == 0)
+ buf.append('?');
+ }
+ else
+ {
+ ElementContentModel ecm = (ElementContentModel) cp.content;
+ buf.append(createRegularExpression(ecm));
+ }
+ if (model.or && i.hasNext())
+ buf.append('|');
+ }
+ buf.append(')');
+ if (model.max == -1)
+ {
+ if (model.min == 0)
+ buf.append('*');
+ else
+ buf.append('+');
+ }
+ else if (model.min == 0)
+ buf.append('?');
+ model.regex = buf.toString();
+ }
+ return model.regex;
+ }
+
+ /**
+ * Performs validation of a document type declaration event.
+ */
+ void validateDoctype()
+ throws XMLStreamException
+ {
+ for (Iterator i = doctype.entityIterator(); i.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ Object entity = entry.getValue();
+ if (entity instanceof ExternalIds)
+ {
+ ExternalIds ids = (ExternalIds) entity;
+ if (ids.notationName != null)
+ {
+ // VC: Notation Declared
+ ExternalIds notation = doctype.getNotation(ids.notationName);
+ if (notation == null)
+ error("Notation name must match the declared name of a " +
+ "notation", ids.notationName);
+ }
+ }
+ }
+ }
+
+ /**
+ * Simple test harness for reading an XML file.
+ * args[0] is the filename of the XML file
+ * If args[1] is "-x", enable XInclude processing
+ */
+ public static void main(String[] args)
+ throws Exception
+ {
+ boolean validating = false;
+ boolean namespaceAware = false;
+ boolean xIncludeAware = false;
+ int pos = 0;
+ while (pos < args.length && args[pos].startsWith("-"))
+ {
+ if ("-x".equals(args[pos]))
+ xIncludeAware = true;
+ else if ("-v".equals(args[pos]))
+ validating = true;
+ else if ("-n".equals(args[pos]))
+ namespaceAware = true;
+ pos++;
+ }
+ if (pos >= args.length)
+ {
+ System.out.println("Syntax: XMLParser [-n] [-v] [-x] <file> [<file2> [...]]");
+ System.out.println("\t-n: use namespace aware mode");
+ System.out.println("\t-v: use validating parser");
+ System.out.println("\t-x: use XInclude aware mode");
+ System.exit(2);
+ }
+ while (pos < args.length)
+ {
+ XMLParser p = new XMLParser(new java.io.FileInputStream(args[pos]),
+ absolutize(null, args[pos]),
+ validating, // validating
+ namespaceAware, // namespaceAware
+ true, // coalescing,
+ true, // replaceERefs
+ true, // externalEntities
+ true, // supportDTD
+ true, // baseAware
+ true, // stringInterning
+ true, // extendedEventTypes
+ null,
+ null);
+ XMLStreamReader reader = p;
+ if (xIncludeAware)
+ reader = new XIncludeFilter(p, args[pos], true, true, true);
+ try
+ {
+ int event;
+ //do
+ while (reader.hasNext())
+ {
+ event = reader.next();
+ Location loc = reader.getLocation();
+ System.out.print(loc.getLineNumber() + ":" +
+ loc.getColumnNumber() + " ");
+ switch (event)
+ {
+ case XMLStreamConstants.START_DOCUMENT:
+ System.out.println("START_DOCUMENT version=" +
+ reader.getVersion() +
+ " encoding=" +
+ reader.getEncoding());
+ break;
+ case XMLStreamConstants.END_DOCUMENT:
+ System.out.println("END_DOCUMENT");
+ break;
+ case XMLStreamConstants.START_ELEMENT:
+ System.out.println("START_ELEMENT " +
+ reader.getName());
+ int l = reader.getNamespaceCount();
+ for (int i = 0; i < l; i++)
+ System.out.println("\tnamespace " +
+ reader.getNamespacePrefix(i) + "='" +
+ reader.getNamespaceURI(i)+"'");
+ l = reader.getAttributeCount();
+ for (int i = 0; i < l; i++)
+ System.out.println("\tattribute " +
+ reader.getAttributeName(i) + "='" +
+ reader.getAttributeValue(i) + "'");
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ System.out.println("END_ELEMENT " + reader.getName());
+ break;
+ case XMLStreamConstants.CHARACTERS:
+ System.out.println("CHARACTERS '" +
+ encodeText(reader.getText()) + "'");
+ break;
+ case XMLStreamConstants.CDATA:
+ System.out.println("CDATA '" +
+ encodeText(reader.getText()) + "'");
+ break;
+ case XMLStreamConstants.SPACE:
+ System.out.println("SPACE '" +
+ encodeText(reader.getText()) + "'");
+ break;
+ case XMLStreamConstants.DTD:
+ System.out.println("DTD " + reader.getText());
+ break;
+ case XMLStreamConstants.ENTITY_REFERENCE:
+ System.out.println("ENTITY_REFERENCE " + reader.getText());
+ break;
+ case XMLStreamConstants.COMMENT:
+ System.out.println("COMMENT '" +
+ encodeText(reader.getText()) + "'");
+ break;
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ System.out.println("PROCESSING_INSTRUCTION " +
+ reader.getPITarget() + " " +
+ reader.getPIData());
+ break;
+ case START_ENTITY:
+ System.out.println("START_ENTITY " + reader.getText());
+ break;
+ case END_ENTITY:
+ System.out.println("END_ENTITY " + reader.getText());
+ break;
+ default:
+ System.out.println("Unknown event: " + event);
+ }
+ }
+ }
+ catch (XMLStreamException e)
+ {
+ Location l = reader.getLocation();
+ System.out.println("At line "+l.getLineNumber()+
+ ", column "+l.getColumnNumber()+
+ " of "+l.getSystemId());
+ throw e;
+ }
+ pos++;
+ }
+ }
+
+ /**
+ * Escapes control characters in the specified text. For debugging.
+ */
+ private static String encodeText(String text)
+ {
+ CPStringBuilder b = new CPStringBuilder();
+ int len = text.length();
+ for (int i = 0; i < len; i++)
+ {
+ char c = text.charAt(i);
+ switch (c)
+ {
+ case '\t':
+ b.append("\\t");
+ break;
+ case '\n':
+ b.append("\\n");
+ break;
+ case '\r':
+ b.append("\\r");
+ break;
+ default:
+ b.append(c);
+ }
+ }
+ return b.toString();
+ }
+
+ /**
+ * An attribute instance.
+ */
+ class Attribute
+ {
+
+ /**
+ * Attribute name.
+ */
+ final String name;
+
+ /**
+ * Attribute type as declared in the DTD, or CDATA otherwise.
+ */
+ final String type;
+
+ /**
+ * Whether the attribute was specified or defaulted.
+ */
+ final boolean specified;
+
+ /**
+ * The attribute value.
+ */
+ final String value;
+
+ /**
+ * The namespace prefix.
+ */
+ final String prefix;
+
+ /**
+ * The namespace local-name.
+ */
+ final String localName;
+
+ Attribute(String name, String type, boolean specified, String value)
+ {
+ this.name = name;
+ this.type = type;
+ this.specified = specified;
+ this.value = value;
+ int ci = name.indexOf(':');
+ if (ci == -1)
+ {
+ prefix = null;
+ localName = intern(name);
+ }
+ else
+ {
+ prefix = intern(name.substring(0, ci));
+ localName = intern(name.substring(ci + 1));
+ }
+ }
+
+ public boolean equals(Object other)
+ {
+ if (other instanceof Attribute)
+ {
+ Attribute a = (Attribute) other;
+ if (namespaceAware)
+ {
+ if (!a.localName.equals(localName))
+ return false;
+ String auri = getNamespaceURI(a.prefix);
+ String uri = getNamespaceURI(prefix);
+ if (uri == null && (auri == null ||
+ (input.xml11 && "".equals(auri))))
+ return true;
+ if (uri != null)
+ {
+ if ("".equals(uri) && input.xml11 && "".equals(auri))
+ return true;
+ return uri.equals(auri);
+ }
+ return false;
+ }
+ else
+ return a.name.equals(name);
+ }
+ return false;
+ }
+
+ public String toString()
+ {
+ CPStringBuilder buf = new CPStringBuilder(getClass().getName());
+ buf.append('[');
+ buf.append("name=");
+ buf.append(name);
+ if (value != null)
+ {
+ buf.append(",value=");
+ buf.append(value);
+ }
+ if (type != null)
+ {
+ buf.append(",type=");
+ buf.append(type);
+ }
+ if (specified)
+ buf.append(",specified");
+ buf.append(']');
+ return buf.toString();
+ }
+
+ }
+
+ /**
+ * Representation of a DTD.
+ */
+ class Doctype
+ {
+
+ /**
+ * Name of the root element.
+ */
+ final String rootName;
+
+ /**
+ * Public ID, if any, of external subset.
+ */
+ final String publicId;
+
+ /**
+ * System ID (URL), if any, of external subset.
+ */
+ final String systemId;
+
+ /**
+ * Map of element names to content models.
+ */
+ private final LinkedHashMap elements = new LinkedHashMap();
+
+ /**
+ * Map of element names to maps of attribute declarations.
+ */
+ private final LinkedHashMap attlists = new LinkedHashMap();
+
+ /**
+ * Map of entity names to entities (String or ExternalIds).
+ */
+ private final LinkedHashMap entities = new LinkedHashMap();
+
+ /**
+ * Map of notation names to ExternalIds.
+ */
+ private final LinkedHashMap notations = new LinkedHashMap();
+
+ /**
+ * Map of anonymous keys to comments.
+ */
+ private final LinkedHashMap comments = new LinkedHashMap();
+
+ /**
+ * Map of anonymous keys to processing instructions (String[2]
+ * containing {target, data}).
+ */
+ private final LinkedHashMap pis = new LinkedHashMap();
+
+ /**
+ * List of keys to all markup entries in the DTD.
+ */
+ private final LinkedList entries = new LinkedList();
+
+ /**
+ * Set of the entities defined in the external subset.
+ */
+ private final HashSet externalEntities = new HashSet();
+
+ /**
+ * Set of the notations defined in the external subset.
+ */
+ private final HashSet externalNotations = new HashSet();
+
+ /**
+ * Counter for making anonymous keys.
+ */
+ private int anon = 1;
+
+ /**
+ * Constructor.
+ */
+ Doctype(String rootName, String publicId, String systemId)
+ {
+ this.rootName = rootName;
+ this.publicId = publicId;
+ this.systemId = systemId;
+ }
+
+ /**
+ * Adds an element declaration.
+ * @param name the element name
+ * @param text the content model text
+ * @param model the parsed content model
+ */
+ void addElementDecl(String name, String text, ContentModel model)
+ {
+ if (elements.containsKey(name))
+ return;
+ model.text = text;
+ model.external = (inputStack.size() != 1);
+ elements.put(name, model);
+ entries.add("E" + name);
+ }
+
+ /**
+ * Adds an attribute declaration.
+ * @param ename the element name
+ * @param aname the attribute name
+ * @param decl the attribute declaration details
+ */
+ void addAttributeDecl(String ename, String aname, AttributeDecl decl)
+ {
+ LinkedHashMap attlist = (LinkedHashMap) attlists.get(ename);
+ if (attlist == null)
+ {
+ attlist = new LinkedHashMap();
+ attlists.put(ename, attlist);
+ }
+ else if (attlist.containsKey(aname))
+ return;
+ attlist.put(aname, decl);
+ String key = "A" + ename;
+ if (!entries.contains(key))
+ entries.add(key);
+ }
+
+ /**
+ * Adds an entity declaration.
+ * @param name the entity name
+ * @param text the entity replacement text
+ * @param inExternalSubset if we are in the exernal subset
+ */
+ void addEntityDecl(String name, String text, boolean inExternalSubset)
+ {
+ if (entities.containsKey(name))
+ return;
+ entities.put(name, text);
+ entries.add("e" + name);
+ if (inExternalSubset)
+ externalEntities.add(name);
+ }
+
+ /**
+ * Adds an entity declaration.
+ * @param name the entity name
+ * @param ids the external IDs
+ * @param inExternalSubset if we are in the exernal subset
+ */
+ void addEntityDecl(String name, ExternalIds ids, boolean inExternalSubset)
+ {
+ if (entities.containsKey(name))
+ return;
+ entities.put(name, ids);
+ entries.add("e" + name);
+ if (inExternalSubset)
+ externalEntities.add(name);
+ }
+
+ /**
+ * Adds a notation declaration.
+ * @param name the notation name
+ * @param ids the external IDs
+ * @param inExternalSubset if we are in the exernal subset
+ */
+ void addNotationDecl(String name, ExternalIds ids, boolean inExternalSubset)
+ {
+ if (notations.containsKey(name))
+ return;
+ notations.put(name, ids);
+ entries.add("n" + name);
+ if (inExternalSubset)
+ externalNotations.add(name);
+ }
+
+ /**
+ * Adds a comment.
+ */
+ void addComment(String text)
+ {
+ String key = Integer.toString(anon++);
+ comments.put(key, text);
+ entries.add("c" + key);
+ }
+
+ /**
+ * Adds a processing instruction.
+ */
+ void addPI(String target, String data)
+ {
+ String key = Integer.toString(anon++);
+ pis.put(key, new String[] {target, data});
+ entries.add("p" + key);
+ }
+
+ /**
+ * Returns the content model for the specified element.
+ * @param name the element name
+ */
+ ContentModel getElementModel(String name)
+ {
+ return (ContentModel) elements.get(name);
+ }
+
+ /**
+ * Returns the attribute definition for the given attribute
+ * @param ename the element name
+ * @param aname the attribute name
+ */
+ AttributeDecl getAttributeDecl(String ename, String aname)
+ {
+ LinkedHashMap attlist = (LinkedHashMap) attlists.get(ename);
+ return (attlist == null) ? null : (AttributeDecl) attlist.get(aname);
+ }
+
+ /**
+ * Indicates whether the specified attribute was declared in the DTD.
+ * @param ename the element name
+ * @param aname the attribute name
+ */
+ boolean isAttributeDeclared(String ename, String aname)
+ {
+ LinkedHashMap attlist = (LinkedHashMap) attlists.get(ename);
+ return (attlist == null) ? false : attlist.containsKey(aname);
+ }
+
+ /**
+ * Returns an iterator over the entries in the attribute list for the
+ * given element.
+ * @param ename the element name
+ */
+ Iterator attlistIterator(String ename)
+ {
+ LinkedHashMap attlist = (LinkedHashMap) attlists.get(ename);
+ return (attlist == null) ? Collections.EMPTY_LIST.iterator() :
+ attlist.entrySet().iterator();
+ }
+
+ /**
+ * Returns the entity (String or ExternalIds) for the given entity name.
+ */
+ Object getEntity(String name)
+ {
+ return entities.get(name);
+ }
+
+ /**
+ * Indicates whether the specified entity was declared in the external
+ * subset.
+ */
+ boolean isEntityExternal(String name)
+ {
+ return externalEntities.contains(name);
+ }
+
+ /**
+ * Returns an iterator over the entity map entries.
+ */
+ Iterator entityIterator()
+ {
+ return entities.entrySet().iterator();
+ }
+
+ /**
+ * Returns the notation IDs for the given notation name.
+ */
+ ExternalIds getNotation(String name)
+ {
+ return (ExternalIds) notations.get(name);
+ }
+
+ /**
+ * Indicates whether the specified notation was declared in the external
+ * subset.
+ */
+ boolean isNotationExternal(String name)
+ {
+ return externalNotations.contains(name);
+ }
+
+ /**
+ * Returns the comment associated with the specified (anonymous) key.
+ */
+ String getComment(String key)
+ {
+ return (String) comments.get(key);
+ }
+
+ /**
+ * Returns the processing instruction associated with the specified
+ * (anonymous) key.
+ */
+ String[] getPI(String key)
+ {
+ return (String[]) pis.get(key);
+ }
+
+ /**
+ * Returns an iterator over the keys of the markup entries in this DTD,
+ * in the order declared.
+ */
+ Iterator entryIterator()
+ {
+ return entries.iterator();
+ }
+
+ }
+
+ /**
+ * Combination of an ExternalID and an optional NDataDecl.
+ */
+ class ExternalIds
+ {
+
+ /**
+ * The public ID.
+ */
+ String publicId;
+
+ /**
+ * The system ID.
+ */
+ String systemId;
+
+ /**
+ * The notation name declared with the NDATA keyword.
+ */
+ String notationName;
+ }
+
+ /**
+ * A content model.
+ */
+ abstract class ContentModel
+ {
+ static final int EMPTY = 0;
+ static final int ANY = 1;
+ static final int ELEMENT = 2;
+ static final int MIXED = 3;
+
+ int min;
+ int max;
+ final int type;
+ String text;
+ boolean external;
+
+ ContentModel(int type)
+ {
+ this.type = type;
+ min = 1;
+ max = 1;
+ }
+
+ }
+
+ /**
+ * The EMPTY content model.
+ */
+ class EmptyContentModel
+ extends ContentModel
+ {
+
+ EmptyContentModel()
+ {
+ super(ContentModel.EMPTY);
+ min = 0;
+ max = 0;
+ }
+
+ }
+
+ /**
+ * The ANY content model.
+ */
+ class AnyContentModel
+ extends ContentModel
+ {
+
+ AnyContentModel()
+ {
+ super(ContentModel.ANY);
+ min = 0;
+ max = -1;
+ }
+
+ }
+
+ /**
+ * An element content model.
+ */
+ class ElementContentModel
+ extends ContentModel
+ {
+
+ LinkedList contentParticles;
+ boolean or;
+ String regex; // regular expression cache
+
+ ElementContentModel()
+ {
+ super(ContentModel.ELEMENT);
+ contentParticles = new LinkedList();
+ }
+
+ void addContentParticle(ContentParticle cp)
+ {
+ contentParticles.add(cp);
+ }
+
+ }
+
+ class ContentParticle
+ {
+
+ int min = 1;
+ int max = 1;
+ Object content; // Name (String) or ElementContentModel
+
+ }
+
+ /**
+ * A mixed content model.
+ */
+ class MixedContentModel
+ extends ContentModel
+ {
+
+ private HashSet names;
+
+ MixedContentModel()
+ {
+ super(ContentModel.MIXED);
+ names = new HashSet();
+ }
+
+ void addName(String name)
+ {
+ names.add(name);
+ }
+
+ boolean containsName(String name)
+ {
+ return names.contains(name);
+ }
+
+ }
+
+ /**
+ * An attribute definition.
+ */
+ class AttributeDecl
+ {
+
+ /**
+ * The attribute type (CDATA, ID, etc).
+ */
+ final String type;
+
+ /**
+ * The default value.
+ */
+ final String value;
+
+ /**
+ * The value type (#FIXED, #IMPLIED, etc).
+ */
+ final int valueType;
+
+ /**
+ * The enumeration text.
+ */
+ final String enumeration;
+
+ /**
+ * The enumeration tokens.
+ */
+ final HashSet values;
+
+ /**
+ * Whether this attribute declaration occurred in the external subset.
+ */
+ final boolean external;
+
+ AttributeDecl(String type, String value,
+ int valueType, String enumeration,
+ HashSet values, boolean external)
+ {
+ this.type = type;
+ this.value = value;
+ this.valueType = valueType;
+ this.enumeration = enumeration;
+ this.values = values;
+ this.external = external;
+ }
+
+ }
+
+ /**
+ * An XML input source.
+ */
+ static class Input
+ implements Location
+ {
+
+ int line = 1, markLine;
+ int column, markColumn;
+ int offset, markOffset;
+ final String publicId, systemId, name;
+ final boolean report; // report start- and end-entity
+ final boolean normalize; // normalize CR, etc to LF
+
+ InputStream in;
+ Reader reader;
+ UnicodeReader unicodeReader;
+ boolean initialized;
+ boolean encodingDetected;
+ String inputEncoding;
+ boolean xml11;
+
+ Input(InputStream in, Reader reader, String publicId, String systemId,
+ String name, String inputEncoding, boolean report,
+ boolean normalize)
+ {
+ if (inputEncoding == null)
+ inputEncoding = "UTF-8";
+ this.inputEncoding = inputEncoding;
+ this.publicId = publicId;
+ this.systemId = systemId;
+ this.name = name;
+ this.report = report;
+ this.normalize = normalize;
+ if (in != null)
+ {
+ if (reader != null)
+ throw new IllegalStateException("both byte and char streams "+
+ "specified");
+ if (normalize)
+ in = new CRLFInputStream(in);
+ in = new BufferedInputStream(in);
+ this.in = in;
+ }
+ else
+ {
+ this.reader = normalize ? new CRLFReader(reader) : reader;
+ unicodeReader = new UnicodeReader(this.reader);
+ }
+ initialized = false;
+ }
+
+ // -- Location --
+
+ public int getCharacterOffset()
+ {
+ return offset;
+ }
+
+ public int getColumnNumber()
+ {
+ return column;
+ }
+
+ public int getLineNumber()
+ {
+ return line;
+ }
+
+ public String getPublicId()
+ {
+ return publicId;
+ }
+
+ public String getSystemId()
+ {
+ return systemId;
+ }
+
+ void init()
+ throws IOException
+ {
+ if (initialized)
+ return;
+ if (in != null)
+ detectEncoding();
+ initialized = true;
+ }
+
+ void mark(int len)
+ throws IOException
+ {
+ markOffset = offset;
+ markLine = line;
+ markColumn = column;
+ if (unicodeReader != null)
+ unicodeReader.mark(len);
+ else
+ in.mark(len);
+ }
+
+ /**
+ * Character read.
+ */
+ int read()
+ throws IOException
+ {
+ offset++;
+ int ret = (unicodeReader != null) ? unicodeReader.read() : in.read();
+ if (normalize &&
+ (ret == 0x0d || (xml11 && (ret == 0x85 || ret == 0x2028))))
+ {
+ // Normalize CR etc to LF
+ ret = 0x0a;
+ }
+ // Locator handling
+ if (ret == 0x0a)
+ {
+ line++;
+ column = 0;
+ }
+ else
+ column++;
+ return ret;
+ }
+
+ /**
+ * Block read.
+ */
+ int read(int[] b, int off, int len)
+ throws IOException
+ {
+ int ret;
+ if (unicodeReader != null)
+ {
+ ret = unicodeReader.read(b, off, len);
+ }
+ else
+ {
+ byte[] b2 = new byte[len];
+ ret = in.read(b2, 0, len);
+ if (ret != -1)
+ {
+ String s = new String(b2, 0, ret, inputEncoding);
+ int[] c = UnicodeReader.toCodePointArray(s);
+ ret = c.length;
+ System.arraycopy(c, 0, b, off, ret);
+ }
+ }
+ if (ret != -1)
+ {
+ // Locator handling
+ for (int i = 0; i < ret; i++)
+ {
+ int c = b[off + i];
+ if (normalize &&
+ (c == 0x0d || (xml11 && (c == 0x85 || c == 0x2028))))
+ {
+ // Normalize CR etc to LF
+ c = 0x0a;
+ b[off + i] = c;
+ }
+ if (c == 0x0a)
+ {
+ line++;
+ column = 0;
+ }
+ else
+ column++;
+ }
+ }
+ return ret;
+ }
+
+ void reset()
+ throws IOException
+ {
+ if (unicodeReader != null)
+ unicodeReader.reset();
+ else
+ in.reset();
+ offset = markOffset;
+ line = markLine;
+ column = markColumn;
+ }
+
+ // Detection of input encoding
+
+ private static final int[] SIGNATURE_UCS_4_1234 =
+ new int[] { 0x00, 0x00, 0x00, 0x3c };
+ private static final int[] SIGNATURE_UCS_4_4321 =
+ new int[] { 0x3c, 0x00, 0x00, 0x00 };
+ private static final int[] SIGNATURE_UCS_4_2143 =
+ new int[] { 0x00, 0x00, 0x3c, 0x00 };
+ private static final int[] SIGNATURE_UCS_4_3412 =
+ new int[] { 0x00, 0x3c, 0x00, 0x00 };
+ private static final int[] SIGNATURE_UCS_2_12 =
+ new int[] { 0xfe, 0xff };
+ private static final int[] SIGNATURE_UCS_2_21 =
+ new int[] { 0xff, 0xfe };
+ private static final int[] SIGNATURE_UCS_2_12_NOBOM =
+ new int[] { 0x00, 0x3c, 0x00, 0x3f };
+ private static final int[] SIGNATURE_UCS_2_21_NOBOM =
+ new int[] { 0x3c, 0x00, 0x3f, 0x00 };
+ private static final int[] SIGNATURE_UTF_8 =
+ new int[] { 0x3c, 0x3f, 0x78, 0x6d };
+ private static final int[] SIGNATURE_UTF_8_BOM =
+ new int[] { 0xef, 0xbb, 0xbf };
+
+ /**
+ * Detect the input encoding.
+ */
+ private void detectEncoding()
+ throws IOException
+ {
+ int[] signature = new int[4];
+ in.mark(4);
+ for (int i = 0; i < 4; i++)
+ signature[i] = in.read();
+ in.reset();
+
+ // 4-byte encodings
+ if (equals(SIGNATURE_UCS_4_1234, signature))
+ {
+ in.read();
+ in.read();
+ in.read();
+ in.read();
+ setInputEncoding("UTF-32BE");
+ encodingDetected = true;
+ }
+ else if (equals(SIGNATURE_UCS_4_4321, signature))
+ {
+ in.read();
+ in.read();
+ in.read();
+ in.read();
+ setInputEncoding("UTF-32LE");
+ encodingDetected = true;
+ }
+ else if (equals(SIGNATURE_UCS_4_2143, signature) ||
+ equals(SIGNATURE_UCS_4_3412, signature))
+ throw new UnsupportedEncodingException("unsupported UCS-4 byte ordering");
+
+ // 2-byte encodings
+ else if (equals(SIGNATURE_UCS_2_12, signature))
+ {
+ in.read();
+ in.read();
+ setInputEncoding("UTF-16BE");
+ encodingDetected = true;
+ }
+ else if (equals(SIGNATURE_UCS_2_21, signature))
+ {
+ in.read();
+ in.read();
+ setInputEncoding("UTF-16LE");
+ encodingDetected = true;
+ }
+ else if (equals(SIGNATURE_UCS_2_12_NOBOM, signature))
+ {
+ //setInputEncoding("UTF-16BE");
+ throw new UnsupportedEncodingException("no byte-order mark for UCS-2 entity");
+ }
+ else if (equals(SIGNATURE_UCS_2_21_NOBOM, signature))
+ {
+ //setInputEncoding("UTF-16LE");
+ throw new UnsupportedEncodingException("no byte-order mark for UCS-2 entity");
+ }
+ // ASCII-derived encodings
+ else if (equals(SIGNATURE_UTF_8, signature))
+ {
+ // UTF-8 input encoding implied, TextDecl
+ }
+ else if (equals(SIGNATURE_UTF_8_BOM, signature))
+ {
+ in.read();
+ in.read();
+ in.read();
+ setInputEncoding("UTF-8");
+ encodingDetected = true;
+ }
+ }
+
+ private static boolean equals(int[] b1, int[] b2)
+ {
+ for (int i = 0; i < b1.length; i++)
+ {
+ if (b1[i] != b2[i])
+ return false;
+ }
+ return true;
+ }
+
+ void setInputEncoding(String encoding)
+ throws IOException
+ {
+ if (encoding.equals(inputEncoding))
+ return;
+ if ("UTF-16".equalsIgnoreCase(encoding) &&
+ inputEncoding.startsWith("UTF-16"))
+ return;
+ if (encodingDetected)
+ throw new UnsupportedEncodingException("document is not in its " +
+ "declared encoding " +
+ inputEncoding +
+ ": " + encoding);
+ inputEncoding = encoding;
+ finalizeEncoding();
+ }
+
+ void finalizeEncoding()
+ throws IOException
+ {
+ if (reader != null)
+ return;
+ reader = new BufferedReader(new InputStreamReader(in, inputEncoding));
+ unicodeReader = new UnicodeReader(reader);
+ mark(1);
+ }
+
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/XMLStreamWriterImpl.java b/libjava/classpath/gnu/xml/stream/XMLStreamWriterImpl.java
new file mode 100644
index 000000000..83b8f7239
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/XMLStreamWriterImpl.java
@@ -0,0 +1,1016 @@
+/* XMLStreamWriterImpl.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Set;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.xml.sax.helpers.NamespaceSupport;
+
+/**
+ * Simple XML stream writer.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+public class XMLStreamWriterImpl
+ implements XMLStreamWriter
+{
+
+ /**
+ * The underlying character stream to write to.
+ */
+ protected final Writer writer;
+
+ /**
+ * The encoding being used.
+ * Note that this must match the encoding of the character stream.
+ */
+ protected final String encoding;
+
+ /**
+ * Whether prefix defaulting is being used.
+ * If true and a prefix has not been defined for a namespace specified on
+ * an element or an attribute, a new prefix and namespace declaration will
+ * be created.
+ */
+ protected final boolean prefixDefaulting;
+
+ /**
+ * The namespace context used to determine the namespace-prefix mappings
+ * in scope.
+ */
+ protected NamespaceContext namespaceContext;
+
+ /**
+ * The stack of elements in scope.
+ * Used to close the remaining elements.
+ */
+ private LinkedList elements;
+
+ /**
+ * Whether a start element has been opened but not yet closed.
+ */
+ private boolean inStartElement;
+
+ /**
+ * Whether we are in an empty element.
+ */
+ private boolean emptyElement;
+
+ private NamespaceSupport namespaces;
+ private int count = 0;
+
+ private boolean xml11;
+ private boolean hasXML11RestrictedChars;
+
+ /**
+ * Constructor.
+ * @see #writer
+ * @see #encoding
+ * @see #prefixDefaulting
+ */
+ protected XMLStreamWriterImpl(Writer writer, String encoding,
+ boolean prefixDefaulting)
+ {
+ this.writer = writer;
+ this.encoding = encoding;
+ this.prefixDefaulting = prefixDefaulting;
+ elements = new LinkedList();
+ namespaces = new NamespaceSupport();
+ }
+
+ /**
+ * Write the end of a start-element event.
+ * This will close the element if it was defined to be an empty element.
+ */
+ private void endStartElement()
+ throws IOException
+ {
+ if (!inStartElement)
+ return;
+ if (emptyElement)
+ {
+ writer.write('/');
+ elements.removeLast();
+ namespaces.popContext();
+ emptyElement = false;
+ }
+ writer.write('>');
+ inStartElement = false;
+ }
+
+ public void writeStartElement(String localName)
+ throws XMLStreamException
+ {
+ try
+ {
+ if (!isName(localName))
+ throw new IllegalArgumentException("illegal Name: " + localName);
+
+ endStartElement();
+ namespaces.pushContext();
+
+ writer.write('<');
+ writer.write(localName);
+
+ elements.addLast(new String[] { null, localName });
+ inStartElement = true;
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeStartElement(String namespaceURI, String localName)
+ throws XMLStreamException
+ {
+ try
+ {
+ if (namespaceURI != null && !isURI(namespaceURI))
+ throw new IllegalArgumentException("illegal URI: " + namespaceURI);
+ if (!isName(localName))
+ throw new IllegalArgumentException("illegal Name: " + localName);
+
+ endStartElement();
+ namespaces.pushContext();
+
+ String prefix = getPrefix(namespaceURI);
+ boolean isDeclared = (prefix != null);
+ if (!isDeclared)
+ {
+ if (prefixDefaulting)
+ prefix = createPrefix(namespaceURI);
+ else
+ throw new XMLStreamException("namespace " + namespaceURI +
+ " has not been declared");
+ }
+ writer.write('<');
+ if (!"".equals(prefix))
+ {
+ writer.write(prefix);
+ writer.write(':');
+ }
+ writer.write(localName);
+ inStartElement = true;
+ if (!isDeclared)
+ {
+ writeNamespaceImpl(prefix, namespaceURI);
+ }
+
+ elements.addLast(new String[] { prefix, localName });
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ /**
+ * Creates a new unique prefix in the document.
+ * Subclasses may override this method to provide a suitably unique prefix
+ * for the given namespace.
+ * @param namespaceURI the namespace URI
+ */
+ protected String createPrefix(String namespaceURI)
+ {
+ Set prefixes = new HashSet();
+ for (Enumeration e = namespaces.getPrefixes(); e.hasMoreElements(); )
+ prefixes.add(e.nextElement());
+ String ret;
+ do
+ {
+ ret = "ns" + (count++);
+ }
+ while (prefixes.contains(ret));
+ return ret;
+ }
+
+ public void writeStartElement(String prefix, String localName,
+ String namespaceURI)
+ throws XMLStreamException
+ {
+ try
+ {
+ if (namespaceURI != null && !isURI(namespaceURI))
+ throw new IllegalArgumentException("illegal URI: " + namespaceURI);
+ if (prefix != null && !isPrefix(prefix))
+ throw new IllegalArgumentException("illegal NCName: " + prefix);
+ if (!isNCName(localName))
+ throw new IllegalArgumentException("illegal NCName: " + localName);
+
+ endStartElement();
+ namespaces.pushContext();
+
+ String currentPrefix = getPrefix(namespaceURI);
+ boolean isCurrent = prefix.equals(currentPrefix);
+ writer.write('<');
+ if (!"".equals(prefix))
+ {
+ writer.write(prefix);
+ writer.write(':');
+ }
+ writer.write(localName);
+ if (prefixDefaulting && !isCurrent)
+ {
+ writeNamespaceImpl(prefix, namespaceURI);
+ }
+
+ elements.addLast(new String[] { prefix, localName });
+ inStartElement = true;
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeEmptyElement(String namespaceURI, String localName)
+ throws XMLStreamException
+ {
+ writeStartElement(namespaceURI, localName);
+ emptyElement = true;
+ }
+
+ public void writeEmptyElement(String prefix, String localName,
+ String namespaceURI)
+ throws XMLStreamException
+ {
+ writeStartElement(prefix, localName, namespaceURI);
+ emptyElement = true;
+ }
+
+ public void writeEmptyElement(String localName)
+ throws XMLStreamException
+ {
+ writeStartElement(localName);
+ emptyElement = true;
+ }
+
+ public void writeEndElement()
+ throws XMLStreamException
+ {
+ if (elements.isEmpty())
+ throw new IllegalStateException("no matching start element");
+ try
+ {
+ endStartElement();
+ String[] element = (String[]) elements.removeLast();
+ namespaces.popContext();
+
+ writer.write('<');
+ writer.write('/');
+ if (element[0] != null && !"".equals(element[0]))
+ {
+ writer.write(element[0]);
+ writer.write(':');
+ }
+ writer.write(element[1]);
+ writer.write('>');
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeEndDocument()
+ throws XMLStreamException
+ {
+ while (!elements.isEmpty())
+ writeEndElement();
+ }
+
+ public void close()
+ throws XMLStreamException
+ {
+ flush();
+ }
+
+ public void flush()
+ throws XMLStreamException
+ {
+ try
+ {
+ writer.flush();
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeAttribute(String localName, String value)
+ throws XMLStreamException
+ {
+ if (!inStartElement)
+ throw new IllegalStateException();
+ try
+ {
+ if (!isName(localName))
+ throw new IllegalArgumentException("illegal Name: " + localName);
+ if (!isChars(value))
+ throw new IllegalArgumentException("illegal character: " + value);
+
+ writer.write(' ');
+ writer.write(localName);
+ writer.write('=');
+ writer.write('"');
+ if (hasXML11RestrictedChars)
+ writeEncodedWithRestrictedChars(value, true);
+ else
+ writeEncoded(value, true);
+ writer.write('"');
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeAttribute(String prefix, String namespaceURI,
+ String localName, String value)
+ throws XMLStreamException
+ {
+ if (!inStartElement)
+ throw new IllegalStateException();
+ try
+ {
+ if (namespaceURI != null && !isURI(namespaceURI))
+ throw new IllegalArgumentException("illegal URI: " + namespaceURI);
+ if (prefix != null && !isPrefix(prefix))
+ throw new IllegalArgumentException("illegal NCName: " + prefix);
+ if (!isNCName(localName))
+ throw new IllegalArgumentException("illegal NCName: " + localName);
+ if (!isChars(value))
+ throw new IllegalArgumentException("illegal character: " + value);
+
+ String currentPrefix = getPrefix(namespaceURI);
+ if (currentPrefix == null)
+ {
+ if (prefixDefaulting)
+ writeNamespaceImpl(prefix, namespaceURI);
+ else
+ throw new XMLStreamException("namespace " + namespaceURI +
+ " is not bound");
+ }
+ else if (!currentPrefix.equals(prefix))
+ throw new XMLStreamException("namespace " + namespaceURI +
+ " is bound to prefix " +
+ currentPrefix);
+ writer.write(' ');
+ if (!"".equals(prefix))
+ {
+ writer.write(prefix);
+ writer.write(':');
+ }
+ writer.write(localName);
+ writer.write('=');
+ writer.write('"');
+ if (hasXML11RestrictedChars)
+ writeEncodedWithRestrictedChars(value, true);
+ else
+ writeEncoded(value, true);
+ writer.write('"');
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeAttribute(String namespaceURI, String localName,
+ String value)
+ throws XMLStreamException
+ {
+ if (!inStartElement)
+ throw new IllegalStateException();
+ try
+ {
+ if (namespaceURI != null && !isURI(namespaceURI))
+ throw new IllegalArgumentException("illegal URI: " + namespaceURI);
+ if (!isName(localName))
+ throw new IllegalArgumentException("illegal Name: " + localName);
+ if (!isChars(value))
+ throw new IllegalArgumentException("illegal character: " + value);
+
+ String prefix = getPrefix(namespaceURI);
+ if (prefix == null)
+ {
+ if (prefixDefaulting)
+ {
+ prefix = XMLConstants.DEFAULT_NS_PREFIX;
+ writeNamespaceImpl(prefix, namespaceURI);
+ }
+ else
+ throw new XMLStreamException("namespace " + namespaceURI +
+ " is not bound");
+ }
+ writer.write(' ');
+ if (!"".equals(prefix))
+ {
+ writer.write(prefix);
+ writer.write(':');
+ }
+ writer.write(localName);
+ writer.write('=');
+ writer.write('"');
+ if (hasXML11RestrictedChars)
+ writeEncodedWithRestrictedChars(value, true);
+ else
+ writeEncoded(value, true);
+ writer.write('"');
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeNamespace(String prefix, String namespaceURI)
+ throws XMLStreamException
+ {
+ if (prefix == null || "".equals(prefix) || "xmlns".equals(prefix))
+ {
+ writeDefaultNamespace(namespaceURI);
+ return;
+ }
+ if (!inStartElement)
+ throw new IllegalStateException();
+ try
+ {
+ if (!isURI(namespaceURI))
+ throw new IllegalArgumentException("illegal URI: " + namespaceURI);
+ if (!isPrefix(prefix))
+ throw new IllegalArgumentException("illegal NCName: " + prefix);
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ writeNamespaceImpl(prefix, namespaceURI);
+ }
+
+ private void writeNamespaceImpl(String prefix, String namespaceURI)
+ throws XMLStreamException
+ {
+ try
+ {
+ if (prefix == null)
+ prefix = XMLConstants.DEFAULT_NS_PREFIX;
+
+ setPrefix(prefix, namespaceURI);
+
+ writer.write(' ');
+ writer.write("xmlns");
+ if (!XMLConstants.DEFAULT_NS_PREFIX.equals(prefix))
+ {
+ writer.write(':');
+ writer.write(prefix);
+ }
+ writer.write('=');
+ writer.write('"');
+ writer.write(namespaceURI);
+ writer.write('"');
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeDefaultNamespace(String namespaceURI)
+ throws XMLStreamException
+ {
+ if (!inStartElement)
+ throw new IllegalStateException();
+ if (!isURI(namespaceURI))
+ throw new IllegalArgumentException("illegal URI: " + namespaceURI);
+ writeNamespaceImpl(XMLConstants.DEFAULT_NS_PREFIX, namespaceURI);
+ }
+
+ public void writeComment(String data)
+ throws XMLStreamException
+ {
+ if (data == null)
+ return;
+ try
+ {
+ if (!isChars(data))
+ throw new IllegalArgumentException("illegal XML character: " + data);
+ if (data.indexOf("--") != -1)
+ throw new IllegalArgumentException("illegal comment: " + data);
+
+ endStartElement();
+
+ writer.write("<!--");
+ if (hasXML11RestrictedChars)
+ {
+ int[] seq = UnicodeReader.toCodePointArray(data);
+ for (int i = 0; i < seq.length; i++)
+ {
+ int c = seq[i];
+ if (XMLParser.isXML11RestrictedChar(c))
+ writer.write("&#x" + Integer.toHexString(c) + ";");
+ else
+ writer.write(Character.toChars(i));
+ }
+ }
+ else
+ writer.write(data);
+ writer.write("-->");
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeProcessingInstruction(String target)
+ throws XMLStreamException
+ {
+ writeProcessingInstruction(target, null);
+ }
+
+ public void writeProcessingInstruction(String target, String data)
+ throws XMLStreamException
+ {
+ try
+ {
+ if (!isName(target) || "xml".equalsIgnoreCase(target))
+ throw new IllegalArgumentException("illegal PITarget: " + target);
+ if (data != null && !isChars(data))
+ throw new IllegalArgumentException("illegal XML character: " + data);
+
+ endStartElement();
+
+ writer.write('<');
+ writer.write('?');
+ writer.write(target);
+ if (data != null)
+ {
+ writer.write(' ');
+ if (hasXML11RestrictedChars)
+ {
+ int[] seq = UnicodeReader.toCodePointArray(data);
+ for (int i = 0; i < seq.length; i++)
+ {
+ int c = seq[i];
+ if (XMLParser.isXML11RestrictedChar(c))
+ writer.write("&#x" + Integer.toHexString(c) + ";");
+ else
+ writer.write(Character.toChars(i));
+ }
+ }
+ else
+ writer.write(data);
+ }
+ writer.write('?');
+ writer.write('>');
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeCData(String data)
+ throws XMLStreamException
+ {
+ try
+ {
+ if (!isChars(data) || hasXML11RestrictedChars)
+ throw new IllegalArgumentException("illegal XML character: " + data);
+ if (data.indexOf("]]") != -1)
+ throw new IllegalArgumentException("illegal CDATA section: " + data);
+
+ endStartElement();
+
+ writer.write("<![CDATA[");
+ writer.write(data);
+ writer.write("]]>");
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeDTD(String dtd)
+ throws XMLStreamException
+ {
+ try
+ {
+ // XXX: Should we parse the doctypedecl at this point to ensure
+ // wellformedness?
+ writer.write("<!DOCTYPE ");
+ writer.write(dtd);
+ writer.write('>');
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeEntityRef(String name)
+ throws XMLStreamException
+ {
+ try
+ {
+ if (!isName(name))
+ throw new IllegalArgumentException("illegal Name: " + name);
+
+ endStartElement();
+
+ writer.write('&');
+ writer.write(name);
+ writer.write(';');
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeStartDocument()
+ throws XMLStreamException
+ {
+ writeStartDocument(null, null);
+ }
+
+ public void writeStartDocument(String version)
+ throws XMLStreamException
+ {
+ writeStartDocument(null, version);
+ }
+
+ public void writeStartDocument(String encoding, String version)
+ throws XMLStreamException
+ {
+ if (version == null)
+ version = "1.0";
+ else if ("1.1".equals(version))
+ xml11 = true;
+ encoding = this.encoding; // YES: the parameter must be ignored
+ if (encoding == null)
+ encoding = "UTF-8";
+ if (!"1.0".equals(version) && !"1.1".equals(version))
+ throw new IllegalArgumentException(version);
+ try
+ {
+ writer.write("<?xml version=\"");
+ writer.write(version);
+ writer.write("\" encoding=\"");
+ writer.write(encoding);
+ writer.write("\"?>");
+ writer.write(System.getProperty("line.separator"));
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeCharacters(String text)
+ throws XMLStreamException
+ {
+ if (text == null)
+ return;
+ try
+ {
+ if (!isChars(text))
+ throw new IllegalArgumentException("illegal XML character: " + text);
+
+ endStartElement();
+
+ if (hasXML11RestrictedChars)
+ writeEncodedWithRestrictedChars(text, false);
+ else
+ writeEncoded(text, false);
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ public void writeCharacters(char[] text, int start, int len)
+ throws XMLStreamException
+ {
+ writeCharacters(new String(text, start, len));
+ }
+
+ public String getPrefix(String uri)
+ throws XMLStreamException
+ {
+ String prefix = namespaces.getPrefix(uri);
+ if (prefix == null && namespaceContext != null)
+ prefix = namespaceContext.getPrefix(uri);
+ return prefix;
+ }
+
+ public void setPrefix(String prefix, String uri)
+ throws XMLStreamException
+ {
+ try
+ {
+ if (!isURI(uri))
+ throw new IllegalArgumentException("illegal URI: " + uri);
+ if (!isPrefix(prefix))
+ throw new IllegalArgumentException("illegal NCName: " + prefix);
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e);
+ e2.initCause(e);
+ throw e2;
+ }
+ if (!namespaces.declarePrefix(prefix, uri))
+ throw new XMLStreamException("illegal prefix " + prefix);
+ }
+
+ public void setDefaultNamespace(String uri)
+ throws XMLStreamException
+ {
+ if (!isURI(uri))
+ throw new IllegalArgumentException("illegal URI: " + uri);
+ if (!namespaces.declarePrefix(XMLConstants.DEFAULT_NS_PREFIX, uri))
+ throw new XMLStreamException("illegal default namespace prefix");
+ }
+
+ public void setNamespaceContext(NamespaceContext context)
+ throws XMLStreamException
+ {
+ namespaceContext = context;
+ }
+
+ public NamespaceContext getNamespaceContext()
+ {
+ return namespaceContext;
+ }
+
+ public Object getProperty(String name)
+ throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException(name);
+ }
+
+ /**
+ * Write the specified text, ensuring that the content is suitably encoded
+ * for XML.
+ * @param text the text to write
+ * @param inAttr whether we are in an attribute value
+ */
+ private void writeEncoded(String text, boolean inAttr)
+ throws IOException
+ {
+ char[] chars = text.toCharArray();
+ int start = 0;
+ int end = chars.length;
+ int len = 0;
+ for (int i = start; i < end; i++)
+ {
+ char c = chars[i];
+ if (c == '<' || c == '>' || c == '&')
+ {
+ writer.write(chars, start, len);
+ if (c == '<')
+ writer.write("&lt;");
+ else if (c == '>')
+ writer.write("&gt;");
+ else
+ writer.write("&amp;");
+ start = i + 1;
+ len = 0;
+ }
+ else if (inAttr && (c == '"' || c == '\''))
+ {
+ writer.write(chars, start, len);
+ if (c == '"')
+ writer.write("&quot;");
+ else
+ writer.write("&apos;");
+ start = i + 1;
+ len = 0;
+ }
+ else
+ len++;
+ }
+ if (len > 0)
+ writer.write(chars, start, len);
+ }
+
+ /**
+ * Writes the specified text, in the knowledge that some of the
+ * characters are XML 1.1 restricted characters.
+ */
+ private void writeEncodedWithRestrictedChars(String text, boolean inAttr)
+ throws IOException
+ {
+ int[] seq = UnicodeReader.toCodePointArray(text);
+ for (int i = 0; i < seq.length; i++)
+ {
+ int c = seq[i];
+ switch (c)
+ {
+ case 0x3c: // '<'
+ writer.write("&lt;");
+ break;
+ case 0x3e: // '>'
+ writer.write("&gt;");
+ break;
+ case 0x26: // '&'
+ writer.write("&amp;");
+ break;
+ case 0x22: // '"'
+ if (inAttr)
+ writer.write("&quot;");
+ else
+ writer.write(c);
+ break;
+ case 0x27: // '\''
+ if (inAttr)
+ writer.write("&apos;");
+ else
+ writer.write(c);
+ break;
+ default:
+ if (XMLParser.isXML11RestrictedChar(c))
+ writer.write("&#x" + Integer.toHexString(c) + ";");
+ else
+ {
+ char[] chars = Character.toChars(c);
+ writer.write(chars, 0, chars.length);
+ }
+ }
+ }
+ }
+
+ private boolean isName(String text)
+ throws IOException
+ {
+ if (text == null)
+ return false;
+ int[] seq = UnicodeReader.toCodePointArray(text);
+ if (seq.length < 1)
+ return false;
+ if (!XMLParser.isNameStartCharacter(seq[0], xml11))
+ return false;
+ for (int i = 1; i < seq.length; i++)
+ {
+ if (!XMLParser.isNameCharacter(seq[i], xml11))
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isPrefix(String text)
+ throws IOException
+ {
+ if (XMLConstants.DEFAULT_NS_PREFIX.equals(text)) {
+ return true;
+ }
+ return isNCName(text);
+ }
+
+ private boolean isNCName(String text)
+ throws IOException
+ {
+ if (text == null)
+ return false;
+ int[] seq = UnicodeReader.toCodePointArray(text);
+ if (seq.length < 1)
+ return false;
+ if (!XMLParser.isNameStartCharacter(seq[0], xml11) || seq[0] == 0x3a)
+ return false;
+ for (int i = 1; i < seq.length; i++)
+ {
+ if (!XMLParser.isNameCharacter(seq[i], xml11) || seq[i] == 0x3a)
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isChars(String text)
+ throws IOException
+ {
+ if (text == null)
+ return false;
+ int[] seq = UnicodeReader.toCodePointArray(text);
+ hasXML11RestrictedChars = false;
+ if (xml11)
+ {
+ for (int i = 0; i < seq.length; i++)
+ {
+ if (!XMLParser.isXML11Char(seq[i]))
+ return false;
+ if (XMLParser.isXML11RestrictedChar(seq[i]))
+ hasXML11RestrictedChars = true;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < seq.length; i++)
+ {
+ if (!XMLParser.isChar(seq[i]))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isURI(String text)
+ {
+ if (text == null)
+ return false;
+ char[] chars = text.toCharArray();
+ if (chars.length < 1)
+ return false;
+ for (int i = 0; i < chars.length; i++)
+ {
+ if (chars[i] < 0x20 || chars[i] >= 0x7f)
+ return false;
+ }
+ return true;
+ }
+
+}