mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-06-30 07:14:49 +02:00
4133eb175c
Introducing Smack's own XmlPullParser interface which tries to stay as compatible as possible to XPP3. The interface is used to either wrap StAX's XMLStreamReader if Smack is used on Java SE, and XPP3's XmlPullParser if Smack is used on on Android. Fixes SMACK-591. Also introduce JUnit 5 and non-strict javadoc projects.
302 lines
8.4 KiB
Java
302 lines
8.4 KiB
Java
/**
|
|
*
|
|
* Copyright 2019 Florian Schmaus
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package org.jivesoftware.smack.xml.stax;
|
|
|
|
import java.io.IOException;
|
|
|
|
import javax.xml.XMLConstants;
|
|
import javax.xml.namespace.NamespaceContext;
|
|
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 org.jivesoftware.smack.xml.XmlPullParser;
|
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
|
|
|
public final class StaxXmlPullParser implements XmlPullParser {
|
|
|
|
private final XMLStreamReader xmlStreamReader;
|
|
|
|
private int depth;
|
|
|
|
StaxXmlPullParser(XMLStreamReader xmlStreamReader) {
|
|
this.xmlStreamReader = xmlStreamReader;
|
|
}
|
|
|
|
@Override
|
|
public Object getProperty(String name) {
|
|
return xmlStreamReader.getProperty(name);
|
|
}
|
|
|
|
@Override
|
|
public String getInputEncoding() {
|
|
return xmlStreamReader.getEncoding();
|
|
}
|
|
|
|
@Override
|
|
public int getNamespaceCount() {
|
|
return xmlStreamReader.getNamespaceCount();
|
|
}
|
|
|
|
@Override
|
|
public String getNamespacePrefix(int pos) {
|
|
return xmlStreamReader.getNamespacePrefix(pos);
|
|
}
|
|
|
|
@Override
|
|
public String getNamespaceUri(int pos) {
|
|
return xmlStreamReader.getNamespaceURI(pos);
|
|
}
|
|
|
|
@Override
|
|
public String getNamespace(String prefix) {
|
|
if (prefix == null) {
|
|
prefix = XMLConstants.DEFAULT_NS_PREFIX;
|
|
}
|
|
NamespaceContext namespaceContext = xmlStreamReader.getNamespaceContext();
|
|
return namespaceContext.getNamespaceURI(prefix);
|
|
}
|
|
|
|
@Override
|
|
public int getDepth() {
|
|
return depth;
|
|
}
|
|
|
|
@Override
|
|
public String getPositionDescription() {
|
|
Location location = xmlStreamReader.getLocation();
|
|
return location.toString();
|
|
}
|
|
|
|
@Override
|
|
public int getLineNumber() {
|
|
Location location = xmlStreamReader.getLocation();
|
|
return location.getLineNumber();
|
|
}
|
|
|
|
@Override
|
|
public int getColumnNumber() {
|
|
Location location = xmlStreamReader.getLocation();
|
|
return location.getColumnNumber();
|
|
}
|
|
|
|
@Override
|
|
public boolean isWhiteSpace() {
|
|
return xmlStreamReader.isWhiteSpace();
|
|
}
|
|
|
|
@Override
|
|
public String getText() {
|
|
return xmlStreamReader.getText();
|
|
}
|
|
|
|
@Override
|
|
public String getNamespace() {
|
|
NamespaceContext namespaceContext = xmlStreamReader.getNamespaceContext();
|
|
String prefix = getPrefix();
|
|
return namespaceContext.getNamespaceURI(prefix);
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
QName qname = getQName();
|
|
return qname.getLocalPart();
|
|
}
|
|
|
|
@Override
|
|
public QName getQName() {
|
|
return xmlStreamReader.getName();
|
|
}
|
|
|
|
@Override
|
|
public String getPrefix() {
|
|
return xmlStreamReader.getPrefix();
|
|
}
|
|
|
|
@Override
|
|
public int getAttributeCount() {
|
|
return xmlStreamReader.getAttributeCount();
|
|
}
|
|
|
|
@Override
|
|
public String getAttributeNamespace(int index) {
|
|
return xmlStreamReader.getAttributeNamespace(index);
|
|
}
|
|
|
|
@Override
|
|
public String getAttributeName(int index) {
|
|
QName qname = getAttributeQName(index);
|
|
if (qname == null) {
|
|
return null;
|
|
}
|
|
return qname.getLocalPart();
|
|
}
|
|
|
|
@Override
|
|
public QName getAttributeQName(int index) {
|
|
return xmlStreamReader.getAttributeName(index);
|
|
}
|
|
|
|
@Override
|
|
public String getAttributePrefix(int index) {
|
|
return xmlStreamReader.getAttributePrefix(index);
|
|
}
|
|
|
|
@Override
|
|
public String getAttributeType(int index) {
|
|
return xmlStreamReader.getAttributeType(index);
|
|
}
|
|
|
|
@Override
|
|
public String getAttributeValue(int index) {
|
|
return xmlStreamReader.getAttributeValue(index);
|
|
}
|
|
|
|
@Override
|
|
public String getAttributeValue(String namespace, String name) {
|
|
String namespaceURI = namespace;
|
|
String localName = name;
|
|
return xmlStreamReader.getAttributeValue(namespaceURI, localName);
|
|
}
|
|
|
|
@Override
|
|
public Event getEventType() {
|
|
int staxEventInt = xmlStreamReader.getEventType();
|
|
return staxEventIntegerToEvent(staxEventInt);
|
|
}
|
|
|
|
private boolean delayedDepthDecrement;
|
|
|
|
@Override
|
|
public Event next() throws XmlPullParserException {
|
|
preNextEvent();
|
|
|
|
int staxEventInt;
|
|
try {
|
|
staxEventInt = xmlStreamReader.next();
|
|
} catch (XMLStreamException e) {
|
|
throw new XmlPullParserException(e);
|
|
}
|
|
|
|
Event event = staxEventIntegerToEvent(staxEventInt);
|
|
switch (event) {
|
|
case START_ELEMENT:
|
|
depth++;
|
|
break;
|
|
case END_ELEMENT:
|
|
delayedDepthDecrement = true;
|
|
break;
|
|
default:
|
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
|
break;
|
|
}
|
|
return event;
|
|
}
|
|
|
|
@Override
|
|
public String nextText() throws IOException, XmlPullParserException {
|
|
final String nextText;
|
|
try {
|
|
nextText = xmlStreamReader.getElementText();
|
|
} catch (XMLStreamException e) {
|
|
throw new XmlPullParserException(e);
|
|
}
|
|
|
|
// XMLStreamReader.getElementText() will forward to the next END_ELEMENT, hence we need to set
|
|
// delayedDepthDecrement to true.
|
|
delayedDepthDecrement = true;
|
|
|
|
return nextText;
|
|
}
|
|
|
|
@Override
|
|
public TagEvent nextTag() throws IOException, XmlPullParserException {
|
|
preNextEvent();
|
|
|
|
int staxEventInt;
|
|
try {
|
|
staxEventInt = xmlStreamReader.nextTag();
|
|
} catch (XMLStreamException e) {
|
|
throw new XmlPullParserException(e);
|
|
}
|
|
|
|
switch (staxEventInt) {
|
|
case XMLStreamConstants.START_ELEMENT:
|
|
depth++;
|
|
return TagEvent.START_ELEMENT;
|
|
case XMLStreamConstants.END_ELEMENT:
|
|
delayedDepthDecrement = true;
|
|
return TagEvent.END_ELEMENT;
|
|
default:
|
|
throw new AssertionError();
|
|
}
|
|
}
|
|
|
|
private void preNextEvent() {
|
|
if (delayedDepthDecrement) {
|
|
depth--;
|
|
delayedDepthDecrement = false;
|
|
assert depth >= 0;
|
|
}
|
|
}
|
|
|
|
private static Event staxEventIntegerToEvent(int staxEventInt) {
|
|
switch (staxEventInt) {
|
|
case XMLStreamConstants.START_ELEMENT:
|
|
return Event.START_ELEMENT;
|
|
case XMLStreamConstants.END_ELEMENT:
|
|
return Event.END_ELEMENT;
|
|
case XMLStreamConstants.PROCESSING_INSTRUCTION:
|
|
return Event.PROCESSING_INSTRUCTION;
|
|
case XMLStreamConstants.CHARACTERS:
|
|
return Event.TEXT_CHARACTERS;
|
|
case XMLStreamConstants.COMMENT:
|
|
return Event.COMMENT;
|
|
case XMLStreamConstants.SPACE:
|
|
return Event.IGNORABLE_WHITESPACE;
|
|
case XMLStreamConstants.START_DOCUMENT:
|
|
return Event.START_DOCUMENT;
|
|
case XMLStreamConstants.END_DOCUMENT:
|
|
return Event.END_DOCUMENT;
|
|
case XMLStreamConstants.ENTITY_REFERENCE:
|
|
return Event.ENTITY_REFERENCE;
|
|
case XMLStreamConstants.ATTRIBUTE:
|
|
return Event.OTHER;
|
|
case XMLStreamConstants.DTD:
|
|
return Event.OTHER;
|
|
case XMLStreamConstants.CDATA:
|
|
return Event.OTHER;
|
|
case XMLStreamConstants.NAMESPACE:
|
|
return Event.OTHER;
|
|
case XMLStreamConstants.NOTATION_DECLARATION:
|
|
return Event.OTHER;
|
|
case XMLStreamConstants.ENTITY_DECLARATION:
|
|
return Event.OTHER;
|
|
default:
|
|
throw new IllegalArgumentException("Unknown Stax event integer: " + staxEventInt);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean supportsRoundtrip() {
|
|
// TODO: Is there a StAX parser implementation which does support roundtrip?
|
|
return false;
|
|
}
|
|
}
|