diff options
Diffstat (limited to 'libjava/classpath/gnu/xml/stream')
19 files changed, 602 insertions, 1573 deletions
diff --git a/libjava/classpath/gnu/xml/stream/CRLFReader.java b/libjava/classpath/gnu/xml/stream/CRLFReader.java index 1d214ce52c1..dad02b94a1d 100644 --- a/libjava/classpath/gnu/xml/stream/CRLFReader.java +++ b/libjava/classpath/gnu/xml/stream/CRLFReader.java @@ -1,5 +1,5 @@ /* CRLFReader.java -- - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005,2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -153,13 +153,14 @@ class CRLFReader throws IOException { doReset = false; - int lm1 = len - 1; - for (int i = off; i < len; i++) + int end = off + len; + int em1 = end - 1; + for (int i = off; i < end; i++) { if (b[i] == '\r') // CR { int d; - if (i == lm1) + if (i == em1) { d = in.read(); doReset = true; diff --git a/libjava/classpath/gnu/xml/stream/EndEntityImpl.java b/libjava/classpath/gnu/xml/stream/EndEntityImpl.java deleted file mode 100644 index fd36ee267d3..00000000000 --- a/libjava/classpath/gnu/xml/stream/EndEntityImpl.java +++ /dev/null @@ -1,80 +0,0 @@ -/* EndEntityImpl.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.EndEntity; - -/** - * An end-entity event. - * - * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> - */ -public class EndEntityImpl - extends XMLEventImpl - implements EndEntity -{ - - protected final String name; - - protected EndEntityImpl(Location location, String name) - { - super(location); - this.name = name; - } - - public int getEventType() - { - return END_ENTITY; - } - - public String getName() - { - return name; - } - - public void writeAsEncodedUnicode(Writer writer) - throws XMLStreamException - { - } - -} - diff --git a/libjava/classpath/gnu/xml/stream/EntityReferenceImpl.java b/libjava/classpath/gnu/xml/stream/EntityReferenceImpl.java index 4b40bfa526a..38e1f00b1af 100644 --- a/libjava/classpath/gnu/xml/stream/EntityReferenceImpl.java +++ b/libjava/classpath/gnu/xml/stream/EntityReferenceImpl.java @@ -1,5 +1,5 @@ /* EntityReferenceImpl.java -- - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005,2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,7 +41,7 @@ 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.EntityDeclaration; import javax.xml.stream.events.EntityReference; /** @@ -54,26 +54,16 @@ public class EntityReferenceImpl implements EntityReference { - //protected final EntityDeclaration decl; + protected final EntityDeclaration decl; protected final String name; - protected final String baseUri; - protected final String publicId; - protected final String systemId; - protected final String replacementText; protected EntityReferenceImpl(Location location, - //EntityDeclaration decl, - String name, - String baseUri, String publicId, - String systemId, String replacementText) + EntityDeclaration decl, + String name) { super(location); - //this.decl = decl; + this.decl = decl; this.name = name; - this.baseUri = baseUri; - this.publicId = publicId; - this.systemId = systemId; - this.replacementText = replacementText; } public int getEventType() @@ -81,36 +71,16 @@ public class EntityReferenceImpl return ENTITY_REFERENCE; } - /*public EntityDeclaration getDeclaration() + public EntityDeclaration getDeclaration() { return decl; - }*/ + } public String getName() { return name; } - public String getBaseUri() - { - return baseUri; - } - - public String getPublicId() - { - return publicId; - } - - public String getSystemId() - { - return systemId; - } - - public String getReplacementText() - { - return replacementText; - } - public void writeAsEncodedUnicode(Writer writer) throws XMLStreamException { diff --git a/libjava/classpath/gnu/xml/stream/FilteredEventReader.java b/libjava/classpath/gnu/xml/stream/FilteredEventReader.java index 3bf0f2518b5..fd6fe8b0721 100644 --- a/libjava/classpath/gnu/xml/stream/FilteredEventReader.java +++ b/libjava/classpath/gnu/xml/stream/FilteredEventReader.java @@ -1,5 +1,5 @@ /* FilteredEventReader.java -- - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005,2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -56,24 +56,37 @@ class FilteredEventReader } public boolean hasNext() - throws XMLStreamException { // XXX ??? return super.hasNext(); } - public XMLEvent next() + public XMLEvent nextEvent() throws XMLStreamException { XMLEvent ret; do { - ret = super.next(); + 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 { diff --git a/libjava/classpath/gnu/xml/stream/LocationImpl.java b/libjava/classpath/gnu/xml/stream/LocationImpl.java deleted file mode 100644 index 1900aeb45c3..00000000000 --- a/libjava/classpath/gnu/xml/stream/LocationImpl.java +++ /dev/null @@ -1,89 +0,0 @@ -/* LocationImpl.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.Location; - -/** - * Information about the location of an XML event within the underlying - * stream. - * - * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> - */ -public class LocationImpl - implements Location -{ - - protected final int offset; - - protected final int col; - - protected final int line; - - protected final String systemId; - - protected LocationImpl(int offset, int col, int line, String systemId) - { - this.offset = offset; - this.col = col; - this.line = line; - this.systemId = systemId; - } - - public int getLineNumber() - { - return line; - } - - public int getColumnNumber() - { - return col; - } - - public int getCharacterOffset() - { - return offset; - } - - public String getLocationURI() - { - return systemId; - } - -} - diff --git a/libjava/classpath/gnu/xml/stream/SAXParser.java b/libjava/classpath/gnu/xml/stream/SAXParser.java index 54c8b36244b..fd768a43da3 100644 --- a/libjava/classpath/gnu/xml/stream/SAXParser.java +++ b/libjava/classpath/gnu/xml/stream/SAXParser.java @@ -1,5 +1,5 @@ /* SAXParser.java -- - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -92,8 +92,7 @@ import org.xml.sax.ext.Locator2; */ public class SAXParser extends javax.xml.parsers.SAXParser - implements XMLReader, Attributes2, Locator2, XMLReporter, - XMLParser.XMLResolver2 + implements XMLReader, Attributes2, Locator2, XMLReporter, XMLResolver { ContentHandler contentHandler; @@ -323,6 +322,7 @@ public class SAXParser supportDTD, baseAware, stringInterning, + true, this, this); else @@ -338,6 +338,7 @@ public class SAXParser supportDTD, baseAware, stringInterning, + true, this, this); } @@ -357,6 +358,7 @@ public class SAXParser supportDTD, baseAware, stringInterning, + true, this, this); } @@ -486,14 +488,14 @@ public class SAXParser contentHandler.processingInstruction(target, data); } break; - case XMLStreamConstants.START_ENTITY: + case XMLParser.START_ENTITY: if (lexicalHandler != null) { String name = reader.getText(); lexicalHandler.startEntity(name); } break; - case XMLStreamConstants.END_ENTITY: + case XMLParser.END_ENTITY: if (lexicalHandler != null) { String name = reader.getText(); @@ -649,24 +651,36 @@ public class SAXParser lexicalHandler.endDTD(); } } + reset(); + if (opened) + in.close(); } - catch (XMLStreamException e) + catch (Exception e) { - if (!startDocumentDone && contentHandler != null) - contentHandler.startDocument(); SAXParseException e2 = new SAXParseException(e.getMessage(), this); e2.initCause(e); - if (errorHandler != null) - errorHandler.fatalError(e2); - if (contentHandler != null) - contentHandler.endDocument(); - throw e2; - } - finally - { + 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(); - reset(); + if (e instanceof SAXException) + throw (SAXException) e; + if (e instanceof IOException) + throw (IOException) e; + else + throw e2; } } @@ -685,7 +699,7 @@ public class SAXParser int ac = reader.getAttributeCount(); for (int i = 0; i < ac; i++) { - QName aname = reader.getAttributeQName(i); + QName aname = reader.getAttributeName(i); if ("space".equals(aname.getLocalPart()) && XMLConstants.XML_NS_URI.equals(aname.getNamespaceURI())) { @@ -726,7 +740,7 @@ public class SAXParser int len = reader.getAttributeCount(); for (int i = 0; i < len; i++) { - QName q = reader.getAttributeQName(i); + QName q = reader.getAttributeName(i); String localName = q.getLocalPart(); String prefix = q.getPrefix(); String qn = ("".equals(prefix)) ? localName : prefix + ":" + localName; @@ -741,7 +755,7 @@ public class SAXParser int len = reader.getAttributeCount(); for (int i = 0; i < len; i++) { - QName q = reader.getAttributeQName(i); + QName q = reader.getAttributeName(i); String ln = q.getLocalPart(); String u = q.getNamespaceURI(); if (u == null && uri != null) @@ -761,12 +775,12 @@ public class SAXParser public String getLocalName(int index) { - return reader.getAttributeName(index); + return reader.getAttributeLocalName(index); } public String getQName(int index) { - QName q = reader.getAttributeQName(index); + QName q = reader.getAttributeName(index); String localName = q.getLocalPart(); String prefix = q.getPrefix(); return ("".equals(prefix)) ? localName : prefix + ":" + localName; @@ -864,13 +878,14 @@ public class SAXParser public String getPublicId() { - return null; + Location l = reader.getLocation(); + return l.getPublicId(); } public String getSystemId() { Location l = reader.getLocation(); - return l.getLocationURI(); + return l.getSystemId(); } public String getEncoding() @@ -885,13 +900,8 @@ public class SAXParser // -- XMLResolver -- - public InputStream resolve(String uri) - throws XMLStreamException - { - return resolve(null, uri); - } - - public InputStream resolve(String publicId, String systemId) + public Object resolveEntity(String publicId, String systemId, + String baseURI, String namespace) throws XMLStreamException { if (entityResolver != null) @@ -901,7 +911,16 @@ public class SAXParser InputSource input = entityResolver.resolveEntity(publicId, systemId); if (input != null) - return input.getByteStream(); + { + 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) { diff --git a/libjava/classpath/gnu/xml/stream/StartEntityImpl.java b/libjava/classpath/gnu/xml/stream/StartEntityImpl.java deleted file mode 100644 index 6e4ca257a2c..00000000000 --- a/libjava/classpath/gnu/xml/stream/StartEntityImpl.java +++ /dev/null @@ -1,80 +0,0 @@ -/* StartEntityImpl.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.StartEntity; - -/** - * A start-entity event. - * - * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> - */ -public class StartEntityImpl - extends XMLEventImpl - implements StartEntity -{ - - protected final String name; - - protected StartEntityImpl(Location location, String name) - { - super(location); - this.name = name; - } - - public int getEventType() - { - return START_ENTITY; - } - - public String getName() - { - return name; - } - - public void writeAsEncodedUnicode(Writer writer) - throws XMLStreamException - { - } - -} - diff --git a/libjava/classpath/gnu/xml/stream/UnicodeReader.java b/libjava/classpath/gnu/xml/stream/UnicodeReader.java index c38516c30f8..9350cb2e0b6 100644 --- a/libjava/classpath/gnu/xml/stream/UnicodeReader.java +++ b/libjava/classpath/gnu/xml/stream/UnicodeReader.java @@ -45,7 +45,7 @@ import java.io.Reader; * * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> */ -class UnicodeReader +public class UnicodeReader { final Reader in; @@ -152,6 +152,10 @@ class UnicodeReader in.close(); } + /** + * Returns the specified UTF-16 char array as an array of Unicode code + * points. + */ public static int[] toCodePointArray(String text) throws IOException { diff --git a/libjava/classpath/gnu/xml/stream/XIncludeFilter.java b/libjava/classpath/gnu/xml/stream/XIncludeFilter.java index e151ac69d3c..7e707820d52 100644 --- a/libjava/classpath/gnu/xml/stream/XIncludeFilter.java +++ b/libjava/classpath/gnu/xml/stream/XIncludeFilter.java @@ -42,6 +42,7 @@ import java.io.InputStreamReader; import java.io.IOException; import java.io.Reader; import java.net.HttpURLConnection; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.HashSet; @@ -121,7 +122,17 @@ class XIncludeFilter boolean expandERefs) { super(reader); - this.systemId = XMLParser.absolutize(null, systemId); + try + { + this.systemId = XMLParser.absolutize(null, systemId); + } + catch (MalformedURLException e) + { + RuntimeException e2 = new RuntimeException("unsupported URL: " + + systemId); + e2.initCause(e); + throw e2; + } this.namespaceAware = namespaceAware; this.validating = validating; this.expandERefs = expandERefs; @@ -137,7 +148,7 @@ class XIncludeFilter return super.getAttributeCount(); } - public String getAttributeName(int index) + public String getAttributeLocalName(int index) { if (current != null) { @@ -147,7 +158,7 @@ class XIncludeFilter Node attr = attrs.item(index); return attr.getLocalName(); } - return super.getAttributeName(index); + return super.getAttributeLocalName(index); } public String getAttributeNamespace(int index) @@ -176,7 +187,7 @@ class XIncludeFilter return super.getAttributePrefix(index); } - public QName getAttributeQName(int index) + public QName getAttributeName(int index) { if (current != null) { @@ -189,7 +200,7 @@ class XIncludeFilter String prefix = attr.getPrefix(); return new QName(uri, localName, prefix); } - return super.getAttributeQName(index); + return super.getAttributeName(index); } public String getAttributeType(int index) diff --git a/libjava/classpath/gnu/xml/stream/XMLEventAllocatorImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventAllocatorImpl.java index 4b21b6c7110..666bffabe23 100644 --- a/libjava/classpath/gnu/xml/stream/XMLEventAllocatorImpl.java +++ b/libjava/classpath/gnu/xml/stream/XMLEventAllocatorImpl.java @@ -1,5 +1,5 @@ /* XMLEventAllocatorImpl.java -- - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005,2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -116,10 +116,9 @@ public class XMLEventAllocatorImpl namespaces); case XMLStreamConstants.ENTITY_REFERENCE: String name = reader.getLocalName(); - //EntityDeclaration decl = - // (EntityDeclaration) entityDeclarations.get(name); - //return new EntityReferenceImpl(location, decl, name); - return new EntityReferenceImpl(location, name, null, null, null, null); + EntityDeclaration decl = + (EntityDeclaration) entityDeclarations.get(name); + return new EntityReferenceImpl(location, decl, name); case XMLStreamConstants.PROCESSING_INSTRUCTION: return new ProcessingInstructionImpl(location, reader.getPITarget(), @@ -132,7 +131,7 @@ public class XMLEventAllocatorImpl return new CharactersImpl(location, text, whitespace, false, ignorableWhitespace); case XMLStreamConstants.START_DOCUMENT: - String systemId = location.getLocationURI(); + String systemId = location.getSystemId(); String encoding = reader.getCharacterEncodingScheme(); boolean encodingDeclared = encoding != null; if (encoding == null) @@ -164,7 +163,7 @@ public class XMLEventAllocatorImpl List attributes = new LinkedList(); for (int i = 0; i < len; i++) attributes.add(new AttributeImpl(location, - reader.getAttributeQName(i), + reader.getAttributeName(i), reader.getAttributeValue(i), QName.valueOf(reader.getAttributeType(i)), reader.isAttributeSpecified(i))); diff --git a/libjava/classpath/gnu/xml/stream/XMLEventFactoryImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventFactoryImpl.java index a839b182c09..e1d7d6ab82f 100644 --- a/libjava/classpath/gnu/xml/stream/XMLEventFactoryImpl.java +++ b/libjava/classpath/gnu/xml/stream/XMLEventFactoryImpl.java @@ -1,5 +1,5 @@ /* XMLEventFactoryImpl.java -- - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005,2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -233,12 +233,9 @@ public class XMLEventFactoryImpl } public EntityReference createEntityReference(String name, - //EntityDeclaration declaration) - String replacementText) + EntityDeclaration declaration) { - //return new EntityReferenceImpl(location, declaration, name); - return new EntityReferenceImpl(location, name, null, null, null, - replacementText); + return new EntityReferenceImpl(location, declaration, name); } public Comment createComment(String text) diff --git a/libjava/classpath/gnu/xml/stream/XMLEventImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventImpl.java index a8b522f88a7..9f57d89d828 100644 --- a/libjava/classpath/gnu/xml/stream/XMLEventImpl.java +++ b/libjava/classpath/gnu/xml/stream/XMLEventImpl.java @@ -1,5 +1,5 @@ /* XMLEventImpl.java -- - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005,2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -116,16 +116,6 @@ public abstract class XMLEventImpl return getEventType() == END_DOCUMENT; } - public boolean isStartEntity() - { - return getEventType() == START_ENTITY; - } - - public boolean isEndEntity() - { - return getEventType() == END_ENTITY; - } - public StartElement asStartElement() { return (StartElement) this; diff --git a/libjava/classpath/gnu/xml/stream/XMLEventReaderImpl.java b/libjava/classpath/gnu/xml/stream/XMLEventReaderImpl.java index 70481d7c407..bb64b1e3f9d 100644 --- a/libjava/classpath/gnu/xml/stream/XMLEventReaderImpl.java +++ b/libjava/classpath/gnu/xml/stream/XMLEventReaderImpl.java @@ -67,7 +67,7 @@ public class XMLEventReaderImpl this.systemId = systemId; } - public XMLEvent next() + public XMLEvent nextEvent() throws XMLStreamException { XMLEvent ret = peek(); @@ -75,10 +75,32 @@ public class XMLEventReaderImpl return ret; } + public Object next() + { + try + { + return nextEvent(); + } + catch (XMLStreamException e) + { + RuntimeException e2 = new RuntimeException(); + e2.initCause(e); + throw e2; + } + } + public boolean hasNext() - throws XMLStreamException { - return peekEvent != null || reader.hasNext(); + if (peekEvent != null) + return true; + try + { + return reader.hasNext(); + } + catch (XMLStreamException e) + { + return false; + } } public XMLEvent peek() @@ -121,5 +143,16 @@ public class XMLEventReaderImpl 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 index 45024158da6..72b7adce24c 100644 --- a/libjava/classpath/gnu/xml/stream/XMLEventWriterImpl.java +++ b/libjava/classpath/gnu/xml/stream/XMLEventWriterImpl.java @@ -155,7 +155,7 @@ public class XMLEventWriterImpl throws XMLStreamException { while (reader.hasNext()) - add(reader.next()); + add(reader.nextEvent()); } public String getPrefix(String uri) diff --git a/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java b/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java index 164774d8236..5f72e361e52 100644 --- a/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java +++ b/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java @@ -1,5 +1,5 @@ /* XMLInputFactoryImpl.java -- - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005,2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -89,14 +89,15 @@ public class XMLInputFactoryImpl public XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException { - /* - return new XMLStreamReaderImpl(reader, null, null, - resolver, reporter, - validating, namespaceAware, - coalescing, replacingEntityReferences, - externalEntities, supportDTD); - */ - XMLParser ret = new XMLParser(reader, null, + 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, @@ -105,24 +106,30 @@ public class XMLInputFactoryImpl supportDTD, baseAware, stringInterning, + false, reporter, resolver); if (xIncludeAware) - return new XIncludeFilter(ret, null, namespaceAware, validating, + return new XIncludeFilter(ret, systemId, namespaceAware, validating, replacingEntityReferences); return ret; } - public XMLStreamReader createXMLStreamReader(Source source) + 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 { - String systemId = source.getSystemId(); - InputStream in = getInputStream(source); - /*return new XMLStreamReaderImpl(in, null, systemId, - resolver, reporter, - validating, namespaceAware, - coalescing, replacingEntityReferences, - externalEntities, supportDTD);*/ XMLParser ret = new XMLParser(in, systemId, validating, namespaceAware, @@ -132,23 +139,19 @@ public class XMLInputFactoryImpl supportDTD, baseAware, stringInterning, + false, reporter, resolver); if (xIncludeAware) - return new XIncludeFilter(ret, systemId, namespaceAware, validating, + return new XIncludeFilter(ret, null, namespaceAware, validating, replacingEntityReferences); return ret; } - - public XMLStreamReader createXMLStreamReader(InputStream in) + + public XMLStreamReader createXMLStreamReader(String systemId, Reader reader) throws XMLStreamException { - /*return new XMLStreamReaderImpl(in, null, null, - resolver, reporter, - validating, namespaceAware, - coalescing, replacingEntityReferences, - externalEntities, supportDTD);*/ - XMLParser ret = new XMLParser(in, null, + XMLParser ret = new XMLParser(reader, systemId, validating, namespaceAware, coalescing, @@ -157,6 +160,7 @@ public class XMLInputFactoryImpl supportDTD, baseAware, stringInterning, + false, reporter, resolver); if (xIncludeAware) @@ -164,12 +168,6 @@ public class XMLInputFactoryImpl replacingEntityReferences); return ret; } - - public XMLStreamReader createXMLStreamReader(InputStream in, String encoding) - throws XMLStreamException - { - return createXMLStreamReader(in); - } public XMLEventReader createXMLEventReader(Reader reader) throws XMLStreamException @@ -178,6 +176,13 @@ public class XMLInputFactoryImpl 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 { @@ -205,6 +210,13 @@ public class XMLInputFactoryImpl 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 diff --git a/libjava/classpath/gnu/xml/stream/XMLOutputFactoryImpl.java b/libjava/classpath/gnu/xml/stream/XMLOutputFactoryImpl.java index 05b6d6c0f11..c8c651fb1af 100644 --- a/libjava/classpath/gnu/xml/stream/XMLOutputFactoryImpl.java +++ b/libjava/classpath/gnu/xml/stream/XMLOutputFactoryImpl.java @@ -42,6 +42,8 @@ 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; @@ -94,6 +96,22 @@ public class XMLOutputFactoryImpl } } + 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 { @@ -116,10 +134,26 @@ public class XMLOutputFactoryImpl 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_PREFIX_DEFAULTING.equals(name)) + if (IS_REPAIRING_NAMESPACES.equals(name)) prefixDefaulting = ((Boolean) value).booleanValue(); else throw new IllegalArgumentException(name); @@ -128,14 +162,14 @@ public class XMLOutputFactoryImpl public Object getProperty(String name) throws IllegalArgumentException { - if (IS_PREFIX_DEFAULTING.equals(name)) + if (IS_REPAIRING_NAMESPACES.equals(name)) return new Boolean(prefixDefaulting); throw new IllegalArgumentException(name); } public boolean isPropertySupported(String name) { - if (IS_PREFIX_DEFAULTING.equals(name)) + if (IS_REPAIRING_NAMESPACES.equals(name)) return true; return false; } diff --git a/libjava/classpath/gnu/xml/stream/XMLParser.java b/libjava/classpath/gnu/xml/stream/XMLParser.java index 6f10b9303dc..9bb4834267e 100644 --- a/libjava/classpath/gnu/xml/stream/XMLParser.java +++ b/libjava/classpath/gnu/xml/stream/XMLParser.java @@ -137,6 +137,10 @@ public class XMLParser 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. */ @@ -318,6 +322,12 @@ public class XMLParser 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; @@ -389,6 +399,7 @@ public class XMLParser boolean supportDTD, boolean baseAware, boolean stringInterning, + boolean extendedEventTypes, XMLReporter reporter, XMLResolver resolver) { @@ -400,6 +411,7 @@ public class XMLParser this.supportDTD = supportDTD; this.baseAware = baseAware; this.stringInterning = stringInterning; + this.extendedEventTypes = extendedEventTypes; this.reporter = reporter; this.resolver = resolver; if (validating) @@ -446,6 +458,7 @@ public class XMLParser boolean supportDTD, boolean baseAware, boolean stringInterning, + boolean extendedEventTypes, XMLReporter reporter, XMLResolver resolver) { @@ -457,6 +470,7 @@ public class XMLParser this.supportDTD = supportDTD; this.baseAware = baseAware; this.stringInterning = stringInterning; + this.extendedEventTypes = extendedEventTypes; this.reporter = reporter; this.resolver = resolver; if (validating) @@ -561,7 +575,7 @@ public class XMLParser return attrs.size(); } - public String getAttributeName(int index) + public String getAttributeLocalName(int index) { Attribute a = (Attribute) attrs.get(index); return a.localName; @@ -579,7 +593,7 @@ public class XMLParser return a.prefix; } - public QName getAttributeQName(int index) + public QName getAttributeName(int index) { Attribute a = (Attribute) attrs.get(index); String namespaceURI = getNamespaceURI(a.prefix); @@ -710,7 +724,7 @@ public class XMLParser public int getNamespaceCount() { - if (!namespaceAware) + if (!namespaceAware || namespaces.isEmpty()) return 0; switch (event) { @@ -984,10 +998,10 @@ public class XMLParser if (event == XMLStreamConstants.END_ELEMENT) { // Pop namespace context - if (namespaceAware) + if (namespaceAware && !namespaces.isEmpty()) namespaces.removeFirst(); // Pop base context - if (baseAware) + if (baseAware && !bases.isEmpty()) bases.removeFirst(); } if (!startEntityStack.isEmpty()) @@ -995,16 +1009,16 @@ public class XMLParser String entityName = (String) startEntityStack.removeFirst(); buf.setLength(0); buf.append(entityName); - event = XMLStreamConstants.START_ENTITY; - return event; + event = START_ENTITY; + return extendedEventTypes ? event : next(); } else if (!endEntityStack.isEmpty()) { String entityName = (String) endEntityStack.removeFirst(); buf.setLength(0); buf.append(entityName); - event = XMLStreamConstants.END_ENTITY; - return event; + event = END_ENTITY; + return extendedEventTypes ? event : next(); } try { @@ -1484,7 +1498,6 @@ public class XMLParser { if (!externalEntities) return; - InputStream in = null; String url = absolutize(input.systemId, ids.systemId); // Check for recursion for (Iterator i = inputStack.iterator(); i.hasNext(); ) @@ -1497,12 +1510,13 @@ public class XMLParser } if (name == null || "".equals(name)) report = false; - if (in == null && url != null && resolver != null) + InputStream in = null; + if (resolver != null) { - if (resolver instanceof XMLResolver2) - in = ((XMLResolver2) resolver).resolve(ids.publicId, url); - else - in = resolver.resolve(url); + Object obj = resolver.resolveEntity(ids.publicId, url, getXMLBase(), + null); + if (obj instanceof InputStream) + in = (InputStream) obj; } if (in == null) in = resolve(url); @@ -1535,12 +1549,13 @@ public class XMLParser * @param base the current base URL * @param href the (absolute or relative) URL to resolve */ - static String absolutize(String base, String href) + public static String absolutize(String base, String href) + throws MalformedURLException { if (href == null) return null; int ci = href.indexOf(':'); - if (ci > 1 && isLowercaseAscii(href.substring(0, ci))) + if (ci > 1 && isURLScheme(href.substring(0, ci))) { // href is absolute already return href; @@ -1565,40 +1580,23 @@ public class XMLParser if (!base.endsWith("/")) base += "/"; } - if (href.startsWith("/")) - { - if (base.startsWith("file:")) - return "file://" + href; - int i = base.indexOf("://"); - if (i != -1) - { - i = base.indexOf('/', i + 3); - if (i != -1) - base = base.substring(0, i); - } - } - else - { - while (href.startsWith("..")) - { - int i = base.lastIndexOf('/', base.length() - 2); - if (i != -1) - base = base.substring(0, i + 1); - href = href.substring(2); - if (href.startsWith("/")) - href = href.substring(1); - } - } - return base + href; + return new URL(new URL(base), href).toString(); } - private static boolean isLowercaseAscii(String text) + /** + * 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 < 97 || c > 122) + if (c == '+' || c == '.' || c == '-') + continue; + if (c < 65 || (c > 90 && c < 97) || c > 122) return false; } return true; @@ -1607,7 +1605,7 @@ public class XMLParser /** * Returns an input stream for the given URL. */ - private InputStream resolve(String url) + static InputStream resolve(String url) throws IOException { try @@ -1618,6 +1616,12 @@ public class XMLParser { return null; } + catch (IOException e) + { + IOException e2 = new IOException("error resolving " + url); + e2.initCause(e); + throw e2; + } } /** @@ -1891,7 +1895,10 @@ public class XMLParser throws IOException, XMLStreamException { requireWhitespace(); + boolean saved = expandPE; + expandPE = (inputStack.size() > 1); String name = readNmtoken(true); + expandPE = saved; requireWhitespace(); readContentspec(name); skipWhitespace(); @@ -2106,7 +2113,10 @@ public class XMLParser throws IOException, XMLStreamException { requireWhitespace(); + boolean saved = expandPE; + expandPE = (inputStack.size() > 1); String elementName = readNmtoken(true); + expandPE = saved; boolean white = tryWhitespace(); while (!tryRead('>')) { @@ -2419,11 +2429,11 @@ public class XMLParser } else { - if (!isNameStartCharacter(cp[0])) + 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])) + if (!isNameCharacter(cp[i], input.xml11)) error("malformed reference in entity value", value); } } @@ -2838,8 +2848,6 @@ public class XMLParser error("Duplicate default namespace declaration"); if (XMLConstants.XML_NS_URI.equals(attr.value)) error("can't bind XML namespace"); - if ("".equals(attr.value) && !input.xml11) - error("illegal use of 1.1-style prefix unbinding in 1.0 document"); ctx.put(XMLConstants.DEFAULT_NS_PREFIX, attr.value); return true; } @@ -3087,7 +3095,15 @@ public class XMLParser break; case 0x3c: // '<' reset(); - read(tmpBuf, 0, i); + // 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 @@ -3258,15 +3274,7 @@ public class XMLParser reset(); char[] ref = readCharacterRef(hex ? 16 : 10); for (int i = 0; i < ref.length; i++) - { - char x = ref[i]; - if ((flags & (LIT_ATTRIBUTE | LIT_PUBID)) != 0 && - (x == 0x0a || x == 0x0d)) - x = 0x20; // normalize - else if ((flags & LIT_ATTRIBUTE) != 0 && x == 0x09) - x = 0x20; // normalize - literalBuf.append(x); - } + literalBuf.append(ref[i]); entities = true; continue; } @@ -3469,13 +3477,13 @@ public class XMLParser int c = readCh(); if (isName) { - if (!isNameStartCharacter(c)) + if (!isNameStartCharacter(c, input.xml11)) error("not a name start character", "U+" + Integer.toHexString(c)); } else { - if (!isNameCharacter(c)) + if (!isNameCharacter(c, input.xml11)) error("not a name character", "U+" + Integer.toHexString(c)); } @@ -3510,7 +3518,7 @@ public class XMLParser reset(); return intern(buf.toString()); default: - if (!isNameCharacter(c)) + if (!isNameCharacter(c, input.xml11)) error("not a name character", "U+" + Integer.toHexString(c)); else @@ -3523,7 +3531,7 @@ public class XMLParser /** * Indicates whether the specified Unicode character is an XML 1.1 Char. */ - private boolean isXML11Char(int c) + public static boolean isXML11Char(int c) { return ((c >= 0x0001 && c <= 0xD7FF) || (c >= 0xE000 && c < 0xFFFD) || // NB exclude 0xfffd @@ -3534,7 +3542,7 @@ public class XMLParser * Indicates whether the specified Unicode character is an XML 1.1 * RestrictedChar. */ - private boolean isXML11RestrictedChar(int c) + public static boolean isXML11RestrictedChar(int c) { return ((c >= 0x0001 && c <= 0x0008) || (c >= 0x000B && c <= 0x000C) || @@ -3556,17 +3564,17 @@ public class XMLParser return false; if (isName) { - if (!isNameStartCharacter(cp[0])) + if (!isNameStartCharacter(cp[0], input.xml11)) return false; } else { - if (!isNameCharacter(cp[0])) + if (!isNameCharacter(cp[0], input.xml11)) return false; } for (int i = 1; i < cp.length; i++) { - if (!isNameCharacter(cp[i])) + if (!isNameCharacter(cp[i], input.xml11)) return false; } return true; @@ -3581,9 +3589,9 @@ public class XMLParser * Indicates whether the specified Unicode character is a Name start * character. */ - private boolean isNameStartCharacter(int c) + public static boolean isNameStartCharacter(int c, boolean xml11) { - if (input.xml11) + if (xml11) return ((c >= 0x0041 && c <= 0x005a) || (c >= 0x0061 && c <= 0x007a) || c == 0x3a | @@ -3608,9 +3616,9 @@ public class XMLParser * Indicates whether the specified Unicode character is a Name non-initial * character. */ - private boolean isNameCharacter(int c) + public static boolean isNameCharacter(int c, boolean xml11) { - if (input.xml11) + if (xml11) return ((c >= 0x0041 && c <= 0x005a) || (c >= 0x0061 && c <= 0x007a) || (c >= 0x0030 && c <= 0x0039) || @@ -4255,6 +4263,7 @@ public class XMLParser true, // supportDTD true, // baseAware true, // stringInterning + true, // extendedEventTypes null, null); XMLStreamReader reader = p; @@ -4286,7 +4295,7 @@ public class XMLParser "='"+reader.getNamespaceURI(i)+"'"); l = reader.getAttributeCount(); for (int i = 0; i < l; i++) - System.out.println("\tattribute "+reader.getAttributeQName(i)+ + System.out.println("\tattribute "+reader.getAttributeName(i)+ "='"+reader.getAttributeValue(i)+"'"); break; case XMLStreamConstants.END_ELEMENT: @@ -4314,10 +4323,10 @@ public class XMLParser System.out.println("PROCESSING_INSTRUCTION "+reader.getPITarget()+ " "+reader.getPIData()); break; - case XMLStreamConstants.START_ENTITY: + case START_ENTITY: System.out.println("START_ENTITY "+reader.getText()); break; - case XMLStreamConstants.END_ENTITY: + case END_ENTITY: System.out.println("END_ENTITY "+reader.getText()); break; default: @@ -4330,7 +4339,7 @@ public class XMLParser Location l = reader.getLocation(); System.out.println("At line "+l.getLineNumber()+ ", column "+l.getColumnNumber()+ - " of "+l.getLocationURI()); + " of "+l.getSystemId()); throw e; } } @@ -4939,19 +4948,6 @@ public class XMLParser } /** - * Compatibility interface that can be used to resolve based on a public - * ID, not just an URL. - */ - interface XMLResolver2 - extends XMLResolver - { - - InputStream resolve(String publicId, String systemId) - throws XMLStreamException; - - } - - /** * An XML input source. */ static class Input @@ -5019,7 +5015,12 @@ public class XMLParser return line; } - public String getLocationURI() + public String getPublicId() + { + return publicId; + } + + public String getSystemId() { return systemId; } diff --git a/libjava/classpath/gnu/xml/stream/XMLStreamReaderImpl.java b/libjava/classpath/gnu/xml/stream/XMLStreamReaderImpl.java deleted file mode 100644 index 568d800ae0d..00000000000 --- a/libjava/classpath/gnu/xml/stream/XMLStreamReaderImpl.java +++ /dev/null @@ -1,1037 +0,0 @@ -/* XMLStreamReaderImpl.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.IOException; -import java.io.Reader; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Map; -import javax.xml.namespace.NamespaceContext; -import javax.xml.namespace.QName; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import javax.xml.stream.Location; -import javax.xml.stream.XMLResolver; -import javax.xml.stream.XMLReporter; -import javax.xml.stream.XMLStreamConstants; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; - -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.EndEntity; -import javax.xml.stream.events.EntityDeclaration; -import javax.xml.stream.events.EntityReference; -import javax.xml.stream.events.Namespace; -import javax.xml.stream.events.NotationDeclaration; -import javax.xml.stream.events.ProcessingInstruction; -import javax.xml.stream.events.StartDocument; -import javax.xml.stream.events.StartElement; -import javax.xml.stream.events.StartEntity; -import javax.xml.stream.events.XMLEvent; - -import org.xml.sax.Attributes; -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.Locator; -import org.xml.sax.SAXException; -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; -import org.xml.sax.helpers.NamespaceSupport; - -/** - * An XML parser. - * - * This implementation uses SAX to create a series of events in memory, - * and then iterates over this series. This has the advantage of being simple - * and unifying the existing XML parsing code. However, it is quite - * memory-inefficient and obviously won't cope with streams of arbitrary - * length. - * - * A future task could be to write a real, progressive/incremental - * implementation of this class. In that case we should consider making that - * the default XML parser implementation and using a SAX wrapper to it to - * provide the GNU SAX implementation. - * - * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> - */ -public class XMLStreamReaderImpl - implements XMLStreamReader, NamespaceContext -{ - - private LinkedList events; - private XMLEvent currentEvent; - private int eventType; - private NamespaceSupport namespaces; - - protected String publicId; - protected String systemId; - - protected XMLResolver resolver; - protected XMLReporter reporter; - protected boolean validating; - protected boolean namespaceAware; - protected boolean coalescing; - protected boolean replacingEntityReferences; - protected boolean externalEntities; - protected boolean supportDTD; - - protected XMLStreamReaderImpl(InputStream in, - String publicId, - String systemId, - XMLResolver resolver, - XMLReporter reporter, - boolean validating, - boolean namespaceAware, - boolean coalescing, - boolean replacingEntityReferences, - boolean externalEntities, - boolean supportDTD) - throws XMLStreamException - { - //this.in = in; - this.publicId = publicId; - this.systemId = systemId; - this.resolver = resolver; - this.reporter = reporter; - this.validating = validating; - this.namespaceAware = namespaceAware; - this.coalescing = coalescing; - this.replacingEntityReferences = replacingEntityReferences; - this.externalEntities = externalEntities; - this.supportDTD = supportDTD; - namespaces = new NamespaceSupport(); - events = new LinkedList(); - - // Configure the SAX parser and perform the parse - try - { - SAXParserFactory f = SAXParserFactory.newInstance(); - f.setNamespaceAware(namespaceAware); - f.setValidating(validating); - SAXParser p = f.newSAXParser(); - XMLReader r = p.getXMLReader(); - CallbackHandler ch = this.new CallbackHandler(r); - r.setFeature("http://xml.org/sax/features/external-general-entities", - externalEntities); - r.setFeature("http://xml.org/sax/features/namespaces", - namespaceAware); - r.setContentHandler(ch); - r.setDTDHandler(ch); - r.setEntityResolver(ch); - r.setErrorHandler(ch); - r.setProperty("http://xml.org/sax/properties/lexical-handler", - ch); - InputSource source = new InputSource(in); - source.setSystemId(systemId); - r.parse(source); - } - catch (SAXException e) - { - events.add(e); - } - catch (IOException e) - { - events.add(e); - } - catch (ParserConfigurationException e) - { - XMLStreamException e2 = new XMLStreamException(e); - e2.initCause(e); - throw e2; - } - } - - protected XMLStreamReaderImpl(Reader reader, - String publicId, - String systemId, - XMLResolver resolver, - XMLReporter reporter, - boolean validating, - boolean namespaceAware, - boolean coalescing, - boolean replacingEntityReferences, - boolean externalEntities, - boolean supportDTD) - throws XMLStreamException - { - //this.reader = reader; - this.publicId = publicId; - this.systemId = systemId; - this.resolver = resolver; - this.reporter = reporter; - this.validating = validating; - this.namespaceAware = namespaceAware; - this.coalescing = coalescing; - this.replacingEntityReferences = replacingEntityReferences; - this.externalEntities = externalEntities; - this.supportDTD = supportDTD; - namespaces = new NamespaceSupport(); - events = new LinkedList(); - - // Configure the SAX parser and perform the parse - try - { - SAXParserFactory f = SAXParserFactory.newInstance(); - f.setNamespaceAware(namespaceAware); - f.setValidating(validating); - SAXParser p = f.newSAXParser(); - XMLReader r = p.getXMLReader(); - CallbackHandler ch = this.new CallbackHandler(r); - r.setFeature("http://xml.org/sax/features/external-general-entities", - externalEntities); - r.setFeature("http://xml.org/sax/features/namespaces", - namespaceAware); - r.setContentHandler(ch); - r.setDTDHandler(ch); - r.setEntityResolver(ch); - r.setErrorHandler(ch); - r.setProperty("http://xml.org/sax/properties/lexical-handler", - ch); - InputSource source = new InputSource(reader); - source.setSystemId(systemId); - r.parse(source); - } - catch (SAXException e) - { - events.add(e); - } - catch (IOException e) - { - events.add(e); - } - catch (ParserConfigurationException e) - { - XMLStreamException e2 = new XMLStreamException(e); - e2.initCause(e); - throw e2; - } - } - - public Object getProperty(String name) - throws IllegalArgumentException - { - throw new IllegalArgumentException(name); - } - - public int next() - throws XMLStreamException - { - if (events.isEmpty()) - throw new XMLStreamException("EOF"); - Object event = events.removeFirst(); - if (event instanceof Exception) - { - Exception e = (Exception) event; - XMLStreamException e2 = new XMLStreamException(e); - e2.initCause(e); - throw e2; - } - currentEvent = (XMLEvent) event; - eventType = currentEvent.getEventType(); - return eventType; - } - - public void require(int type, String namespaceURI, String localName) - throws XMLStreamException - { - // TODO - throw new UnsupportedOperationException(); - } - - public String getElementText() - throws XMLStreamException - { - // TODO - throw new UnsupportedOperationException(); - } - - public int nextTag() - throws XMLStreamException - { - int ret; - do - { - ret = next(); - } - while (ret != XMLStreamConstants.START_ELEMENT && - ret != XMLStreamConstants.END_ELEMENT); - return ret; - } - - public boolean hasNext() - throws XMLStreamException - { - return !events.isEmpty(); - } - - public void close() - throws XMLStreamException - { - } - - public String getNamespaceURI(String prefix) - { - return namespaces.getURI(prefix); - } - - public String getPrefix(String namespaceURI) - { - return namespaces.getPrefix(namespaceURI); - } - - public Iterator getPrefixes(String namespaceURI) - { - LinkedList acc = new LinkedList(); - for (Enumeration e = namespaces.getPrefixes(namespaceURI); - e.hasMoreElements(); ) - acc.add(e.nextElement()); - return acc.iterator(); - } - - public boolean isStartElement() - { - return eventType == START_ELEMENT; - } - - public boolean isEndElement() - { - return eventType == END_ELEMENT; - } - - public boolean isCharacters() - { - return eventType == CHARACTERS || eventType == CDATA; - } - - public boolean isWhiteSpace() - { - return eventType == SPACE; - } - - public String getAttributeValue(String namespaceURI, String localName) - { - StartElement se = (StartElement) currentEvent; - for (Iterator i = se.getAttributes(); i.hasNext(); ) - { - Attribute attr = (Attribute) i.next(); - QName name = attr.getName(); - if (namespaceURI != null && - !namespaceURI.equals(name.getNamespaceURI())) - continue; - if (!localName.equals(name.getLocalPart())) - continue; - return attr.getValue(); - } - return null; - } - - public int getAttributeCount() - { - StartElement se = (StartElement) currentEvent; - int count = 0; - for (Iterator i = se.getAttributes(); i.hasNext(); ) - { - i.next(); - count++; - } - return count; - } - - public QName getAttributeQName(int index) - { - StartElement se = (StartElement) currentEvent; - int count = 0; - for (Iterator i = se.getAttributes(); i.hasNext(); ) - { - Attribute attr = (Attribute) i.next(); - if (index == count) - return attr.getName(); - count++; - } - return null; - } - - public String getAttributeNamespace(int index) - { - QName name = getAttributeQName(index); - return (name == null) ? null : name.getNamespaceURI(); - } - - public String getAttributeName(int index) - { - QName name = getAttributeQName(index); - return (name == null) ? null : name.getLocalPart(); - } - - public String getAttributePrefix(int index) - { - QName name = getAttributeQName(index); - return (name == null) ? null : name.getPrefix(); - } - - public String getAttributeType(int index) - { - StartElement se = (StartElement) currentEvent; - int count = 0; - for (Iterator i = se.getAttributes(); i.hasNext(); ) - { - Attribute attr = (Attribute) i.next(); - if (index == count) - { - QName type = attr.getDTDType(); - return (type == null) ? "CDATA" : type.toString(); - } - count++; - } - return null; - } - - public String getAttributeValue(int index) - { - StartElement se = (StartElement) currentEvent; - int count = 0; - for (Iterator i = se.getAttributes(); i.hasNext(); ) - { - Attribute attr = (Attribute) i.next(); - if (index == count) - return attr.getValue(); - count++; - } - return null; - } - - public boolean isAttributeSpecified(int index) - { - StartElement se = (StartElement) currentEvent; - int count = 0; - for (Iterator i = se.getAttributes(); i.hasNext(); ) - { - Attribute attr = (Attribute) i.next(); - if (index == count) - return attr.isSpecified(); - count++; - } - return false; - } - - public int getNamespaceCount() - { - Iterator i = null; - switch (eventType) - { - case XMLStreamConstants.START_ELEMENT: - i = ((StartElement) currentEvent).getNamespaces(); - break; - case XMLStreamConstants.END_ELEMENT: - i = ((EndElement) currentEvent).getNamespaces(); - break; - default: - throw new IllegalStateException(); - } - int count = 0; - while (i.hasNext()) - { - i.next(); - count++; - } - return count; - } - - public String getNamespacePrefix(int index) - { - Iterator i = null; - switch (eventType) - { - case XMLStreamConstants.START_ELEMENT: - i = ((StartElement) currentEvent).getNamespaces(); - break; - case XMLStreamConstants.END_ELEMENT: - i = ((EndElement) currentEvent).getNamespaces(); - break; - default: - throw new IllegalStateException(); - } - int count = 0; - while (i.hasNext()) - { - Namespace ns = (Namespace) i.next(); - if (index == count) - return ns.getPrefix(); - count++; - } - return null; - } - - public String getNamespaceURI(int index) - { - Iterator i = null; - switch (eventType) - { - case XMLStreamConstants.START_ELEMENT: - i = ((StartElement) currentEvent).getNamespaces(); - break; - case XMLStreamConstants.END_ELEMENT: - i = ((EndElement) currentEvent).getNamespaces(); - break; - default: - throw new IllegalStateException(); - } - int count = 0; - while (i.hasNext()) - { - Namespace ns = (Namespace) i.next(); - if (index == count) - return ns.getNamespaceURI(); - count++; - } - return null; - } - - public NamespaceContext getNamespaceContext() - { - return this; - } - - public int getEventType() - { - return eventType; - } - - public String getText() - { - switch (eventType) - { - case XMLStreamConstants.CHARACTERS: - case XMLStreamConstants.CDATA: - case XMLStreamConstants.SPACE: - return ((Characters) currentEvent).getData(); - case XMLStreamConstants.COMMENT: - return ((Comment) currentEvent).getText(); - case XMLStreamConstants.ENTITY_REFERENCE: - return ((EntityReference) currentEvent).getReplacementText(); - case XMLStreamConstants.DTD: - return ((DTD) currentEvent).getDocumentTypeDeclaration(); - } - return null; - } - - public char[] getTextCharacters() - { - String text = getText(); - return (text == null) ? null : text.toCharArray(); - } - - public int getTextCharacters(int sourceStart, char[] target, - int targetStart, int length) - throws XMLStreamException - { - char[] source = getTextCharacters(); - int len = Math.min(source.length, length); - System.arraycopy(source, sourceStart, target, targetStart, len); - return len; - } - - public int getTextStart() - { - return 0; - } - - public int getTextLength() - { - String text = getText(); - return (text == null) ? 0 : text.length(); - } - - public String getEncoding() - { - // XXX SAX doesn't provide this - return null; - } - - public boolean hasText() - { - return eventType == CHARACTERS || eventType == DTD || - eventType == SPACE || eventType == ENTITY_REFERENCE || - eventType == COMMENT || eventType == DTD; - } - - public Location getLocation() - { - return currentEvent.getLocation(); - } - - public QName getName() - { - switch (eventType) - { - case XMLStreamConstants.START_ELEMENT: - return ((StartElement) currentEvent).getName(); - case XMLStreamConstants.END_ELEMENT: - return ((EndElement) currentEvent).getName(); - case XMLStreamConstants.ATTRIBUTE: - return ((Attribute) currentEvent).getName(); - } - return null; - } - - public String getLocalName() - { - QName name = getName(); - return (name == null) ? null : name.getLocalPart(); - } - - public boolean hasName() - { - return getName() != null; - } - - public String getNamespaceURI() - { - QName name = getName(); - return (name == null) ? null : name.getNamespaceURI(); - } - - public String getPrefix() - { - QName name = getName(); - return (name == null) ? null : name.getPrefix(); - } - - public String getVersion() - { - StartDocument sd = (StartDocument) currentEvent; - return sd.getVersion(); - } - - public boolean isStandalone() - { - StartDocument sd = (StartDocument) currentEvent; - return sd.isStandalone(); - } - - public boolean standaloneSet() - { - StartDocument sd = (StartDocument) currentEvent; - return sd.standaloneSet(); - } - - public String getCharacterEncodingScheme() - { - StartDocument sd = (StartDocument) currentEvent; - return sd.getCharacterEncodingScheme(); - } - - public String getPITarget() - { - ProcessingInstruction pi = (ProcessingInstruction) currentEvent; - return pi.getTarget(); - } - - public String getPIData() - { - ProcessingInstruction pi = (ProcessingInstruction) currentEvent; - return pi.getData(); - } - - /** - * This class is used to construct the event series from SAX callbacks. - */ - class CallbackHandler - implements ContentHandler, DTDHandler, LexicalHandler, - DeclHandler, EntityResolver, ErrorHandler - { - - XMLReader reader; - Locator locator; - Location location; - private boolean inCDATA; - private LinkedList namespaces = new LinkedList(); - private LinkedList notations; - private LinkedList entities; - - CallbackHandler(XMLReader reader) - { - this.reader = reader; - } - - public void setDocumentLocator(Locator locator) - { - this.locator = locator; - location = new LocationImpl(-1, - locator.getColumnNumber(), - locator.getLineNumber(), - locator.getSystemId()); - } - - public void startDocument() - throws SAXException - { - String version = (locator instanceof Locator2) ? - ((Locator2) locator).getXMLVersion() : null; - String encoding = (locator instanceof Locator2) ? - ((Locator2) locator).getEncoding() : null; - boolean standalone = - reader.getFeature("http://xml.org/sax/features/is-standalone"); - boolean standaloneDeclared = standalone; - boolean encodingDeclared = (encoding != null); - events.add(new StartDocumentImpl(location, - location.getLocationURI(), - encoding, - version, - standalone, - standaloneDeclared, - encodingDeclared)); - } - - public void endDocument() - throws SAXException - { - events.add(new EndDocumentImpl(location)); - } - - public void startPrefixMapping(String prefix, String uri) - throws SAXException - { - namespaces.add(new NamespaceImpl(location, prefix, uri)); - } - - public void endPrefixMapping(String prefix) - throws SAXException - { - } - - public void startElement(String namespaceURI, String localName, - String qName, Attributes atts) - throws SAXException - { - LinkedList ns = namespaces; - namespaces = new LinkedList(); - int ci = qName.indexOf(':'); - String prefix = null; - localName = qName; - if (ci != -1) - { - prefix = qName.substring(0, ci); - localName = qName.substring(ci + 1); - } - QName name = new QName(namespaceURI, localName, prefix); - LinkedList attrs = new LinkedList(); - StartElementImpl se = new StartElementImpl(location, name, - attrs, ns, null); - events.add(se); - // Add namespaces - //for (Iterator i = ns.iterator(); i.hasNext(); ) - // events.add(i.next()); - // Add attributes - int len = atts.getLength(); - for (int i = 0; i < len; i++) - { - String attURI = atts.getURI(i); - String attQName = atts.getQName(i); - String value = atts.getValue(i); - QName type = QName.valueOf(atts.getType(i)); - boolean specified = (atts instanceof Attributes2) && - ((Attributes2) atts).isSpecified(i); - ci = attQName.indexOf(':'); - String attPrefix = null; - String attLocalName = attQName; - if (ci != -1) - { - attPrefix = attQName.substring(0, ci); - attLocalName = attQName.substring(ci + 1); - } - if ("xmlns".equals(attPrefix) || "xmlns".equals(attQName)) - continue; - QName attrName = new QName(attURI, attLocalName, attPrefix); - AttributeImpl attr = new AttributeImpl(location, attrName, - value, type, specified); - attrs.add(attr); - //events.add(attr); - } - } - - public void endElement(String namespaceURI, String localName, - String qName) - throws SAXException - { - int ci = qName.indexOf(':'); - String prefix = null; - localName = qName; - if (ci != -1) - { - prefix = qName.substring(0, ci); - localName = qName.substring(ci + 1); - } - QName name = new QName(namespaceURI, localName, prefix); - events.add(new EndElementImpl(location, name, new LinkedList())); - // TODO namespaces out of scope - } - - public void characters(char[] ch, int start, int length) - throws SAXException - { - boolean whitespace = isWhitespace(ch, start, length); - events.add(new CharactersImpl(location, new String(ch, start, length), - whitespace, inCDATA, false)); - } - - public void ignorableWhitespace(char[] ch, int start, int length) - throws SAXException - { - boolean whitespace = isWhitespace(ch, start, length); - events.add(new CharactersImpl(location, new String(ch, start, length), - whitespace, inCDATA, true)); - } - - boolean isWhitespace(char[] ch, int start, int len) - { - int end = start + len; - for (int i = start; i < end; i++) - { - char c = ch[i]; - if (c != ' ' && c != '\t' && c != '\n' && c != '\r') - return false; - } - return true; - } - - public void processingInstruction(String target, String data) - throws SAXException - { - events.add(new ProcessingInstructionImpl(location, target, data)); - } - - public void skippedEntity(String name) - throws SAXException - { - } - - public void startDTD(String name, String publicId, String systemId) - throws SAXException - { - notations = new LinkedList(); - entities = new LinkedList(); - events.add(new DTDImpl(location, null, null, notations, entities)); - } - - public void endDTD() - throws SAXException - { - } - - public void startEntity(String name) - throws SAXException - { - events.add(new StartEntityImpl(location, name)); - } - - public void endEntity(String name) - throws SAXException - { - events.add(new EndEntityImpl(location, name)); - } - - public void startCDATA() - throws SAXException - { - inCDATA = true; - } - - public void endCDATA() - throws SAXException - { - inCDATA = false; - } - - public void comment(char[] ch, int start, int length) - throws SAXException - { - events.add(new CommentImpl(location, new String(ch, start, length))); - } - - public void notationDecl(String name, String publicId, String systemId) - throws SAXException - { - Object n = new NotationDeclarationImpl(location, name, publicId, - systemId); - notations.add(n); - //events.add(n); - } - - public void unparsedEntityDecl(String name, String publicId, - String systemId, String notationName) - throws SAXException - { - Object e = new EntityDeclarationImpl(location, publicId, systemId, - name, notationName, - null, null); - entities.add(e); - //events.add(e); - } - - public void elementDecl(String name, String model) - throws SAXException - { - } - - public void attributeDecl(String eName, String aName, String type, - String valueDefault, String value) - throws SAXException - { - } - - public void internalEntityDecl(String name, String value) - throws SAXException - { - Object e = new EntityDeclarationImpl(location, null, null, - name, null, value, null); - entities.add(e); - //events.add(e); - } - - public void externalEntityDecl(String name, String publicId, - String systemId) - throws SAXException - { - Object e = new EntityDeclarationImpl(location, publicId, systemId, - name, null, null, null); - entities.add(e); - //events.add(e); - } - - public void warning(SAXParseException e) - throws SAXException - { - if (reporter != null) - { - try - { - reporter.report(e.getMessage(), "warning", e, location); - } - catch (XMLStreamException e2) - { - SAXException e3 = new SAXException(e2.getMessage()); - e3.initCause(e2); - throw e3; - } - } - } - - public void error(SAXParseException e) - throws SAXException - { - if (reporter != null) - { - try - { - reporter.report(e.getMessage(), "error", e, location); - } - catch (XMLStreamException e2) - { - SAXException e3 = new SAXException(e2.getMessage()); - e3.initCause(e2); - throw e3; - } - } - } - - public void fatalError(SAXParseException e) - throws SAXException - { - if (reporter != null) - { - try - { - reporter.report(e.getMessage(), "fatal-error", e, location); - } - catch (XMLStreamException e2) - { - SAXException e3 = new SAXException(e2.getMessage()); - e3.initCause(e2); - throw e3; - } - } - } - - public InputSource resolveEntity(String publicId, String systemId) - throws SAXException, IOException - { - if (resolver != null) - { - try - { - InputStream in = resolver.resolve(systemId); - if (in != null) - { - InputSource ret = new InputSource(in); - ret.setPublicId(publicId); - ret.setSystemId(systemId); - return ret; - } - } - catch (XMLStreamException e) - { - SAXException e2 = new SAXException(e.getMessage()); - e2.initCause(e); - throw e2; - } - } - return null; - } - - } - -} - diff --git a/libjava/classpath/gnu/xml/stream/XMLStreamWriterImpl.java b/libjava/classpath/gnu/xml/stream/XMLStreamWriterImpl.java index 6157296c6b8..291016e6716 100644 --- a/libjava/classpath/gnu/xml/stream/XMLStreamWriterImpl.java +++ b/libjava/classpath/gnu/xml/stream/XMLStreamWriterImpl.java @@ -104,6 +104,9 @@ public class XMLStreamWriterImpl private NamespaceSupport namespaces; private int count = 0; + private boolean xml11; + private boolean hasXML11RestrictedChars; + /** * Constructor. * @see #writer @@ -145,6 +148,9 @@ public class XMLStreamWriterImpl { try { + if (!isName(localName)) + throw new IllegalArgumentException("illegal Name: " + localName); + endStartElement(); namespaces.pushContext(); @@ -167,6 +173,11 @@ public class XMLStreamWriterImpl { try { + if (namespaceURI != null && !isURI(namespaceURI)) + throw new IllegalArgumentException("illegal URI: " + namespaceURI); + if (!isName(localName)) + throw new IllegalArgumentException("illegal Name: " + localName); + endStartElement(); namespaces.pushContext(); @@ -190,7 +201,7 @@ public class XMLStreamWriterImpl inStartElement = true; if (!isDeclared) { - writeNamespace(prefix, namespaceURI); + writeNamespaceImpl(prefix, namespaceURI); } elements.addLast(new String[] { prefix, localName }); @@ -229,6 +240,13 @@ public class XMLStreamWriterImpl { try { + if (namespaceURI != null && !isURI(namespaceURI)) + throw new IllegalArgumentException("illegal URI: " + namespaceURI); + if (prefix != null && !isNCName(prefix)) + throw new IllegalArgumentException("illegal NCName: " + prefix); + if (!isNCName(localName)) + throw new IllegalArgumentException("illegal NCName: " + localName); + endStartElement(); namespaces.pushContext(); @@ -243,7 +261,7 @@ public class XMLStreamWriterImpl writer.write(localName); if (prefixDefaulting && !isCurrent) { - writeNamespace(prefix, namespaceURI); + writeNamespaceImpl(prefix, namespaceURI); } elements.addLast(new String[] { prefix, localName }); @@ -343,11 +361,19 @@ public class XMLStreamWriterImpl 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('"'); - writeEncoded(value, true); + if (hasXML11RestrictedChars) + writeEncodedWithRestrictedChars(value, true); + else + writeEncoded(value, true); writer.write('"'); } catch (IOException e) @@ -366,11 +392,20 @@ public class XMLStreamWriterImpl throw new IllegalStateException(); try { + if (namespaceURI != null && !isURI(namespaceURI)) + throw new IllegalArgumentException("illegal URI: " + namespaceURI); + if (prefix != null && !isNCName(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) - writeNamespace(prefix, namespaceURI); + writeNamespaceImpl(prefix, namespaceURI); else throw new XMLStreamException("namespace " + namespaceURI + " is not bound"); @@ -388,7 +423,10 @@ public class XMLStreamWriterImpl writer.write(localName); writer.write('='); writer.write('"'); - writeEncoded(value, true); + if (hasXML11RestrictedChars) + writeEncodedWithRestrictedChars(value, true); + else + writeEncoded(value, true); writer.write('"'); } catch (IOException e) @@ -407,13 +445,20 @@ public class XMLStreamWriterImpl 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; - writeNamespace(prefix, namespaceURI); + writeNamespaceImpl(prefix, namespaceURI); } else throw new XMLStreamException("namespace " + namespaceURI + @@ -428,7 +473,10 @@ public class XMLStreamWriterImpl writer.write(localName); writer.write('='); writer.write('"'); - writeEncoded(value, true); + if (hasXML11RestrictedChars) + writeEncodedWithRestrictedChars(value, true); + else + writeEncoded(value, true); writer.write('"'); } catch (IOException e) @@ -446,6 +494,25 @@ public class XMLStreamWriterImpl throw new IllegalStateException(); try { + if (!isURI(namespaceURI)) + throw new IllegalArgumentException("illegal URI: " + namespaceURI); + if (!isNCName(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; @@ -474,21 +541,41 @@ public class XMLStreamWriterImpl public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException { - writeNamespace(XMLConstants.DEFAULT_NS_PREFIX, namespaceURI); + 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(); - if (data != null && data.indexOf("--") != -1) - throw new IllegalArgumentException(data); - writer.write("<!--"); - if (data != null) + 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("-->"); } @@ -511,6 +598,11 @@ public class XMLStreamWriterImpl { 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('<'); @@ -519,7 +611,20 @@ public class XMLStreamWriterImpl if (data != null) { writer.write(' '); - writer.write(data); + 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('>'); @@ -537,10 +642,12 @@ public class XMLStreamWriterImpl { try { - endStartElement(); - + if (!isChars(data) || hasXML11RestrictedChars) + throw new IllegalArgumentException("illegal XML character: " + data); if (data.indexOf("]]") != -1) - throw new IllegalArgumentException(data); + throw new IllegalArgumentException("illegal CDATA section: " + data); + + endStartElement(); writer.write("<![CDATA["); writer.write(data); @@ -557,8 +664,12 @@ public class XMLStreamWriterImpl public void writeDTD(String dtd) throws XMLStreamException { + // Really thoroughly pointless method... try { + if (!isName(dtd)) + throw new IllegalArgumentException("illegal Name: " + dtd); + writer.write("<!DOCTYPE "); writer.write(dtd); writer.write('>'); @@ -576,6 +687,9 @@ public class XMLStreamWriterImpl { try { + if (!isName(name)) + throw new IllegalArgumentException("illegal Name: " + name); + endStartElement(); writer.write('&'); @@ -607,6 +721,8 @@ public class XMLStreamWriterImpl { 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"; @@ -632,11 +748,18 @@ public class XMLStreamWriterImpl public void writeCharacters(String text) throws XMLStreamException { + if (text == null) + return; try { + if (!isChars(text)) + throw new IllegalArgumentException("illegal XML character: " + text); + endStartElement(); - if (text != null) + if (hasXML11RestrictedChars) + writeEncodedWithRestrictedChars(text, false); + else writeEncoded(text, false); } catch (IOException e) @@ -650,39 +773,7 @@ public class XMLStreamWriterImpl public void writeCharacters(char[] text, int start, int len) throws XMLStreamException { - try - { - endStartElement(); - - int end = start + len; - len = 0; - for (int i = start; i < end; i++) - { - char c = text[i]; - if (c == '<' || c == '>' || c == '&') - { - writer.write(text, start, len); - if (c == '<') - writer.write("<"); - else if (c == '>') - writer.write(">"); - else - writer.write("&"); - start = i + 1; - len = 0; - } - else - len++; - } - if (len > 0) - writer.write(text, start, len); - } - catch (IOException e) - { - XMLStreamException e2 = new XMLStreamException(e); - e2.initCause(e); - throw e2; - } + writeCharacters(new String(text, start, len)); } public String getPrefix(String uri) @@ -697,6 +788,19 @@ public class XMLStreamWriterImpl public void setPrefix(String prefix, String uri) throws XMLStreamException { + try + { + if (!isURI(uri)) + throw new IllegalArgumentException("illegal URI: " + uri); + if (!isNCName(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); } @@ -704,6 +808,8 @@ public class XMLStreamWriterImpl 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"); } @@ -769,6 +875,131 @@ public class XMLStreamWriterImpl 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("<"); + break; + case 0x3e: // '>' + writer.write(">"); + break; + case 0x26: // '&' + writer.write("&"); + break; + case 0x22: // '"' + if (inAttr) + writer.write("""); + else + writer.write(c); + break; + case 0x27: // '\'' + if (inAttr) + writer.write("'"); + 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 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; + } } |