1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2025-09-11 01:59:38 +02:00

Compare commits

..

No commits in common. "c6c904cc3eb9409641b4ad334851debeb8e3b492" and "870756997faec1e1bfabfac0cd6c2395b04da873" have entirely different histories.

588 changed files with 5088 additions and 8787 deletions

View file

@ -1,7 +1,7 @@
language: android
android:
components:
- android-19
- android-16
jdk:
- oraclejdk8
- openjdk8
@ -11,7 +11,7 @@ cache:
- $HOME/.m2
before_install:
- export GRADLE_VERSION=5.2.1
- export GRADLE_VERSION=5.1.1
- wget https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-all.zip
- unzip -q gradle-${GRADLE_VERSION}-all.zip
- export PATH="$(pwd)/gradle-${GRADLE_VERSION}/bin:$PATH"

View file

@ -14,8 +14,8 @@ buildscript {
}
plugins {
id 'ru.vyarus.animalsniffer' version '1.5.0'
id 'net.ltgt.errorprone' version '0.8'
id 'ru.vyarus.animalsniffer' version '1.4.6'
id 'net.ltgt.errorprone' version '0.6'
}
apply plugin: 'org.kordamp.gradle.markdown'
@ -24,7 +24,6 @@ apply from: 'version.gradle'
allprojects {
apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'jacoco'
@ -81,8 +80,6 @@ allprojects {
':smack-omemo',
':smack-omemo-signal',
':smack-openpgp',
':smack-xmlparser',
':smack-xmlparser-xpp3',
].collect{ project(it) }
androidBootClasspathProjects = [
':smack-android',
@ -100,37 +97,13 @@ allprojects {
':smack-omemo-signal',
':smack-omemo-signal-integration-test',
].collect{ project(it) }
// When this list is empty, then move the according javadoc
// tool Werror option into the global configure section.
nonStrictJavadocProjects = [
':smack-bosh',
':smack-core',
':smack-experimental',
':smack-extensions',
':smack-im',
':smack-integration-test',
':smack-jingle-old',
':smack-legacy',
':smack-omemo',
':smack-tcp',
].collect{ project(it) }
// Lazily evaluate the Android bootClasspath and offline
// Javadoc using a closure, so that targets which do not
// require it are still able to succeed without an Android
// SDK.
androidBootClasspath = { getAndroidRuntimeJar() }
androidJavadocOffline = { getAndroidJavadocOffline() }
junit4Projects = [
':smack-core',
':smack-extensions',
':smack-im',
':smack-integration-test',
':smack-omemo',
':smack-omemo-signal',
':smack-openpgp',
].collect { project(it) }
junitVersion = '5.4.2'
powerMockVersion = '2.0.2'
junitVersion = '5.2.0'
}
group = 'org.igniterealtime.smack'
sourceCompatibility = JavaVersion.VERSION_1_8
@ -141,10 +114,6 @@ allprojects {
}
test {
useJUnitPlatform()
maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
// Enable full stacktraces of failed tests. Especially handy
// for environments like Travis.
testLogging {
@ -201,25 +170,21 @@ allprojects {
'-Xlint:-options',
'-Werror',
]
options.errorprone {
error("UnusedVariable", "UnusedMethod")
errorproneArgs = [
// Disable errorprone checks
'-Xep:TypeParameterUnusedInFormals:OFF',
// Disable errorpone StringSplitter check, as it
// recommends using Splitter from Guava, which we don't
// have (nor want to use in Smack).
'-Xep:StringSplitter:OFF',
'-Xep:JdkObsolete:OFF',
// Disabled because sinttest re-uses BeforeClass from junit.
// TODO: change sinttest so that it has it's own
// BeforeClass and re-enable this check.
'-Xep:JUnit4ClassAnnotationNonStatic:OFF',
// Disabled but should be re-enabled at some point
//'-Xep:InconsistentCapitalization:OFF',
'-Xep:MixedMutabilityReturnType:OFF',
]
}
options.errorprone.errorproneArgs = [
// Disable errorprone checks
'-Xep:TypeParameterUnusedInFormals:OFF',
// Disable errorpone StringSplitter check, as it
// recommends using Splitter from Guava, which we don't
// have (nor want to use in Smack).
'-Xep:StringSplitter:OFF',
'-Xep:JdkObsolete:OFF',
// Disabled because sinttest re-uses BeforeClass from junit.
// TODO: change sinttest so that it has it's own
// BeforeClass and re-enable this check.
'-Xep:JUnit4ClassAnnotationNonStatic:OFF',
// Disabled but should be re-enabled at some point
//'-Xep:InconsistentCapitalization:OFF',
]
}
tasks.withType(ScalaCompile) {
@ -267,11 +232,7 @@ allprojects {
}
dependencies {
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
testImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
errorprone 'com.google.errorprone:error_prone_core:2.3.3'
errorprone 'com.google.errorprone:error_prone_core:2.3.2'
errorproneJavac('com.google.errorprone:javac:9+181-r4173-1')
}
@ -280,15 +241,6 @@ allprojects {
test { dependsOn javadoc }
}
configure (junit4Projects) {
dependencies {
testImplementation "org.junit.vintage:junit-vintage-engine:$junitVersion"
testImplementation "org.powermock:powermock-module-junit4:$powerMockVersion"
testImplementation "org.powermock:powermock-module-junit4-rule:$powerMockVersion"
testImplementation "org.powermock:powermock-api-mockito2:$powerMockVersion"
}
}
gradle.taskGraph.whenReady { taskGraph ->
if (signingRequired
&& taskGraph.allTasks.any { it instanceof Sign }) {
@ -567,21 +519,19 @@ configure(integrationTestProjects + project(':smack-repl')) {
project(':smack-omemo').clirr.enabled = false
project(':smack-omemo-signal').clirr.enabled = false
configure(
[ ':smack-omemo',
':smack-omemo-signal',
':smack-omemo-signal-integration-test',
].collect{ project(it) }) {
}
subprojects*.jar {
manifest {
from sharedManifest
}
}
configure(subprojects - nonStrictJavadocProjects) {
tasks.withType(Javadoc) {
// Abort on javadoc warnings.
// See JDK-8200363 (https://bugs.openjdk.java.net/browse/JDK-8200363)
// for information about the -Xwerror option.
options.addStringOption('Xwerror', '-quiet')
}
}
configure(subprojects - gplLicensedProjects) {
checkstyle {
configProperties.checkstyleLicenseHeader = "header"
@ -696,7 +646,15 @@ def getGitCommit() {
}
def getAndroidRuntimeJar() {
def androidApiLevel = ext.smackMinAndroidSdk
// We set a different Android API level compared to
// smackMinAndroidSdk here. The runtime jar retrieved via this
// method is, compared to earlier Smack versions, not used to
// check for Android API compatibility. Instead it is used to for
// the eclipse classpath, for javadoc and when compiling the pure
// Android subprojects of Smack. Currently we require level 16
// here, because of the @TargetApi annotation found in
// AndroidUsingLinkProperties of minidns-android21.
def androidApiLevel = 16
def androidHome = getAndroidHome()
def androidJar = new File("$androidHome/platforms/android-${androidApiLevel}/android.jar")
if (androidJar.isFile()) {

View file

@ -39,7 +39,12 @@
<property name="format" value="^\s+$"/>
<property name="message" value="Line containing only whitespace character(s)"/>
</module>
<module name="FileTabCharacter"/>
<module name="RegexpSingleline">
<!-- We use {2,} instead of + here to address the typical case where a file was written
with tabs but javadoc is causing '\t *' -->
<property name="format" value="^\t+ {2,}"/>
<property name="message" value="Line containing space(s) after tab(s)"/>
</module>
<module name="RegexpSingleline">
<!--
Explaining the following Regex
@ -142,7 +147,6 @@
, LITERAL_DO
, LITERAL_FOR
, DO_WHILE
, COMMA
"/>
</module>
<module name="WhitespaceAround">

View file

@ -27,11 +27,11 @@ public MyExtension parse(XmlPullParser parser, int initialDepth) {
outerloop: while(true) {
// Make sure to have already parse all attributes of the outermost element,
// i.e. 'attrFoo' of 'myExtension' in this example. Then advance the parser
XmlPullParser.Event event = parser.next();
int event = parser.next();
// Use switch/case of int instead of a if/else-if cascade
switch (event) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
// Determine the name of the element which start tag we are seeing
String name = parser.getName();
// We can use switch/case of Strings since Java7, make use of its advantages
@ -52,15 +52,12 @@ public MyExtension parse(XmlPullParser parser, int initialDepth) {
break;
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
// The abort condition with the break labeled loop statement
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}

View file

@ -56,25 +56,23 @@ Smack Extensions and currently supported XEPs of smack-extensions
| [SI File Transfer](filetransfer.md) | [XEP-0096](https://xmpp.org/extensions/xep-0096.html) | n/a | Transfer files between two users over XMPP. |
| User Mood | [XEP-0107](https://xmpp.org/extensions/xep-0107.html) | 1.2.1 | Communicate the users current mood. |
| [Entity Capabilities](caps.md) | [XEP-0115](https://xmpp.org/extensions/xep-0115.html) | n/a | Broadcasting and dynamic discovery of entity capabilities. |
| [Jingle](jingle.html) | [XEP-0116](https://xmpp.org/extensions/xep-0166.html) | n/a | Initiate and manage sessions between two XMPP entities. |
| Data Forms Validation | [XEP-0122](https://xmpp.org/extensions/xep-0122.html) | n/a | Enables an application to specify additional validation guidelines . |
| Service Administration | [XEP-0133](https://xmpp.org/extensions/xep-0133.html) | n/a | Recommended best practices for service-level administration of servers and components using Ad-Hoc Commands. |
| Stream Compression | [XEP-0138](https://xmpp.org/extensions/xep-0138.html) | n/a | Support for optional compression of the XMPP stream.
| Data Forms Layout | [XEP-0141](https://xmpp.org/extensions/xep-0141.html) | n/a | Enables an application to specify form layouts. |
| Personal Eventing Protocol | [XEP-0163](https://xmpp.org/extensions/xep-0163.html) | n/a | Using the XMPP publish-subscribe protocol to broadcast state change events associated with an XMPP account. |
| [Jingle](jingle.html) | [XEP-0166](https://xmpp.org/extensions/xep-0166.html) | n/a | Initiate and manage sessions between two XMPP entities. |
| Message Delivery Receipts | [XEP-0184](https://xmpp.org/extensions/xep-0184.html) | n/a | Extension for message delivery receipts. The sender can request notification that the message has been delivered. |
| [Blocking Command](blockingcommand.md) | [XEP-0191](https://xmpp.org/extensions/xep-0191.html) | n/a | Communications blocking that is intended to be simpler than privacy lists (XEP-0016). |
| XMPP Ping | [XEP-0199](https://xmpp.org/extensions/xep-0199.html) | n/a | Sending application-level pings over XML streams.
| Entity Time | [XEP-0202](https://xmpp.org/extensions/xep-0202.html) | n/a | Allows entities to communicate their local time |
| Delayed Delivery | [XEP-0203](https://xmpp.org/extensions/xep-0203.html) | n/a | Extension for communicating the fact that an XML stanza has been delivered with a delay. |
| XMPP Over BOSH | [XEP-0206](https://xmpp.org/extensions/xep-0206.html) | n/a | Use Bidirectional-streams Over Synchronous HTTP (BOSH) to transport XMPP stanzas. |
| Data Forms Media Element | [XEP-0221](https://xmpp.org/extensions/xep-0221.html) | n/a | Allows to include media data in XEP-0004 data forms. |
| Attention | [XEP-0224](https://xmpp.org/extensions/xep-0224.html) | n/a | Getting attention of another user. |
| Bits of Binary | [XEP-0231](https://xmpp.org/extensions/xep-0231.html) | n/a | Including or referring to small bits of binary data in an XML stanza. |
| Best Practices for Resource Locking | [XEP-0296](https://xmpp.org/extensions/xep-0296.html) | n/a | Specifies best practices to be followed by Jabber/XMPP clients about when to lock into, and unlock away from, resources. |
| Last Message Correction | [XEP-0308](https://xmpp.org/extensions/xep-0308.html) | n/a | Provides a method for indicating that a message is a correction of the last sent message. |
| Last User Interaction in Presence | [XEP-0319](https://xmpp.org/extensions/xep-0319.html) | n/a | Communicate time of last user interaction via XMPP presence notifications. |
| Data Forms Geolocation Element | [XEP-0350](https://xmpp.org/extensions/xep-0350.html) | n/a | Allows to include XEP-0080 gelocation data in XEP-0004 data forms. |
| [Group Chat Invitations](invitation.md) | n/a | n/a | Send invitations to other users to join a group chat room. |
| [Jive Properties](properties.md) | n/a | n/a | TODO |

View file

@ -23,7 +23,7 @@ Whenever a packet extension is found in a packet, parsing will be
passed to the correct provider. Each provider must extend the
ExtensionElementProvider abstract class. Each extension provider is
responsible for parsing the raw XML stream, via the
Smack's `XmlPullParser` interface, to construct an object.
[XML Pull Parser](http://www.xmlpull.org/), to contruct an object.
You can also create an introspection provider
(`provider.IntrospectionProvider.PacketExtensionIntrospectionProvider`). Here,
@ -161,9 +161,9 @@ public class MyIQProvider extends IQProvider<MyIQ> {
// Start parsing loop
outerloop: while(true) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
switch(eventType) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
String elementName = parser.getName();
switch (elementName) {
case "user":
@ -175,15 +175,12 @@ public class MyIQProvider extends IQProvider<MyIQ> {
break;
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
// Abort condition: if the are on a end tag (closing element) of the same depth
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}
@ -228,9 +225,9 @@ _Disco Items IQProvider_
String node = "";
discoverItems.setNode(parser.getAttributeValue("", "node"));
outerloop: while (true) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
String elementName = parser.getName();
switch (elementName) {
case "item":
@ -242,7 +239,7 @@ _Disco Items IQProvider_
break;
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
String elementName = parser.getName();
switch (elementName) {
case "item":
@ -298,17 +295,17 @@ _Subscription PacketExtensionProvider Implementation_
String state = parser.getAttributeValue(null, "subscription");
boolean isRequired = false;
XmlPullParser.Event tag = parser.next();
int tag = parser.next();
if ((tag == XmlPullParser.START_ELEMENT) && parser.getName().equals("subscribe-options")) {
if ((tag == XmlPullParser.START_TAG) && parser.getName().equals("subscribe-options")) {
tag = parser.next();
if ((tag == XmlPullParser.START_ELEMENT) && parser.getName().equals("required"))
if ((tag == XmlPullParser.START_TAG) && parser.getName().equals("required"))
isRequired = true;
while (parser.next() != XmlPullParser.END_ELEMENT && parser.getName() != "subscribe-options");
while (parser.next() != XmlPullParser.END_TAG && parser.getName() != "subscribe-options");
}
while (parser.getEventType() != XmlPullParser.END_ELEMENT) parser.next();
while (parser.getEventType() != XmlPullParser.END_TAG) parser.next();
return new Subscription(jid, nodeId, subId, state == null ? null : Subscription.State.valueOf(state), isRequired);
}
}

View file

@ -169,10 +169,14 @@ recommended when using Smack.
</p>
<p>
Smack tries to depend on as few as possible libraries. The only
requirement is <a href="http://jxmpp.org">jXMPP</a>. For DNS
resolution we recommend to
use <a href="http://minidns.org">MiniDNS</a>.
If you dont' use a
dependency resolution system, like gradle or maven, then you will need
to download at least
the <a href="http://www.extreme.indiana.edu/xgws/xsoap/xpp/mxp1/">Xml
Pull Parser 3rd Edition (XPP3) library</a> or any other library that
implements the XmlPullParser interface
(like <a href="http://kxml.org/">kXML</a>) and the set of
<a href="http://jxmpp.org">jXMPP libraries</a>.
</p>
<p>

View file

@ -28,7 +28,4 @@ include 'smack-core',
'smack-omemo-signal',
'smack-omemo-signal-integration-test',
'smack-repl',
'smack-openpgp',
'smack-xmlparser',
'smack-xmlparser-stax',
'smack-xmlparser-xpp3'
'smack-openpgp'

View file

@ -7,7 +7,6 @@ smack-extensions and smack-experimental."""
// Note that the test dependencies (junit, ) are inferred from the
// sourceSet.test of the core subproject
dependencies {
api project(':smack-xmlparser-xpp3')
// Depend on minidns-android21 as optional dependency, even if may
// not need it. Can't hurt to have it in the programm path with
// the correct MiniDNS version as it won't hurt even if the

View file

@ -1,6 +1,6 @@
/**
*
* Copyright © 2014-2019 Florian Schmaus
* Copyright © 2014-2018 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,8 +16,9 @@
*/
package org.jivesoftware.smack.util.stringencoder.android;
import java.nio.charset.StandardCharsets;
import java.io.UnsupportedEncodingException;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.stringencoder.StringEncoder;
import android.util.Base64;
@ -38,13 +39,21 @@ public final class AndroidBase64UrlSafeEncoder implements StringEncoder<String>
@Override
public String encode(String string) {
return Base64.encodeToString(string.getBytes(StandardCharsets.UTF_8), BASE64_ENCODER_FLAGS);
try {
return Base64.encodeToString(string.getBytes(StringUtils.UTF8), BASE64_ENCODER_FLAGS);
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 not supported", e);
}
}
@Override
public String decode(String string) {
byte[] bytes = Base64.decode(string, BASE64_ENCODER_FLAGS);
return new String(bytes, StandardCharsets.UTF_8);
try {
return new String(bytes, StringUtils.UTF8);
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 not supported", e);
}
}
}

View file

@ -20,6 +20,7 @@ package org.jivesoftware.smack.bosh;
import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.io.StringReader;
import java.io.Writer;
import java.util.Map;
import java.util.logging.Level;
@ -43,7 +44,6 @@ import org.jivesoftware.smack.sasl.packet.SaslStreamElements.SASLFailure;
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Success;
import org.jivesoftware.smack.util.CloseableUtil;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.igniterealtime.jbosh.AbstractBody;
import org.igniterealtime.jbosh.BOSHClient;
@ -56,8 +56,11 @@ import org.igniterealtime.jbosh.BOSHException;
import org.igniterealtime.jbosh.BOSHMessageEvent;
import org.igniterealtime.jbosh.BodyQName;
import org.igniterealtime.jbosh.ComposableBody;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.parts.Resourcepart;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
/**
* Creates a connection to an XMPP server via HTTP binding.
@ -476,13 +479,14 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
if (streamId == null) {
streamId = body.getAttribute(BodyQName.create(XMPPBOSHConnection.BOSH_URI, "authid"));
}
final XmlPullParser parser = PacketParserUtils.getParserFor(body.toXML());
XmlPullParser.Event eventType = parser.getEventType();
final XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new StringReader(body.toXML()));
int eventType = parser.getEventType();
do {
eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
String name = parser.getName();
switch (name) {
case Message.ELEMENT:
@ -524,12 +528,9 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
}
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}
while (eventType != XmlPullParser.Event.END_DOCUMENT);
while (eventType != XmlPullParser.END_DOCUMENT);
}
catch (Exception e) {
if (isConnected()) {

View file

@ -2,27 +2,23 @@ description = """\
Smack core components."""
ext {
xmlUnitVersion = '2.6.2'
xmlUnitVersion = "2.6.0"
powerMockVersion = "1.7.3"
}
dependencies {
compile project(':smack-xmlparser')
compile 'xpp3:xpp3:1.1.4c'
compile "org.jxmpp:jxmpp-core:$jxmppVersion"
compile "org.jxmpp:jxmpp-jid:$jxmppVersion"
compile "org.minidns:minidns-core:$miniDnsVersion"
testCompile project(':smack-xmlparser-stax')
testCompile project(':smack-xmlparser-xpp3')
testCompile "org.jxmpp:jxmpp-jid:$jxmppVersion:tests"
testCompile "org.junit.jupiter:junit-jupiter-api:$junitVersion"
testCompile "org.junit.vintage:junit-vintage-engine:$junitVersion"
testCompile "org.xmlunit:xmlunit-core:$xmlUnitVersion"
// Explictily add assertj-core which is a dependency of
// xmlunit-assertj, but gradle fails to resolves it with:
// Execution failed for task ':smack-core:compileTestJava'.
// > Could not resolve all files for configuration ':smack-core:testCompileClasspath'.
// > Could not find org.assertj:assertj-core:.
// Required by:
// project :smack-core > org.xmlunit:xmlunit-assertj:2.6.2
testCompile "org.assertj:assertj-core:3.11.1"
testCompile "org.xmlunit:xmlunit-assertj:$xmlUnitVersion"
testCompile "org.xmlunit:xmlunit-legacy:$xmlUnitVersion"
testCompile "org.powermock:powermock-module-junit4:$powerMockVersion"
testCompile "org.powermock:powermock-module-junit4-rule:$powerMockVersion"
testCompile "org.powermock:powermock-api-mockito2:$powerMockVersion"
testCompile 'com.jamesmurty.utils:java-xmlbuilder:1.2'
}

View file

@ -16,9 +16,9 @@ package org.jivesoftware.smack.packet;
import org.jivesoftware.smack.provider.PrivacyProvider;
import org.jivesoftware.smack.test.SmackTestCase;
import org.jivesoftware.smack.xml.XmlPullParserFactory;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.StringReader;

View file

@ -32,8 +32,8 @@ import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.TCPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.util.ConnectionUtils;
import org.jivesoftware.smack.xml.XmlPullParserFactory;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlPullParser;
/**
* Base class for all the test cases which provides a pre-configured execution context. This
@ -414,9 +414,9 @@ public abstract class SmackTestCase extends TestCase {
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(systemStream, "UTF-8");
XmlPullParser.Event eventType = parser.getEventType();
int eventType = parser.getEventType();
do {
if (eventType == START_ELEMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("host")) {
host = parser.nextText();
}
@ -459,7 +459,7 @@ public abstract class SmackTestCase extends TestCase {
}
eventType = parser.next();
}
while (eventType != END_DOCUMENT);
while (eventType != XmlPullParser.END_DOCUMENT);
parsedOK = true;
}
catch (Exception e) {

View file

@ -20,9 +20,9 @@ import java.io.StringReader;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.test.SmackTestCase;
import org.jivesoftware.smack.xml.XmlPullParserFactory;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class XMPPErrorTest extends SmackTestCase {

View file

@ -23,7 +23,6 @@ import java.io.InputStream;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
@ -65,7 +64,6 @@ import javax.net.ssl.X509TrustManager;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.PasswordCallback;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.ConnectionConfiguration.DnssecMode;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
@ -123,8 +121,6 @@ import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.dns.HostAddress;
import org.jivesoftware.smack.util.dns.SmackDaneProvider;
import org.jivesoftware.smack.util.dns.SmackDaneVerifier;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.EntityFullJid;
@ -134,6 +130,8 @@ import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;
import org.jxmpp.util.XmppStringUtils;
import org.minidns.dnsname.DnsName;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
/**
@ -235,11 +233,11 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
private XmlEnvironment incomingStreamXmlEnvironment;
final Map<QName, NonzaCallback> nonzaCallbacks = new HashMap<>();
final Map<String, NonzaCallback> nonzaCallbacks = new HashMap<>();
protected final Lock connectionLock = new ReentrantLock();
protected final Map<QName, FullyQualifiedElement> streamFeatures = new HashMap<>();
protected final Map<String, FullyQualifiedElement> streamFeatures = new HashMap<>();
/**
* The full JID of the authenticated user, as returned by the resource binding response of the server.
@ -338,12 +336,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
Thread thread = new Thread(runnable);
thread.setName("Smack Cached Executor");
thread.setDaemon(true);
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
LOGGER.log(Level.WARNING, t + " encountered uncaught exception", e);
}
});
return thread;
}
});
@ -389,8 +381,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
protected Exception currentConnectionException;
private final Map<QName, IQRequestHandler> setIqRequestHandler = new HashMap<>();
private final Map<QName, IQRequestHandler> getIqRequestHandler = new HashMap<>();
private final Map<String, IQRequestHandler> setIqRequestHandler = new HashMap<>();
private final Map<String, IQRequestHandler> getIqRequestHandler = new HashMap<>();
/**
* Create a new XMPPConnection to an XMPP server.
@ -1221,7 +1213,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
protected final void parseAndProcessNonza(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException {
final String element = parser.getName();
final String namespace = parser.getNamespace();
final QName key = new QName(namespace, element);
final String key = XmppStringUtils.generateKey(element, namespace);
NonzaProvider<? extends Nonza> nonzaProvider = ProviderManager.getNonzaProvider(key);
if (nonzaProvider == null) {
@ -1251,7 +1243,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
try {
stanza = PacketParserUtils.parseStanza(parser, incomingStreamXmlEnvironment);
}
catch (XmlPullParserException | SmackParsingException | IOException e) {
catch (Exception e) {
CharSequence content = PacketParserUtils.parseContentDepth(parser,
parserDepth);
UnparseableStanza message = new UnparseableStanza(content, e);
@ -1303,7 +1295,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
final IQ iq = (IQ) packet;
if (iq.isRequestIQ()) {
final IQ iqRequest = iq;
final QName key = iqRequest.getChildElementQName();
final String key = XmppStringUtils.generateKey(iq.getChildElementName(), iq.getChildElementNamespace());
IQRequestHandler iqRequestHandler;
final IQ.Type type = iq.getType();
switch (type) {
@ -1622,9 +1614,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
streamFeatures.clear();
final int initialDepth = parser.getDepth();
while (true) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
if (eventType == XmlPullParser.Event.START_ELEMENT && parser.getDepth() == initialDepth + 1) {
if (eventType == XmlPullParser.START_TAG && parser.getDepth() == initialDepth + 1) {
FullyQualifiedElement streamFeature = null;
String name = parser.getName();
String namespace = parser.getNamespace();
@ -1655,7 +1647,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
addStreamFeature(streamFeature);
}
}
else if (eventType == XmlPullParser.Event.END_ELEMENT && parser.getDepth() == initialDepth) {
else if (eventType == XmlPullParser.END_TAG && parser.getDepth() == initialDepth) {
break;
}
}
@ -1694,8 +1686,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
@SuppressWarnings("unchecked")
@Override
public <F extends FullyQualifiedElement> F getFeature(String element, String namespace) {
QName qname = new QName(namespace, element);
return (F) streamFeatures.get(qname);
return (F) streamFeatures.get(XmppStringUtils.generateKey(element, namespace));
}
@Override
@ -1704,7 +1695,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
}
protected void addStreamFeature(FullyQualifiedElement feature) {
QName key = feature.getQName();
String key = XmppStringUtils.generateKey(feature.getElementName(), feature.getNamespace());
streamFeatures.put(key, feature);
}
@ -1813,7 +1804,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
@Override
public IQRequestHandler registerIQRequestHandler(final IQRequestHandler iqRequestHandler) {
final QName key = iqRequestHandler.getQName();
final String key = XmppStringUtils.generateKey(iqRequestHandler.getElement(), iqRequestHandler.getNamespace());
switch (iqRequestHandler.getType()) {
case set:
synchronized (setIqRequestHandler) {
@ -1836,7 +1827,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
@Override
public IQRequestHandler unregisterIQRequestHandler(String element, String namespace, IQ.Type type) {
final QName key = new QName(namespace, element);
final String key = XmppStringUtils.generateKey(element, namespace);
switch (type) {
case set:
synchronized (setIqRequestHandler) {
@ -2053,13 +2044,13 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
try {
Constructor<?> c = Class.forName("sun.security.pkcs11.SunPKCS11").getConstructor(InputStream.class);
String pkcs11Config = "name = SmartCard\nlibrary = " + config.getPKCS11Library();
ByteArrayInputStream config = new ByteArrayInputStream(pkcs11Config.getBytes(StandardCharsets.UTF_8));
ByteArrayInputStream config = new ByteArrayInputStream(pkcs11Config.getBytes(StringUtils.UTF8));
Provider p = (Provider) c.newInstance(config);
Security.addProvider(p);
ks = KeyStore.getInstance("PKCS11", p);
pcb = new PasswordCallback("PKCS11 Password: ", false);
ks = KeyStore.getInstance("PKCS11",p);
pcb = new PasswordCallback("PKCS11 Password: ",false);
callbackHandler.handle(new Callback[] {pcb});
ks.load(null, pcb.getPassword());
ks.load(null,pcb.getPassword());
}
catch (Exception e) {
LOGGER.log(Level.WARNING, "Exception", e);
@ -2067,8 +2058,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
}
}
else if ("Apple".equals(keyStoreType)) {
ks = KeyStore.getInstance("KeychainStore", "Apple");
ks.load(null, null);
ks = KeyStore.getInstance("KeychainStore","Apple");
ks.load(null,null);
// pcb = new PasswordCallback("Apple Keychain",false);
// pcb.setPassword(null);
}

View file

@ -25,8 +25,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.SocketFactory;
import javax.net.ssl.HostnameVerifier;
@ -48,7 +46,6 @@ import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;
import org.minidns.dnsname.DnsName;
import org.minidns.dnsname.InvalidDnsNameException;
import org.minidns.util.InetAddressUtil;
/**
@ -84,8 +81,6 @@ public abstract class ConnectionConfiguration {
SmackConfiguration.getVersion();
}
private static final Logger LOGGER = Logger.getLogger(ConnectionConfiguration.class.getName());
/**
* The XMPP domain of the XMPP Service. Usually servers use the same service name as the name
* of the server. However, there are some servers like google where host would be
@ -93,8 +88,6 @@ public abstract class ConnectionConfiguration {
*/
protected final DomainBareJid xmppServiceDomain;
protected final DnsName xmppServiceDomainDnsName;
protected final InetAddress hostAddress;
protected final DnsName host;
protected final int port;
@ -156,7 +149,7 @@ public abstract class ConnectionConfiguration {
private final boolean compressionEnabled;
protected ConnectionConfiguration(Builder<?, ?> builder) {
protected ConnectionConfiguration(Builder<?,?> builder) {
authzid = builder.authzid;
username = builder.username;
password = builder.password;
@ -169,19 +162,6 @@ public abstract class ConnectionConfiguration {
if (xmppServiceDomain == null) {
throw new IllegalArgumentException("Must define the XMPP domain");
}
DnsName xmppServiceDomainDnsName;
try {
xmppServiceDomainDnsName = DnsName.from(xmppServiceDomain);
} catch (InvalidDnsNameException e) {
LOGGER.log(Level.INFO,
"Could not transform XMPP service domain '" + xmppServiceDomain
+ "' to a DNS name. TLS X.509 certificate validiation may not be possible.",
e);
xmppServiceDomainDnsName = null;
}
this.xmppServiceDomainDnsName = xmppServiceDomainDnsName;
hostAddress = builder.hostAddress;
host = builder.host;
port = builder.port;
@ -245,17 +225,6 @@ public abstract class ConnectionConfiguration {
return xmppServiceDomain;
}
/**
* Returns the XMPP service domain as DNS name if possible. Note that since not every XMPP address domainpart is a
* valid DNS name, this method may return <code>null</code>.
*
* @return the XMPP service domain as DNS name or <code>null</code>.
* @since 4.3.4
*/
public DnsName getXmppServiceDomainAsDnsNameIfPossible() {
return xmppServiceDomainDnsName;
}
/**
* Returns the TLS security mode used when making the connection. By default,
* the mode is {@link SecurityMode#ifpossible}.

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2018-2019 Florian Schmaus
* Copyright 2018 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,18 +19,18 @@ package org.jivesoftware.smack;
import java.util.HashMap;
import java.util.Map;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPException.FailedNonzaException;
import org.jivesoftware.smack.packet.Nonza;
import org.jivesoftware.smack.util.XmppElementUtil;
import org.jxmpp.util.XmppStringUtils;
public class NonzaCallback {
protected final AbstractXMPPConnection connection;
protected final Map<QName, GenericElementListener<? extends Nonza>> filterAndListeners;
protected final Map<String, GenericElementListener<? extends Nonza>> filterAndListeners;
private NonzaCallback(Builder builder) {
this.connection = builder.connection;
@ -39,7 +39,7 @@ public class NonzaCallback {
}
void onNonzaReceived(Nonza nonza) {
QName key = nonza.getQName();
String key = XmppStringUtils.generateKey(nonza.getElementName(), nonza.getNamespace());
GenericElementListener<? extends Nonza> nonzaListener = filterAndListeners.get(key);
nonzaListener.processElement(nonza);
@ -47,8 +47,8 @@ public class NonzaCallback {
public void cancel() {
synchronized (connection.nonzaCallbacks) {
for (Map.Entry<QName, GenericElementListener<? extends Nonza>> entry : filterAndListeners.entrySet()) {
QName filterKey = entry.getKey();
for (Map.Entry<String, GenericElementListener<? extends Nonza>> entry : filterAndListeners.entrySet()) {
String filterKey = entry.getKey();
NonzaCallback installedCallback = connection.nonzaCallbacks.get(filterKey);
if (equals(installedCallback)) {
connection.nonzaCallbacks.remove(filterKey);
@ -63,7 +63,7 @@ public class NonzaCallback {
}
synchronized (connection.nonzaCallbacks) {
for (QName key : filterAndListeners.keySet()) {
for (String key : filterAndListeners.keySet()) {
connection.nonzaCallbacks.put(key, this);
}
}
@ -78,8 +78,8 @@ public class NonzaCallback {
Builder builder) {
super(builder);
final QName successNonzaKey = XmppElementUtil.getQNameFor(successNonzaClass);
final QName failedNonzaKey = XmppElementUtil.getQNameFor(failedNonzaClass);
final String successNonzaKey = XmppElementUtil.getKeyFor(successNonzaClass);
final String failedNonzaKey = XmppElementUtil.getKeyFor(failedNonzaClass);
final GenericElementListener<SN> successListener = new GenericElementListener<SN>(successNonzaClass) {
@Override
@ -139,14 +139,14 @@ public class NonzaCallback {
public static final class Builder {
private final AbstractXMPPConnection connection;
private Map<QName, GenericElementListener<? extends Nonza>> filterAndListeners = new HashMap<>();
private Map<String, GenericElementListener<? extends Nonza>> filterAndListeners = new HashMap<>();
Builder(AbstractXMPPConnection connection) {
this.connection = connection;
}
public <N extends Nonza> Builder listenFor(Class<? extends N> nonza, GenericElementListener<? extends N> nonzaListener) {
QName key = XmppElementUtil.getQNameFor(nonza);
String key = XmppElementUtil.getKeyFor(nonza);
filterAndListeners.put(key, nonzaListener);
return this;
}

View file

@ -29,7 +29,6 @@ import javax.net.ssl.HostnameVerifier;
import org.jivesoftware.smack.compression.XMPPInputOutputStream;
import org.jivesoftware.smack.debugger.ReflectionDebuggerFactory;
import org.jivesoftware.smack.debugger.SmackDebuggerFactory;
import org.jivesoftware.smack.parsing.ExceptionThrowingCallback;
import org.jivesoftware.smack.parsing.ExceptionThrowingCallbackWithHint;
import org.jivesoftware.smack.parsing.ParsingExceptionCallback;
import org.jivesoftware.smack.util.Objects;
@ -381,5 +380,4 @@ public final class SmackConfiguration {
public static int getDefaultConcurrencyLevelLimit() {
return defaultConcurrencyLevelLimit;
}
}

View file

@ -20,7 +20,6 @@ package org.jivesoftware.smack;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
@ -45,9 +44,10 @@ import org.jivesoftware.smack.sasl.core.SCRAMSHA1Mechanism;
import org.jivesoftware.smack.sasl.core.ScramSha1PlusMechanism;
import org.jivesoftware.smack.util.CloseableUtil;
import org.jivesoftware.smack.util.FileUtils;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
public final class SmackInitialization {
@ -69,7 +69,7 @@ public final class SmackInitialization {
String smackVersion;
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(FileUtils.getStreamForClasspathFile("org.jivesoftware.smack/version", null), StandardCharsets.UTF_8));
reader = new BufferedReader(new InputStreamReader(FileUtils.getStreamForClasspathFile("org.jivesoftware.smack/version", null), StringUtils.UTF8));
smackVersion = reader.readLine();
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Could not determine Smack version", e);
@ -141,10 +141,12 @@ public final class SmackInitialization {
public static void processConfigFile(InputStream cfgFileStream,
Collection<Exception> exceptions, ClassLoader classLoader) throws Exception {
XmlPullParser parser = PacketParserUtils.getParserFor(cfgFileStream);
XmlPullParser.Event eventType = parser.getEventType();
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(cfgFileStream, "UTF-8");
int eventType = parser.getEventType();
do {
if (eventType == XmlPullParser.Event.START_ELEMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("startupClasses")) {
parseClassesToLoad(parser, false, exceptions, classLoader);
}
@ -154,7 +156,7 @@ public final class SmackInitialization {
}
eventType = parser.next();
}
while (eventType != XmlPullParser.Event.END_DOCUMENT);
while (eventType != XmlPullParser.END_DOCUMENT);
CloseableUtil.maybeClose(cfgFileStream, LOGGER);
}
@ -162,10 +164,12 @@ public final class SmackInitialization {
Collection<Exception> exceptions, ClassLoader classLoader)
throws Exception {
final String startName = parser.getName();
XmlPullParser.Event eventType;
int eventType;
String name;
outerloop: do {
eventType = parser.next();
if (eventType == XmlPullParser.Event.START_ELEMENT && "className".equals(parser.getName())) {
name = parser.getName();
if (eventType == XmlPullParser.START_TAG && "className".equals(name)) {
String classToLoad = parser.nextText();
if (SmackConfiguration.isDisabledSmackClass(classToLoad)) {
continue outerloop;
@ -184,7 +188,7 @@ public final class SmackInitialization {
}
}
}
while (!(eventType == XmlPullParser.Event.END_ELEMENT && startName.equals(parser.getName())));
while (!(eventType == XmlPullParser.END_TAG && startName.equals(name)));
}
private static void loadSmackClass(String className, boolean optional, ClassLoader classLoader) throws Exception {

View file

@ -149,8 +149,9 @@ public class SmackReactor {
long releaseTimeEpoch = System.currentTimeMillis() + unit.toMillis(delay);
Date releaseTimeDate = new Date(releaseTimeEpoch);
ScheduledAction scheduledAction = new ScheduledAction(runnable, releaseTimeDate, this);
scheduledActions.add(scheduledAction);
selector.wakeup();
synchronized (scheduledActions) {
scheduledActions.add(scheduledAction);
}
return scheduledAction;
}
@ -208,8 +209,7 @@ public class SmackReactor {
long selectWait;
if (nextScheduledAction == null) {
// There is no next scheduled action, wait indefinitely in select() or until another thread invokes
// selector.wakeup().
// There is no next scheduled action, wait indefinitely in select().
selectWait = 0;
} else {
selectWait = nextScheduledAction.getTimeToDueMillis();

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2003-2007 Jive Software, 2016-2019 Florian Schmaus.
* Copyright 2003-2007 Jive Software, 2016-2018 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -41,7 +41,7 @@ import org.jivesoftware.smack.packet.Stanza;
* @see XMPPConnection#createStanzaCollector(StanzaFilter)
* @author Matt Tucker
*/
public final class StanzaCollector implements AutoCloseable {
public class StanzaCollector implements AutoCloseable {
private final StanzaFilter packetFilter;
@ -69,7 +69,7 @@ public final class StanzaCollector implements AutoCloseable {
* @param connection the connection the collector is tied to.
* @param configuration the configuration used to construct this collector
*/
StanzaCollector(XMPPConnection connection, Configuration configuration) {
protected StanzaCollector(XMPPConnection connection, Configuration configuration) {
this.connection = connection;
this.packetFilter = configuration.packetFilter;
this.resultQueue = new ArrayDeque<>(configuration.size);
@ -98,6 +98,18 @@ public final class StanzaCollector implements AutoCloseable {
}
}
/**
* Returns the stanza filter associated with this stanza collector. The packet
* filter is used to determine what packets are queued as results.
*
* @return the stanza filter.
* @deprecated use {@link #getStanzaFilter()} instead.
*/
@Deprecated
public StanzaFilter getPacketFilter() {
return getStanzaFilter();
}
/**
* Returns the stanza filter associated with this stanza collector. The stanza
* filter is used to determine what stanzas are queued as results.
@ -317,21 +329,6 @@ public final class StanzaCollector implements AutoCloseable {
return resultQueue.size();
}
private String stringCache;
@Override
public String toString() {
if (stringCache == null) {
StringBuilder sb = new StringBuilder(128);
sb.append("Stanza Collector filter='").append(packetFilter).append('\'');
if (request != null) {
sb.append(" request='").append(request).append('\'');
}
stringCache = sb.toString();
}
return stringCache;
}
synchronized void notifyConnectionError(Exception exception) {
connectionException = exception;
notifyAll();
@ -383,6 +380,19 @@ public final class StanzaCollector implements AutoCloseable {
private Configuration() {
}
/**
* Set the stanza filter used by this collector. If <code>null</code>, then all packets will
* get collected by this collector.
*
* @param packetFilter
* @return a reference to this configuration.
* @deprecated use {@link #setStanzaFilter(StanzaFilter)} instead.
*/
@Deprecated
public Configuration setPacketFilter(StanzaFilter packetFilter) {
return setStanzaFilter(packetFilter);
}
/**
* Set the stanza filter used by this collector. If <code>null</code>, then all stanzas will
* get collected by this collector.

View file

@ -20,7 +20,7 @@ import org.jivesoftware.smack.compress.packet.Compressed;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.provider.NonzaProvider;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.xmlpull.v1.XmlPullParser;
public final class CompressedProvider extends NonzaProvider<Compressed> {

View file

@ -27,8 +27,8 @@ import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.provider.NonzaProvider;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public final class FailureProvider extends NonzaProvider<Failure> {
@ -46,9 +46,9 @@ public final class FailureProvider extends NonzaProvider<Failure> {
XmlEnvironment failureXmlEnvironment = XmlEnvironment.from(parser, xmlEnvironment);
outerloop: while (true) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
String name = parser.getName();
String namespace = parser.getNamespace();
switch (namespace) {
@ -72,12 +72,11 @@ public final class FailureProvider extends NonzaProvider<Failure> {
break;
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
default: // fall out
}
}

View file

@ -1,70 +0,0 @@
/**
*
* 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.datatypes;
public abstract class Scalar extends java.lang.Number {
/**
*
*/
private static final long serialVersionUID = 1L;
private final java.lang.Number number;
protected Scalar(java.lang.Number number) {
this.number = number;
}
public final Number number() {
return number;
}
@Override
public final int intValue() {
return number.intValue();
}
@Override
public final long longValue() {
return number.longValue();
}
@Override
public final float floatValue() {
return number.floatValue();
}
@Override
public final double doubleValue() {
return number.doubleValue();
}
@Override
public final int hashCode() {
return number.hashCode();
}
@Override
public final boolean equals(Object other) {
return number.equals(other);
}
@Override
public final String toString() {
return number.toString();
}
}

View file

@ -1,42 +0,0 @@
/**
*
* 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.datatypes;
import org.jivesoftware.smack.util.NumberUtil;
/**
* A number representing an unsigned 16-bit integer. Can be used for values with the XML schema type "xs:unsingedShort".
*/
public final class UInt16 extends Scalar {
private static final long serialVersionUID = 1L;
private final int number;
private UInt16(int number) {
super(NumberUtil.requireUShort16(number));
this.number = number;
}
public int nativeRepresentation() {
return number;
}
public static UInt16 from(int number) {
return new UInt16(number);
}
}

View file

@ -1,42 +0,0 @@
/**
*
* 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.datatypes;
import org.jivesoftware.smack.util.NumberUtil;
/**
* A number representing an unsigned 32-bit integer. Can be used for values with the XML schema type "xs:unsignedInt".
*/
public final class UInt32 extends Scalar {
private static final long serialVersionUID = 1L;
private final long number;
private UInt32(long number) {
super(NumberUtil.requireUInt32(number));
this.number = number;
}
public long nativeRepresentation() {
return number;
}
public static UInt32 from(long number) {
return new UInt32(number);
}
}

View file

@ -1,21 +0,0 @@
/**
*
* 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.
*/
/**
* Custom datatypes for Integers.
*/
package org.jivesoftware.smack.datatypes;

View file

@ -57,10 +57,10 @@ import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Challenge;
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Success;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jxmpp.jid.parts.Resourcepart;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public abstract class AbstractXmppStateMachineConnection extends AbstractXMPPConnection {
@ -310,10 +310,10 @@ public abstract class AbstractXmppStateMachineConnection extends AbstractXMPPCon
// Skip the enclosing stream open what is guaranteed to be there.
parser.next();
XmlPullParser.Event event = parser.getEventType();
int event = parser.getEventType();
outerloop: while (true) {
switch (event) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
final String name = parser.getName();
// Note that we don't handle "stream" here as it's done in the splitter.
switch (name) {
@ -353,9 +353,8 @@ public abstract class AbstractXmppStateMachineConnection extends AbstractXMPPCon
break;
}
break;
case END_DOCUMENT:
case XmlPullParser.END_DOCUMENT:
break outerloop;
default: // fall out
}
event = parser.next();
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2015-2019 Florian Schmaus
* Copyright 2015 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,8 +16,6 @@
*/
package org.jivesoftware.smack.iqrequest;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.packet.IQ;
/**
@ -52,8 +50,4 @@ public interface IQRequestHandler {
String getElement();
String getNamespace();
default QName getQName() {
return new QName(getNamespace(), getElement());
}
}

View file

@ -52,7 +52,7 @@ public class DefaultExtensionElement implements ExtensionElement {
private String elementName;
private String namespace;
private Map<String, String> map;
private Map<String,String> map;
/**
* Creates a new generic stanza extension.
@ -107,7 +107,7 @@ public class DefaultExtensionElement implements ExtensionElement {
if (map == null) {
return Collections.emptySet();
}
return Collections.unmodifiableSet(new HashMap<String, String>(map).keySet());
return Collections.unmodifiableSet(new HashMap<String,String>(map).keySet());
}
/**
@ -131,7 +131,7 @@ public class DefaultExtensionElement implements ExtensionElement {
*/
public synchronized void setValue(String name, String value) {
if (map == null) {
map = new HashMap<String, String>();
map = new HashMap<String,String>();
}
map.put(name, value);
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2018-2019 Florian Schmaus
* Copyright 2018 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,8 +16,6 @@
*/
package org.jivesoftware.smack.packet;
import javax.xml.namespace.QName;
public interface FullyQualifiedElement extends NamedElement {
/**
@ -27,9 +25,4 @@ public interface FullyQualifiedElement extends NamedElement {
*/
String getNamespace();
default QName getQName() {
String namespaceURI = getNamespace();
String localPart = getElementName();
return new QName(namespaceURI, localPart);
}
}

View file

@ -20,8 +20,6 @@ package org.jivesoftware.smack.packet;
import java.util.List;
import java.util.Locale;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.XmlStringBuilder;
@ -48,7 +46,6 @@ public abstract class IQ extends Stanza {
public static final String IQ_ELEMENT = "iq";
public static final String QUERY_ELEMENT = "query";
private final QName childElementQName;
private final String childElementName;
private final String childElementNamespace;
@ -59,7 +56,6 @@ public abstract class IQ extends Stanza {
type = iq.getType();
this.childElementName = iq.childElementName;
this.childElementNamespace = iq.childElementNamespace;
this.childElementQName = iq.childElementQName;
}
protected IQ(String childElementName) {
@ -69,11 +65,6 @@ public abstract class IQ extends Stanza {
protected IQ(String childElementName, String childElementNamespace) {
this.childElementName = childElementName;
this.childElementNamespace = childElementNamespace;
if (childElementName == null) {
childElementQName = null;
} else {
childElementQName = new QName(childElementNamespace, childElementName);
}
}
/**
@ -124,10 +115,6 @@ public abstract class IQ extends Stanza {
return !isRequestIQ();
}
public final QName getChildElementQName() {
return childElementQName;
}
public final String getChildElementName() {
return childElementName;
}

View file

@ -24,8 +24,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.jivesoftware.smack.util.EqualsUtil;
import org.jivesoftware.smack.util.HashCode;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.TypedCloneable;
import org.jivesoftware.smack.util.XmlStringBuilder;
@ -563,22 +561,32 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
return subject;
}
private final HashCode.Cache hashCodeCache = new HashCode.Cache();
@Override
public int hashCode() {
return hashCodeCache.getHashCode(c ->
c.append(language)
.append(subject)
);
final int prime = 31;
int result = 1;
if (language != null) {
result = prime * result + this.language.hashCode();
}
result = prime * result + this.subject.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
return EqualsUtil.equals(this, obj, (e, o) ->
e.append(language, o.language)
.append(subject, o.subject)
);
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Subject other = (Subject) obj;
// simplified comparison because language and subject are always set
return this.language.equals(other.language) && this.subject.equals(other.subject);
}
@Override
@ -662,22 +670,31 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
return message;
}
private final HashCode.Cache hashCodeCache = new HashCode.Cache();
@Override
public int hashCode() {
return hashCodeCache.getHashCode(c ->
c.append(language)
.append(message)
);
final int prime = 31;
int result = 1;
if (language != null) {
result = prime * result + this.language.hashCode();
}
result = prime * result + this.message.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
return EqualsUtil.equals(this, obj, (e, o) ->
e.append(language, o.language)
.append(message, o.message)
);
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Body other = (Body) obj;
// simplified comparison because language and message are always set
return Objects.equals(this.language, other.language) && this.message.equals(other.message);
}
@Override

View file

@ -150,7 +150,7 @@ public interface Packet extends TopLevelStreamElement {
/**
* Returns the first extension of this stanza that has the given namespace.
* <p>
* When possible, use {@link #getExtension(String, String)} instead.
* When possible, use {@link #getExtension(String,String)} instead.
* </p>
*
* @param namespace the namespace of the extension that is desired.

View file

@ -68,12 +68,12 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
private String status = null;
/**
* The priority of the presence. It is <code>null</code> to indicate that the original
* The priority of the presence. The magic value {@link Integer#MIN_VALUE} is used to indicate that the original
* presence stanza did not had an explicit priority set. In which case the priority defaults to 0.
*
* @see <a href="https://tools.ietf.org/html/rfc6121#section-4.7.2.3">RFC 6121 § 4.7.2.3.</a>
*/
private Byte priority;
private int priority = Integer.MIN_VALUE;
private Mode mode = null;
@ -203,13 +203,13 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
}
/**
* Returns the priority of the presence.
* Returns the priority of the presence, or Integer.MIN_VALUE if no priority has been set.
*
* @return the priority.
* @see <a href="https://tools.ietf.org/html/rfc6121#section-4.7.2.3">RFC 6121 § 4.7.2.3. Priority Element</a>
*/
public int getPriority() {
if (priority == null) {
if (priority == Integer.MIN_VALUE) {
return 0;
}
return priority;
@ -227,10 +227,6 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
throw new IllegalArgumentException("Priority value " + priority +
" is not valid. Valid range is -128 through 127.");
}
setPriority((byte) priority);
}
public void setPriority(byte priority) {
this.priority = priority;
}
@ -268,7 +264,7 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
if (!StringUtils.isNullOrEmpty(status)) {
sb.append("status=").append(status).append(',');
}
if (priority != null) {
if (priority != Integer.MIN_VALUE) {
sb.append("prio=").append(priority).append(',');
}
sb.append(']');
@ -286,7 +282,9 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
buf.rightAngleBracket();
buf.optElement("status", status);
buf.optElement("priority", priority);
if (priority != Integer.MIN_VALUE) {
buf.element("priority", Integer.toString(priority));
}
if (mode != null && mode != Mode.available) {
buf.element("show", mode);
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2015-2019 Florian Schmaus.
* Copyright 2015 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,13 +21,13 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.util.MultiMap;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jxmpp.util.XmppStringUtils;
/**
* An {@link ExtensionElement} modeling the often required and used XML features when using XMPP. It
* is therefore suitable for most use cases. Use
@ -47,7 +47,7 @@ public final class StandardExtensionElement implements ExtensionElement {
private final String namespace;
private final Map<String, String> attributes;
private final String text;
private final MultiMap<QName, StandardExtensionElement> elements;
private final MultiMap<String, StandardExtensionElement> elements;
private XmlStringBuilder xmlCache;
@ -65,7 +65,7 @@ public final class StandardExtensionElement implements ExtensionElement {
}
private StandardExtensionElement(String name, String namespace, Map<String, String> attributes, String text,
MultiMap<QName, StandardExtensionElement> elements) {
MultiMap<String, StandardExtensionElement> elements) {
this.name = StringUtils.requireNotNullNorEmpty(name, "Name must not be null nor empty");
this.namespace = StringUtils.requireNotNullNorEmpty(namespace, "Namespace must not be null nor empty");
if (attributes == null) {
@ -100,7 +100,7 @@ public final class StandardExtensionElement implements ExtensionElement {
if (elements == null) {
return null;
}
QName key = new QName(namespace, element);
String key = XmppStringUtils.generateKey(element, namespace);
return elements.getFirst(key);
}
@ -112,7 +112,7 @@ public final class StandardExtensionElement implements ExtensionElement {
if (elements == null) {
return null;
}
QName key = new QName(namespace, element);
String key = XmppStringUtils.generateKey(element, namespace);
return elements.getAll(key);
}
@ -145,7 +145,7 @@ public final class StandardExtensionElement implements ExtensionElement {
xml.optEscape(text);
if (elements != null) {
for (Map.Entry<QName, StandardExtensionElement> entry : elements.entrySet()) {
for (Map.Entry<String, StandardExtensionElement> entry : elements.entrySet()) {
xml.append(entry.getValue().toXML(getNamespace()));
}
}
@ -165,7 +165,7 @@ public final class StandardExtensionElement implements ExtensionElement {
private Map<String, String> attributes;
private String text;
private MultiMap<QName, StandardExtensionElement> elements;
private MultiMap<String, StandardExtensionElement> elements;
private Builder(String name, String namespace) {
this.name = name;
@ -200,8 +200,7 @@ public final class StandardExtensionElement implements ExtensionElement {
if (elements == null) {
elements = new MultiMap<>();
}
QName key = element.getQName();
String key = XmppStringUtils.generateKey(element.getElementName(), element.getNamespace());
elements.put(key, element);
return this;
}

View file

@ -23,8 +23,6 @@ import java.util.Collection;
import java.util.List;
import java.util.Locale;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.packet.id.StanzaIdUtil;
import org.jivesoftware.smack.util.MultiMap;
import org.jivesoftware.smack.util.PacketUtil;
@ -33,6 +31,7 @@ import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.stringprep.XmppStringprepException;
import org.jxmpp.util.XmppStringUtils;
/**
* Base class for XMPP Stanzas, which are called Stanza in older versions of Smack (i.e. &lt; 4.1).
@ -57,7 +56,7 @@ public abstract class Stanza implements TopLevelStreamElement {
protected static final String DEFAULT_LANGUAGE =
java.util.Locale.getDefault().getLanguage().toLowerCase(Locale.US);
private final MultiMap<QName, ExtensionElement> extensionElements = new MultiMap<>();
private final MultiMap<String, ExtensionElement> packetExtensions = new MultiMap<>();
private String id = null;
private Jid to;
@ -307,9 +306,9 @@ public abstract class Stanza implements TopLevelStreamElement {
* @return a list of all extension elements of this stanza.
*/
public List<ExtensionElement> getExtensions() {
synchronized (extensionElements) {
synchronized (packetExtensions) {
// No need to create a new list, values() will already create a new one for us
return extensionElements.values();
return packetExtensions.values();
}
}
@ -327,14 +326,14 @@ public abstract class Stanza implements TopLevelStreamElement {
public List<ExtensionElement> getExtensions(String elementName, String namespace) {
requireNotNullNorEmpty(elementName, "elementName must not be null nor empty");
requireNotNullNorEmpty(namespace, "namespace must not be null nor empty");
QName key = new QName(namespace, elementName);
return extensionElements.getAll(key);
String key = XmppStringUtils.generateKey(elementName, namespace);
return packetExtensions.getAll(key);
}
/**
* Returns the first extension of this stanza that has the given namespace.
* <p>
* When possible, use {@link #getExtension(String, String)} instead.
* When possible, use {@link #getExtension(String,String)} instead.
* </p>
*
* @param namespace the namespace of the extension that is desired.
@ -360,10 +359,10 @@ public abstract class Stanza implements TopLevelStreamElement {
if (namespace == null) {
return null;
}
QName key = new QName(namespace, elementName);
String key = XmppStringUtils.generateKey(elementName, namespace);
ExtensionElement packetExtension;
synchronized (extensionElements) {
packetExtension = extensionElements.getFirst(key);
synchronized (packetExtensions) {
packetExtension = packetExtensions.getFirst(key);
}
if (packetExtension == null) {
return null;
@ -378,9 +377,9 @@ public abstract class Stanza implements TopLevelStreamElement {
*/
public void addExtension(ExtensionElement extension) {
if (extension == null) return;
QName key = extension.getQName();
synchronized (extensionElements) {
extensionElements.put(key, extension);
String key = XmppStringUtils.generateKey(extension.getElementName(), extension.getNamespace());
synchronized (packetExtensions) {
packetExtensions.put(key, extension);
}
}
@ -394,7 +393,7 @@ public abstract class Stanza implements TopLevelStreamElement {
*/
public ExtensionElement overrideExtension(ExtensionElement extension) {
if (extension == null) return null;
synchronized (extensionElements) {
synchronized (packetExtensions) {
// Note that we need to use removeExtension(String, String) here. If would use
// removeExtension(ExtensionElement) then we would remove based on the equality of ExtensionElement, which
// is not what we want in this case.
@ -430,9 +429,9 @@ public abstract class Stanza implements TopLevelStreamElement {
if (elementName == null) {
return hasExtension(namespace);
}
QName key = new QName(namespace, elementName);
synchronized (extensionElements) {
return extensionElements.containsKey(key);
String key = XmppStringUtils.generateKey(elementName, namespace);
synchronized (packetExtensions) {
return packetExtensions.containsKey(key);
}
}
@ -443,8 +442,8 @@ public abstract class Stanza implements TopLevelStreamElement {
* @return true if a stanza extension exists, false otherwise.
*/
public boolean hasExtension(String namespace) {
synchronized (extensionElements) {
for (ExtensionElement packetExtension : extensionElements.values()) {
synchronized (packetExtensions) {
for (ExtensionElement packetExtension : packetExtensions.values()) {
if (packetExtension.getNamespace().equals(namespace)) {
return true;
}
@ -461,9 +460,9 @@ public abstract class Stanza implements TopLevelStreamElement {
* @return the removed stanza extension or null.
*/
public ExtensionElement removeExtension(String elementName, String namespace) {
QName key = new QName(namespace, elementName);
synchronized (extensionElements) {
return extensionElements.remove(key);
String key = XmppStringUtils.generateKey(elementName, namespace);
synchronized (packetExtensions) {
return packetExtensions.remove(key);
}
}
@ -474,9 +473,9 @@ public abstract class Stanza implements TopLevelStreamElement {
* @return the removed stanza extension or null.
*/
public ExtensionElement removeExtension(ExtensionElement extension) {
QName key = extension.getQName();
synchronized (extensionElements) {
List<ExtensionElement> list = extensionElements.getAll(key);
String key = XmppStringUtils.generateKey(extension.getElementName(), extension.getNamespace());
synchronized (packetExtensions) {
List<ExtensionElement> list = packetExtensions.getAll(key);
boolean removed = list.remove(extension);
if (removed) {
return extension;

View file

@ -19,7 +19,7 @@ package org.jivesoftware.smack.packet;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.xmlpull.v1.XmlPullParser;
public class XmlEnvironment {

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2015-2019 Florian Schmaus.
* Copyright 2015 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -26,8 +26,8 @@ import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
/**
* The parser for {@link StandardExtensionElement}s.
@ -47,7 +47,7 @@ public class StandardExtensionElementProvider extends ExtensionElementProvider<S
String name = parser.getName();
String namespace = parser.getNamespace();
StandardExtensionElement.Builder builder = StandardExtensionElement.builder(name, namespace);
final int namespaceCount = parser.getNamespaceCount();
final int namespaceCount = parser.getNamespaceCount(initialDepth);
final int attributeCount = parser.getAttributeCount();
final Map<String, String> attributes = new LinkedHashMap<>(namespaceCount + attributeCount);
for (int i = 0; i < namespaceCount; i++) {
@ -77,22 +77,19 @@ public class StandardExtensionElementProvider extends ExtensionElementProvider<S
builder.addAttributes(attributes);
outerloop: while (true) {
XmlPullParser.Event event = parser.next();
int event = parser.next();
switch (event) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
builder.addElement(parse(parser, parser.getDepth(), xmlEnvironment));
break;
case TEXT_CHARACTERS:
case XmlPullParser.TEXT:
builder.setText(parser.getText());
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
if (initialDepth == parser.getDepth()) {
break outerloop;
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}

View file

@ -20,12 +20,12 @@ import java.io.IOException;
import org.jivesoftware.smack.packet.Bind;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.jid.parts.Resourcepart;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class BindIQProvider extends IQProvider<Bind> {
@ -34,9 +34,9 @@ public class BindIQProvider extends IQProvider<Bind> {
String name;
Bind bind = null;
outerloop: while (true) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
name = parser.getName();
switch (name) {
case "resource":
@ -49,14 +49,11 @@ public class BindIQProvider extends IQProvider<Bind> {
break;
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}
return bind;

View file

@ -24,8 +24,8 @@ import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class BodyElementProvider extends ExtensionElementProvider<Message.Body> {

View file

@ -27,8 +27,8 @@ import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
/**
*
@ -97,14 +97,14 @@ public abstract class EmbeddedExtensionProvider<PE extends ExtensionElement> ext
}
List<ExtensionElement> extensions = new ArrayList<>();
XmlPullParser.Event event;
int event;
do {
event = parser.next();
if (event == XmlPullParser.Event.START_ELEMENT)
if (event == XmlPullParser.START_TAG)
PacketParserUtils.addExtensionElement(extensions, parser, xmlEnvironment);
}
while (!(event == XmlPullParser.Event.END_ELEMENT && parser.getDepth() == initialDepth));
while (!(event == XmlPullParser.END_TAG && parser.getDepth() == initialDepth));
return createReturnExtension(name, namespace, attMap, extensions);
}

View file

@ -24,8 +24,8 @@ import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class IntrospectionProvider{
@ -81,9 +81,9 @@ public class IntrospectionProvider{
ParserUtils.assertAtStartTag(parser);
Object object = objectClass.getConstructor().newInstance();
outerloop: while (true) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
String name = parser.getName();
String stringValue = parser.nextText();
Class<?> propertyType = object.getClass().getMethod(
@ -97,14 +97,11 @@ public class IntrospectionProvider{
propertyType).invoke(object, value);
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}
ParserUtils.assertAtEndTag(parser);

View file

@ -26,8 +26,8 @@ import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
/**
* Smack provider are the parsers used to deserialize raw XMPP into the according Java {@link Element}s.

View file

@ -26,8 +26,9 @@ import java.util.logging.Logger;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
/**
* Loads the {@link IQProvider} and {@link ExtensionElementProvider} information from a standard provider file in preparation
@ -53,10 +54,12 @@ public class ProviderFileLoader implements ProviderLoader {
public ProviderFileLoader(InputStream providerStream, ClassLoader classLoader) {
// Load processing providers.
try (InputStream is = providerStream) {
XmlPullParser parser = PacketParserUtils.getParserFor(is);
XmlPullParser.Event eventType = parser.getEventType();
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(is, "UTF-8");
int eventType = parser.getEventType();
do {
if (eventType == XmlPullParser.Event.START_ELEMENT) {
if (eventType == XmlPullParser.START_TAG) {
final String typeName = parser.getName();
try {
@ -131,7 +134,7 @@ public class ProviderFileLoader implements ProviderLoader {
}
eventType = parser.next();
}
while (eventType != XmlPullParser.Event.END_DOCUMENT);
while (eventType != XmlPullParser.END_DOCUMENT);
}
catch (Exception e) {
LOGGER.log(Level.SEVERE, "Unknown error occurred while parsing provider file", e);

View file

@ -22,8 +22,6 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.IQ;
@ -31,6 +29,8 @@ import org.jivesoftware.smack.packet.Nonza;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.XmppElementUtil;
import org.jxmpp.util.XmppStringUtils;
/**
* Manages providers for parsing custom XML sub-documents of XMPP packets. Two types of
* providers exist:<ul>
@ -112,10 +112,10 @@ import org.jivesoftware.smack.util.XmppElementUtil;
*/
public final class ProviderManager {
private static final Map<QName, ExtensionElementProvider<ExtensionElement>> extensionProviders = new ConcurrentHashMap<>();
private static final Map<QName, IQProvider<IQ>> iqProviders = new ConcurrentHashMap<>();
private static final Map<QName, ExtensionElementProvider<ExtensionElement>> streamFeatureProviders = new ConcurrentHashMap<>();
private static final Map<QName, NonzaProvider<? extends Nonza>> nonzaProviders = new ConcurrentHashMap<>();
private static final Map<String, ExtensionElementProvider<ExtensionElement>> extensionProviders = new ConcurrentHashMap<String, ExtensionElementProvider<ExtensionElement>>();
private static final Map<String, IQProvider<IQ>> iqProviders = new ConcurrentHashMap<String, IQProvider<IQ>>();
private static final Map<String, ExtensionElementProvider<ExtensionElement>> streamFeatureProviders = new ConcurrentHashMap<String, ExtensionElementProvider<ExtensionElement>>();
private static final Map<String, NonzaProvider<? extends Nonza>> nonzaProviders = new ConcurrentHashMap<>();
static {
// Ensure that Smack is initialized by calling getVersion, so that user
@ -168,7 +168,7 @@ public final class ProviderManager {
* @return the IQ provider.
*/
public static IQProvider<IQ> getIQProvider(String elementName, String namespace) {
QName key = getQName(elementName, namespace);
String key = getKey(elementName, namespace);
return iqProviders.get(key);
}
@ -199,7 +199,7 @@ public final class ProviderManager {
Object provider) {
validate(elementName, namespace);
// First remove existing providers
QName key = removeIQProvider(elementName, namespace);
String key = removeIQProvider(elementName, namespace);
if (provider instanceof IQProvider) {
iqProviders.put(key, (IQProvider<IQ>) provider);
} else {
@ -214,10 +214,10 @@ public final class ProviderManager {
*
* @param elementName the XML element name.
* @param namespace the XML namespace.
* @return the QName of the removed provider
* @return the key of the removed IQ Provider
*/
public static QName removeIQProvider(String elementName, String namespace) {
QName key = getQName(elementName, namespace);
public static String removeIQProvider(String elementName, String namespace) {
String key = getKey(elementName, namespace);
iqProviders.remove(key);
return key;
}
@ -242,7 +242,7 @@ public final class ProviderManager {
* @return the extension provider.
*/
public static ExtensionElementProvider<ExtensionElement> getExtensionProvider(String elementName, String namespace) {
QName key = getQName(elementName, namespace);
String key = getKey(elementName, namespace);
return extensionProviders.get(key);
}
@ -260,7 +260,7 @@ public final class ProviderManager {
Object provider) {
validate(elementName, namespace);
// First remove existing providers
QName key = removeExtensionProvider(elementName, namespace);
String key = removeExtensionProvider(elementName, namespace);
if (provider instanceof ExtensionElementProvider) {
extensionProviders.put(key, (ExtensionElementProvider<ExtensionElement>) provider);
} else {
@ -275,10 +275,10 @@ public final class ProviderManager {
*
* @param elementName the XML element name.
* @param namespace the XML namespace.
* @return the QName of the removed stanza extension provider
* @return the key of the removed stanza extension provider
*/
public static QName removeExtensionProvider(String elementName, String namespace) {
QName key = getQName(elementName, namespace);
public static String removeExtensionProvider(String elementName, String namespace) {
String key = getKey(elementName, namespace);
extensionProviders.remove(key);
return key;
}
@ -297,48 +297,48 @@ public final class ProviderManager {
}
public static ExtensionElementProvider<ExtensionElement> getStreamFeatureProvider(String elementName, String namespace) {
QName key = getQName(elementName, namespace);
String key = getKey(elementName, namespace);
return streamFeatureProviders.get(key);
}
public static void addStreamFeatureProvider(String elementName, String namespace, ExtensionElementProvider<ExtensionElement> provider) {
validate(elementName, namespace);
QName key = getQName(elementName, namespace);
String key = getKey(elementName, namespace);
streamFeatureProviders.put(key, provider);
}
public static void removeStreamFeatureProvider(String elementName, String namespace) {
QName key = getQName(elementName, namespace);
String key = getKey(elementName, namespace);
streamFeatureProviders.remove(key);
}
public static NonzaProvider<? extends Nonza> getNonzaProvider(String elementName, String namespace) {
QName key = getQName(elementName, namespace);
String key = getKey(elementName, namespace);
return getNonzaProvider(key);
}
public static NonzaProvider<? extends Nonza> getNonzaProvider(QName key) {
public static NonzaProvider<? extends Nonza> getNonzaProvider(String key) {
return nonzaProviders.get(key);
}
public static void addNonzaProvider(NonzaProvider<? extends Nonza> nonzaProvider) {
Class<? extends Nonza> nonzaClass = nonzaProvider.getElementClass();
QName key = XmppElementUtil.getQNameFor(nonzaClass);
String key = XmppElementUtil.getKeyFor(nonzaClass);
nonzaProviders.put(key, nonzaProvider);
}
public static void removeNonzaProvider(Class<? extends Nonza> nonzaClass) {
QName key = XmppElementUtil.getQNameFor(nonzaClass);
String key = XmppElementUtil.getKeyFor(nonzaClass);
nonzaProviders.remove(key);
}
public static void removeNonzaProvider(String elementName, String namespace) {
QName key = getQName(elementName, namespace);
String key = getKey(elementName, namespace);
nonzaProviders.remove(key);
}
private static QName getQName(String elementName, String namespace) {
return new QName(namespace, elementName);
private static String getKey(String elementName, String namespace) {
return XmppStringUtils.generateKey(elementName, namespace);
}
private static void validate(String elementName, String namespace) {

View file

@ -19,7 +19,7 @@ package org.jivesoftware.smack.provider;
import org.jivesoftware.smack.packet.TlsProceed;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.xmlpull.v1.XmlPullParser;
public final class TlsFailureProvider extends NonzaProvider<TlsProceed> {

View file

@ -19,7 +19,7 @@ package org.jivesoftware.smack.provider;
import org.jivesoftware.smack.packet.TlsFailure;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.xmlpull.v1.XmlPullParser;
public final class TlsProceedProvider extends NonzaProvider<TlsFailure> {

View file

@ -22,7 +22,8 @@ import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import org.jivesoftware.smack.util.StringUtils;
/**
* Socket factory for socks4 proxy.
@ -72,6 +73,7 @@ public class Socks4ProxySocketConnection implements ProxySocketConnection {
of all zero bits.
*/
index = 0;
buf[index++] = 4;
buf[index++] = 1;
@ -85,7 +87,7 @@ public class Socks4ProxySocketConnection implements ProxySocketConnection {
}
if (user != null) {
byte[] userBytes = user.getBytes(StandardCharsets.UTF_8);
byte[] userBytes = user.getBytes(StringUtils.UTF8);
System.arraycopy(userBytes, 0, buf, index, user.length());
index += user.length();
}

View file

@ -21,10 +21,10 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.logging.Logger;
import org.jivesoftware.smack.util.CloseableUtil;
import org.jivesoftware.smack.util.StringUtils;
/**
* Socket factory for Socks5 proxy.
@ -133,11 +133,11 @@ public class Socks5ProxySocketConnection implements ProxySocketConnection {
index = 0;
buf[index++] = 1;
buf[index++] = (byte) user.length();
byte[] userBytes = user.getBytes(StandardCharsets.UTF_8);
byte[] userBytes = user.getBytes(StringUtils.UTF8);
System.arraycopy(userBytes, 0, buf, index,
user.length());
index += user.length();
byte[] passwordBytes = passwd.getBytes(StandardCharsets.UTF_8);
byte[] passwordBytes = passwd.getBytes(StringUtils.UTF8);
buf[index++] = (byte) passwordBytes.length;
System.arraycopy(passwordBytes, 0, buf, index,
passwd.length());
@ -204,7 +204,7 @@ public class Socks5ProxySocketConnection implements ProxySocketConnection {
buf[index++] = 1; // CONNECT
buf[index++] = 0;
byte[] hostb = host.getBytes(StandardCharsets.UTF_8);
byte[] hostb = host.getBytes(StringUtils.UTF8);
int len = hostb.length;
buf[index++] = 3; // DOMAINNAME
buf[index++] = (byte) len;

View file

@ -31,13 +31,13 @@ public class SASLErrorException extends XMPPException {
private final SASLFailure saslFailure;
private final String mechanism;
private final Map<String, String> texts;
private final Map<String,String> texts;
public SASLErrorException(String mechanism, SASLFailure saslFailure) {
this(mechanism, saslFailure, new HashMap<String, String>());
}
public SASLErrorException(String mechanism, SASLFailure saslFailure, Map<String, String> texts) {
public SASLErrorException(String mechanism, SASLFailure saslFailure, Map<String,String> texts) {
super("SASLError using " + mechanism + ": " + saslFailure.getSASLErrorString());
this.mechanism = mechanism;
this.saslFailure = saslFailure;
@ -52,7 +52,7 @@ public class SASLErrorException extends XMPPException {
return mechanism;
}
public Map<String, String> getTexts() {
public Map<String,String> getTexts() {
return texts;
}
}

View file

@ -16,7 +16,7 @@
*/
package org.jivesoftware.smack.sasl.core;
import java.nio.charset.StandardCharsets;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.SecureRandom;
import java.util.Collections;
@ -114,8 +114,14 @@ public abstract class ScramMechanism extends SASLMechanism {
@Override
protected byte[] evaluateChallenge(byte[] challenge) throws SmackSaslException {
// TODO: Where is it specified that this is an UTF-8 encoded string?
String challengeString = new String(challenge, StandardCharsets.UTF_8);
String challengeString;
try {
// TODO: Where is it specified that this is an UTF-8 encoded string?
challengeString = new String(challenge, StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
switch (state) {
case AUTH_TEXT_SENT:
@ -380,9 +386,14 @@ public abstract class ScramMechanism extends SASLMechanism {
* @throws SmackSaslException if a SASL related error occurs.
*/
private byte[] hi(String normalizedPassword, byte[] salt, int iterations) throws SmackSaslException {
// According to RFC 5802 § 2.2, the resulting string of the normalization is also in UTF-8.
byte[] key = normalizedPassword.getBytes(StandardCharsets.UTF_8);
byte[] key;
try {
// According to RFC 5802 § 2.2, the resulting string of the normalization is also in UTF-8.
key = normalizedPassword.getBytes(StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError();
}
// U1 := HMAC(str, salt + INT(1))
byte[] u = hmac(key, ByteUtils.concat(salt, ONE));
byte[] res = u.clone();

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2014-2019 Florian Schmaus
* Copyright 2014-2018 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -110,7 +110,7 @@ public class ArrayBlockingQueueWithShutdown<E> extends AbstractQueue<E> implemen
private void checkNotShutdown() throws InterruptedException {
if (isShutdown) {
throw new InterruptedException("Queue was already shut down");
throw new InterruptedException();
}
}

View file

@ -16,7 +16,7 @@
*/
package org.jivesoftware.smack.util;
public interface CallbackRecipient<V, E> {
public interface CallbackRecipient<V,E> {
CallbackRecipient<V, E> onSuccess(SuccessCallback<V> successCallback);

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2018-2019 Florian Schmaus
* Copyright 2018 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,10 +23,6 @@ import java.util.logging.Logger;
public class CloseableUtil {
public static void maybeClose(Closeable closable) {
maybeClose(closable, null);
}
public static void maybeClose(Closeable closable, Logger logger) {
if (closable == null) {
return;
@ -35,9 +31,7 @@ public class CloseableUtil {
try {
closable.close();
} catch (IOException e) {
if (logger != null) {
logger.log(Level.WARNING, "Could not close " + closable, e);
}
logger.log(Level.WARNING, "Could not close " + closable, e);
}
}
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2015-2019 Florian Schmaus
* Copyright 2015-2018 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -49,10 +49,4 @@ public class CollectionUtil {
public interface Predicate<T> {
boolean test(T t);
}
public static <T> ArrayList<T> newListWith(Collection<? extends T> collection) {
ArrayList<T> arrayList = new ArrayList<>(collection.size());
arrayList.addAll(collection);
return arrayList;
}
}

View file

@ -1,243 +0,0 @@
/**
*
* 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.util;
public final class EqualsUtil {
private EqualsUtil() {
}
public static <T> boolean equals(T thisObject, Object other, EqualsComperator<T> equalsComperator) {
if (other == null) {
return false;
}
if (thisObject == other) {
return true;
}
@SuppressWarnings("unchecked")
Class<T> thisObjectClass = (Class<T>) thisObject.getClass();
if (thisObjectClass != other.getClass()) {
return false;
}
EqualsUtil.Builder equalsBuilder = new EqualsUtil.Builder();
equalsComperator.compare(equalsBuilder, thisObjectClass.cast(other));
return equalsBuilder.isEquals;
}
@FunctionalInterface
public interface EqualsComperator<T> {
void compare(EqualsUtil.Builder equalsBuilder, T other);
}
public static final class Builder {
private boolean isEquals = true;
private Builder() {
}
private void nullSafeCompare(Object left, Object right, Runnable runnable) {
if (!isEquals) {
return;
}
if (left == right) {
return;
}
if (left == null || right == null) {
isEquals = false;
return;
}
runnable.run();
}
public <O> Builder append(O left, O right) {
if (!isEquals) {
return this;
}
if (left == right) {
return this;
}
if (left == null || right == null) {
isEquals = false;
return this;
}
isEquals = left.equals(right);
return this;
}
public Builder append(boolean left, boolean right) {
if (!isEquals) {
return this;
}
isEquals = left == right;
return this;
}
public Builder append(boolean[] left, boolean[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}
public Builder append(byte left, byte right) {
if (!isEquals) {
return this;
}
isEquals = left == right;
return this;
}
public Builder append(byte[] left, byte[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}
public Builder append(char left, char right) {
if (!isEquals) {
return this;
}
isEquals = left == right;
return this;
}
public Builder append(char[] left, char[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}
public Builder append(double left, double right) {
if (!isEquals) {
return this;
}
return append(Double.doubleToLongBits(left), Double.doubleToLongBits(right));
}
public Builder append(double[] left, double[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}
public Builder append(float left, float right) {
if (!isEquals) {
return this;
}
return append(Float.floatToIntBits(left), Float.floatToIntBits(right));
}
public Builder append(float[] left, float[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}
public Builder append(int left, int right) {
if (!isEquals) {
return this;
}
isEquals = left == right;
return this;
}
public Builder append(int[] left, int[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}
public Builder append(long left, long right) {
if (!isEquals) {
return this;
}
isEquals = left == right;
return this;
}
public Builder append(long[] left, long[] right) {
nullSafeCompare(left, right, () -> {
if (left.length != right.length) {
isEquals = false;
return;
}
for (int i = 0; i < left.length && isEquals; i++) {
append(left[i], right[i]);
}
});
return this;
}
}
}

View file

@ -34,7 +34,7 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class EventManger<K, R, E extends Exception> {
private final Map<K, Reference<R>> events = new ConcurrentHashMap<>();
private final Map<K,Reference<R>> events = new ConcurrentHashMap<>();
/**
* Perform an action and wait for an event.

View file

@ -30,7 +30,6 @@ import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@ -91,7 +90,7 @@ public final class FileUtils {
public static boolean addLines(String uriString, Set<String> set) throws MalformedURLException, IOException {
URI uri = URI.create(uriString);
InputStream is = getStreamForUri(uri, null);
InputStreamReader sr = new InputStreamReader(is, StandardCharsets.UTF_8);
InputStreamReader sr = new InputStreamReader(is, StringUtils.UTF8);
BufferedReader br = new BufferedReader(sr);
try {
String line;

View file

@ -1,211 +0,0 @@
/**
*
* 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.util;
public class HashCode {
private static final int MULTIPLIER_VALUE = 37;
public static class Cache {
private boolean calculated;
private int hashcode;
public int getHashCode(Calculator hashCodeCalculator) {
if (calculated) {
return hashcode;
}
HashCode.Builder hashCodeBuilder = new HashCode.Builder();
hashCodeCalculator.calculateHash(hashCodeBuilder);
calculated = true;
hashcode = hashCodeBuilder.hashcode;
return hashcode;
}
}
@FunctionalInterface
public interface Calculator {
void calculateHash(HashCode.Builder hashCodeBuilder);
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private int hashcode = 17;
private void applyHash() {
applyHash(0);
}
private void applyHash(int hash) {
hashcode = MULTIPLIER_VALUE * hashcode + hash;
}
public Builder append(Object object) {
if (object == null) {
applyHash();
return this;
}
if (object.getClass().isArray()) {
if (object instanceof int[]) {
append((int[]) object);
} else if (object instanceof long[]) {
append((long[]) object);
} else if (object instanceof boolean[]) {
append((boolean[]) object);
} else if (object instanceof double[]) {
append((double[]) object);
} else if (object instanceof float[]) {
append((float[]) object);
} else if (object instanceof short[]) {
append((short[]) object);
} else if (object instanceof char[]) {
append((char[]) object);
} else if (object instanceof byte[]) {
append((byte[]) object);
} else {
append((Object[]) object);
}
}
applyHash(object.hashCode());
return this;
}
public Builder append(boolean value) {
applyHash(value ? 0 : 1);
return this;
}
public Builder append(boolean[] array) {
if (array == null) {
applyHash();
return this;
}
for (boolean bool : array) {
append(bool);
}
return this;
}
public Builder append(byte value) {
applyHash(value);
return this;
}
public Builder append(byte[] array) {
if (array == null) {
applyHash();
return this;
}
for (byte b : array) {
append(b);
}
return this;
}
public Builder append(char value) {
applyHash(value);
return this;
}
public Builder append(char[] array) {
if (array == null) {
applyHash();
return this;
}
for (char c : array) {
append(c);
}
return this;
}
public Builder append(double value) {
return append(Double.doubleToLongBits(value));
}
public Builder append(double[] array) {
if (array == null) {
applyHash();
return this;
}
for (double d : array) {
append(d);
}
return this;
}
public Builder append(float value) {
return append(Float.floatToIntBits(value));
}
public Builder append(float[] array) {
if (array == null) {
applyHash();
return this;
}
for (float f : array) {
append(f);
}
return this;
}
public Builder append(long value) {
applyHash((int) (value ^ (value >>> 32)));
return this;
}
public Builder append(long[] array) {
if (array == null) {
applyHash();
return this;
}
for (long l : array) {
append(l);
}
return this;
}
public Builder append(Object[] array) {
if (array == null) {
applyHash();
return this;
}
for (Object element : array) {
append(element);
}
return this;
}
public int build() {
return hashcode;
}
}
}

View file

@ -1,213 +0,0 @@
/**
*
* 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.util;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.minidns.dnslabel.DnsLabel;
import org.minidns.dnsname.DnsName;
import org.minidns.dnsname.InvalidDnsNameException;
import org.minidns.util.InetAddressUtil;
/**
* An internet address, can be given as IP or as DNS name.
* <p>
* This type is meant for strings that hold an internet address. The original string used to construct this type is
* stored and returning in the {@link #toString()} method.
* </p>
*
* @since 4.4.0
*/
public abstract class InternetAddress implements CharSequence {
protected final String originalString;
protected InternetAddress(String originalString) {
this.originalString = Objects.requireNonNull(originalString, "The 'originalString' argument must not be null");
}
public abstract InetAddress asInetAddress() throws UnknownHostException;
@Override
public String toString() {
return originalString;
}
@Override
public int length() {
return originalString.length();
}
@Override
public char charAt(int index) {
return originalString.charAt(index);
}
@Override
public CharSequence subSequence(int start, int end) {
return originalString.subSequence(start, end);
}
public static InternetAddress from(String address) {
final InternetAddress internetAddress;
if (InetAddressUtil.isIpV4Address(address)) {
internetAddress = new InternetAddress.Ipv4(address);
} else if (InetAddressUtil.isIpV6Address(address)) {
internetAddress = new InternetAddress.Ipv6(address);
} else if (address.contains(".")) {
InternetAddress domainNameInternetAddress;
try {
DnsName dnsName = DnsName.from(address);
domainNameInternetAddress = new InternetAddress.DomainName(address, dnsName);
} catch (InvalidDnsNameException e) {
domainNameInternetAddress = new InternetAddress.InvalidDomainName(address, e);
}
internetAddress = domainNameInternetAddress;
} else {
DnsLabel dnsLabel = DnsLabel.from(address);
internetAddress = new InternetAddress.DomainNameLabel(address, dnsLabel);
}
return internetAddress;
}
public static InternetAddress from(InetAddress inetAddress) {
if (inetAddress instanceof Inet4Address) {
return new InternetAddress.Ipv4(inetAddress.getHostAddress(), (Inet4Address) inetAddress);
} else if (inetAddress instanceof Inet6Address) {
return new InternetAddress.Ipv6(inetAddress.getHostAddress(), (Inet6Address) inetAddress);
} else {
throw new IllegalArgumentException("Unknown type " + inetAddress.getClass() + " of " + inetAddress);
}
}
private static class InetAddressInternetAddress extends InternetAddress {
private final InetAddress inetAddress;
protected InetAddressInternetAddress(String originalString, InetAddress inetAddress) {
super(originalString);
this.inetAddress = inetAddress;
}
@Override
public InetAddress asInetAddress() {
return inetAddress;
}
}
public static final class Ipv4 extends InetAddressInternetAddress {
private final Inet4Address inet4Address;
private Ipv4(String originalString) {
this(originalString, InetAddressUtil.ipv4From(originalString));
}
private Ipv4(String originalString, Inet4Address inet4Address) {
super(originalString, inet4Address);
this.inet4Address = inet4Address;
}
public Inet4Address getInet4Address() {
return inet4Address;
}
}
public static final class Ipv6 extends InetAddressInternetAddress {
private Inet6Address inet6Address;
private Ipv6(String originalString) {
this(originalString, InetAddressUtil.ipv6From(originalString));
}
private Ipv6(String originalString, Inet6Address inet6Address) {
super(originalString, inet6Address);
this.inet6Address = inet6Address;
}
public Inet6Address getInet6Address() {
return inet6Address;
}
}
private static class NonNumericInternetAddress extends InternetAddress {
private boolean attemptedToResolveInetAddress;
private InetAddress inetAddress;
protected NonNumericInternetAddress(String originalString) {
super(originalString);
}
@Override
public InetAddress asInetAddress() throws UnknownHostException {
if (inetAddress != null || attemptedToResolveInetAddress) {
return inetAddress;
}
attemptedToResolveInetAddress = true;
inetAddress = InetAddress.getByName(originalString);
return inetAddress;
}
}
public static final class DomainName extends NonNumericInternetAddress {
private final DnsName dnsName;
private DomainName(String originalString, DnsName dnsName) {
super(originalString);
this.dnsName = dnsName;
}
public DnsName getDnsName() {
return dnsName;
}
}
public static final class DomainNameLabel extends NonNumericInternetAddress {
private final DnsLabel dnsLabel;
private DomainNameLabel(String originalString, DnsLabel dnsLabel) {
super(originalString);
this.dnsLabel = dnsLabel;
}
public DnsLabel getDnsLabel() {
return dnsLabel;
}
}
public static final class InvalidDomainName extends NonNumericInternetAddress {
private final InvalidDnsNameException invalidDnsNameException;
private InvalidDomainName(String originalString, InvalidDnsNameException invalidDnsNameException) {
super(originalString);
this.invalidDnsNameException = invalidDnsNameException;
}
public InvalidDnsNameException getInvalidDnsNameException() {
return invalidDnsNameException;
}
}
}

View file

@ -22,7 +22,6 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
@ -34,7 +33,7 @@ import java.util.Set;
* @param <K> the type of the keys the map uses.
* @param <V> the type of the values the map uses.
*/
public class MultiMap<K, V> {
public class MultiMap<K,V> {
/**
* The constant value {@value}.
@ -58,11 +57,7 @@ public class MultiMap<K, V> {
* @param size the initial capacity.
*/
public MultiMap(int size) {
this(new LinkedHashMap<>(size));
}
private MultiMap(Map<K, List<V>> map) {
this.map = map;
map = new LinkedHashMap<>(size);
}
public int size() {
@ -77,11 +72,11 @@ public class MultiMap<K, V> {
return map.isEmpty();
}
public boolean containsKey(K key) {
public boolean containsKey(Object key) {
return map.containsKey(key);
}
public boolean containsValue(V value) {
public boolean containsValue(Object value) {
for (List<V> list : map.values()) {
if (list.contains(value)) {
return true;
@ -96,7 +91,7 @@ public class MultiMap<K, V> {
* @param key
* @return the first value or null.
*/
public V getFirst(K key) {
public V getFirst(Object key) {
List<V> res = getAll(key);
if (res.isEmpty()) {
return null;
@ -114,7 +109,7 @@ public class MultiMap<K, V> {
* @param key
* @return all values for the given key.
*/
public List<V> getAll(K key) {
public List<V> getAll(Object key) {
List<V> res = map.get(key);
if (res == null) {
res = Collections.emptyList();
@ -143,7 +138,7 @@ public class MultiMap<K, V> {
* @param key
* @return the first value of the given key or null.
*/
public V remove(K key) {
public V remove(Object key) {
List<V> res = map.remove(key);
if (res == null) {
return null;
@ -162,7 +157,7 @@ public class MultiMap<K, V> {
* @param value
* @return true if the mapping was removed, false otherwise.
*/
public boolean removeOne(K key, V value) {
public boolean removeOne(Object key, V value) {
List<V> list = map.get(key);
if (list == null) {
return false;
@ -240,18 +235,6 @@ public class MultiMap<K, V> {
return entrySet;
}
public MultiMap<K, V> asUnmodifiableMultiMap() {
LinkedHashMap<K, List<V>> mapCopy = new LinkedHashMap<>(map.size());
for (Entry<K, List<V>> entry : map.entrySet()) {
K key = entry.getKey();
List<V> values = entry.getValue();
mapCopy.put(key, Collections.unmodifiableList(values));
}
return new MultiMap<K, V>(Collections.unmodifiableMap(mapCopy));
}
private static final class SimpleMapEntry<K, V> implements Map.Entry<K, V> {
private final K key;

View file

@ -1,6 +1,6 @@
/**
*
* Copyright © 2015-2019 Florian Schmaus
* Copyright © 2015 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,41 +22,13 @@ public class NumberUtil {
* Checks if the given long is within the range of an unsigned 32-bit integer, the XML type "xs:unsignedInt".
*
* @param value
* @deprecated use {@link #requireUInt32(long)} instead.
*/
@Deprecated
// TODO: Remove in Smack 4.5.
public static void checkIfInUInt32Range(long value) {
requireUInt32(value);
}
/**
* Checks if the given long is within the range of an unsigned 32-bit integer, the XML type "xs:unsignedInt".
*
* @param value
*/
public static long requireUInt32(long value) {
if (value < 0) {
throw new IllegalArgumentException("unsigned 32-bit integers can't be negative");
}
if (value > ((1L << 32) - 1)) {
throw new IllegalArgumentException("unsigned 32-bit integers can't be greater then 2^32 - 1");
}
return value;
}
/**
* Checks if the given int is within the range of an unsigned 16-bit integer, the XML type "xs:unsignedShort".
*
* @param value
*/
public static int requireUShort16(int value) {
if (value < 0) {
throw new IllegalArgumentException("unsigned 16-bit integers can't be negative");
}
if (value > ((1 << 16) - 1)) {
throw new IllegalArgumentException("unsigned 16-bit integers can't be greater than 2^16 - 1");
}
return value;
}
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2015-2019 Florian Schmaus
* Copyright 2015-2018 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,26 +20,9 @@ import java.util.Collection;
public class Objects {
/**
* Checks that the specified object reference is not <code>null</code> and throws a customized
* {@link IllegalArgumentException} if it is.
* <p>
* Note that unlike <code>java.util.Objects</code>, this method throws an {@link IllegalArgumentException} instead
* of an {@link NullPointerException}.
* </p>
*
* @param <T> the type of the reference.
* @param obj the object reference to check for nullity.
* @param message detail message to be used in the event that a {@link IllegalArgumentException} is thrown.
* @return <code>obj</code> if not null.
* @throws IllegalArgumentException in case <code>obj</code> is <code>null</code>.
*/
public static <T> T requireNonNull(T obj, String message) throws IllegalArgumentException {
public static <T> T requireNonNull(T obj, String message) {
if (obj == null) {
if (message == null) {
message = "Can not provide null argument";
}
throw new IllegalArgumentException(message);
throw new NullPointerException(message);
}
return obj;
}

View file

@ -17,19 +17,18 @@
package org.jivesoftware.smack.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.compress.packet.Compress;
import org.jivesoftware.smack.packet.EmptyResultIQ;
import org.jivesoftware.smack.packet.ErrorIQ;
@ -50,12 +49,11 @@ import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.SASLFailure;
import org.jivesoftware.smack.xml.SmackXmlParser;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jxmpp.jid.Jid;
import org.jxmpp.stringprep.XmppStringprepException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
/**
* Utility class that helps to parse packets. Any parsing packets method that must be shared
@ -66,22 +64,51 @@ import org.jxmpp.stringprep.XmppStringprepException;
public class PacketParserUtils {
private static final Logger LOGGER = Logger.getLogger(PacketParserUtils.class.getName());
public static final String FEATURE_XML_ROUNDTRIP = "http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
private static final XmlPullParserFactory XML_PULL_PARSER_FACTORY;
/**
* True if the XmlPullParser supports the XML_ROUNDTRIP feature.
*/
public static final boolean XML_PULL_PARSER_SUPPORTS_ROUNDTRIP;
static {
// Ensure that Smack is initialized.
SmackConfiguration.getVersion();
XmlPullParser xmlPullParser;
boolean roundtrip = false;
try {
XML_PULL_PARSER_FACTORY = XmlPullParserFactory.newInstance();
xmlPullParser = XML_PULL_PARSER_FACTORY.newPullParser();
try {
xmlPullParser.setFeature(FEATURE_XML_ROUNDTRIP, true);
// We could successfully set the feature
roundtrip = true;
} catch (XmlPullParserException e) {
// Doesn't matter if FEATURE_XML_ROUNDTRIP isn't available
LOGGER.log(Level.FINEST, "XmlPullParser does not support XML_ROUNDTRIP", e);
}
}
catch (XmlPullParserException e) {
// Something really bad happened
throw new AssertionError(e);
}
XML_PULL_PARSER_SUPPORTS_ROUNDTRIP = roundtrip;
}
// TODO: Rename argument name from 'stanza' to 'element'.
public static XmlPullParser getParserFor(String stanza) throws XmlPullParserException, IOException {
return getParserFor(new StringReader(stanza));
}
public static XmlPullParser getParserFor(InputStream inputStream) throws XmlPullParserException {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
return SmackXmlParser.newXmlParser(inputStreamReader);
}
public static XmlPullParser getParserFor(Reader reader) throws XmlPullParserException, IOException {
XmlPullParser parser = SmackXmlParser.newXmlParser(reader);
XmlPullParser parser = newXmppParser(reader);
// Wind the parser forward to the first start tag
XmlPullParser.Event event = parser.getEventType();
while (event != XmlPullParser.Event.START_ELEMENT) {
if (event == XmlPullParser.Event.END_DOCUMENT) {
int event = parser.getEventType();
while (event != XmlPullParser.START_TAG) {
if (event == XmlPullParser.END_DOCUMENT) {
throw new IllegalArgumentException("Document contains no start tag");
}
event = parser.next();
@ -89,8 +116,28 @@ public class PacketParserUtils {
return parser;
}
public static XmlPullParser getParserFor(String stanza, String startTag)
throws XmlPullParserException, IOException {
XmlPullParser parser = getParserFor(stanza);
while (true) {
int event = parser.getEventType();
String name = parser.getName();
if (event == XmlPullParser.START_TAG && name.equals(startTag)) {
break;
}
else if (event == XmlPullParser.END_DOCUMENT) {
throw new IllegalArgumentException("Could not find start tag '" + startTag
+ "' in stanza: " + stanza);
}
parser.next();
}
return parser;
}
@SuppressWarnings("unchecked")
public static <S extends Stanza> S parseStanza(String stanza) throws XmlPullParserException, SmackParsingException, IOException {
public static <S extends Stanza> S parseStanza(String stanza) throws Exception {
return (S) parseStanza(getParserFor(stanza), null);
}
@ -102,11 +149,9 @@ public class PacketParserUtils {
* @param parser
* @param outerXmlEnvironment the outer XML environment (optional).
* @return a stanza which is either a Message, IQ or Presence.
* @throws XmlPullParserException
* @throws SmackParsingException
* @throws IOException
* @throws Exception
*/
public static Stanza parseStanza(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, SmackParsingException, IOException {
public static Stanza parseStanza(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws Exception {
ParserUtils.assertAtStartTag(parser);
final String name = parser.getName();
switch (name) {
@ -121,6 +166,53 @@ 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);
if (XML_PULL_PARSER_SUPPORTS_ROUNDTRIP) {
try {
parser.setFeature(FEATURE_XML_ROUNDTRIP, true);
}
catch (XmlPullParserException e) {
LOGGER.log(Level.SEVERE,
"XmlPullParser does not support XML_ROUNDTRIP, although it was first determined to be supported",
e);
}
}
return parser;
}
/**
* 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>
*
* @param reader
* @return A suitable XmlPullParser for XMPP parsing
* @throws XmlPullParserException
*/
public static XmlPullParser newXmppParser(Reader reader) throws XmlPullParserException {
XmlPullParser parser = newXmppParser();
parser.setInput(reader);
return parser;
}
public static Message parseMessage(XmlPullParser parser) throws XmlPullParserException, IOException, SmackParsingException {
return parseMessage(parser, null);
}
@ -157,9 +249,9 @@ public class PacketParserUtils {
// in arbitrary sub-elements.
String thread = null;
outerloop: while (true) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
String elementName = parser.getName();
String namespace = parser.getNamespace();
switch (elementName) {
@ -184,12 +276,11 @@ public class PacketParserUtils {
break;
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
default: // fall out
}
}
@ -204,9 +295,9 @@ public class PacketParserUtils {
/**
* Returns the textual content of an element as String. After this method returns the parser
* position will be END_ELEMENT, following the established pull parser calling convention.
* position will be END_TAG, following the established pull parser calling convention.
* <p>
* The parser must be positioned on a START_ELEMENT of an element which MUST NOT contain Mixed
* 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
@ -218,28 +309,33 @@ public class PacketParserUtils {
* @throws IOException
*/
public static String parseElementText(XmlPullParser parser) throws XmlPullParserException, IOException {
assert (parser.getEventType() == XmlPullParser.Event.START_ELEMENT);
assert (parser.getEventType() == XmlPullParser.START_TAG);
String res;
// Advance to the text of the Element
XmlPullParser.Event event = parser.next();
if (event != XmlPullParser.Event.TEXT_CHARACTERS) {
if (event == XmlPullParser.Event.END_ELEMENT) {
// Assume this is the end tag of the start tag at the
// beginning of this method. Typical examples where this
// happens are body elements containing the empty string,
// ie. <body></body>, which appears to be valid XMPP, or a
// least it's not explicitly forbidden by RFC 6121 5.2.3
return "";
} else {
throw new XmlPullParserException(
"Non-empty element tag not followed by text, while Mixed Content (XML 3.2.2) is disallowed");
}
if (parser.isEmptyElementTag()) {
res = "";
}
res = parser.getText();
event = parser.next();
if (event != XmlPullParser.Event.END_ELEMENT) {
throw new XmlPullParserException(
"Non-empty element tag contains child-elements, while Mixed Content (XML 3.2.2) is disallowed");
else {
// Advance to the text of the Element
int event = parser.next();
if (event != XmlPullParser.TEXT) {
if (event == XmlPullParser.END_TAG) {
// Assume this is the end tag of the start tag at the
// beginning of this method. Typical examples where this
// happens are body elements containing the empty string,
// ie. <body></body>, which appears to be valid XMPP, or a
// least it's not explicitly forbidden by RFC 6121 5.2.3
return "";
} else {
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;
}
@ -247,7 +343,7 @@ public class PacketParserUtils {
/**
* Returns the current element as string.
* <p>
* The parser must be positioned on START_ELEMENT.
* The parser must be positioned on START_TAG.
* </p>
* Note that only the outermost namespace attributes ("xmlns") will be returned, not nested ones.
*
@ -263,10 +359,37 @@ public class PacketParserUtils {
public static CharSequence parseElement(XmlPullParser parser,
boolean fullNamespaces) throws XmlPullParserException,
IOException {
assert (parser.getEventType() == XmlPullParser.Event.START_ELEMENT);
assert (parser.getEventType() == XmlPullParser.START_TAG);
return parseContentDepth(parser, parser.getDepth(), fullNamespaces);
}
/**
* Returns the content of a element.
* <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
* @throws XmlPullParserException if parser encounters invalid XML
* @throws IOException if an IO error occurs
*/
public static CharSequence parseContent(XmlPullParser parser)
throws XmlPullParserException, IOException {
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(), false);
}
public static CharSequence parseContentDepth(XmlPullParser parser, int depth)
throws XmlPullParserException, IOException {
return parseContentDepth(parser, depth, false);
@ -279,7 +402,7 @@ public class PacketParserUtils {
* parent elements will be added to child elements that don't define a different namespace.
* <p>
* This method is able to parse the content with MX- and KXmlParser. KXmlParser does not support
* xml-roundtrip. i.e. return a String on getText() on START_ELEMENT and END_ELEMENT. We check for the
* xml-roundtrip. i.e. return a String on getText() on START_TAG and END_TAG. We check for the
* XML_ROUNDTRIP feature. If it's not found we are 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, if <code>fullNamespaces</code> is set to false.
@ -296,7 +419,7 @@ public class PacketParserUtils {
* @throws IOException
*/
public static CharSequence parseContentDepth(XmlPullParser parser, int depth, boolean fullNamespaces) throws XmlPullParserException, IOException {
if (parser.supportsRoundtrip()) {
if (parser.getFeature(FEATURE_XML_ROUNDTRIP)) {
return parseContentDepthWithRoundtrip(parser, depth, fullNamespaces);
} else {
return parseContentDepthWithoutRoundtrip(parser, depth, fullNamespaces);
@ -306,21 +429,15 @@ public class PacketParserUtils {
private static CharSequence parseContentDepthWithoutRoundtrip(XmlPullParser parser, int depth,
boolean fullNamespaces) throws XmlPullParserException, IOException {
XmlStringBuilder xml = new XmlStringBuilder();
XmlPullParser.Event event = parser.getEventType();
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;
boolean startElementJustSeen = false;
outerloop: while (true) {
switch (event) {
case START_ELEMENT:
if (startElementJustSeen) {
xml.rightAngleBracket();
}
else {
startElementJustSeen = true;
}
case XmlPullParser.START_TAG:
xml.halfOpenElement(parser.getName());
if (namespaceElement == null || fullNamespaces) {
String namespace = parser.getNamespace();
@ -332,11 +449,18 @@ public class PacketParserUtils {
for (int i = 0; i < parser.getAttributeCount(); i++) {
xml.attribute(parser.getAttributeName(i), parser.getAttributeValue(i));
}
break;
case END_ELEMENT:
if (startElementJustSeen) {
if (parser.isEmptyElementTag()) {
xml.closeEmptyElement();
startElementJustSeen = false;
isEmptyElement = true;
}
else {
xml.rightAngleBracket();
}
break;
case XmlPullParser.END_TAG:
if (isEmptyElement) {
// Do nothing as the element was already closed, just reset the flag
isEmptyElement = false;
}
else {
xml.closeElement(parser.getName());
@ -350,58 +474,31 @@ public class PacketParserUtils {
break outerloop;
}
break;
case TEXT_CHARACTERS:
if (startElementJustSeen) {
startElementJustSeen = false;
xml.rightAngleBracket();
}
case XmlPullParser.TEXT:
xml.escape(parser.getText());
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
event = parser.next();
}
return xml;
}
@SuppressWarnings("UnusedVariable")
private static CharSequence parseContentDepthWithRoundtrip(XmlPullParser parser, int depth, boolean fullNamespaces)
throws XmlPullParserException, IOException {
XmlStringBuilder sb = new XmlStringBuilder();
XmlPullParser.Event event = parser.getEventType();
boolean startElementJustSeen = false;
StringBuilder sb = new StringBuilder();
int event = parser.getEventType();
outerloop: while (true) {
switch (event) {
case START_ELEMENT:
if (startElementJustSeen) {
sb.rightAngleBracket();
}
startElementJustSeen = true;
break;
case END_ELEMENT:
boolean isEmptyElement = false;
if (startElementJustSeen) {
isEmptyElement = true;
startElementJustSeen = false;
}
if (!isEmptyElement) {
String text = parser.getText();
sb.append(text);
}
if (parser.getDepth() <= depth) {
break outerloop;
}
break;
default:
startElementJustSeen = false;
// Only append the text if the parser is not on on an empty element' start tag. Empty elements are reported
// twice, so in order to prevent duplication we only add their text when we are on their end tag.
if (!(event == XmlPullParser.START_TAG && parser.isEmptyElementTag())) {
CharSequence text = parser.getText();
if (event == XmlPullParser.Event.TEXT_CHARACTERS) {
text = StringUtils.escapeForXml(text);
if (event == XmlPullParser.TEXT) {
text = StringUtils.escapeForXmlText(text);
}
sb.append(text);
break;
}
if (event == XmlPullParser.END_TAG && parser.getDepth() <= depth) {
break outerloop;
}
event = parser.next();
}
@ -439,14 +536,16 @@ public class PacketParserUtils {
String language = ParserUtils.getXmlLang(parser);
if (language != null && !"".equals(language.trim())) {
presence.setLanguage(language);
// CHECKSTYLE:OFF
presence.setLanguage(language);
// CHECKSTYLE:ON
}
// Parse sub-elements
outerloop: while (true) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
String elementName = parser.getName();
String namespace = parser.getNamespace();
switch (elementName) {
@ -454,7 +553,7 @@ public class PacketParserUtils {
presence.setStatus(parser.nextText());
break;
case "priority":
Byte priority = ParserUtils.getByteAttributeFromNextText(parser);
int priority = Integer.parseInt(parser.nextText());
presence.setPriority(priority);
break;
case "show":
@ -488,14 +587,11 @@ public class PacketParserUtils {
break;
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}
return presence;
@ -511,12 +607,9 @@ public class PacketParserUtils {
* @param parser the XML parser, positioned at the start of an IQ packet.
* @param outerXmlEnvironment the outer XML environment (optional).
* @return an IQ object.
* @throws XmlPullParserException
* @throws XmppStringprepException
* @throws IOException
* @throws SmackParsingException
* @throws Exception
*/
public static IQ parseIQ(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, XmppStringprepException, IOException, SmackParsingException {
public static IQ parseIQ(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws Exception {
ParserUtils.assertAtStartTag(parser);
final int initialDepth = parser.getDepth();
XmlEnvironment iqXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment);
@ -529,10 +622,10 @@ public class PacketParserUtils {
final IQ.Type type = IQ.Type.fromString(parser.getAttributeValue("", "type"));
outerloop: while (true) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
String elementName = parser.getName();
String namespace = parser.getNamespace();
switch (elementName) {
@ -547,7 +640,7 @@ public class PacketParserUtils {
iqPacket = provider.parse(parser, outerXmlEnvironment);
}
// Note that if we reach this code, it is guranteed that the result IQ contained a child element
// (RFC 6120 § 8.2.3 6) because otherwhise we would have reached the END_ELEMENT first.
// (RFC 6120 § 8.2.3 6) because otherwhise we would have reached the END_TAG first.
else {
// No Provider found for the IQ stanza, parse it to an UnparsedIQ instance
// so that the content of the IQ can be examined later on
@ -556,14 +649,11 @@ public class PacketParserUtils {
break;
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}
// Decide what to do when an IQ packet was not understood
@ -604,15 +694,15 @@ public class PacketParserUtils {
List<String> mechanisms = new ArrayList<String>();
boolean done = false;
while (!done) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
if (eventType == XmlPullParser.Event.START_ELEMENT) {
if (eventType == XmlPullParser.START_TAG) {
String elementName = parser.getName();
if (elementName.equals("mechanism")) {
mechanisms.add(parser.nextText());
}
}
else if (eventType == XmlPullParser.Event.END_ELEMENT) {
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("mechanisms")) {
done = true;
}
@ -631,14 +721,14 @@ public class PacketParserUtils {
*/
public static Compress.Feature parseCompressionFeature(XmlPullParser parser)
throws IOException, XmlPullParserException {
assert (parser.getEventType() == XmlPullParser.Event.START_ELEMENT);
assert (parser.getEventType() == XmlPullParser.START_TAG);
String name;
final int initialDepth = parser.getDepth();
List<String> methods = new LinkedList<>();
outerloop: while (true) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
name = parser.getName();
switch (name) {
case "method":
@ -646,7 +736,7 @@ public class PacketParserUtils {
break;
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
name = parser.getName();
switch (name) {
case Compress.Feature.ELEMENT:
@ -654,13 +744,9 @@ public class PacketParserUtils {
break outerloop;
}
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}
assert (parser.getEventType() == XmlPullParser.Event.END_ELEMENT);
assert (parser.getEventType() == XmlPullParser.END_TAG);
assert (parser.getDepth() == initialDepth);
return new Compress.Feature(methods);
}
@ -696,9 +782,9 @@ public class PacketParserUtils {
String condition = null;
Map<String, String> descriptiveTexts = null;
outerloop: while (true) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
String name = parser.getName();
if (name.equals("text")) {
descriptiveTexts = parseDescriptiveTexts(parser, descriptiveTexts);
@ -708,14 +794,11 @@ public class PacketParserUtils {
condition = parser.getName();
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}
return new SASLFailure(condition, descriptiveTexts);
@ -743,9 +826,9 @@ public class PacketParserUtils {
String conditionText = null;
XmlEnvironment streamErrorXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment);
outerloop: while (true) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
String name = parser.getName();
String namespace = parser.getNamespace();
switch (namespace) {
@ -758,9 +841,8 @@ public class PacketParserUtils {
// If it's not a text element, that is qualified by the StreamError.NAMESPACE,
// then it has to be the stream error code
condition = StreamError.Condition.fromString(name);
conditionText = parser.nextText();
if (conditionText.isEmpty()) {
conditionText = null;
if (!parser.isEmptyElementTag()) {
conditionText = parser.nextText();
}
break;
}
@ -770,14 +852,11 @@ public class PacketParserUtils {
break;
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}
return new StreamError(condition, conditionText, descriptiveTexts, extensions);
@ -809,9 +888,9 @@ public class PacketParserUtils {
builder.setErrorGenerator(parser.getAttributeValue("", "by"));
outerloop: while (true) {
XmlPullParser.Event eventType = parser.next();
int eventType = parser.next();
switch (eventType) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
String name = parser.getName();
String namespace = parser.getNamespace();
switch (namespace) {
@ -822,9 +901,8 @@ public class PacketParserUtils {
break;
default:
builder.setCondition(StanzaError.Condition.fromString(name));
String conditionText = parser.nextText();
if (!conditionText.isEmpty()) {
builder.setConditionText(conditionText);
if (!parser.isEmptyElementTag()) {
builder.setConditionText(parser.nextText());
}
break;
}
@ -833,14 +911,10 @@ public class PacketParserUtils {
PacketParserUtils.addExtensionElement(extensions, parser, name, namespace, stanzaErrorXmlEnvironment);
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}
builder.setExtensions(extensions).setDescriptiveTexts(descriptiveTexts);
@ -875,14 +949,14 @@ public class PacketParserUtils {
public static StartTls parseStartTlsFeature(XmlPullParser parser)
throws XmlPullParserException, IOException {
assert (parser.getEventType() == XmlPullParser.Event.START_ELEMENT);
assert (parser.getEventType() == XmlPullParser.START_TAG);
assert (parser.getNamespace().equals(StartTls.NAMESPACE));
int initalDepth = parser.getDepth();
boolean required = false;
outerloop: while (true) {
XmlPullParser.Event event = parser.next();
int event = parser.next();
switch (event) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
String name = parser.getName();
switch (name) {
case "required":
@ -890,17 +964,13 @@ public class PacketParserUtils {
break;
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
if (parser.getDepth() == initalDepth) {
break outerloop;
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}
assert (parser.getEventType() == XmlPullParser.Event.END_ELEMENT);
assert (parser.getEventType() == XmlPullParser.END_TAG);
return new StartTls(required);
}
@ -908,11 +978,14 @@ public class PacketParserUtils {
ParserUtils.assertAtStartTag(parser);
final int initialDepth = parser.getDepth();
boolean optional = false;
if (parser.isEmptyElementTag()) {
return new Session.Feature(optional);
}
outerloop: while (true) {
XmlPullParser.Event event = parser.next();
int event = parser.next();
switch (event) {
case START_ELEMENT:
case XmlPullParser.START_TAG:
String name = parser.getName();
switch (name) {
case Session.Feature.OPTIONAL_ELEMENT:
@ -920,14 +993,10 @@ public class PacketParserUtils {
break;
}
break;
case END_ELEMENT:
case XmlPullParser.END_TAG:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
}

View file

@ -23,15 +23,12 @@ import java.text.ParseException;
import java.util.Date;
import java.util.Locale;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.datatypes.UInt16;
import org.jivesoftware.smack.datatypes.UInt32;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.parsing.SmackParsingException.SmackTextParseException;
import org.jivesoftware.smack.parsing.SmackParsingException.SmackUriSyntaxParsingException;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.EntityFullJid;
@ -41,6 +38,8 @@ import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;
import org.jxmpp.util.XmppDateTime;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class ParserUtils {
@ -50,7 +49,7 @@ public class ParserUtils {
public static final String JID = "jid";
public static void assertAtStartTag(XmlPullParser parser) throws XmlPullParserException {
assert (parser.getEventType() == XmlPullParser.Event.START_ELEMENT);
assert (parser.getEventType() == XmlPullParser.START_TAG);
}
public static void assertAtStartTag(XmlPullParser parser, String name) throws XmlPullParserException {
@ -59,13 +58,13 @@ public class ParserUtils {
}
public static void assertAtEndTag(XmlPullParser parser) throws XmlPullParserException {
assert (parser.getEventType() == XmlPullParser.Event.END_ELEMENT);
assert (parser.getEventType() == XmlPullParser.END_TAG);
}
public static void forwardToEndTagOfDepth(XmlPullParser parser, int depth)
throws XmlPullParserException, IOException {
XmlPullParser.Event event = parser.getEventType();
while (!(event == XmlPullParser.Event.END_ELEMENT && parser.getDepth() == depth)) {
int event = parser.getEventType();
while (!(event == XmlPullParser.END_TAG && parser.getDepth() == depth)) {
event = parser.next();
}
}
@ -179,11 +178,6 @@ public class ParserUtils {
}
}
public static Byte getByteAttributeFromNextText(XmlPullParser parser) throws IOException, XmlPullParserException {
String nextText = parser.nextText();
return Byte.valueOf(nextText);
}
public static int getIntegerAttributeOrThrow(XmlPullParser parser, String name, String throwMessage)
throws IOException {
Integer res = getIntegerAttribute(parser, name);
@ -211,14 +205,6 @@ public class ParserUtils {
}
}
public static UInt16 getUInt16Attribute(XmlPullParser parser, String name) {
Integer integer = getIntegerAttribute(parser, name);
if (integer == null) {
return null;
}
return UInt16.from(integer);
}
public static int getIntegerFromNextText(XmlPullParser parser) throws XmlPullParserException, IOException {
String intString = parser.nextText();
return Integer.valueOf(intString);
@ -241,14 +227,6 @@ public class ParserUtils {
}
}
public static UInt32 getUInt32Attribute(XmlPullParser parser, String name) {
Long l = getLongAttribute(parser, name);
if (l == null) {
return null;
}
return UInt32.from(l);
}
public static double getDoubleFromNextText(XmlPullParser parser) throws XmlPullParserException, IOException {
String doubleString = parser.nextText();
return Double.valueOf(doubleString);
@ -345,16 +323,13 @@ public class ParserUtils {
return parser.getAttributeValue("http://www.w3.org/XML/1998/namespace", "lang");
}
/**
* Get the QName of the current element.
*
* @param parser the parser.
* @return the Qname.
* @deprecated use {@link XmlPullParser#getQName()} instead.
*/
@Deprecated
// TODO: Remove in Smack 4.5
public static QName getQName(XmlPullParser parser) {
return parser.getQName();
String elementName = parser.getName();
String prefix = parser.getPrefix();
if (prefix == null) {
prefix = XMLConstants.DEFAULT_NS_PREFIX;
}
String namespace = parser.getNamespace();
return new QName(namespace, elementName, prefix);
}
}

View file

@ -17,9 +17,7 @@
package org.jivesoftware.smack.util;
import java.io.IOException;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Random;
@ -31,23 +29,7 @@ public class StringUtils {
public static final String MD5 = "MD5";
public static final String SHA1 = "SHA-1";
/**
* Deprecated, do not use.
*
* @deprecated use StandardCharsets.UTF_8 instead.
*/
// TODO: Remove in Smack 4.5.
@Deprecated
public static final String UTF8 = "UTF-8";
/**
* Deprecated, do not use.
*
* @deprecated use StandardCharsets.US_ASCII instead.
*/
// TODO: Remove in Smack 4.5.
@Deprecated
public static final String USASCII = "US-ASCII";
public static final String QUOTE_ENCODE = "&quot;";
@ -262,13 +244,22 @@ public class StringUtils {
}
public static byte[] toUtf8Bytes(String string) {
return string.getBytes(StandardCharsets.UTF_8);
try {
return string.getBytes(StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 encoding not supported by platform", e);
}
}
/**
* 24 upper case characters from the latin alphabet and numbers without '0' and 'O'.
* Array of numbers and letters of mixed case. Numbers appear in the list
* twice so that there is a more equal chance that a number will be picked.
* We can use the array to get a random number or letter by picking a random
* array index.
*/
private static final char[] UNAMBIGUOUS_NUMBERS_AND_LETTER = "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ".toCharArray();
private static final char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
/**
* Returns a random String of numbers and letters (lower and upper case)
@ -287,74 +278,6 @@ public class StringUtils {
return randomString(length, RandomUtil.RANDOM.get());
}
public static String secureOnlineAttackSafeRandomString() {
// 34^10 = 2.06e15 possible combinations. Which is enough to protect against online brute force attacks.
// See also https://www.grc.com/haystack.htm
final int REQUIRED_LENGTH = 10;
return randomString(RandomUtil.SECURE_RANDOM.get(), UNAMBIGUOUS_NUMBERS_AND_LETTER, REQUIRED_LENGTH);
}
public static String secureUniqueRandomString() {
// 34^13 = 8.11e19 possible combinations, which is > 2^64.
final int REQUIRED_LENGTH = 13;
return randomString(RandomUtil.SECURE_RANDOM.get(), UNAMBIGUOUS_NUMBERS_AND_LETTER, REQUIRED_LENGTH);
}
/**
* Generate a secure random string with is human readable. The resulting string consists of 24 upper case characters
* from the Latin alphabet and numbers without '0' and 'O', grouped into 4-characters chunks, e.g.
* "TWNK-KD5Y-MT3T-E1GS-DRDB-KVTW". The characters are randomly selected by a cryptographically secure pseudorandom
* number generator (CSPRNG).
* <p>
* The string can be used a backup "code" for secrets, and is in fact the same as the one backup code specified in
* XEP-0373 and the one used by the <a href="https://github.com/open-keychain/open-keychain/wiki/Backups">Backup
* Format v2 of OpenKeychain</a>.
* </p>
*
* @see <a href="https://xmpp.org/extensions/xep-0373.html#backup-encryption"> XEP-0373 §5.4 Encrypting the Secret
* Key Backup</a>
* @return a human readable secure random string.
*/
public static String secureOfflineAttackSafeRandomString() {
// 34^24 = 2^122.10 possible combinations. Which is enough to protect against offline brute force attacks.
// See also https://www.grc.com/haystack.htm
final int REQUIRED_LENGTH = 24;
return randomString(RandomUtil.SECURE_RANDOM.get(), UNAMBIGUOUS_NUMBERS_AND_LETTER, REQUIRED_LENGTH);
}
private static final int RANDOM_STRING_CHUNK_SIZE = 4;
private static String randomString(Random random, char[] alphabet, int numRandomChars) {
// The buffer most hold the size of the requested number of random chars and the chunk separators ('-').
int bufferSize = numRandomChars + ((numRandomChars - 1) / RANDOM_STRING_CHUNK_SIZE);
CharBuffer charBuffer = CharBuffer.allocate(bufferSize);
try {
randomString(charBuffer, random, alphabet, numRandomChars);
} catch (IOException e) {
// This should never happen if we calcuate the buffer size correctly.
throw new AssertionError(e);
}
return charBuffer.flip().toString();
}
private static void randomString(Appendable appendable, Random random, char[] alphabet, int numRandomChars)
throws IOException {
for (int randomCharNum = 1; randomCharNum <= numRandomChars; randomCharNum++) {
int randomIndex = random.nextInt(alphabet.length);
char randomChar = alphabet[randomIndex];
appendable.append(randomChar);
if (randomCharNum % RANDOM_STRING_CHUNK_SIZE == 0 && randomCharNum < numRandomChars) {
appendable.append('-');
}
}
}
public static String randomString(final int length) {
return randomString(length, RandomUtil.SECURE_RANDOM.get());
}
@ -364,14 +287,24 @@ public class StringUtils {
return "";
}
byte[] randomBytes = new byte[length];
random.nextBytes(randomBytes);
char[] randomChars = new char[length];
for (int i = 0; i < length; i++) {
int index = random.nextInt(UNAMBIGUOUS_NUMBERS_AND_LETTER.length);
randomChars[i] = UNAMBIGUOUS_NUMBERS_AND_LETTER[index];
randomChars[i] = getPrintableChar(randomBytes[i]);
}
return new String(randomChars);
}
private static char getPrintableChar(byte indexByte) {
assert (numbersAndLetters.length < Byte.MAX_VALUE * 2);
// Convert indexByte as it where an unsigned byte by promoting it to int
// and masking it with 0xff. Yields results from 0 - 254.
int index = indexByte & 0xff;
return numbersAndLetters[index % numbersAndLetters.length];
}
/**
* Returns true if CharSequence is not null and is not empty, false otherwise.
* Examples:

View file

@ -64,7 +64,7 @@ public class TLSUtils {
*
* @return the given builder
*/
public static <B extends ConnectionConfiguration.Builder<B, ?>> B setTLSOnly(B builder) {
public static <B extends ConnectionConfiguration.Builder<B,?>> B setTLSOnly(B builder) {
builder.setEnabledSSLProtocols(new String[] { PROTO_TLSV1_2, PROTO_TLSV1_1, PROTO_TLSV1 });
return builder;
}
@ -84,7 +84,7 @@ public class TLSUtils {
*
* @return the given builder
*/
public static <B extends ConnectionConfiguration.Builder<B, ?>> B setSSLv3AndTLSOnly(B builder) {
public static <B extends ConnectionConfiguration.Builder<B,?>> B setSSLv3AndTLSOnly(B builder) {
builder.setEnabledSSLProtocols(new String[] { PROTO_TLSV1_2, PROTO_TLSV1_1, PROTO_TLSV1, PROTO_SSL3 });
return builder;
}
@ -103,7 +103,7 @@ public class TLSUtils {
* @throws KeyManagementException
* @return the given builder.
*/
public static <B extends ConnectionConfiguration.Builder<B, ?>> B acceptAllCertificates(B builder) throws NoSuchAlgorithmException, KeyManagementException {
public static <B extends ConnectionConfiguration.Builder<B,?>> B acceptAllCertificates(B builder) throws NoSuchAlgorithmException, KeyManagementException {
SSLContext context = SSLContext.getInstance(TLS);
context.init(null, new TrustManager[] { new AcceptAllTrustManager() }, new SecureRandom());
builder.setCustomSSLContext(context);
@ -130,7 +130,7 @@ public class TLSUtils {
* @param <B> Type of the ConnectionConfiguration builder.
* @return the given builder.
*/
public static <B extends ConnectionConfiguration.Builder<B, ?>> B disableHostnameVerificationForTlsCertificates(B builder) {
public static <B extends ConnectionConfiguration.Builder<B,?>> B disableHostnameVerificationForTlsCertificates(B builder) {
builder.setHostnameVerifier(DOES_NOT_VERIFY_VERIFIER);
return builder;
}

View file

@ -269,20 +269,10 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element {
public XmlStringBuilder attribute(String name, Enum<?> value) {
assert value != null;
// TODO: Should use toString() instead of name().
attribute(name, value.name());
return this;
}
public <E extends Enum<?>> XmlStringBuilder attribute(String name, E value, E implicitDefault) {
if (value == null || value == implicitDefault) {
return this;
}
attribute(name, value.toString());
return this;
}
public XmlStringBuilder attribute(String name, int value) {
assert name != null;
return attribute(name, String.valueOf(value));
@ -337,13 +327,6 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element {
return this;
}
public XmlStringBuilder optAttribute(String name, Number number) {
if (number != null) {
attribute(name, number.toString());
}
return this;
}
/**
* Add the given attribute if {@code value => 0}.
*

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2018-2019 Florian Schmaus
* Copyright 2018 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,13 +16,13 @@
*/
package org.jivesoftware.smack.util;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.packet.FullyQualifiedElement;
import org.jxmpp.util.XmppStringUtils;
public class XmppElementUtil {
public static QName getQNameFor(Class<? extends FullyQualifiedElement> fullyQualifiedElement) {
public static String getKeyFor(Class<? extends FullyQualifiedElement> fullyQualifiedElement) {
String element, namespace;
try {
element = (String) fullyQualifiedElement.getField("ELEMENT").get(null);
@ -32,7 +32,14 @@ public class XmppElementUtil {
throw new IllegalArgumentException(e);
}
return new QName(namespace, element);
String key = XmppStringUtils.generateKey(element, namespace);
return key;
}
public static String getKeyFor(FullyQualifiedElement fullyQualifiedElement) {
String element = fullyQualifiedElement.getElementName();
String namespace = fullyQualifiedElement.getNamespace();
String key = XmppStringUtils.generateKey(element, namespace);
return key;
}
}

View file

@ -19,7 +19,9 @@ package org.jivesoftware.smack.util.stringencoder;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.io.UnsupportedEncodingException;
import org.jivesoftware.smack.util.StringUtils;
/**
* Base32 string encoding is useful for when filenames case-insensitive filesystems are encoded.
@ -53,8 +55,13 @@ public class Base32 {
public static String decode(String str) {
ByteArrayOutputStream bs = new ByteArrayOutputStream();
byte[] raw = str.getBytes(StandardCharsets.UTF_8);
byte[] raw;
try {
raw = str.getBytes(StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
for (int i = 0; i < raw.length; i++) {
char c = (char) raw[i];
if (!Character.isWhitespace(c)) {
@ -107,12 +114,24 @@ public class Base32 {
}
}
String res = new String(bs.toByteArray(), StandardCharsets.UTF_8);
String res;
try {
res = new String(bs.toByteArray(), StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
return res;
}
public static String encode(String str) {
byte[] b = str.getBytes(StandardCharsets.UTF_8);
byte[] b;
try {
b = str.getBytes(StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
for (int i = 0; i < (b.length + 4) / 5; i++) {
@ -155,7 +174,13 @@ public class Base32 {
os.write(c);
}
}
String res = new String(os.toByteArray(), StandardCharsets.UTF_8);
String res;
try {
res = new String(os.toByteArray(), StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
return res;
}

View file

@ -16,9 +16,10 @@
*/
package org.jivesoftware.smack.util.stringencoder;
import java.nio.charset.StandardCharsets;
import java.io.UnsupportedEncodingException;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.StringUtils;
public class Base64 {
@ -30,7 +31,11 @@ public class Base64 {
}
public static final String encode(String string) {
return encodeToString(string.getBytes(StandardCharsets.UTF_8));
try {
return encodeToString(string.getBytes(StringUtils.UTF8));
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 not supported", e);
}
}
public static final String encodeToString(byte[] input) {
@ -51,7 +56,11 @@ public class Base64 {
public static final String decodeToString(String string) {
byte[] bytes = decode(string);
return new String(bytes, StandardCharsets.UTF_8);
try {
return new String(bytes, StringUtils.UTF8);
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 not supported", e);
}
}
// TODO: We really should not mask the IllegalArgumentException. But some unit test depend on this behavior, like
@ -65,7 +74,12 @@ public class Base64 {
}
public static final byte[] decode(byte[] input) {
String string = new String(input, StandardCharsets.US_ASCII);
String string;
try {
string = new String(input, StringUtils.USASCII);
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
return decode(string);
}

View file

@ -30,7 +30,7 @@ public class StanzaCollectorTest {
@Test
public void verifyRollover() throws InterruptedException {
StanzaCollector collector = createTestStanzaCollector(null, new OKEverything(), 5);
TestStanzaCollector collector = new TestStanzaCollector(null, new OKEverything(), 5);
for (int i = 0; i < 6; i++) {
Stanza testPacket = new TestPacket(i);
@ -70,7 +70,7 @@ public class StanzaCollectorTest {
@Test
public void verifyThreadSafety() throws InterruptedException {
final int insertCount = 500;
final StanzaCollector collector = createTestStanzaCollector(null, new OKEverything(), insertCount);
final TestStanzaCollector collector = new TestStanzaCollector(null, new OKEverything(), insertCount);
final AtomicInteger consumer1Dequeued = new AtomicInteger();
final AtomicInteger consumer2Dequeued = new AtomicInteger();
@ -170,8 +170,10 @@ public class StanzaCollectorTest {
}
private static StanzaCollector createTestStanzaCollector(XMPPConnection connection, StanzaFilter packetFilter, int size) {
return new StanzaCollector(connection, StanzaCollector.newConfiguration().setStanzaFilter(packetFilter).setSize(size));
static class TestStanzaCollector extends StanzaCollector {
protected TestStanzaCollector(XMPPConnection conection, StanzaFilter packetFilter, int size) {
super(conection, StanzaCollector.newConfiguration().setStanzaFilter(packetFilter).setSize(size));
}
}
static class TestPacket extends Stanza {

View file

@ -16,7 +16,7 @@
*/
package org.jivesoftware.smack.compress.packet;
import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar;
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
import java.io.IOException;
@ -35,7 +35,7 @@ public class FailureTest {
final String expectedXml = "<failure xmlns='http://jabber.org/protocol/compress'><processing-failed/></failure>";
assertXmlSimilar(expectedXml, xml.toString());
assertXMLEqual(expectedXml, xml.toString());
}
@Test
@ -53,6 +53,6 @@ public class FailureTest {
+ "</error>"
+ "</failure>";
assertXmlSimilar(expectedXml, xml.toString());
assertXMLEqual(expectedXml, xml.toString());
}
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2018-2019 Florian Schmaus
* Copyright 2018 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,9 +22,9 @@ import org.jivesoftware.smack.compress.packet.Failure;
import org.jivesoftware.smack.packet.StanzaError;
import org.jivesoftware.smack.packet.StanzaError.Condition;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
public class FailureProviderTest {

View file

@ -16,7 +16,7 @@
*/
package org.jivesoftware.smack.packet;
import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar;
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@ -26,6 +26,8 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.jivesoftware.smack.test.util.XmlUnitUtils;
import org.junit.Test;
import org.xml.sax.SAXException;
@ -47,7 +49,7 @@ public class MessageTest {
Message messageTypeInConstructor = new Message(null, Message.Type.chat);
messageTypeInConstructor.setStanzaId(null);
assertEquals(type, messageTypeInConstructor.getType());
assertXmlSimilar(control, messageTypeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, messageTypeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
controlBuilder = new StringBuilder();
controlBuilder.append("<message")
@ -60,7 +62,7 @@ public class MessageTest {
Message messageTypeSet = getNewMessage();
messageTypeSet.setType(type2);
assertEquals(type2, messageTypeSet.getType());
assertXmlSimilar(control, messageTypeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, messageTypeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
}
@Test(expected = NullPointerException.class)
@ -85,7 +87,7 @@ public class MessageTest {
message.setSubject(messageSubject);
assertEquals(messageSubject, message.getSubject());
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
}
@Test
@ -104,7 +106,7 @@ public class MessageTest {
message.setBody(messageBody);
assertEquals(messageBody, message.getBody());
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
}
@Test
@ -137,7 +139,7 @@ public class MessageTest {
message.addBody(null, messageBody1);
message.addBody(lang2, messageBody2);
message.addBody(lang3, messageBody3);
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE));
XmlUnitUtils.assertSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE));
Collection<String> languages = message.getBodyLanguages();
List<String> controlLanguages = new ArrayList<>();
@ -181,7 +183,7 @@ public class MessageTest {
message.setThread(messageThread);
assertEquals(messageThread, message.getThread());
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
}
@Test
@ -199,7 +201,7 @@ public class MessageTest {
Message message = getNewMessage();
message.setLanguage(lang);
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
}
private static Message getNewMessage() {

View file

@ -16,15 +16,14 @@
*/
package org.jivesoftware.smack.packet;
import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar;
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.IOException;
import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.xml.sax.SAXException;
public class PresenceTest {
@ -44,7 +43,7 @@ public class PresenceTest {
Presence presenceTypeInConstructor = new Presence(type);
presenceTypeInConstructor.setStanzaId(null);
assertEquals(type, presenceTypeInConstructor.getType());
assertXmlSimilar(control, presenceTypeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, presenceTypeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
controlBuilder = new StringBuilder();
controlBuilder.append("<presence")
@ -57,14 +56,12 @@ public class PresenceTest {
Presence presenceTypeSet = getNewPresence();
presenceTypeSet.setType(type2);
assertEquals(type2, presenceTypeSet.getType());
assertXmlSimilar(control, presenceTypeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, presenceTypeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
}
@Test
@Test(expected = NullPointerException.class)
public void setNullPresenceTypeTest() {
assertThrows(IllegalArgumentException.class, () ->
getNewPresence().setType(null)
);
getNewPresence().setType(null);
}
@Test
@ -93,7 +90,7 @@ public class PresenceTest {
presence.setStatus(status);
assertEquals(status, presence.getStatus());
assertXmlSimilar(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
}
@Test
@ -112,14 +109,12 @@ public class PresenceTest {
presence.setPriority(priority);
assertEquals(priority, presence.getPriority());
assertXmlSimilar(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
}
@Test
@Test(expected = IllegalArgumentException.class)
public void setIllegalPriorityTest() {
assertThrows(IllegalArgumentException.class, () ->
getNewPresence().setPriority(Integer.MIN_VALUE)
);
getNewPresence().setPriority(Integer.MIN_VALUE);
}
@Test
@ -147,7 +142,7 @@ public class PresenceTest {
mode1);
presenceModeInConstructor.setStanzaId(null);
assertEquals(mode1, presenceModeInConstructor.getMode());
assertXmlSimilar(control, presenceModeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, presenceModeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
controlBuilder = new StringBuilder();
controlBuilder.append("<presence>")
@ -160,7 +155,7 @@ public class PresenceTest {
Presence presenceModeSet = getNewPresence();
presenceModeSet.setMode(mode2);
assertEquals(mode2, presenceModeSet.getMode());
assertXmlSimilar(control, presenceModeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, presenceModeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
}
@Test
@ -188,7 +183,7 @@ public class PresenceTest {
Presence presence = getNewPresence();
presence.setLanguage(lang);
assertXmlSimilar(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
}
private static Presence getNewPresence() {

View file

@ -18,25 +18,19 @@ package org.jivesoftware.smack.packet;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.io.IOException;
import static org.junit.Assert.fail;
import org.jivesoftware.smack.packet.StreamError.Condition;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.test.util.SmackTestUtil;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
public class StreamErrorTest {
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testParsingOfSimpleStreamError(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException, SmackParsingException {
@Test
public void testParsingOfSimpleStreamError() {
StreamError error = null;
final String xml =
// Usually the stream:stream element has more attributes (to, version, ...)
// We omit those, since they are not relevant for testing
@ -45,17 +39,19 @@ public class StreamErrorTest {
"<conflict xmlns='urn:ietf:params:xml:ns:xmpp-streams' /> +" +
"</stream:error>" +
"</stream:stream>";
XmlPullParser parser = SmackTestUtil.getParserFor(xml, "error", parserKind);
StreamError error = PacketParserUtils.parseStreamError(parser);
try {
XmlPullParser parser = PacketParserUtils.getParserFor(xml, "error");
error = PacketParserUtils.parseStreamError(parser);
} catch (Exception e) {
fail(e.getMessage());
}
assertNotNull(error);
assertEquals(Condition.conflict, error.getCondition());
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testParsingOfStreamErrorWithText(SmackTestUtil.XmlPullParserKind parserKind) throws XmlPullParserException, IOException, SmackParsingException {
@Test
public void testParsingOfStreamErrorWithText() {
StreamError error = null;
final String xml =
// Usually the stream:stream element has more attributes (to, version, ...)
// We omit those, since they are not relevant for testing
@ -67,19 +63,20 @@ public class StreamErrorTest {
"</text>" +
"</stream:error>" +
"</stream:stream>";
XmlPullParser parser = SmackTestUtil.getParserFor(xml, "error", parserKind);
StreamError error = PacketParserUtils.parseStreamError(parser);
try {
XmlPullParser parser = PacketParserUtils.getParserFor(xml, "error");
error = PacketParserUtils.parseStreamError(parser);
} catch (Exception e) {
fail(e.getMessage());
}
assertNotNull(error);
assertEquals(Condition.conflict, error.getCondition());
assertEquals("Replaced by new connection", error.getDescriptiveText());
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testParsingOfStreamErrorWithTextAndOptionalElement(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException, SmackParsingException {
@Test
public void testParsingOfStreamErrorWithTextAndOptionalElement() {
StreamError error = null;
final String xml =
// Usually the stream:stream element has more attributes (to, version, ...)
// We omit those, since they are not relevant for testing
@ -94,10 +91,12 @@ public class StreamErrorTest {
"</appSpecificElement>" +
"</stream:error>" +
"</stream:stream>";
XmlPullParser parser = SmackTestUtil.getParserFor(xml, "error", parserKind);
StreamError error = PacketParserUtils.parseStreamError(parser);
try {
XmlPullParser parser = PacketParserUtils.getParserFor(xml, "error");
error = PacketParserUtils.parseStreamError(parser);
} catch (Exception e) {
fail(e.getMessage());
}
assertNotNull(error);
assertEquals(Condition.conflict, error.getCondition());
assertEquals("Replaced by new connection", error.getDescriptiveText());
@ -105,20 +104,21 @@ public class StreamErrorTest {
assertNotNull(appSpecificElement);
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testStreamErrorXmlNotWellFormed(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException, SmackParsingException {
@Test
public void testStreamErrorXmlNotWellFormed() {
StreamError error = null;
final String xml =
// Usually the stream:stream element has more attributes (to, version, ...)
// We omit those, since they are not relevant for testing
"<stream:stream from='im.example.com' id='++TR84Sm6A3hnt3Q065SnAbbk3Y=' xmlns:stream='http://etherx.jabber.org/streams'>" +
"<stream:error><xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/></stream:error>" +
"</stream:stream>";
XmlPullParser parser = SmackTestUtil.getParserFor(xml, "error", parserKind);
StreamError error = PacketParserUtils.parseStreamError(parser);
try {
XmlPullParser parser = PacketParserUtils.getParserFor(xml, "error");
error = PacketParserUtils.parseStreamError(parser);
} catch (Exception e) {
fail(e.getMessage());
}
assertNotNull(error);
assertEquals(Condition.not_well_formed, error.getCondition());
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright © 2014-2019 Florian Schmaus
* Copyright © 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.
@ -19,7 +19,7 @@ package org.jivesoftware.smack.packet;
public class TestIQ extends SimpleIQ {
public TestIQ() {
this("https://igniterealtime.org/projects/smack", "test-iq");
this(null, null);
}
public TestIQ(String element, String namespace) {

View file

@ -27,11 +27,11 @@ import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
public class ParsingExceptionTest {
@ -39,7 +39,6 @@ public class ParsingExceptionTest {
"<extension2 xmlns='namespace'>" +
"<bar node='testNode'>" +
"<i id='testid1'>" +
"text content" +
"</i>" +
"</bar>" +
"</extension2>";
@ -58,7 +57,8 @@ public class ParsingExceptionTest {
public void consumeUnparsedInput() throws Exception {
final String MESSAGE_EXCEPTION_ELEMENT =
"<" + ThrowException.ELEMENT + " xmlns='" + ThrowException.NAMESPACE + "'>" +
"<nothingInHere/>" +
"<nothingInHere>" +
"</nothingInHere>" +
"</" + ThrowException.ELEMENT + ">";
XmlPullParser parser = TestUtils.getMessageParser(
"<message from='user@server.example' to='francisco@denmark.lit' id='foo'>" +

View file

@ -22,10 +22,10 @@ import java.util.Collection;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.FileUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.junit.Assert;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
public class ProviderConfigTest {

View file

@ -21,9 +21,9 @@ import static org.junit.Assert.assertTrue;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
public class ProviderManagerTest {

View file

@ -1,6 +1,6 @@
/**
*
* Copyright © 2014-2019 Florian Schmaus
* Copyright © 2014-2017 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,10 +16,10 @@
*/
package org.jivesoftware.smack.sasl;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.nio.charset.StandardCharsets;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
@ -39,14 +39,14 @@ public class DigestMd5SaslTest extends AbstractSaslTest {
super(saslMechanism);
}
protected void runTest(boolean useAuthzid) throws SmackException, InterruptedException, XmppStringprepException {
protected void runTest(boolean useAuthzid) throws SmackException, InterruptedException, XmppStringprepException, UnsupportedEncodingException {
EntityBareJid authzid = null;
if (useAuthzid) {
authzid = JidCreate.entityBareFrom("shazbat@xmpp.org");
}
saslMechanism.authenticate("florian", "irrelevant", JidCreate.domainBareFrom("xmpp.org"), "secret", authzid, null);
byte[] response = saslMechanism.evaluateChallenge(challengeBytes);
String responseString = new String(response, StandardCharsets.UTF_8);
String responseString = new String(response, StringUtils.UTF8);
String[] responseParts = responseString.split(",");
Map<String, String> responsePairs = new HashMap<String, String>();
for (String part : responseParts) {

View file

@ -18,7 +18,6 @@ package org.jivesoftware.smack.test.util;
import java.util.Base64;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.util.stringencoder.Base64.Encoder;
/**
@ -28,7 +27,6 @@ import org.jivesoftware.smack.util.stringencoder.Base64.Encoder;
public class SmackTestSuite {
static {
SmackConfiguration.getVersion();
org.jivesoftware.smack.util.stringencoder.Base64.setEncoder(new Encoder() {
@Override

View file

@ -1,165 +0,0 @@
/**
*
* 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.test.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.function.Predicate;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.packet.Element;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.provider.Provider;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smack.xml.XmlPullParserFactory;
import org.jivesoftware.smack.xml.stax.StaxXmlPullParserFactory;
import org.jivesoftware.smack.xml.xpp3.Xpp3XmlPullParserFactory;
public class SmackTestUtil {
@SuppressWarnings("ImmutableEnumChecker")
public enum XmlPullParserKind {
StAX(StaxXmlPullParserFactory.class),
XPP3(Xpp3XmlPullParserFactory.class),
;
public final XmlPullParserFactory factory;
XmlPullParserKind(Class<? extends XmlPullParserFactory> factoryClass) {
try {
factory = factoryClass.getDeclaredConstructor().newInstance();
}
catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
throw new AssertionError(e);
}
}
}
public static <E extends Element, P extends Provider<E>> E parse(CharSequence xml, Class<P> providerClass, XmlPullParserKind parserKind)
throws XmlPullParserException, IOException, SmackParsingException {
P provider = providerClassToProvider(providerClass);
return parse(xml, provider, parserKind);
}
public static <E extends Element, P extends Provider<E>> E parse(InputStream inputStream, Class<P> providerClass, XmlPullParserKind parserKind)
throws XmlPullParserException, IOException, SmackParsingException {
P provider = providerClassToProvider(providerClass);
return parse(inputStream, provider, parserKind);
}
public static <E extends Element, P extends Provider<E>> E parse(Reader reader, Class<P> providerClass, XmlPullParserKind parserKind)
throws XmlPullParserException, IOException, SmackParsingException {
P provider = providerClassToProvider(providerClass);
return parse(reader, provider, parserKind);
}
public static <E extends Element> E parse(CharSequence xml, Provider<E> provider, XmlPullParserKind parserKind)
throws XmlPullParserException, IOException, SmackParsingException {
String xmlString = xml.toString();
Reader reader = new StringReader(xmlString);
return parse(reader, provider, parserKind);
}
public static <E extends Element> E parse(InputStream inputStream, Provider<E> provider, XmlPullParserKind parserKind)
throws XmlPullParserException, IOException, SmackParsingException {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
return parse(inputStreamReader, provider, parserKind);
}
public static <E extends Element> E parse(Reader reader, Provider<E> provider, XmlPullParserKind parserKind)
throws XmlPullParserException, IOException, SmackParsingException {
XmlPullParser parser = getParserFor(reader, parserKind);
E element = provider.parse(parser);
return element;
}
public static XmlPullParser getParserFor(String xml, XmlPullParserKind parserKind) throws XmlPullParserException, IOException {
Reader reader = new StringReader(xml);
return getParserFor(reader, parserKind);
}
public static XmlPullParser getParserFor(InputStream inputStream, XmlPullParserKind parserKind) throws XmlPullParserException, IOException {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
return getParserFor(inputStreamReader, parserKind);
}
public static XmlPullParser getParserFor(Reader reader, XmlPullParserKind parserKind) throws XmlPullParserException, IOException {
XmlPullParser parser = parserKind.factory.newXmlPullParser(reader);
forwardParserToStartElement(parser);
return parser;
}
public static XmlPullParser getParserFor(String xml, QName startTagQName, XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
XmlPullParser parser = getParserFor(xml, parserKind);
forwardParserToStartElement(parser, (p) -> p.getQName().equals(startTagQName));
return parser;
}
public static XmlPullParser getParserFor(String xml, String startTagLocalpart, XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
XmlPullParser parser = getParserFor(xml, parserKind);
forwardParserToStartElement(parser, (p) -> p.getName().equals(startTagLocalpart));
return parser;
}
private static <E extends Element, P extends Provider<E>> P providerClassToProvider(Class<P> providerClass) {
P provider;
// TODO: Consider adding a shortcut in case there is a static INSTANCE field holding an instance of the
// requested provider.
try {
provider = providerClass.getDeclaredConstructor().newInstance();
}
catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
throw new AssertionError(e);
}
return provider;
}
private static void forwardParserToStartElement(XmlPullParser parser) throws XmlPullParserException, IOException {
forwardParserToStartElement(parser, p -> true);
}
private static void forwardParserToStartElement(XmlPullParser parser,
Predicate<XmlPullParser> doneForwarding) throws XmlPullParserException, IOException {
outerloop: while (true) {
XmlPullParser.Event event = parser.getEventType();
switch (event) {
case START_ELEMENT:
if (doneForwarding.test(parser)) {
break outerloop;
}
break;
case END_DOCUMENT:
throw new IllegalArgumentException("Not matching START_ELEMENT found");
default:
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
break;
}
parser.next();
}
}
}

View file

@ -20,11 +20,14 @@ import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import org.jivesoftware.smack.xml.SmackXmlParser;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.util.ParserUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
// TODO: Remove this class and replace it with SmackTestUtil.
public final class TestUtils {
private TestUtils() {
}
@ -49,12 +52,12 @@ public final class TestUtils {
return getParser(new StringReader(string), startTag);
}
private static XmlPullParser getParser(Reader reader, String startTag) {
public static XmlPullParser getParser(Reader reader, String startTag) {
XmlPullParser parser;
try {
parser = SmackXmlParser.newXmlParser(reader);
parser = PacketParserUtils.newXmppParser(reader);
if (startTag == null) {
while (parser.getEventType() != XmlPullParser.Event.START_ELEMENT) {
while (parser.getEventType() != XmlPullParser.START_TAG) {
parser.next();
}
return parser;
@ -62,7 +65,7 @@ public final class TestUtils {
boolean found = false;
while (!found) {
if ((parser.next() == XmlPullParser.Event.START_ELEMENT) && parser.getName().equals(startTag))
if ((parser.next() == XmlPullParser.START_TAG) && parser.getName().equals(startTag))
found = true;
}
@ -76,4 +79,17 @@ public final class TestUtils {
return parser;
}
public static <EE extends ExtensionElement> EE parseExtensionElement(String elementString)
throws Exception {
return parseExtensionElement(getParser(elementString), null);
}
@SuppressWarnings("unchecked")
public static <EE extends ExtensionElement> EE parseExtensionElement(XmlPullParser parser, XmlEnvironment outerXmlEnvironment)
throws Exception {
ParserUtils.assertAtStartTag(parser);
final String elementName = parser.getName();
final String namespace = parser.getNamespace();
return (EE) PacketParserUtils.parseExtensionElement(elementName, namespace, parser, outerXmlEnvironment);
}
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2014-2019 Florian Schmaus
* Copyright 2014-2018 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,36 +16,24 @@
*/
package org.jivesoftware.smack.test.util;
import java.io.StringReader;
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
import javax.xml.transform.stream.StreamSource;
import java.io.IOException;
import org.xmlunit.assertj.CompareAssert;
import org.xmlunit.assertj.XmlAssert;
import org.xmlunit.diff.DefaultNodeMatcher;
import org.xmlunit.diff.ElementSelectors;
import org.xmlunit.input.NormalizedSource;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.examples.RecursiveElementNameAndTextQualifier;
import org.xml.sax.SAXException;
// TODO: Rename this class to XmlAssertUtil
public class XmlUnitUtils {
public static void assertXmlNotSimilar(CharSequence xmlOne, CharSequence xmlTwo) {
normalizedCompare(xmlOne, xmlTwo).areNotSimilar();
// TOOD: Remove this method.
public static void assertSimilar(CharSequence expected, CharSequence actual) throws SAXException, IOException {
assertXmlSimilar(expected, actual);
}
public static void assertXmlSimilar(CharSequence expected, CharSequence actual) {
normalizedCompare(expected, actual).areSimilar();
}
private static CompareAssert normalizedCompare(CharSequence expectedCharSequence, CharSequence actualCharSequence) {
String expectedString = expectedCharSequence.toString();
String actualString = actualCharSequence.toString();
NormalizedSource expected = new NormalizedSource(new StreamSource(new StringReader(expectedString)));
NormalizedSource actual = new NormalizedSource(new StreamSource(new StringReader(actualString)));
return XmlAssert.assertThat(expected).and(actual)
.ignoreChildNodesOrder()
.withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndAllAttributes, ElementSelectors.byNameAndText))
.normalizeWhitespace();
public static void assertXmlSimilar(CharSequence expected, CharSequence actual) throws SAXException, IOException {
Diff diff = new Diff(expected.toString(), actual.toString());
diff.overrideElementQualifier(new RecursiveElementNameAndTextQualifier());
assertXMLEqual(diff, true);
}
}

View file

@ -16,8 +16,8 @@
*/
package org.jivesoftware.smack.util;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.jupiter.api.Assertions.fail;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
@ -51,7 +51,6 @@ public class MemoryLeakTestUtil {
private static final Logger LOGGER = Logger.getLogger(MemoryLeakTestUtil.class.getName());
@SuppressWarnings("UnusedVariable")
public static <M extends Manager> void noResourceLeakTest(Function<DummyConnection, M> managerSupplier)
throws XmppStringprepException, IllegalArgumentException, InterruptedException {
final int numConnections = 10;
@ -104,27 +103,10 @@ public class MemoryLeakTestUtil {
}
private static void assertReferencesQueueSize(ReferenceQueue<?> referenceQueue, int expectedSize) throws IllegalArgumentException, InterruptedException {
final int timeout = 120000;
final int maxAttempts = 3;
final int timeout = 60000;
for (int itemsRemoved = 0; itemsRemoved < expectedSize; ++itemsRemoved) {
int attempt = 0;
Reference<?> reference = null;
do {
reference = referenceQueue.remove(timeout);
if (reference != null) {
break;
}
attempt++;
String message = "No reference to a gc'ed object found after " + timeout + "ms in the " + attempt
+ ". attempt.";
if (attempt >= maxAttempts) {
fail(message);
}
LOGGER.warning(message);
triggerGarbageCollection();
} while (true);
Reference<?> reference = referenceQueue.remove(timeout);
assertNotNull("No reference found after " + timeout + "ms", reference);
reference.clear();
}
@ -137,7 +119,6 @@ public class MemoryLeakTestUtil {
assertNull(reference);
}
@SuppressWarnings("UnusedVariable")
private static void triggerGarbageCollection() {
Object object = new Object();
WeakReference<Object> weakReference = new WeakReference<>(object);
@ -149,8 +130,6 @@ public class MemoryLeakTestUtil {
throw new AssertionError("No observed gargabe collection after " + gcCalls + " calls of System.gc()");
}
System.gc();
// TODO: Would a Thread.yield() here improve the chances of a full GC? It appears that on some systems we
// observe a partial GC here.
gcCalls++;
} while (weakReference.get() != null);

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2016-2019 Florian Schmaus
* Copyright 2016 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -27,7 +27,7 @@ public class NetworkUtil {
private static final Logger LOGGER = Logger.getLogger(NetworkUtil.class.getName());
public static ServerSocket getSocketOnLoopback() throws IOException {
public static ServerSocket getSocketOnLoopback() {
final InetAddress loopbackAddress = InetAddress.getLoopbackAddress();
final int portMin = 1024;
final int portMax = (1 << 16) - 1;
@ -40,12 +40,13 @@ public class NetworkUtil {
break;
} catch (BindException e) {
LOGGER.log(Level.FINEST, "Could not bind port " + port + ", trying next", e);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
if (serverSocket == null) {
throw new IOException("Could not bind any port between " + portMin + " and " + portMax
+ " on loopback address" + loopbackAddress);
throw new IllegalStateException();
}
return serverSocket;

View file

@ -16,8 +16,8 @@
*/
package org.jivesoftware.smack.util;
import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlNotSimilar;
import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar;
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
import static org.custommonkey.xmlunit.XMLAssert.assertXMLNotEqual;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@ -29,8 +29,6 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
@ -44,17 +42,15 @@ import org.jivesoftware.smack.packet.StreamOpen;
import org.jivesoftware.smack.sasl.SASLError;
import org.jivesoftware.smack.sasl.packet.SaslStreamElements;
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.SASLFailure;
import org.jivesoftware.smack.test.util.SmackTestUtil;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smack.test.util.XmlUnitUtils;
import com.jamesmurty.utils.XMLBuilder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.xml.sax.SAXException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
public class PacketParserUtilsTest {
@ -63,9 +59,8 @@ public class PacketParserUtilsTest {
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void singleMessageBodyTest(SmackTestUtil.XmlPullParserKind parserKind) throws Exception {
@Test
public void singleMessageBodyTest() throws Exception {
String defaultLanguage = Stanza.getDefaultLanguage();
String otherLanguage = determineNonDefaultLanguage();
@ -84,13 +79,13 @@ public class PacketParserUtilsTest {
.asString(outputProperties);
Message message = PacketParserUtils
.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
.parseMessage(PacketParserUtils.getParserFor(control));
assertEquals(defaultLanguage, message.getBody());
assertTrue(message.getBodyLanguages().isEmpty());
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
assertNull(message.getBody(otherLanguage));
assertXmlSimilar(control, message.toXML().toString());
assertXMLEqual(control, message.toXML().toString());
// message has non-default language, body has no language
control = XMLBuilder.create("message")
@ -104,13 +99,13 @@ public class PacketParserUtilsTest {
.t(otherLanguage)
.asString(outputProperties);
message = PacketParserUtils.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
message = PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
assertEquals(otherLanguage, message.getBody());
assertTrue(message.getBodyLanguages().isEmpty());
assertEquals(otherLanguage, message.getBody(otherLanguage));
assertNull(message.getBody(defaultLanguage));
assertXmlSimilar(control, message.toXML().toString());
assertXMLEqual(control, message.toXML().toString());
// message has no language, body has no language
control = XMLBuilder.create("message")
@ -123,13 +118,13 @@ public class PacketParserUtilsTest {
.t(defaultLanguage)
.asString(outputProperties);
message = PacketParserUtils.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
message = PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
assertEquals(defaultLanguage, message.getBody());
assertTrue(message.getBodyLanguages().isEmpty());
assertEquals(defaultLanguage, message.getBody(null));
assertNull(message.getBody(otherLanguage));
assertXmlSimilar(control, message.toXML().toString());
assertXMLEqual(control, message.toXML().toString());
// message has no language, body has default language
control = XMLBuilder.create("message")
@ -143,14 +138,14 @@ public class PacketParserUtilsTest {
.t(defaultLanguage)
.asString(outputProperties);
message = PacketParserUtils.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
message = PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
assertNull(message.getBody());
assertFalse(message.getBodyLanguages().isEmpty());
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
assertNull(message.getBody(otherLanguage));
assertXmlSimilar(control, message.toXML().toString());
assertXMLEqual(control, message.toXML().toString());
// message has no language, body has non-default language
control = XMLBuilder.create("message")
@ -164,14 +159,14 @@ public class PacketParserUtilsTest {
.t(otherLanguage)
.asString(outputProperties);
message = PacketParserUtils.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
message = PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
assertNull(message.getBody());
assertFalse(message.getBodyLanguages().isEmpty());
assertTrue(message.getBodyLanguages().contains(otherLanguage));
assertEquals(otherLanguage, message.getBody(otherLanguage));
assertNull(message.getBody(defaultLanguage));
assertXmlSimilar(control, message.toXML().toString());
assertXMLEqual(control, message.toXML().toString());
// message has default language, body has non-default language
control = XMLBuilder.create("message")
@ -186,14 +181,14 @@ public class PacketParserUtilsTest {
.t(otherLanguage)
.asString(outputProperties);
message = PacketParserUtils.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
message = PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
assertNull(message.getBody());
assertFalse(message.getBodyLanguages().isEmpty());
assertTrue(message.getBodyLanguages().contains(otherLanguage));
assertEquals(otherLanguage, message.getBody(otherLanguage));
assertNull(message.getBody(defaultLanguage));
assertXmlSimilar(control, message.toXML().toString());
assertXMLEqual(control, message.toXML().toString());
// message has non-default language, body has default language
control = XMLBuilder.create("message")
@ -208,14 +203,14 @@ public class PacketParserUtilsTest {
.t(defaultLanguage)
.asString(outputProperties);
message = PacketParserUtils.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
message = PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
assertNull(message.getBody());
assertFalse(message.getBodyLanguages().isEmpty());
assertTrue(message.getBodyLanguages().contains(defaultLanguage));
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
assertNull(message.getBody(otherLanguage));
assertXmlSimilar(control, message.toXML().toString());
assertXMLEqual(control, message.toXML().toString());
}
@ -244,7 +239,7 @@ public class PacketParserUtilsTest {
assertTrue(message.getSubjectLanguages().isEmpty());
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
assertNull(message.getSubject(otherLanguage));
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
// message has non-default language, subject has no language
control = XMLBuilder.create("message")
@ -263,7 +258,7 @@ public class PacketParserUtilsTest {
assertTrue(message.getSubjectLanguages().isEmpty());
assertEquals(otherLanguage, message.getSubject(otherLanguage));
assertNull(message.getSubject(defaultLanguage));
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
// message has no language, subject has no language
control = XMLBuilder.create("message")
@ -281,7 +276,7 @@ public class PacketParserUtilsTest {
assertTrue(message.getSubjectLanguages().isEmpty());
assertEquals(defaultLanguage, message.getSubject(null));
assertNull(message.getSubject(otherLanguage));
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
// message has no language, subject has default language
control = XMLBuilder.create("message")
@ -300,7 +295,7 @@ public class PacketParserUtilsTest {
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
assertNull(message.getSubject(otherLanguage));
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
// message has no language, subject has non-default language
control = XMLBuilder.create("message")
@ -320,7 +315,7 @@ public class PacketParserUtilsTest {
assertTrue(message.getSubjectLanguages().contains(otherLanguage));
assertEquals(otherLanguage, message.getSubject(otherLanguage));
assertNull(message.getSubject(defaultLanguage));
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
// message has default language, subject has non-default language
control = XMLBuilder.create("message")
@ -341,7 +336,7 @@ public class PacketParserUtilsTest {
assertTrue(message.getSubjectLanguages().contains(otherLanguage));
assertEquals(otherLanguage, message.getSubject(otherLanguage));
assertNull(message.getSubject(defaultLanguage));
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
// message has non-default language, subject has default language
control = XMLBuilder.create("message")
@ -362,7 +357,7 @@ public class PacketParserUtilsTest {
assertTrue(message.getSubjectLanguages().contains(defaultLanguage));
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
assertNull(message.getSubject(otherLanguage));
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
}
@ -398,7 +393,7 @@ public class PacketParserUtilsTest {
assertEquals(2, message.getBodies().size());
assertEquals(1, message.getBodyLanguages().size());
assertTrue(message.getBodyLanguages().contains(otherLanguage));
assertXmlSimilar(control, message.toXML().toString());
assertXMLEqual(control, message.toXML().toString());
// message has non-default language, first body no language, second body default language
control = XMLBuilder.create("message")
@ -424,7 +419,7 @@ public class PacketParserUtilsTest {
assertEquals(2, message.getBodies().size());
assertEquals(1, message.getBodyLanguages().size());
assertTrue(message.getBodyLanguages().contains(defaultLanguage));
assertXmlSimilar(control, message.toXML().toString());
assertXMLEqual(control, message.toXML().toString());
}
// TODO: Re-enable once we throw an exception on duplicate body elements.
@ -457,7 +452,7 @@ public class PacketParserUtilsTest {
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
assertEquals(1, message.getBodies().size());
assertEquals(0, message.getBodyLanguages().size());
assertXmlNotSimilar(control, message.toXML().toString());
assertXMLNotEqual(control, message.toXML().toString());
}
@Ignore
@ -515,7 +510,7 @@ public class PacketParserUtilsTest {
assertEquals(otherLanguage, message.getBody(otherLanguage));
assertEquals(2, message.getBodies().size());
assertEquals(1, message.getBodyLanguages().size());
assertXmlSimilar(control, message.toXML().toString());
assertXMLEqual(control, message.toXML().toString());
}
@Test
@ -549,7 +544,7 @@ public class PacketParserUtilsTest {
assertEquals(2, message.getSubjects().size());
assertEquals(1, message.getSubjectLanguages().size());
assertTrue(message.getSubjectLanguages().contains(otherLanguage));
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
// message has default language, first subject no language, second subject default language
control = XMLBuilder.create("message")
@ -573,7 +568,7 @@ public class PacketParserUtilsTest {
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
assertEquals(1, message.getSubjects().size());
assertEquals(0, message.getSubjectLanguages().size());
assertXmlNotSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLNotEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
// message has non-default language, first subject no language, second subject default language
control = XMLBuilder.create("message")
@ -598,7 +593,7 @@ public class PacketParserUtilsTest {
assertEquals(2, message.getSubjects().size());
assertEquals(1, message.getSubjectLanguages().size());
assertTrue(message.getSubjectLanguages().contains(defaultLanguage));
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
/*
// message has no language, first subject no language, second subject default language
@ -646,7 +641,7 @@ public class PacketParserUtilsTest {
assertEquals(otherLanguage, message.getSubject(otherLanguage));
assertEquals(2, message.getSubjects().size());
assertEquals(1, message.getSubjectLanguages().size());
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
// message has no language, first subject no language, second subject no language
control = XMLBuilder.create("message")
@ -713,18 +708,13 @@ public class PacketParserUtilsTest {
.t("Good Message Body")
.asString(outputProperties);
// XPP3 writes "end tag", StAX writes "end-tag".
Supplier<Stream<String>> expectedContentOfExceptionMessage = () -> Stream.of("end tag", "end-tag");
String invalidControl = validControl.replace("Good Message Body", "Bad </span> Body");
try {
PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(invalidControl));
fail("Exception should be thrown");
} catch (XmlPullParserException e) {
String exceptionMessage = e.getMessage();
boolean expectedContentFound = expectedContentOfExceptionMessage.get().anyMatch((expected) -> exceptionMessage.contains(expected));
assertTrue(expectedContentFound);
assertTrue(e.getMessage().contains("end tag name </span>"));
}
invalidControl = validControl.replace("Good Message Body", "Bad </body> Body");
@ -733,9 +723,7 @@ public class PacketParserUtilsTest {
PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(invalidControl));
fail("Exception should be thrown");
} catch (XmlPullParserException e) {
String exceptionMessage = e.getMessage();
boolean expectedContentFound = expectedContentOfExceptionMessage.get().anyMatch((expected) -> exceptionMessage.contains(expected));
assertTrue(expectedContentFound);
assertTrue(e.getMessage().contains("end tag name </body>"));
}
invalidControl = validControl.replace("Good Message Body", "Bad </message> Body");
@ -744,10 +732,9 @@ public class PacketParserUtilsTest {
PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(invalidControl));
fail("Exception should be thrown");
} catch (XmlPullParserException e) {
String exceptionMessage = e.getMessage();
boolean expectedContentFound = expectedContentOfExceptionMessage.get().anyMatch((expected) -> exceptionMessage.contains(expected));
assertTrue(expectedContentFound);
assertTrue(e.getMessage().contains("end tag name </message>"));
}
}
@Test
@ -776,52 +763,58 @@ public class PacketParserUtilsTest {
.asString(outputProperties);
Stanza message = PacketParserUtils.parseStanza(control);
assertXmlSimilar(control, message.toXML());
XmlUnitUtils.assertSimilar(control, message.toXML());
}
@Test
public void validateSimplePresence() throws Exception {
String stanza = "<presence from='juliet@example.com/balcony' to='romeo@example.net'/>";
// CHECKSTYLE:OFF
String stanza = "<presence from='juliet@example.com/balcony' to='romeo@example.net'/>";
Presence presence = PacketParserUtils.parsePresence(PacketParserUtils.getParserFor(stanza));
Presence presence = PacketParserUtils.parsePresence(PacketParserUtils.getParserFor(stanza));
assertXmlSimilar(stanza, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertXMLEqual(stanza, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
// CHECKSTYLE:ON
}
@Test
public void validatePresenceProbe() throws Exception {
String stanza = "<presence from='mercutio@example.com' id='xv291f38' to='juliet@example.com' type='unsubscribed'/>";
// CHECKSTYLE:OFF
String stanza = "<presence from='mercutio@example.com' id='xv291f38' to='juliet@example.com' type='unsubscribed'/>";
Presence presence = PacketParserUtils.parsePresence(PacketParserUtils.getParserFor(stanza));
Presence presence = PacketParserUtils.parsePresence(PacketParserUtils.getParserFor(stanza));
assertXmlSimilar(stanza, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertEquals(Presence.Type.unsubscribed, presence.getType());
assertXMLEqual(stanza, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertEquals(Presence.Type.unsubscribed, presence.getType());
// CHECKSTYLE:ON
}
@Test
public void validatePresenceOptionalElements() throws Exception {
String stanza = "<presence xml:lang='en' type='unsubscribed'>"
+ "<show>dnd</show>"
+ "<status>Wooing Juliet</status>"
+ "<priority>1</priority>"
+ "</presence>";
// CHECKSTYLE:OFF
String stanza = "<presence xml:lang='en' type='unsubscribed'>"
+ "<show>dnd</show>"
+ "<status>Wooing Juliet</status>"
+ "<priority>1</priority>"
+ "</presence>";
Presence presence = PacketParserUtils.parsePresence(PacketParserUtils.getParserFor(stanza));
assertXmlSimilar(stanza, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertEquals(Presence.Type.unsubscribed, presence.getType());
assertEquals("dnd", presence.getMode().name());
assertEquals("en", presence.getLanguage());
assertEquals("Wooing Juliet", presence.getStatus());
assertEquals(1, presence.getPriority());
Presence presence = PacketParserUtils.parsePresence(PacketParserUtils.getParserFor(stanza));
assertXMLEqual(stanza, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
assertEquals(Presence.Type.unsubscribed, presence.getType());
assertEquals("dnd", presence.getMode().name());
assertEquals("en", presence.getLanguage());
assertEquals("Wooing Juliet", presence.getStatus());
assertEquals(1, presence.getPriority());
// CHECKSTYLE:ON
}
// @Test
// public void parseContentDepthTest() throws Exception {
// final String stanza = "<iq type='result' to='foo@bar.com' from='baz.com' id='42'/>";
// XmlPullParser parser = TestUtils.getParser(stanza, "iq");
// CharSequence content = PacketParserUtils.parseContent(parser);
// assertEquals("", content.toString());
// }
@Test
public void parseContentDepthTest() throws Exception {
final String stanza = "<iq type='result' to='foo@bar.com' from='baz.com' id='42'/>";
XmlPullParser parser = TestUtils.getParser(stanza, "iq");
CharSequence content = PacketParserUtils.parseContent(parser);
assertEquals("", content.toString());
}
@Test
public void parseElementMultipleNamespace()
@ -837,7 +830,7 @@ public class PacketParserUtilsTest {
// @formatter:on
XmlPullParser parser = TestUtils.getParser(stanza, "outer");
CharSequence result = PacketParserUtils.parseElement(parser, true);
assertXmlSimilar(stanza, result.toString());
assertXMLEqual(stanza, result.toString());
}
@Test
@ -850,7 +843,7 @@ public class PacketParserUtilsTest {
// @formatter:on
XmlPullParser parser = TestUtils.getParser(saslFailureString, SASLFailure.ELEMENT);
SASLFailure saslFailure = PacketParserUtils.parseSASLFailure(parser);
assertXmlSimilar(saslFailureString, saslFailure.toString());
assertXMLEqual(saslFailureString, saslFailure.toString());
}
@Test
@ -872,7 +865,7 @@ public class PacketParserUtilsTest {
// @formatter:on
XmlPullParser parser = TestUtils.getParser(saslFailureString, SASLFailure.ELEMENT);
SASLFailure saslFailure = PacketParserUtils.parseSASLFailure(parser);
assertXmlSimilar(saslFailureString, saslFailure.toXML(StreamOpen.CLIENT_NAMESPACE));
XmlUnitUtils.assertSimilar(saslFailureString, saslFailure.toXML(StreamOpen.CLIENT_NAMESPACE));
}
@SuppressWarnings("ReferenceEquality")
@ -916,7 +909,7 @@ public class PacketParserUtilsTest {
.element("internal-server-error", StanzaError.ERROR_CONDITION_AND_TEXT_NAMESPACE).up()
.element("text", StanzaError.ERROR_CONDITION_AND_TEXT_NAMESPACE).t(text).up()
.asString();
assertXmlSimilar(errorXml, error.toXML(StreamOpen.CLIENT_NAMESPACE));
XmlUnitUtils.assertSimilar(errorXml, error.toXML(StreamOpen.CLIENT_NAMESPACE));
}
@Test

View file

@ -21,7 +21,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.nio.charset.StandardCharsets;
import java.io.UnsupportedEncodingException;
import org.junit.Test;
@ -31,9 +31,11 @@ import org.junit.Test;
public class StringUtilsTest {
@Test
public void testEscapeForXml() {
String input = null;
assertNull(StringUtils.escapeForXml(null));
String input = "<b>";
input = "<b>";
assertCharSequenceEquals("&lt;b&gt;", StringUtils.escapeForXml(input));
input = "\"";
@ -72,15 +74,15 @@ public class StringUtilsTest {
}
@Test
public void testEncodeHex() {
public void testEncodeHex() throws UnsupportedEncodingException {
String input = "";
String output = "";
assertEquals(new String(StringUtils.encodeHex(input.getBytes(StandardCharsets.UTF_8))),
assertEquals(new String(StringUtils.encodeHex(input.getBytes(StringUtils.UTF8))),
output);
input = "foo bar 123";
output = "666f6f2062617220313233";
assertEquals(new String(StringUtils.encodeHex(input.getBytes(StandardCharsets.UTF_8))),
assertEquals(new String(StringUtils.encodeHex(input.getBytes(StringUtils.UTF8))),
output);
}

View file

@ -1,231 +0,0 @@
/**
*
* 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;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.stream.Stream;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.test.util.SmackTestUtil;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
public class XmlPullParserTest {
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testSimpleEmptyElement(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
Reader reader = new StringReader("<empty-element/>");
XmlPullParser parser = parserKind.factory.newXmlPullParser(reader);
assertEquals(XmlPullParser.Event.START_DOCUMENT, parser.getEventType());
assertEquals(XmlPullParser.Event.START_ELEMENT, parser.next());
QName qname = parser.getQName();
assertEquals(qname.getLocalPart(), "empty-element");
assertEquals(qname.getPrefix(), XMLConstants.DEFAULT_NS_PREFIX);
assertEquals(qname.getNamespaceURI(), XMLConstants.NULL_NS_URI);
assertEquals(XmlPullParser.Event.END_ELEMENT, parser.next());
assertEquals(XmlPullParser.Event.END_DOCUMENT, parser.next());
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testQNameSimpleElement(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
String simpleElement = "<outer-element xmlns='outer-namespace'><inner-element/></outer-element>";
XmlPullParser parser = SmackTestUtil.getParserFor(simpleElement, parserKind);
QName qname = parser.getQName();
assertEquals("outer-element", qname.getLocalPart());
assertEquals("outer-namespace", qname.getNamespaceURI());
assertEquals(XmlPullParser.Event.START_ELEMENT, parser.next());
qname = parser.getQName();
assertEquals("inner-element", qname.getLocalPart());
assertEquals("outer-namespace", qname.getNamespaceURI());
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testQNamePrefixElement(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
String prefixElement = "<outer-element xmlns='outer-namespace' xmlns:inner-prefix='inner-namespace'><inner-prefix:inner-element></outer-element>";
XmlPullParser parser = SmackTestUtil.getParserFor(prefixElement, parserKind);
QName qname = parser.getQName();
assertEquals("outer-element", qname.getLocalPart());
assertEquals("outer-namespace", qname.getNamespaceURI());
assertEquals(XmlPullParser.Event.START_ELEMENT, parser.next());
qname = parser.getQName();
assertEquals("inner-element", qname.getLocalPart());
assertEquals("inner-namespace", qname.getNamespaceURI());
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testAttributesElementWithOneAttribute(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
String elementWithOneAttribute = "<element attribute-one='attribute-one-value'/>";
XmlPullParser parser = SmackTestUtil.getParserFor(elementWithOneAttribute, parserKind);
assertAttributeHolds(parser, 0, "attribute-one", "", "");
assertThrows(NullPointerException.class, () ->
assertAttributeHolds(parser, 1, "attribute-one", "", ""));
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testAttributesNamespacedElementWithOneAttribute(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
String namespacedElementWithOneAttribute = "<element xmlns='element-namespace' attribute-one='attribute-one-value'/>";
XmlPullParser parser = SmackTestUtil.getParserFor(namespacedElementWithOneAttribute, parserKind);
assertAttributeHolds(parser, 0, "attribute-one", "", "");
assertThrows(NullPointerException.class, () ->
assertAttributeHolds(parser, 1, "attribute-one", "", ""));
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testAttributesNamespacedElementWithOneNamespacedAttribute(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
String namespacedElementWithOneNamespacedAttribute = "<element xmlns='element-namespace' xmlns:attribute-namespace='attribute-namespace-value' attribute-namespace:attribute-one='attribute-one-value'/>";
XmlPullParser parser = SmackTestUtil.getParserFor(namespacedElementWithOneNamespacedAttribute, parserKind);
assertAttributeHolds(parser, 0, "attribute-one", "attribute-namespace", "attribute-namespace-value");
assertThrows(NullPointerException.class, () ->
assertAttributeHolds(parser, 1, "attribute-one", "", ""));
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testNamespacedAttributes(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
String element = "<element xmlns:attr='attribute-namespace' attr:attributeOneName='attributeOneValue'/>";
XmlPullParser parser = SmackTestUtil.getParserFor(element, parserKind);
assertEquals(1, parser.getAttributeCount());
assertEquals("attributeOneName", parser.getAttributeName(0));
assertEquals("attr", parser.getAttributePrefix(0));
assertEquals("attribute-namespace", parser.getAttributeNamespace(0));
QName attributeZeroQname = parser.getAttributeQName(0);
assertEquals("attributeOneName", attributeZeroQname.getLocalPart());
assertEquals("attr", attributeZeroQname.getPrefix());
assertEquals("attribute-namespace", attributeZeroQname.getNamespaceURI());
// Test how parser handle non-existent attributes.
assertNull(parser.getAttributeName(1));
assertNull(parser.getAttributePrefix(1));
assertNull(parser.getAttributeNamespace(1));
QName attributeOneQname = parser.getAttributeQName(1);
assertNull(attributeOneQname);
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testAttributeType(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
String element = "<element xmlns:attr='attribute-namespace' attr:attributeOneName='attributeOneValue'/>";
XmlPullParser parser = SmackTestUtil.getParserFor(element, parserKind);
assertEquals("CDATA", parser.getAttributeType(0));
assertNull(parser.getAttributeType(1));
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testNextText(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
XmlPullParser parser;
String simpleElement = "<element>Element text</element>";
parser = SmackTestUtil.getParserFor(simpleElement, parserKind);
assertEquals("Element text", parser.nextText());
String complexElement = "<outer-elment><element1>Element 1 &apos; text</element1><element2>Element 2 text</element2></outer-element>";
parser = SmackTestUtil.getParserFor(complexElement, parserKind);
assertEquals(XmlPullParser.Event.START_ELEMENT, parser.next());
assertEquals("element1", parser.getName());
assertEquals(0, parser.getAttributeCount());
assertEquals("Element 1 ' text", parser.nextText());
assertEquals(XmlPullParser.Event.START_ELEMENT, parser.next());
assertEquals("element2", parser.getName());
assertEquals(0, parser.getAttributeCount());
assertEquals("Element 2 text", parser.nextText());
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testNextTextMixedContent(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
String element = "<element>Mixed content element text<inner-element>Inner element text</inner-element></element>";
XmlPullParser parser = SmackTestUtil.getParserFor(element, parserKind);
assertThrows(XmlPullParserException.class, () -> parser.nextText());
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testNextTextOnEndElement(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
String element = "<element>Element text</element>";
XmlPullParser parser = SmackTestUtil.getParserFor(element, parserKind);
assertEquals(XmlPullParser.Event.START_ELEMENT, parser.getEventType());
assertEquals(XmlPullParser.Event.TEXT_CHARACTERS, parser.next());
assertEquals(XmlPullParser.Event.END_ELEMENT, parser.next());
assertThrows(XmlPullParserException.class, () -> parser.nextText());
}
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testNextTextOnEmptyElement(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException {
String[] emptyElementStream = Stream.of().toArray(String[]::new);
for (String emptyElement : emptyElementStream) {
XmlPullParser parser = SmackTestUtil.getParserFor(emptyElement, parserKind);
assertEquals(XmlPullParser.Event.START_ELEMENT, parser.getEventType());
assertEquals("", parser.nextText());
}
}
private static void assertAttributeHolds(XmlPullParser parser, int attributeIndex, String expectedLocalpart,
String expectedPrefix, String expectedNamespace) {
QName qname = parser.getAttributeQName(attributeIndex);
String qnameNamespaceUri = qname.getNamespaceURI();
assertEquals(expectedLocalpart, qname.getLocalPart());
assertEquals(expectedPrefix, qname.getPrefix());
assertEquals(expectedNamespace, qnameNamespaceUri);
assertEquals(qname.getLocalPart(), parser.getAttributeName(attributeIndex));
assertEquals(qname.getPrefix(), parser.getAttributePrefix(attributeIndex));
final String expectedGetAttributeNamespace;
if (qnameNamespaceUri.equals(XMLConstants.NULL_NS_URI)) {
expectedGetAttributeNamespace = null;
}
else {
expectedGetAttributeNamespace = qnameNamespaceUri;
}
assertEquals(expectedGetAttributeNamespace, parser.getAttributeNamespace(attributeIndex));
}
}

View file

@ -257,9 +257,11 @@ public class EnhancedDebugger extends SmackDebugger {
new DefaultTableModel(
new Object[] {"Hide", "Timestamp", "", "", "Message", "Id", "Type", "To", "From"},
0) {
private static final long serialVersionUID = 8136121224474217264L;
@Override
// CHECKSTYLE:OFF
private static final long serialVersionUID = 8136121224474217264L;
@Override
public boolean isCellEditable(int rowIndex, int mColIndex) {
// CHECKSTYLE:ON
return false;
}
@ -687,9 +689,11 @@ public class EnhancedDebugger extends SmackDebugger {
new DefaultTableModel(new Object[][] { {"IQ", 0, 0}, {"Message", 0, 0},
{"Presence", 0, 0}, {"Other", 0, 0}, {"Total", 0, 0}},
new Object[] {"Type", "Received", "Sent"}) {
private static final long serialVersionUID = -6793886085109589269L;
@Override
// CHECKSTYLE:OFF
private static final long serialVersionUID = -6793886085109589269L;
@Override
public boolean isCellEditable(int rowIndex, int mColIndex) {
// CHECKSTYLE:ON
return false;
}
};

View file

@ -346,7 +346,6 @@ public final class EnhancedDebuggerWindow {
*
* @param evt the event that indicates that the root window is closing
*/
@SuppressWarnings("UnusedVariable")
private synchronized void rootWindowClosing(WindowEvent evt) {
// Notify to all the debuggers to stop debugging
for (EnhancedDebugger debugger : debuggers) {

View file

@ -21,14 +21,15 @@ import java.io.IOException;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension.Direction;
import org.jivesoftware.smackx.forward.packet.Forwarded;
import org.jivesoftware.smackx.forward.provider.ForwardedProvider;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
/**
* This class implements the {@link ExtensionElementProvider} to parse
* carbon copied messages from a packet. It will return a {@link CarbonExtension} stanza extension.
@ -47,11 +48,11 @@ public class CarbonManagerProvider extends ExtensionElementProvider<CarbonExtens
boolean done = false;
while (!done) {
XmlPullParser.Event eventType = parser.next();
if (eventType == XmlPullParser.Event.START_ELEMENT && parser.getName().equals("forwarded")) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG && parser.getName().equals("forwarded")) {
fwd = FORWARDED_PROVIDER.parse(parser);
}
else if (eventType == XmlPullParser.Event.END_ELEMENT && dir == Direction.valueOf(parser.getName()))
else if (eventType == XmlPullParser.END_TAG && dir == Direction.valueOf(parser.getName()))
done = true;
}
if (fwd == null) {

View file

@ -42,7 +42,6 @@ import org.jivesoftware.smack.filter.StanzaExtensionFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements;
import org.jivesoftware.smackx.chat_markers.filter.ChatMarkersFilter;
import org.jivesoftware.smackx.chat_markers.filter.EligibleForChatMarkerFilter;

View file

@ -20,7 +20,6 @@ import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.chat_markers.ChatMarkersState;
/**

View file

@ -18,7 +18,6 @@ package org.jivesoftware.smackx.chat_markers.filter;
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements;
/**

View file

@ -19,7 +19,6 @@ package org.jivesoftware.smackx.chat_markers.filter;
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smackx.chatstates.ChatState;
import org.jivesoftware.smackx.chatstates.ChatStateManager;

Some files were not shown because too many files have changed in this diff Show more