mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2025-09-09 18:29:45 +02:00
Merge branch '4.0'
Conflicts: build.gradle documentation/connections.html documentation/gettingstarted.html smack-core/src/main/java/org/jivesoftware/smack/SmackException.java smack-core/src/test/java/org/jivesoftware/smack/parsing/ParsingExceptionTest.java smack-core/src/test/java/org/jivesoftware/smack/test/util/TestUtils.java smack-core/src/test/java/org/jivesoftware/smack/util/PacketParserUtilsTest.java smack-extensions/src/main/java/org/jivesoftware/smackx/caps/cache/SimpleDirectoryPersistentCache.java smack-extensions/src/main/java/org/jivesoftware/smackx/ping/PingManager.java smack-tcp/src/main/java/org/jivesoftware/smack/tcp/PacketReader.java
This commit is contained in:
commit
94a16ba41e
61 changed files with 806 additions and 300 deletions
|
@ -35,6 +35,7 @@ task dnsJar(type: Jar) {
|
|||
from sourceSets.main.output
|
||||
include('org/jivesoftware/smack/util/dns/**')
|
||||
include('org/jivesoftware/smack/util/DNSUtil.class')
|
||||
include('org/jivesoftware/smack/initializer/**')
|
||||
}
|
||||
|
||||
artifacts {
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
|
||||
package org.jivesoftware.smack;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
@ -34,6 +36,7 @@ import org.jivesoftware.smack.compression.XMPPInputOutputStream;
|
|||
import org.jivesoftware.smack.initializer.SmackInitializer;
|
||||
import org.jivesoftware.smack.parsing.ExceptionThrowingCallback;
|
||||
import org.jivesoftware.smack.parsing.ParsingExceptionCallback;
|
||||
import org.jivesoftware.smack.util.DNSUtil;
|
||||
import org.jivesoftware.smack.util.FileUtils;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
@ -49,8 +52,7 @@ import org.xmlpull.v1.XmlPullParserException;
|
|||
* via the API will override settings in the configuration file.
|
||||
* </ul>
|
||||
*
|
||||
* Configuration settings are stored in org.jivesoftware.smack/smack-config.xml (typically inside the
|
||||
* smack.jar file).
|
||||
* Configuration settings are stored in org.jivesoftware.smack/smack-config.xml.
|
||||
*
|
||||
* @author Gaston Dombiak
|
||||
*/
|
||||
|
@ -95,10 +97,13 @@ public final class SmackConfiguration {
|
|||
static {
|
||||
String smackVersion;
|
||||
try {
|
||||
InputStream is = FileUtils.getStreamForUrl("classpath:org.jivesoftware.smack/version", null);
|
||||
byte[] buf = new byte[1024];
|
||||
is.read(buf);
|
||||
smackVersion = new String(buf, "UTF-8");
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(FileUtils.getStreamForUrl("classpath:org.jivesoftware.smack/version", null)));
|
||||
smackVersion = reader.readLine();
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
LOGGER.log(Level.WARNING, "IOException closing stream", e);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
LOGGER.log(Level.SEVERE, "Could not determine Smack version", e);
|
||||
smackVersion = "unkown";
|
||||
|
@ -162,6 +167,9 @@ public final class SmackConfiguration {
|
|||
catch (Exception e) {
|
||||
// Ignore.
|
||||
}
|
||||
|
||||
// Initialize the DNS resolvers
|
||||
DNSUtil.init();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -134,6 +134,12 @@ public class SmackException extends Exception {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ConnectionException is thrown if Smack is unable to connect to all hosts of a given XMPP
|
||||
* service. The failed hosts can be retrieved with
|
||||
* {@link ConnectionException#getFailedAddresses()}, which will have the exception causing the
|
||||
* connection failure set and retrievable with {@link HostAddress#getException()}.
|
||||
*/
|
||||
public static class ConnectionException extends SmackException {
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
*/
|
||||
package org.jivesoftware.smack.util;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
|
@ -39,6 +41,31 @@ public class DNSUtil {
|
|||
private static final Logger LOGGER = Logger.getLogger(DNSUtil.class.getName());
|
||||
private static DNSResolver dnsResolver = null;
|
||||
|
||||
/**
|
||||
* Initializes DNSUtil. This method is automatically called by SmackConfiguration, you don't
|
||||
* have to call it manually.
|
||||
*/
|
||||
public static void init() {
|
||||
final String[] RESOLVERS = new String[] { "javax.JavaxResolver", "minidns.MiniDnsResolver",
|
||||
"dnsjava.DNSJavaResolver" };
|
||||
for (String resolver :RESOLVERS) {
|
||||
DNSResolver availableResolver = null;
|
||||
String resolverFull = "org.jivesoftware.smack.util.dns" + resolver;
|
||||
try {
|
||||
Class<?> resolverClass = Class.forName(resolverFull);
|
||||
Method getInstanceMethod = resolverClass.getMethod("getInstance");
|
||||
availableResolver = (DNSResolver) getInstanceMethod.invoke(null);
|
||||
if (availableResolver != null) {
|
||||
setDNSResolver(availableResolver);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException|NoSuchMethodException|SecurityException|IllegalAccessException|IllegalArgumentException|InvocationTargetException e) {
|
||||
LOGGER.log(Level.FINE, "Exception on init", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the DNS resolver that should be used to perform DNS lookups.
|
||||
*
|
||||
|
|
|
@ -22,13 +22,20 @@ import java.util.List;
|
|||
public class LazyStringBuilder implements Appendable, CharSequence {
|
||||
|
||||
private final List<CharSequence> list;
|
||||
|
||||
|
||||
private String cache;
|
||||
|
||||
private void invalidateCache() {
|
||||
cache = null;
|
||||
}
|
||||
|
||||
public LazyStringBuilder() {
|
||||
list = new ArrayList<CharSequence>(20);
|
||||
}
|
||||
|
||||
public LazyStringBuilder append(LazyStringBuilder lsb) {
|
||||
list.addAll(lsb.list);
|
||||
invalidateCache();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -36,6 +43,7 @@ public class LazyStringBuilder implements Appendable, CharSequence {
|
|||
public LazyStringBuilder append(CharSequence csq) {
|
||||
assert csq != null;
|
||||
list.add(csq);
|
||||
invalidateCache();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -43,17 +51,22 @@ public class LazyStringBuilder implements Appendable, CharSequence {
|
|||
public LazyStringBuilder append(CharSequence csq, int start, int end) {
|
||||
CharSequence subsequence = csq.subSequence(start, end);
|
||||
list.add(subsequence);
|
||||
invalidateCache();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LazyStringBuilder append(char c) {
|
||||
list.add(Character.toString(c));
|
||||
invalidateCache();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
if (cache != null) {
|
||||
return cache.length();
|
||||
}
|
||||
int length = 0;
|
||||
for (CharSequence csq : list) {
|
||||
length += csq.length();
|
||||
|
@ -63,6 +76,9 @@ public class LazyStringBuilder implements Appendable, CharSequence {
|
|||
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
if (cache != null) {
|
||||
return cache.charAt(index);
|
||||
}
|
||||
for (CharSequence csq : list) {
|
||||
if (index < csq.length()) {
|
||||
return csq.charAt(index);
|
||||
|
@ -80,10 +96,13 @@ public class LazyStringBuilder implements Appendable, CharSequence {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(length());
|
||||
for (CharSequence csq : list) {
|
||||
sb.append(csq);
|
||||
if (cache == null) {
|
||||
StringBuilder sb = new StringBuilder(length());
|
||||
for (CharSequence csq : list) {
|
||||
sb.append(csq);
|
||||
}
|
||||
cache = sb.toString();
|
||||
}
|
||||
return sb.toString();
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,6 +134,24 @@ public class PacketParserUtils {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new XmlPullParser suitable for parsing XMPP. This means in particular that
|
||||
* FEATURE_PROCESS_NAMESPACES is enabled.
|
||||
* <p>
|
||||
* Note that not all XmlPullParser implementations will return a String on
|
||||
* <code>getText()</code> if the parser is on START_TAG or END_TAG. So you must not rely on this
|
||||
* behavior when using the parser.
|
||||
* </p>
|
||||
*
|
||||
* @return A suitable XmlPullParser for XMPP parsing
|
||||
* @throws XmlPullParserException
|
||||
*/
|
||||
public static XmlPullParser newXmppParser() throws XmlPullParserException {
|
||||
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
|
||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
||||
return parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a message packet.
|
||||
*
|
||||
|
@ -179,7 +197,7 @@ public class PacketParserUtils {
|
|||
xmlLang = defaultLanguage;
|
||||
}
|
||||
|
||||
String subject = parseContent(parser);
|
||||
String subject = parseElementText(parser);
|
||||
|
||||
if (message.getSubject(xmlLang) == null) {
|
||||
message.addSubject(xmlLang, subject);
|
||||
|
@ -191,8 +209,8 @@ public class PacketParserUtils {
|
|||
xmlLang = defaultLanguage;
|
||||
}
|
||||
|
||||
String body = parseContent(parser);
|
||||
|
||||
String body = parseElementText(parser);
|
||||
|
||||
if (message.getBody(xmlLang) == null) {
|
||||
message.addBody(xmlLang, body);
|
||||
}
|
||||
|
@ -223,29 +241,156 @@ public class PacketParserUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the content of a tag as string regardless of any tags included.
|
||||
* Returns the textual content of an element as String.
|
||||
* <p>
|
||||
* The parser must be positioned on a START_TAG of an element which MUST NOT contain Mixed
|
||||
* Content (as defined in XML 3.2.2), or else an XmlPullParserException will be thrown.
|
||||
* </p>
|
||||
* This method is used for the parts where the XMPP specification requires elements that contain
|
||||
* only text or are the empty element.
|
||||
*
|
||||
* @param parser
|
||||
* @return the textual content of the element as String
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String parseElementText(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||
assert (parser.getEventType() == XmlPullParser.START_TAG);
|
||||
String res;
|
||||
if (parser.isEmptyElementTag()) {
|
||||
res = "";
|
||||
}
|
||||
else {
|
||||
// Advance to the text of the Element
|
||||
int event = parser.next();
|
||||
if (event != XmlPullParser.TEXT) {
|
||||
throw new XmlPullParserException(
|
||||
"Non-empty element tag not followed by text, while Mixed Content (XML 3.2.2) is disallowed");
|
||||
}
|
||||
res = parser.getText();
|
||||
event = parser.next();
|
||||
if (event != XmlPullParser.END_TAG) {
|
||||
throw new XmlPullParserException(
|
||||
"Non-empty element tag contains child-elements, while Mixed Content (XML 3.2.2) is disallowed");
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current element as string.
|
||||
* <p>
|
||||
* The parser must be positioned on START_TAG.
|
||||
* </p>
|
||||
* Note that only the outermost namespace attributes ("xmlns") will be returned, not nested ones.
|
||||
*
|
||||
* @param parser the XML pull parser
|
||||
* @return the element as string
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String parseElement(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||
assert(parser.getEventType() == XmlPullParser.START_TAG);
|
||||
return parseContentDepth(parser, parser.getDepth());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content of a element as string.
|
||||
* <p>
|
||||
* The parser must be positioned on the START_TAG of the element which content is going to get
|
||||
* returned. If the current element is the empty element, then the empty string is returned. If
|
||||
* it is a element which contains just text, then just the text is returned. If it contains
|
||||
* nested elements (and text), then everything from the current opening tag to the corresponding
|
||||
* closing tag of the same depth is returned as String.
|
||||
* </p>
|
||||
* Note that only the outermost namespace attributes ("xmlns") will be returned, not nested ones.
|
||||
*
|
||||
* @param parser the XML pull parser
|
||||
* @return the content of a tag as string
|
||||
* @throws XmlPullParserException if parser encounters invalid XML
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
private static String parseContent(XmlPullParser parser)
|
||||
public static String parseContent(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
int parserDepth = parser.getDepth();
|
||||
return parseContentDepth(parser, parserDepth);
|
||||
assert(parser.getEventType() == XmlPullParser.START_TAG);
|
||||
if (parser.isEmptyElementTag()) {
|
||||
return "";
|
||||
}
|
||||
// Advance the parser, since we want to parse the content of the current element
|
||||
parser.next();
|
||||
return parseContentDepth(parser, parser.getDepth());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content from the current position of the parser up to the closing tag of the
|
||||
* given depth. Note that only the outermost namespace attributes ("xmlns") will be returned,
|
||||
* not nested ones.
|
||||
* <p>
|
||||
* This method is able to parse the content with MX- and KXmlParser. In order to achieve
|
||||
* this some trade-off has to be make, because KXmlParser does not support xml-roundtrip (ie.
|
||||
* return a String on getText() on START_TAG and END_TAG). We are therefore required to work
|
||||
* around this limitation, which results in only partial support for XML namespaces ("xmlns"):
|
||||
* Only the outermost namespace of elements will be included in the resulting String.
|
||||
* </p>
|
||||
*
|
||||
* @param parser
|
||||
* @param depth
|
||||
* @return the content of the current depth
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String parseContentDepth(XmlPullParser parser, int depth) throws XmlPullParserException, IOException {
|
||||
StringBuilder content = new StringBuilder();
|
||||
while (!(parser.next() == XmlPullParser.END_TAG && parser.getDepth() == depth)) {
|
||||
String text = parser.getText();
|
||||
if (text == null) {
|
||||
throw new IllegalStateException("Parser should never return 'null' on getText() here");
|
||||
XmlStringBuilder xml = new XmlStringBuilder();
|
||||
int event = parser.getEventType();
|
||||
boolean isEmptyElement = false;
|
||||
// XmlPullParser reports namespaces in nested elements even if *only* the outer ones defines
|
||||
// it. This 'flag' ensures that when a namespace is set for an element, it won't be set again
|
||||
// in a nested element. It's an ugly workaround that has the potential to break things.
|
||||
String namespaceElement = null;;
|
||||
while (true) {
|
||||
if (event == XmlPullParser.START_TAG) {
|
||||
xml.halfOpenElement(parser.getName());
|
||||
if (namespaceElement == null) {
|
||||
String namespace = parser.getNamespace();
|
||||
if (StringUtils.isNotEmpty(namespace)) {
|
||||
xml.attribute("xmlns", namespace);
|
||||
namespaceElement = parser.getName();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < parser.getAttributeCount(); i++) {
|
||||
xml.attribute(parser.getAttributeName(i), parser.getAttributeValue(i));
|
||||
}
|
||||
if (parser.isEmptyElementTag()) {
|
||||
xml.closeEmptyElement();
|
||||
isEmptyElement = true;
|
||||
}
|
||||
else {
|
||||
xml.rightAngelBracket();
|
||||
}
|
||||
}
|
||||
content.append(text);
|
||||
else if (event == XmlPullParser.END_TAG) {
|
||||
if (isEmptyElement) {
|
||||
// Do nothing as the element was already closed, just reset the flag
|
||||
isEmptyElement = false;
|
||||
}
|
||||
else {
|
||||
xml.closeElement(parser.getName());
|
||||
}
|
||||
if (namespaceElement != null && namespaceElement.equals(parser.getName())) {
|
||||
// We are on the closing tag, which defined the namespace as starting tag, reset the 'flag'
|
||||
namespaceElement = null;
|
||||
}
|
||||
if (parser.getDepth() <= depth) {
|
||||
// Abort parsing, we are done
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (event == XmlPullParser.TEXT) {
|
||||
xml.append(parser.getText());
|
||||
}
|
||||
event = parser.next();
|
||||
}
|
||||
return content.toString();
|
||||
return xml.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -174,6 +174,25 @@ public class XmlStringBuilder implements Appendable, CharSequence {
|
|||
return this;
|
||||
}
|
||||
|
||||
public XmlStringBuilder emptyElement(String element) {
|
||||
halfOpenElement(element);
|
||||
return closeEmptyElement();
|
||||
}
|
||||
|
||||
public XmlStringBuilder condEmptyElement(boolean condition, String element) {
|
||||
if (condition) {
|
||||
emptyElement(element);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmlStringBuilder condAttribute(boolean condition, String name, String value) {
|
||||
if (condition) {
|
||||
attribute(name, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder append(CharSequence csq) {
|
||||
assert csq != null;
|
||||
|
@ -213,4 +232,18 @@ public class XmlStringBuilder implements Appendable, CharSequence {
|
|||
public String toString() {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof XmlStringBuilder)) {
|
||||
return false;
|
||||
}
|
||||
XmlStringBuilder otherXmlStringBuilder = (XmlStringBuilder) other;
|
||||
return toString().equals(otherXmlStringBuilder.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return toString().hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2013 Florian Schmaus
|
||||
* Copyright © 2013-2014 Florian Schmaus
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,9 +16,11 @@
|
|||
*/
|
||||
package org.jivesoftware.smack.util.dns;
|
||||
|
||||
import org.jivesoftware.smack.SmackException.ConnectionException;
|
||||
|
||||
public class HostAddress {
|
||||
private String fqdn;
|
||||
private int port;
|
||||
private final String fqdn;
|
||||
private final int port;
|
||||
private Exception exception;
|
||||
|
||||
/**
|
||||
|
@ -28,16 +30,8 @@ public class HostAddress {
|
|||
* @throws IllegalArgumentException If the fqdn is null.
|
||||
*/
|
||||
public HostAddress(String fqdn) {
|
||||
if (fqdn == null)
|
||||
throw new IllegalArgumentException("FQDN is null");
|
||||
if (fqdn.charAt(fqdn.length() - 1) == '.') {
|
||||
this.fqdn = fqdn.substring(0, fqdn.length() - 1);
|
||||
}
|
||||
else {
|
||||
this.fqdn = fqdn;
|
||||
}
|
||||
// Set port to the default port for XMPP client communication
|
||||
this.port = 5222;
|
||||
this(fqdn, 5222);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,11 +42,17 @@ public class HostAddress {
|
|||
* @throws IllegalArgumentException If the fqdn is null or port is out of valid range (0 - 65535).
|
||||
*/
|
||||
public HostAddress(String fqdn, int port) {
|
||||
this(fqdn);
|
||||
if (fqdn == null)
|
||||
throw new IllegalArgumentException("FQDN is null");
|
||||
if (port < 0 || port > 65535)
|
||||
throw new IllegalArgumentException(
|
||||
"Port must be a 16-bit unsiged integer (i.e. between 0-65535. Port was: " + port);
|
||||
|
||||
if (fqdn.charAt(fqdn.length() - 1) == '.') {
|
||||
this.fqdn = fqdn.substring(0, fqdn.length() - 1);
|
||||
}
|
||||
else {
|
||||
this.fqdn = fqdn;
|
||||
}
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,17 @@ public class HostAddress {
|
|||
this.exception = e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Exception that caused a connection failure to this HostAddress. Every
|
||||
* HostAddress found in {@link ConnectionException} will have an Exception set,
|
||||
* which can be retrieved with this method.
|
||||
*
|
||||
* @return the Exception causing this HostAddress to fail
|
||||
*/
|
||||
public Exception getException() {
|
||||
return this.exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fqdn + ":" + port;
|
||||
|
|
|
@ -19,7 +19,6 @@ package org.jivesoftware.smack;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
@ -31,11 +30,11 @@ import org.jivesoftware.smack.packet.RosterPacket;
|
|||
import org.jivesoftware.smack.packet.IQ.Type;
|
||||
import org.jivesoftware.smack.packet.RosterPacket.Item;
|
||||
import org.jivesoftware.smack.packet.RosterPacket.ItemType;
|
||||
import org.jivesoftware.smack.test.util.TestUtils;
|
||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
/**
|
||||
|
@ -315,8 +314,6 @@ public class RosterTest {
|
|||
final String contactJID = "nurse@example.com";
|
||||
final Roster roster = connection.getRoster();
|
||||
assertNotNull("Can't get the roster from the provided connection!", roster);
|
||||
final XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
|
||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("<iq id=\"rostertest1\" type=\"set\" ")
|
||||
.append("to=\"").append(connection.getUser()).append("\">")
|
||||
|
@ -324,8 +321,7 @@ public class RosterTest {
|
|||
.append("<item jid=\"").append(contactJID).append("\"/>")
|
||||
.append("</query>")
|
||||
.append("</iq>");
|
||||
parser.setInput(new StringReader(sb.toString()));
|
||||
parser.next();
|
||||
final XmlPullParser parser = TestUtils.getIQParser(sb.toString());
|
||||
final IQ rosterPush = PacketParserUtils.parseIQ(parser, connection);
|
||||
initRoster(connection, roster);
|
||||
rosterListener.reset();
|
||||
|
@ -449,8 +445,6 @@ public class RosterTest {
|
|||
final String contactJID = "nurse@example.com";
|
||||
final Roster roster = connection.getRoster();
|
||||
assertNotNull("Can't get the roster from the provided connection!", roster);
|
||||
final XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
|
||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("<iq id=\"rostertest2\" type=\"set\" ")
|
||||
.append("to=\"").append(connection.getUser()).append("\">")
|
||||
|
@ -460,8 +454,7 @@ public class RosterTest {
|
|||
.append("</item>")
|
||||
.append("</query>")
|
||||
.append("</iq>");
|
||||
parser.setInput(new StringReader(sb.toString()));
|
||||
parser.next();
|
||||
final XmlPullParser parser = TestUtils.getIQParser(sb.toString());
|
||||
final IQ rosterPush = PacketParserUtils.parseIQ(parser, connection);
|
||||
initRoster(connection, roster);
|
||||
rosterListener.reset();
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.jivesoftware.smack.SmackException;
|
|||
import org.jivesoftware.smack.packet.PacketExtension;
|
||||
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
||||
import org.jivesoftware.smack.provider.ProviderManager;
|
||||
import org.jivesoftware.smack.test.util.TestUtils;
|
||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
@ -34,7 +35,7 @@ public class ParsingExceptionTest {
|
|||
private final static String EXTENSION2 =
|
||||
"<extension2 xmlns='namespace'>" +
|
||||
"<bar node='testNode'>" +
|
||||
"<i id='testid1' >" +
|
||||
"<i id='testid1'>" +
|
||||
"</i>" +
|
||||
"</bar>" +
|
||||
"</extension2>";
|
||||
|
@ -51,12 +52,14 @@ public class ParsingExceptionTest {
|
|||
|
||||
@Test
|
||||
public void consumeUnparsedInput() throws Exception {
|
||||
XmlPullParser parser = PacketParserUtils.getParserFor(
|
||||
final String MESSAGE_EXCEPTION_ELEMENT =
|
||||
"<" + ThrowException.ELEMENT + " xmlns='" + ThrowException.NAMESPACE + "'>" +
|
||||
"<nothingInHere>" +
|
||||
"</nothingInHere>" +
|
||||
"</" + ThrowException.ELEMENT + ">";
|
||||
XmlPullParser parser = TestUtils.getMessageParser(
|
||||
"<message from='user@server.example' to='francisco@denmark.lit' id='foo'>" +
|
||||
"<" + ThrowException.ELEMENT + " xmlns='" + ThrowException.NAMESPACE + "'>" +
|
||||
"<nothingInHere>" +
|
||||
"</nothingInHere>" +
|
||||
"</" + ThrowException.ELEMENT + ">" +
|
||||
MESSAGE_EXCEPTION_ELEMENT +
|
||||
EXTENSION2 +
|
||||
"</message>");
|
||||
int parserDepth = parser.getDepth();
|
||||
|
@ -67,8 +70,7 @@ public class ParsingExceptionTest {
|
|||
content = PacketParserUtils.parseContentDepth(parser, parserDepth);
|
||||
}
|
||||
assertNotNull(content);
|
||||
assertEquals(content, "<nothingInHere></nothingInHere>" + "</" + ThrowException.ELEMENT + ">" + EXTENSION2);
|
||||
|
||||
assertEquals(MESSAGE_EXCEPTION_ELEMENT + EXTENSION2 + "</message>", content);
|
||||
}
|
||||
|
||||
static class ThrowException implements PacketExtensionProvider {
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2013 Robin Collier
|
||||
*
|
||||
* 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.test.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
|
||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
final public class TestUtils {
|
||||
private TestUtils() {
|
||||
}
|
||||
|
||||
public static XmlPullParser getIQParser(String stanza) {
|
||||
return getParser(stanza, "iq");
|
||||
}
|
||||
|
||||
public static XmlPullParser getMessageParser(String stanza) {
|
||||
return getParser(stanza, "message");
|
||||
}
|
||||
|
||||
public static XmlPullParser getPresenceParser(String stanza) {
|
||||
return getParser(stanza, "presence");
|
||||
}
|
||||
|
||||
public static XmlPullParser getParser(String string, String startTag) {
|
||||
return getParser(new StringReader(string), startTag);
|
||||
}
|
||||
|
||||
public static XmlPullParser getParser(Reader reader, String startTag) {
|
||||
XmlPullParser parser;
|
||||
try {
|
||||
parser = PacketParserUtils.newXmppParser();
|
||||
parser.setInput(reader);
|
||||
if (startTag == null) {
|
||||
return parser;
|
||||
}
|
||||
boolean found = false;
|
||||
|
||||
while (!found) {
|
||||
if ((parser.next() == XmlPullParser.START_TAG) && parser.getName().equals(startTag))
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
throw new IllegalArgumentException("Can not find start tag '" + startTag + "'");
|
||||
} catch (XmlPullParserException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return parser;
|
||||
}
|
||||
|
||||
}
|
|
@ -27,12 +27,12 @@ import static org.junit.Assert.fail;
|
|||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.custommonkey.xmlunit.DetailedDiff;
|
||||
import org.custommonkey.xmlunit.Diff;
|
||||
import org.custommonkey.xmlunit.examples.RecursiveElementNameAndTextQualifier;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
import org.jivesoftware.smack.test.util.TestUtils;
|
||||
import org.junit.Test;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
@ -653,7 +653,13 @@ public class PacketParserUtilsTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
/**
|
||||
* RFC6121 5.2.3 explicitly disallows mixed content in <body/> elements. Make sure that we throw
|
||||
* an exception if we encounter such an element.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test(expected=XmlPullParserException.class)
|
||||
public void invalidMessageBodyContainingTagTest() throws Exception {
|
||||
String control = XMLBuilder.create("message")
|
||||
.a("from", "romeo@montague.lit/orchard")
|
||||
|
@ -667,23 +673,10 @@ public class PacketParserUtilsTest {
|
|||
.a("style", "font-weight: bold;")
|
||||
.t("Bad Message Body")
|
||||
.asString(outputProperties);
|
||||
|
||||
try {
|
||||
Message message = (Message) PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
|
||||
String body = "<span style=\"font-weight: bold;\">"
|
||||
+ "Bad Message Body</span>";
|
||||
assertEquals(body, message.getBody());
|
||||
|
||||
assertXMLNotEqual(control, message.toXML().toString());
|
||||
|
||||
DetailedDiff diffs = new DetailedDiff(new Diff(control, message.toXML().toString()));
|
||||
|
||||
// body has no namespace URI, span is escaped
|
||||
assertEquals(6, diffs.getAllDifferences().size());
|
||||
} catch(XmlPullParserException e) {
|
||||
fail("No parser exception should be thrown" + e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
Message message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||
|
||||
fail("Should throw exception. Instead got message: " + message.toXML().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -792,8 +785,8 @@ public class PacketParserUtilsTest {
|
|||
@Test
|
||||
public void parseContentDepthTest() throws Exception {
|
||||
final String stanza = "<iq type='result' to='foo@bar.com' from='baz.com' id='42'/>";
|
||||
XmlPullParser parser = PacketParserUtils.getParserFor(stanza, "iq");
|
||||
String content = PacketParserUtils.parseContentDepth(parser, 1);
|
||||
XmlPullParser parser = TestUtils.getParser(stanza, "iq");
|
||||
String content = PacketParserUtils.parseContent(parser);
|
||||
assertEquals("", content);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue