mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-22 20:12:07 +01:00
Compare commits
78 commits
870756997f
...
c6c904cc3e
Author | SHA1 | Date | |
---|---|---|---|
|
c6c904cc3e | ||
|
fa0c16d75c | ||
|
92b02afbff | ||
|
818ee8a727 | ||
|
9bb36fc63c | ||
|
6e1193edaf | ||
|
7d59df9eed | ||
|
e911874e72 | ||
|
ce70308099 | ||
|
c0183775fe | ||
|
832b20a897 | ||
|
b834df65e9 | ||
|
b3b242f397 | ||
|
1f8b7273a8 | ||
|
4d36e3b521 | ||
|
1a99801501 | ||
|
3c306eaff9 | ||
|
9a2cca2bd3 | ||
|
b288768f77 | ||
|
4334ca33ff | ||
|
027cae3bd0 | ||
|
619b8e6f4a | ||
|
58fc39714f | ||
|
839e347676 | ||
|
726a2de273 | ||
|
af6ee76f4c | ||
|
49aa7ce21b | ||
|
6619372bb8 | ||
|
9352225f44 | ||
|
d337474a86 | ||
|
02f7cfcf27 | ||
|
e8d9aed4be | ||
|
f91044657f | ||
|
04238bd36a | ||
|
02e2eba556 | ||
|
48010f3b82 | ||
|
11ae6d6960 | ||
|
ab99f629a3 | ||
|
f7762c5db7 | ||
|
db5f6f648c | ||
|
7e25c3ada5 | ||
|
2ceadc0de1 | ||
|
f60e4055ec | ||
|
381190a45c | ||
|
04f1d79d72 | ||
|
2dedd75cd7 | ||
|
edcde28ecd | ||
|
49f4de0cdb | ||
|
7c6d1f4340 | ||
|
f6be434f66 | ||
|
68b7eb26f3 | ||
|
32429bcb9c | ||
|
07c069e1a1 | ||
|
5e1c3c7aa5 | ||
|
60db42e2f4 | ||
|
d20a2675a8 | ||
|
f4ee7dd541 | ||
|
f8de22478b | ||
|
d2f5efcb20 | ||
|
2a4d110b22 | ||
|
fd89a5e5a5 | ||
|
7f0dc72dab | ||
|
68d7d738b6 | ||
|
575364cc1f | ||
|
e1ed035beb | ||
|
95dbf5bb36 | ||
|
505493d889 | ||
|
0e52560358 | ||
|
4a3dda93af | ||
|
7980e2cedb | ||
|
4133eb175c | ||
|
dd903bec95 | ||
|
1554a33518 | ||
|
b3646abecd | ||
|
ae2c57f56b | ||
|
3b657d36c4 | ||
|
4e7cd83220 | ||
|
f1fb03d08c |
588 changed files with 8799 additions and 5100 deletions
|
@ -1,7 +1,7 @@
|
||||||
language: android
|
language: android
|
||||||
android:
|
android:
|
||||||
components:
|
components:
|
||||||
- android-16
|
- android-19
|
||||||
jdk:
|
jdk:
|
||||||
- oraclejdk8
|
- oraclejdk8
|
||||||
- openjdk8
|
- openjdk8
|
||||||
|
@ -11,7 +11,7 @@ cache:
|
||||||
- $HOME/.m2
|
- $HOME/.m2
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- export GRADLE_VERSION=5.1.1
|
- export GRADLE_VERSION=5.2.1
|
||||||
- wget https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-all.zip
|
- wget https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-all.zip
|
||||||
- unzip -q gradle-${GRADLE_VERSION}-all.zip
|
- unzip -q gradle-${GRADLE_VERSION}-all.zip
|
||||||
- export PATH="$(pwd)/gradle-${GRADLE_VERSION}/bin:$PATH"
|
- export PATH="$(pwd)/gradle-${GRADLE_VERSION}/bin:$PATH"
|
||||||
|
|
112
build.gradle
112
build.gradle
|
@ -14,8 +14,8 @@ buildscript {
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'ru.vyarus.animalsniffer' version '1.4.6'
|
id 'ru.vyarus.animalsniffer' version '1.5.0'
|
||||||
id 'net.ltgt.errorprone' version '0.6'
|
id 'net.ltgt.errorprone' version '0.8'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'org.kordamp.gradle.markdown'
|
apply plugin: 'org.kordamp.gradle.markdown'
|
||||||
|
@ -24,6 +24,7 @@ apply from: 'version.gradle'
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
|
apply plugin: 'java-library'
|
||||||
apply plugin: 'eclipse'
|
apply plugin: 'eclipse'
|
||||||
apply plugin: 'idea'
|
apply plugin: 'idea'
|
||||||
apply plugin: 'jacoco'
|
apply plugin: 'jacoco'
|
||||||
|
@ -80,6 +81,8 @@ allprojects {
|
||||||
':smack-omemo',
|
':smack-omemo',
|
||||||
':smack-omemo-signal',
|
':smack-omemo-signal',
|
||||||
':smack-openpgp',
|
':smack-openpgp',
|
||||||
|
':smack-xmlparser',
|
||||||
|
':smack-xmlparser-xpp3',
|
||||||
].collect{ project(it) }
|
].collect{ project(it) }
|
||||||
androidBootClasspathProjects = [
|
androidBootClasspathProjects = [
|
||||||
':smack-android',
|
':smack-android',
|
||||||
|
@ -97,13 +100,37 @@ allprojects {
|
||||||
':smack-omemo-signal',
|
':smack-omemo-signal',
|
||||||
':smack-omemo-signal-integration-test',
|
':smack-omemo-signal-integration-test',
|
||||||
].collect{ project(it) }
|
].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
|
// Lazily evaluate the Android bootClasspath and offline
|
||||||
// Javadoc using a closure, so that targets which do not
|
// Javadoc using a closure, so that targets which do not
|
||||||
// require it are still able to succeed without an Android
|
// require it are still able to succeed without an Android
|
||||||
// SDK.
|
// SDK.
|
||||||
androidBootClasspath = { getAndroidRuntimeJar() }
|
androidBootClasspath = { getAndroidRuntimeJar() }
|
||||||
androidJavadocOffline = { getAndroidJavadocOffline() }
|
androidJavadocOffline = { getAndroidJavadocOffline() }
|
||||||
junitVersion = '5.2.0'
|
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'
|
||||||
}
|
}
|
||||||
group = 'org.igniterealtime.smack'
|
group = 'org.igniterealtime.smack'
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
@ -114,6 +141,10 @@ allprojects {
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
|
||||||
|
maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
|
||||||
|
|
||||||
// Enable full stacktraces of failed tests. Especially handy
|
// Enable full stacktraces of failed tests. Especially handy
|
||||||
// for environments like Travis.
|
// for environments like Travis.
|
||||||
testLogging {
|
testLogging {
|
||||||
|
@ -170,21 +201,25 @@ allprojects {
|
||||||
'-Xlint:-options',
|
'-Xlint:-options',
|
||||||
'-Werror',
|
'-Werror',
|
||||||
]
|
]
|
||||||
options.errorprone.errorproneArgs = [
|
options.errorprone {
|
||||||
// Disable errorprone checks
|
error("UnusedVariable", "UnusedMethod")
|
||||||
'-Xep:TypeParameterUnusedInFormals:OFF',
|
errorproneArgs = [
|
||||||
// Disable errorpone StringSplitter check, as it
|
// Disable errorprone checks
|
||||||
// recommends using Splitter from Guava, which we don't
|
'-Xep:TypeParameterUnusedInFormals:OFF',
|
||||||
// have (nor want to use in Smack).
|
// Disable errorpone StringSplitter check, as it
|
||||||
'-Xep:StringSplitter:OFF',
|
// recommends using Splitter from Guava, which we don't
|
||||||
'-Xep:JdkObsolete:OFF',
|
// have (nor want to use in Smack).
|
||||||
// Disabled because sinttest re-uses BeforeClass from junit.
|
'-Xep:StringSplitter:OFF',
|
||||||
// TODO: change sinttest so that it has it's own
|
'-Xep:JdkObsolete:OFF',
|
||||||
// BeforeClass and re-enable this check.
|
// Disabled because sinttest re-uses BeforeClass from junit.
|
||||||
'-Xep:JUnit4ClassAnnotationNonStatic:OFF',
|
// TODO: change sinttest so that it has it's own
|
||||||
// Disabled but should be re-enabled at some point
|
// BeforeClass and re-enable this check.
|
||||||
//'-Xep:InconsistentCapitalization:OFF',
|
'-Xep:JUnit4ClassAnnotationNonStatic:OFF',
|
||||||
]
|
// Disabled but should be re-enabled at some point
|
||||||
|
//'-Xep:InconsistentCapitalization:OFF',
|
||||||
|
'-Xep:MixedMutabilityReturnType:OFF',
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(ScalaCompile) {
|
tasks.withType(ScalaCompile) {
|
||||||
|
@ -232,7 +267,11 @@ allprojects {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
errorprone 'com.google.errorprone:error_prone_core:2.3.2'
|
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'
|
||||||
errorproneJavac('com.google.errorprone:javac:9+181-r4173-1')
|
errorproneJavac('com.google.errorprone:javac:9+181-r4173-1')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,6 +280,15 @@ allprojects {
|
||||||
test { dependsOn javadoc }
|
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 ->
|
gradle.taskGraph.whenReady { taskGraph ->
|
||||||
if (signingRequired
|
if (signingRequired
|
||||||
&& taskGraph.allTasks.any { it instanceof Sign }) {
|
&& taskGraph.allTasks.any { it instanceof Sign }) {
|
||||||
|
@ -519,19 +567,21 @@ configure(integrationTestProjects + project(':smack-repl')) {
|
||||||
project(':smack-omemo').clirr.enabled = false
|
project(':smack-omemo').clirr.enabled = false
|
||||||
project(':smack-omemo-signal').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 {
|
subprojects*.jar {
|
||||||
manifest {
|
manifest {
|
||||||
from sharedManifest
|
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) {
|
configure(subprojects - gplLicensedProjects) {
|
||||||
checkstyle {
|
checkstyle {
|
||||||
configProperties.checkstyleLicenseHeader = "header"
|
configProperties.checkstyleLicenseHeader = "header"
|
||||||
|
@ -646,15 +696,7 @@ def getGitCommit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
def getAndroidRuntimeJar() {
|
def getAndroidRuntimeJar() {
|
||||||
// We set a different Android API level compared to
|
def androidApiLevel = ext.smackMinAndroidSdk
|
||||||
// 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 androidHome = getAndroidHome()
|
||||||
def androidJar = new File("$androidHome/platforms/android-${androidApiLevel}/android.jar")
|
def androidJar = new File("$androidHome/platforms/android-${androidApiLevel}/android.jar")
|
||||||
if (androidJar.isFile()) {
|
if (androidJar.isFile()) {
|
||||||
|
|
|
@ -39,12 +39,7 @@
|
||||||
<property name="format" value="^\s+$"/>
|
<property name="format" value="^\s+$"/>
|
||||||
<property name="message" value="Line containing only whitespace character(s)"/>
|
<property name="message" value="Line containing only whitespace character(s)"/>
|
||||||
</module>
|
</module>
|
||||||
<module name="RegexpSingleline">
|
<module name="FileTabCharacter"/>
|
||||||
<!-- 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">
|
<module name="RegexpSingleline">
|
||||||
<!--
|
<!--
|
||||||
Explaining the following Regex
|
Explaining the following Regex
|
||||||
|
@ -147,6 +142,7 @@
|
||||||
, LITERAL_DO
|
, LITERAL_DO
|
||||||
, LITERAL_FOR
|
, LITERAL_FOR
|
||||||
, DO_WHILE
|
, DO_WHILE
|
||||||
|
, COMMA
|
||||||
"/>
|
"/>
|
||||||
</module>
|
</module>
|
||||||
<module name="WhitespaceAround">
|
<module name="WhitespaceAround">
|
||||||
|
|
|
@ -27,11 +27,11 @@ public MyExtension parse(XmlPullParser parser, int initialDepth) {
|
||||||
outerloop: while(true) {
|
outerloop: while(true) {
|
||||||
// Make sure to have already parse all attributes of the outermost element,
|
// Make sure to have already parse all attributes of the outermost element,
|
||||||
// i.e. 'attrFoo' of 'myExtension' in this example. Then advance the parser
|
// i.e. 'attrFoo' of 'myExtension' in this example. Then advance the parser
|
||||||
int event = parser.next();
|
XmlPullParser.Event event = parser.next();
|
||||||
|
|
||||||
// Use switch/case of int instead of a if/else-if cascade
|
// Use switch/case of int instead of a if/else-if cascade
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
// Determine the name of the element which start tag we are seeing
|
// Determine the name of the element which start tag we are seeing
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
// We can use switch/case of Strings since Java7, make use of its advantages
|
// We can use switch/case of Strings since Java7, make use of its advantages
|
||||||
|
@ -52,12 +52,15 @@ public MyExtension parse(XmlPullParser parser, int initialDepth) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
// The abort condition with the break labeled loop statement
|
// The abort condition with the break labeled loop statement
|
||||||
if (parser.getDepth() == initialDepth) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,23 +56,25 @@ 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. |
|
| [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. |
|
| 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. |
|
| [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 . |
|
| 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. |
|
| 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.
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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). |
|
| [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.
|
| 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 |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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 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. |
|
| 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. |
|
| [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 |
|
| [Jive Properties](properties.md) | n/a | n/a | TODO |
|
||||||
|
|
||||||
|
|
|
@ -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
|
passed to the correct provider. Each provider must extend the
|
||||||
ExtensionElementProvider abstract class. Each extension provider is
|
ExtensionElementProvider abstract class. Each extension provider is
|
||||||
responsible for parsing the raw XML stream, via the
|
responsible for parsing the raw XML stream, via the
|
||||||
[XML Pull Parser](http://www.xmlpull.org/), to contruct an object.
|
Smack's `XmlPullParser` interface, to construct an object.
|
||||||
|
|
||||||
You can also create an introspection provider
|
You can also create an introspection provider
|
||||||
(`provider.IntrospectionProvider.PacketExtensionIntrospectionProvider`). Here,
|
(`provider.IntrospectionProvider.PacketExtensionIntrospectionProvider`). Here,
|
||||||
|
@ -161,9 +161,9 @@ public class MyIQProvider extends IQProvider<MyIQ> {
|
||||||
|
|
||||||
// Start parsing loop
|
// Start parsing loop
|
||||||
outerloop: while(true) {
|
outerloop: while(true) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
switch(eventType) {
|
switch(eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
String elementName = parser.getName();
|
String elementName = parser.getName();
|
||||||
switch (elementName) {
|
switch (elementName) {
|
||||||
case "user":
|
case "user":
|
||||||
|
@ -175,12 +175,15 @@ public class MyIQProvider extends IQProvider<MyIQ> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
// Abort condition: if the are on a end tag (closing element) of the same depth
|
// Abort condition: if the are on a end tag (closing element) of the same depth
|
||||||
if (parser.getDepth() == initialDepth) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,9 +228,9 @@ _Disco Items IQProvider_
|
||||||
String node = "";
|
String node = "";
|
||||||
discoverItems.setNode(parser.getAttributeValue("", "node"));
|
discoverItems.setNode(parser.getAttributeValue("", "node"));
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
String elementName = parser.getName();
|
String elementName = parser.getName();
|
||||||
switch (elementName) {
|
switch (elementName) {
|
||||||
case "item":
|
case "item":
|
||||||
|
@ -239,7 +242,7 @@ _Disco Items IQProvider_
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
String elementName = parser.getName();
|
String elementName = parser.getName();
|
||||||
switch (elementName) {
|
switch (elementName) {
|
||||||
case "item":
|
case "item":
|
||||||
|
@ -295,17 +298,17 @@ _Subscription PacketExtensionProvider Implementation_
|
||||||
String state = parser.getAttributeValue(null, "subscription");
|
String state = parser.getAttributeValue(null, "subscription");
|
||||||
boolean isRequired = false;
|
boolean isRequired = false;
|
||||||
|
|
||||||
int tag = parser.next();
|
XmlPullParser.Event tag = parser.next();
|
||||||
|
|
||||||
if ((tag == XmlPullParser.START_TAG) && parser.getName().equals("subscribe-options")) {
|
if ((tag == XmlPullParser.START_ELEMENT) && parser.getName().equals("subscribe-options")) {
|
||||||
tag = parser.next();
|
tag = parser.next();
|
||||||
|
|
||||||
if ((tag == XmlPullParser.START_TAG) && parser.getName().equals("required"))
|
if ((tag == XmlPullParser.START_ELEMENT) && parser.getName().equals("required"))
|
||||||
isRequired = true;
|
isRequired = true;
|
||||||
|
|
||||||
while (parser.next() != XmlPullParser.END_TAG && parser.getName() != "subscribe-options");
|
while (parser.next() != XmlPullParser.END_ELEMENT && parser.getName() != "subscribe-options");
|
||||||
}
|
}
|
||||||
while (parser.getEventType() != XmlPullParser.END_TAG) parser.next();
|
while (parser.getEventType() != XmlPullParser.END_ELEMENT) parser.next();
|
||||||
return new Subscription(jid, nodeId, subId, state == null ? null : Subscription.State.valueOf(state), isRequired);
|
return new Subscription(jid, nodeId, subId, state == null ? null : Subscription.State.valueOf(state), isRequired);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,14 +169,10 @@ recommended when using Smack.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
If you dont' use a
|
Smack tries to depend on as few as possible libraries. The only
|
||||||
dependency resolution system, like gradle or maven, then you will need
|
requirement is <a href="http://jxmpp.org">jXMPP</a>. For DNS
|
||||||
to download at least
|
resolution we recommend to
|
||||||
the <a href="http://www.extreme.indiana.edu/xgws/xsoap/xpp/mxp1/">Xml
|
use <a href="http://minidns.org">MiniDNS</a>.
|
||||||
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>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -28,4 +28,7 @@ include 'smack-core',
|
||||||
'smack-omemo-signal',
|
'smack-omemo-signal',
|
||||||
'smack-omemo-signal-integration-test',
|
'smack-omemo-signal-integration-test',
|
||||||
'smack-repl',
|
'smack-repl',
|
||||||
'smack-openpgp'
|
'smack-openpgp',
|
||||||
|
'smack-xmlparser',
|
||||||
|
'smack-xmlparser-stax',
|
||||||
|
'smack-xmlparser-xpp3'
|
||||||
|
|
|
@ -7,6 +7,7 @@ smack-extensions and smack-experimental."""
|
||||||
// Note that the test dependencies (junit, …) are inferred from the
|
// Note that the test dependencies (junit, …) are inferred from the
|
||||||
// sourceSet.test of the core subproject
|
// sourceSet.test of the core subproject
|
||||||
dependencies {
|
dependencies {
|
||||||
|
api project(':smack-xmlparser-xpp3')
|
||||||
// Depend on minidns-android21 as optional dependency, even if may
|
// Depend on minidns-android21 as optional dependency, even if may
|
||||||
// not need it. Can't hurt to have it in the programm path with
|
// 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
|
// the correct MiniDNS version as it won't hurt even if the
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright © 2014-2018 Florian Schmaus
|
* Copyright © 2014-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,9 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.util.stringencoder.android;
|
package org.jivesoftware.smack.util.stringencoder.android;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
|
||||||
import org.jivesoftware.smack.util.stringencoder.StringEncoder;
|
import org.jivesoftware.smack.util.stringencoder.StringEncoder;
|
||||||
|
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
@ -39,21 +38,13 @@ public final class AndroidBase64UrlSafeEncoder implements StringEncoder<String>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String encode(String string) {
|
public String encode(String string) {
|
||||||
try {
|
return Base64.encodeToString(string.getBytes(StandardCharsets.UTF_8), BASE64_ENCODER_FLAGS);
|
||||||
return Base64.encodeToString(string.getBytes(StringUtils.UTF8), BASE64_ENCODER_FLAGS);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new IllegalStateException("UTF-8 not supported", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String decode(String string) {
|
public String decode(String string) {
|
||||||
byte[] bytes = Base64.decode(string, BASE64_ENCODER_FLAGS);
|
byte[] bytes = Base64.decode(string, BASE64_ENCODER_FLAGS);
|
||||||
try {
|
return new String(bytes, StandardCharsets.UTF_8);
|
||||||
return new String(bytes, StringUtils.UTF8);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new IllegalStateException("UTF-8 not supported", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ package org.jivesoftware.smack.bosh;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PipedReader;
|
import java.io.PipedReader;
|
||||||
import java.io.PipedWriter;
|
import java.io.PipedWriter;
|
||||||
import java.io.StringReader;
|
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -44,6 +43,7 @@ import org.jivesoftware.smack.sasl.packet.SaslStreamElements.SASLFailure;
|
||||||
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Success;
|
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Success;
|
||||||
import org.jivesoftware.smack.util.CloseableUtil;
|
import org.jivesoftware.smack.util.CloseableUtil;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
|
||||||
import org.igniterealtime.jbosh.AbstractBody;
|
import org.igniterealtime.jbosh.AbstractBody;
|
||||||
import org.igniterealtime.jbosh.BOSHClient;
|
import org.igniterealtime.jbosh.BOSHClient;
|
||||||
|
@ -56,11 +56,8 @@ import org.igniterealtime.jbosh.BOSHException;
|
||||||
import org.igniterealtime.jbosh.BOSHMessageEvent;
|
import org.igniterealtime.jbosh.BOSHMessageEvent;
|
||||||
import org.igniterealtime.jbosh.BodyQName;
|
import org.igniterealtime.jbosh.BodyQName;
|
||||||
import org.igniterealtime.jbosh.ComposableBody;
|
import org.igniterealtime.jbosh.ComposableBody;
|
||||||
|
|
||||||
import org.jxmpp.jid.DomainBareJid;
|
import org.jxmpp.jid.DomainBareJid;
|
||||||
import org.jxmpp.jid.parts.Resourcepart;
|
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.
|
* Creates a connection to an XMPP server via HTTP binding.
|
||||||
|
@ -479,14 +476,13 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
||||||
if (streamId == null) {
|
if (streamId == null) {
|
||||||
streamId = body.getAttribute(BodyQName.create(XMPPBOSHConnection.BOSH_URI, "authid"));
|
streamId = body.getAttribute(BodyQName.create(XMPPBOSHConnection.BOSH_URI, "authid"));
|
||||||
}
|
}
|
||||||
final XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
|
final XmlPullParser parser = PacketParserUtils.getParserFor(body.toXML());
|
||||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
|
||||||
parser.setInput(new StringReader(body.toXML()));
|
XmlPullParser.Event eventType = parser.getEventType();
|
||||||
int eventType = parser.getEventType();
|
|
||||||
do {
|
do {
|
||||||
eventType = parser.next();
|
eventType = parser.next();
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case Message.ELEMENT:
|
case Message.ELEMENT:
|
||||||
|
@ -528,9 +524,12 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (eventType != XmlPullParser.END_DOCUMENT);
|
while (eventType != XmlPullParser.Event.END_DOCUMENT);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
if (isConnected()) {
|
if (isConnected()) {
|
||||||
|
|
|
@ -2,23 +2,27 @@ description = """\
|
||||||
Smack core components."""
|
Smack core components."""
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
xmlUnitVersion = "2.6.0"
|
xmlUnitVersion = '2.6.2'
|
||||||
powerMockVersion = "1.7.3"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'xpp3:xpp3:1.1.4c'
|
compile project(':smack-xmlparser')
|
||||||
compile "org.jxmpp:jxmpp-core:$jxmppVersion"
|
compile "org.jxmpp:jxmpp-core:$jxmppVersion"
|
||||||
compile "org.jxmpp:jxmpp-jid:$jxmppVersion"
|
compile "org.jxmpp:jxmpp-jid:$jxmppVersion"
|
||||||
compile "org.minidns:minidns-core:$miniDnsVersion"
|
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.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"
|
testCompile "org.xmlunit:xmlunit-core:$xmlUnitVersion"
|
||||||
testCompile "org.xmlunit:xmlunit-legacy:$xmlUnitVersion"
|
// Explictily add assertj-core which is a dependency of
|
||||||
testCompile "org.powermock:powermock-module-junit4:$powerMockVersion"
|
// xmlunit-assertj, but gradle fails to resolves it with:
|
||||||
testCompile "org.powermock:powermock-module-junit4-rule:$powerMockVersion"
|
// Execution failed for task ':smack-core:compileTestJava'.
|
||||||
testCompile "org.powermock:powermock-api-mockito2:$powerMockVersion"
|
// > 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 'com.jamesmurty.utils:java-xmlbuilder:1.2'
|
testCompile 'com.jamesmurty.utils:java-xmlbuilder:1.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,9 @@ package org.jivesoftware.smack.packet;
|
||||||
|
|
||||||
import org.jivesoftware.smack.provider.PrivacyProvider;
|
import org.jivesoftware.smack.provider.PrivacyProvider;
|
||||||
import org.jivesoftware.smack.test.SmackTestCase;
|
import org.jivesoftware.smack.test.SmackTestCase;
|
||||||
import org.xmlpull.v1.XmlPullParserFactory;
|
import org.jivesoftware.smack.xml.XmlPullParserFactory;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ import org.jivesoftware.smack.ConnectionConfiguration;
|
||||||
import org.jivesoftware.smack.TCPConnection;
|
import org.jivesoftware.smack.TCPConnection;
|
||||||
import org.jivesoftware.smack.XMPPException;
|
import org.jivesoftware.smack.XMPPException;
|
||||||
import org.jivesoftware.smack.util.ConnectionUtils;
|
import org.jivesoftware.smack.util.ConnectionUtils;
|
||||||
import org.xmlpull.v1.XmlPullParserFactory;
|
import org.jivesoftware.smack.xml.XmlPullParserFactory;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all the test cases which provides a pre-configured execution context. This
|
* 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();
|
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
|
||||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
||||||
parser.setInput(systemStream, "UTF-8");
|
parser.setInput(systemStream, "UTF-8");
|
||||||
int eventType = parser.getEventType();
|
XmlPullParser.Event eventType = parser.getEventType();
|
||||||
do {
|
do {
|
||||||
if (eventType == XmlPullParser.START_TAG) {
|
if (eventType == START_ELEMENT) {
|
||||||
if (parser.getName().equals("host")) {
|
if (parser.getName().equals("host")) {
|
||||||
host = parser.nextText();
|
host = parser.nextText();
|
||||||
}
|
}
|
||||||
|
@ -459,7 +459,7 @@ public abstract class SmackTestCase extends TestCase {
|
||||||
}
|
}
|
||||||
eventType = parser.next();
|
eventType = parser.next();
|
||||||
}
|
}
|
||||||
while (eventType != XmlPullParser.END_DOCUMENT);
|
while (eventType != END_DOCUMENT);
|
||||||
parsedOK = true;
|
parsedOK = true;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
|
|
@ -20,9 +20,9 @@ import java.io.StringReader;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.XMPPError;
|
import org.jivesoftware.smack.packet.XMPPError;
|
||||||
import org.jivesoftware.smack.test.SmackTestCase;
|
import org.jivesoftware.smack.test.SmackTestCase;
|
||||||
import org.xmlpull.v1.XmlPullParserFactory;
|
import org.jivesoftware.smack.xml.XmlPullParserFactory;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
public class XMPPErrorTest extends SmackTestCase {
|
public class XMPPErrorTest extends SmackTestCase {
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.io.InputStream;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.KeyManagementException;
|
import java.security.KeyManagementException;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
|
@ -64,6 +65,7 @@ import javax.net.ssl.X509TrustManager;
|
||||||
import javax.security.auth.callback.Callback;
|
import javax.security.auth.callback.Callback;
|
||||||
import javax.security.auth.callback.CallbackHandler;
|
import javax.security.auth.callback.CallbackHandler;
|
||||||
import javax.security.auth.callback.PasswordCallback;
|
import javax.security.auth.callback.PasswordCallback;
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.jivesoftware.smack.ConnectionConfiguration.DnssecMode;
|
import org.jivesoftware.smack.ConnectionConfiguration.DnssecMode;
|
||||||
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
|
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
|
||||||
|
@ -121,6 +123,8 @@ import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smack.util.dns.HostAddress;
|
import org.jivesoftware.smack.util.dns.HostAddress;
|
||||||
import org.jivesoftware.smack.util.dns.SmackDaneProvider;
|
import org.jivesoftware.smack.util.dns.SmackDaneProvider;
|
||||||
import org.jivesoftware.smack.util.dns.SmackDaneVerifier;
|
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.DomainBareJid;
|
||||||
import org.jxmpp.jid.EntityFullJid;
|
import org.jxmpp.jid.EntityFullJid;
|
||||||
|
@ -130,8 +134,6 @@ import org.jxmpp.jid.parts.Resourcepart;
|
||||||
import org.jxmpp.stringprep.XmppStringprepException;
|
import org.jxmpp.stringprep.XmppStringprepException;
|
||||||
import org.jxmpp.util.XmppStringUtils;
|
import org.jxmpp.util.XmppStringUtils;
|
||||||
import org.minidns.dnsname.DnsName;
|
import org.minidns.dnsname.DnsName;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -233,11 +235,11 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
|
|
||||||
private XmlEnvironment incomingStreamXmlEnvironment;
|
private XmlEnvironment incomingStreamXmlEnvironment;
|
||||||
|
|
||||||
final Map<String, NonzaCallback> nonzaCallbacks = new HashMap<>();
|
final Map<QName, NonzaCallback> nonzaCallbacks = new HashMap<>();
|
||||||
|
|
||||||
protected final Lock connectionLock = new ReentrantLock();
|
protected final Lock connectionLock = new ReentrantLock();
|
||||||
|
|
||||||
protected final Map<String, FullyQualifiedElement> streamFeatures = new HashMap<>();
|
protected final Map<QName, FullyQualifiedElement> streamFeatures = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The full JID of the authenticated user, as returned by the resource binding response of the server.
|
* The full JID of the authenticated user, as returned by the resource binding response of the server.
|
||||||
|
@ -336,6 +338,12 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
Thread thread = new Thread(runnable);
|
Thread thread = new Thread(runnable);
|
||||||
thread.setName("Smack Cached Executor");
|
thread.setName("Smack Cached Executor");
|
||||||
thread.setDaemon(true);
|
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;
|
return thread;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -381,8 +389,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
|
|
||||||
protected Exception currentConnectionException;
|
protected Exception currentConnectionException;
|
||||||
|
|
||||||
private final Map<String, IQRequestHandler> setIqRequestHandler = new HashMap<>();
|
private final Map<QName, IQRequestHandler> setIqRequestHandler = new HashMap<>();
|
||||||
private final Map<String, IQRequestHandler> getIqRequestHandler = new HashMap<>();
|
private final Map<QName, IQRequestHandler> getIqRequestHandler = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new XMPPConnection to an XMPP server.
|
* Create a new XMPPConnection to an XMPP server.
|
||||||
|
@ -1213,7 +1221,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
protected final void parseAndProcessNonza(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException {
|
protected final void parseAndProcessNonza(XmlPullParser parser) throws IOException, XmlPullParserException, SmackParsingException {
|
||||||
final String element = parser.getName();
|
final String element = parser.getName();
|
||||||
final String namespace = parser.getNamespace();
|
final String namespace = parser.getNamespace();
|
||||||
final String key = XmppStringUtils.generateKey(element, namespace);
|
final QName key = new QName(namespace, element);
|
||||||
|
|
||||||
NonzaProvider<? extends Nonza> nonzaProvider = ProviderManager.getNonzaProvider(key);
|
NonzaProvider<? extends Nonza> nonzaProvider = ProviderManager.getNonzaProvider(key);
|
||||||
if (nonzaProvider == null) {
|
if (nonzaProvider == null) {
|
||||||
|
@ -1243,7 +1251,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
try {
|
try {
|
||||||
stanza = PacketParserUtils.parseStanza(parser, incomingStreamXmlEnvironment);
|
stanza = PacketParserUtils.parseStanza(parser, incomingStreamXmlEnvironment);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (XmlPullParserException | SmackParsingException | IOException e) {
|
||||||
CharSequence content = PacketParserUtils.parseContentDepth(parser,
|
CharSequence content = PacketParserUtils.parseContentDepth(parser,
|
||||||
parserDepth);
|
parserDepth);
|
||||||
UnparseableStanza message = new UnparseableStanza(content, e);
|
UnparseableStanza message = new UnparseableStanza(content, e);
|
||||||
|
@ -1295,7 +1303,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
final IQ iq = (IQ) packet;
|
final IQ iq = (IQ) packet;
|
||||||
if (iq.isRequestIQ()) {
|
if (iq.isRequestIQ()) {
|
||||||
final IQ iqRequest = iq;
|
final IQ iqRequest = iq;
|
||||||
final String key = XmppStringUtils.generateKey(iq.getChildElementName(), iq.getChildElementNamespace());
|
final QName key = iqRequest.getChildElementQName();
|
||||||
IQRequestHandler iqRequestHandler;
|
IQRequestHandler iqRequestHandler;
|
||||||
final IQ.Type type = iq.getType();
|
final IQ.Type type = iq.getType();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -1614,9 +1622,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
streamFeatures.clear();
|
streamFeatures.clear();
|
||||||
final int initialDepth = parser.getDepth();
|
final int initialDepth = parser.getDepth();
|
||||||
while (true) {
|
while (true) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
|
|
||||||
if (eventType == XmlPullParser.START_TAG && parser.getDepth() == initialDepth + 1) {
|
if (eventType == XmlPullParser.Event.START_ELEMENT && parser.getDepth() == initialDepth + 1) {
|
||||||
FullyQualifiedElement streamFeature = null;
|
FullyQualifiedElement streamFeature = null;
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
String namespace = parser.getNamespace();
|
String namespace = parser.getNamespace();
|
||||||
|
@ -1647,7 +1655,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
addStreamFeature(streamFeature);
|
addStreamFeature(streamFeature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (eventType == XmlPullParser.END_TAG && parser.getDepth() == initialDepth) {
|
else if (eventType == XmlPullParser.Event.END_ELEMENT && parser.getDepth() == initialDepth) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1686,7 +1694,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <F extends FullyQualifiedElement> F getFeature(String element, String namespace) {
|
public <F extends FullyQualifiedElement> F getFeature(String element, String namespace) {
|
||||||
return (F) streamFeatures.get(XmppStringUtils.generateKey(element, namespace));
|
QName qname = new QName(namespace, element);
|
||||||
|
return (F) streamFeatures.get(qname);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1695,7 +1704,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addStreamFeature(FullyQualifiedElement feature) {
|
protected void addStreamFeature(FullyQualifiedElement feature) {
|
||||||
String key = XmppStringUtils.generateKey(feature.getElementName(), feature.getNamespace());
|
QName key = feature.getQName();
|
||||||
streamFeatures.put(key, feature);
|
streamFeatures.put(key, feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1804,7 +1813,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IQRequestHandler registerIQRequestHandler(final IQRequestHandler iqRequestHandler) {
|
public IQRequestHandler registerIQRequestHandler(final IQRequestHandler iqRequestHandler) {
|
||||||
final String key = XmppStringUtils.generateKey(iqRequestHandler.getElement(), iqRequestHandler.getNamespace());
|
final QName key = iqRequestHandler.getQName();
|
||||||
switch (iqRequestHandler.getType()) {
|
switch (iqRequestHandler.getType()) {
|
||||||
case set:
|
case set:
|
||||||
synchronized (setIqRequestHandler) {
|
synchronized (setIqRequestHandler) {
|
||||||
|
@ -1827,7 +1836,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IQRequestHandler unregisterIQRequestHandler(String element, String namespace, IQ.Type type) {
|
public IQRequestHandler unregisterIQRequestHandler(String element, String namespace, IQ.Type type) {
|
||||||
final String key = XmppStringUtils.generateKey(element, namespace);
|
final QName key = new QName(namespace, element);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case set:
|
case set:
|
||||||
synchronized (setIqRequestHandler) {
|
synchronized (setIqRequestHandler) {
|
||||||
|
@ -2044,13 +2053,13 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
try {
|
try {
|
||||||
Constructor<?> c = Class.forName("sun.security.pkcs11.SunPKCS11").getConstructor(InputStream.class);
|
Constructor<?> c = Class.forName("sun.security.pkcs11.SunPKCS11").getConstructor(InputStream.class);
|
||||||
String pkcs11Config = "name = SmartCard\nlibrary = " + config.getPKCS11Library();
|
String pkcs11Config = "name = SmartCard\nlibrary = " + config.getPKCS11Library();
|
||||||
ByteArrayInputStream config = new ByteArrayInputStream(pkcs11Config.getBytes(StringUtils.UTF8));
|
ByteArrayInputStream config = new ByteArrayInputStream(pkcs11Config.getBytes(StandardCharsets.UTF_8));
|
||||||
Provider p = (Provider) c.newInstance(config);
|
Provider p = (Provider) c.newInstance(config);
|
||||||
Security.addProvider(p);
|
Security.addProvider(p);
|
||||||
ks = KeyStore.getInstance("PKCS11",p);
|
ks = KeyStore.getInstance("PKCS11", p);
|
||||||
pcb = new PasswordCallback("PKCS11 Password: ",false);
|
pcb = new PasswordCallback("PKCS11 Password: ", false);
|
||||||
callbackHandler.handle(new Callback[] {pcb});
|
callbackHandler.handle(new Callback[] {pcb});
|
||||||
ks.load(null,pcb.getPassword());
|
ks.load(null, pcb.getPassword());
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
LOGGER.log(Level.WARNING, "Exception", e);
|
LOGGER.log(Level.WARNING, "Exception", e);
|
||||||
|
@ -2058,8 +2067,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ("Apple".equals(keyStoreType)) {
|
else if ("Apple".equals(keyStoreType)) {
|
||||||
ks = KeyStore.getInstance("KeychainStore","Apple");
|
ks = KeyStore.getInstance("KeychainStore", "Apple");
|
||||||
ks.load(null,null);
|
ks.load(null, null);
|
||||||
// pcb = new PasswordCallback("Apple Keychain",false);
|
// pcb = new PasswordCallback("Apple Keychain",false);
|
||||||
// pcb.setPassword(null);
|
// pcb.setPassword(null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.net.SocketFactory;
|
import javax.net.SocketFactory;
|
||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
|
@ -46,6 +48,7 @@ import org.jxmpp.jid.impl.JidCreate;
|
||||||
import org.jxmpp.jid.parts.Resourcepart;
|
import org.jxmpp.jid.parts.Resourcepart;
|
||||||
import org.jxmpp.stringprep.XmppStringprepException;
|
import org.jxmpp.stringprep.XmppStringprepException;
|
||||||
import org.minidns.dnsname.DnsName;
|
import org.minidns.dnsname.DnsName;
|
||||||
|
import org.minidns.dnsname.InvalidDnsNameException;
|
||||||
import org.minidns.util.InetAddressUtil;
|
import org.minidns.util.InetAddressUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,6 +84,8 @@ public abstract class ConnectionConfiguration {
|
||||||
SmackConfiguration.getVersion();
|
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
|
* 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
|
* of the server. However, there are some servers like google where host would be
|
||||||
|
@ -88,6 +93,8 @@ public abstract class ConnectionConfiguration {
|
||||||
*/
|
*/
|
||||||
protected final DomainBareJid xmppServiceDomain;
|
protected final DomainBareJid xmppServiceDomain;
|
||||||
|
|
||||||
|
protected final DnsName xmppServiceDomainDnsName;
|
||||||
|
|
||||||
protected final InetAddress hostAddress;
|
protected final InetAddress hostAddress;
|
||||||
protected final DnsName host;
|
protected final DnsName host;
|
||||||
protected final int port;
|
protected final int port;
|
||||||
|
@ -149,7 +156,7 @@ public abstract class ConnectionConfiguration {
|
||||||
|
|
||||||
private final boolean compressionEnabled;
|
private final boolean compressionEnabled;
|
||||||
|
|
||||||
protected ConnectionConfiguration(Builder<?,?> builder) {
|
protected ConnectionConfiguration(Builder<?, ?> builder) {
|
||||||
authzid = builder.authzid;
|
authzid = builder.authzid;
|
||||||
username = builder.username;
|
username = builder.username;
|
||||||
password = builder.password;
|
password = builder.password;
|
||||||
|
@ -162,6 +169,19 @@ public abstract class ConnectionConfiguration {
|
||||||
if (xmppServiceDomain == null) {
|
if (xmppServiceDomain == null) {
|
||||||
throw new IllegalArgumentException("Must define the XMPP domain");
|
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;
|
hostAddress = builder.hostAddress;
|
||||||
host = builder.host;
|
host = builder.host;
|
||||||
port = builder.port;
|
port = builder.port;
|
||||||
|
@ -225,6 +245,17 @@ public abstract class ConnectionConfiguration {
|
||||||
return xmppServiceDomain;
|
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,
|
* Returns the TLS security mode used when making the connection. By default,
|
||||||
* the mode is {@link SecurityMode#ifpossible}.
|
* the mode is {@link SecurityMode#ifpossible}.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2018 Florian Schmaus
|
* Copyright 2018-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||||
import org.jivesoftware.smack.XMPPException.FailedNonzaException;
|
import org.jivesoftware.smack.XMPPException.FailedNonzaException;
|
||||||
import org.jivesoftware.smack.packet.Nonza;
|
import org.jivesoftware.smack.packet.Nonza;
|
||||||
import org.jivesoftware.smack.util.XmppElementUtil;
|
import org.jivesoftware.smack.util.XmppElementUtil;
|
||||||
|
|
||||||
import org.jxmpp.util.XmppStringUtils;
|
|
||||||
|
|
||||||
public class NonzaCallback {
|
public class NonzaCallback {
|
||||||
|
|
||||||
protected final AbstractXMPPConnection connection;
|
protected final AbstractXMPPConnection connection;
|
||||||
protected final Map<String, GenericElementListener<? extends Nonza>> filterAndListeners;
|
protected final Map<QName, GenericElementListener<? extends Nonza>> filterAndListeners;
|
||||||
|
|
||||||
private NonzaCallback(Builder builder) {
|
private NonzaCallback(Builder builder) {
|
||||||
this.connection = builder.connection;
|
this.connection = builder.connection;
|
||||||
|
@ -39,7 +39,7 @@ public class NonzaCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
void onNonzaReceived(Nonza nonza) {
|
void onNonzaReceived(Nonza nonza) {
|
||||||
String key = XmppStringUtils.generateKey(nonza.getElementName(), nonza.getNamespace());
|
QName key = nonza.getQName();
|
||||||
GenericElementListener<? extends Nonza> nonzaListener = filterAndListeners.get(key);
|
GenericElementListener<? extends Nonza> nonzaListener = filterAndListeners.get(key);
|
||||||
|
|
||||||
nonzaListener.processElement(nonza);
|
nonzaListener.processElement(nonza);
|
||||||
|
@ -47,8 +47,8 @@ public class NonzaCallback {
|
||||||
|
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
synchronized (connection.nonzaCallbacks) {
|
synchronized (connection.nonzaCallbacks) {
|
||||||
for (Map.Entry<String, GenericElementListener<? extends Nonza>> entry : filterAndListeners.entrySet()) {
|
for (Map.Entry<QName, GenericElementListener<? extends Nonza>> entry : filterAndListeners.entrySet()) {
|
||||||
String filterKey = entry.getKey();
|
QName filterKey = entry.getKey();
|
||||||
NonzaCallback installedCallback = connection.nonzaCallbacks.get(filterKey);
|
NonzaCallback installedCallback = connection.nonzaCallbacks.get(filterKey);
|
||||||
if (equals(installedCallback)) {
|
if (equals(installedCallback)) {
|
||||||
connection.nonzaCallbacks.remove(filterKey);
|
connection.nonzaCallbacks.remove(filterKey);
|
||||||
|
@ -63,7 +63,7 @@ public class NonzaCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (connection.nonzaCallbacks) {
|
synchronized (connection.nonzaCallbacks) {
|
||||||
for (String key : filterAndListeners.keySet()) {
|
for (QName key : filterAndListeners.keySet()) {
|
||||||
connection.nonzaCallbacks.put(key, this);
|
connection.nonzaCallbacks.put(key, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,8 +78,8 @@ public class NonzaCallback {
|
||||||
Builder builder) {
|
Builder builder) {
|
||||||
super(builder);
|
super(builder);
|
||||||
|
|
||||||
final String successNonzaKey = XmppElementUtil.getKeyFor(successNonzaClass);
|
final QName successNonzaKey = XmppElementUtil.getQNameFor(successNonzaClass);
|
||||||
final String failedNonzaKey = XmppElementUtil.getKeyFor(failedNonzaClass);
|
final QName failedNonzaKey = XmppElementUtil.getQNameFor(failedNonzaClass);
|
||||||
|
|
||||||
final GenericElementListener<SN> successListener = new GenericElementListener<SN>(successNonzaClass) {
|
final GenericElementListener<SN> successListener = new GenericElementListener<SN>(successNonzaClass) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -139,14 +139,14 @@ public class NonzaCallback {
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
private final AbstractXMPPConnection connection;
|
private final AbstractXMPPConnection connection;
|
||||||
|
|
||||||
private Map<String, GenericElementListener<? extends Nonza>> filterAndListeners = new HashMap<>();
|
private Map<QName, GenericElementListener<? extends Nonza>> filterAndListeners = new HashMap<>();
|
||||||
|
|
||||||
Builder(AbstractXMPPConnection connection) {
|
Builder(AbstractXMPPConnection connection) {
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <N extends Nonza> Builder listenFor(Class<? extends N> nonza, GenericElementListener<? extends N> nonzaListener) {
|
public <N extends Nonza> Builder listenFor(Class<? extends N> nonza, GenericElementListener<? extends N> nonzaListener) {
|
||||||
String key = XmppElementUtil.getKeyFor(nonza);
|
QName key = XmppElementUtil.getQNameFor(nonza);
|
||||||
filterAndListeners.put(key, nonzaListener);
|
filterAndListeners.put(key, nonzaListener);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import javax.net.ssl.HostnameVerifier;
|
||||||
import org.jivesoftware.smack.compression.XMPPInputOutputStream;
|
import org.jivesoftware.smack.compression.XMPPInputOutputStream;
|
||||||
import org.jivesoftware.smack.debugger.ReflectionDebuggerFactory;
|
import org.jivesoftware.smack.debugger.ReflectionDebuggerFactory;
|
||||||
import org.jivesoftware.smack.debugger.SmackDebuggerFactory;
|
import org.jivesoftware.smack.debugger.SmackDebuggerFactory;
|
||||||
|
import org.jivesoftware.smack.parsing.ExceptionThrowingCallback;
|
||||||
import org.jivesoftware.smack.parsing.ExceptionThrowingCallbackWithHint;
|
import org.jivesoftware.smack.parsing.ExceptionThrowingCallbackWithHint;
|
||||||
import org.jivesoftware.smack.parsing.ParsingExceptionCallback;
|
import org.jivesoftware.smack.parsing.ParsingExceptionCallback;
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.Objects;
|
||||||
|
@ -380,4 +381,5 @@ public final class SmackConfiguration {
|
||||||
public static int getDefaultConcurrencyLevelLimit() {
|
public static int getDefaultConcurrencyLevelLimit() {
|
||||||
return defaultConcurrencyLevelLimit;
|
return defaultConcurrencyLevelLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.jivesoftware.smack;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -44,10 +45,9 @@ import org.jivesoftware.smack.sasl.core.SCRAMSHA1Mechanism;
|
||||||
import org.jivesoftware.smack.sasl.core.ScramSha1PlusMechanism;
|
import org.jivesoftware.smack.sasl.core.ScramSha1PlusMechanism;
|
||||||
import org.jivesoftware.smack.util.CloseableUtil;
|
import org.jivesoftware.smack.util.CloseableUtil;
|
||||||
import org.jivesoftware.smack.util.FileUtils;
|
import org.jivesoftware.smack.util.FileUtils;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserFactory;
|
|
||||||
|
|
||||||
|
|
||||||
public final class SmackInitialization {
|
public final class SmackInitialization {
|
||||||
|
@ -69,7 +69,7 @@ public final class SmackInitialization {
|
||||||
String smackVersion;
|
String smackVersion;
|
||||||
BufferedReader reader = null;
|
BufferedReader reader = null;
|
||||||
try {
|
try {
|
||||||
reader = new BufferedReader(new InputStreamReader(FileUtils.getStreamForClasspathFile("org.jivesoftware.smack/version", null), StringUtils.UTF8));
|
reader = new BufferedReader(new InputStreamReader(FileUtils.getStreamForClasspathFile("org.jivesoftware.smack/version", null), StandardCharsets.UTF_8));
|
||||||
smackVersion = reader.readLine();
|
smackVersion = reader.readLine();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.log(Level.SEVERE, "Could not determine Smack version", e);
|
LOGGER.log(Level.SEVERE, "Could not determine Smack version", e);
|
||||||
|
@ -141,12 +141,10 @@ public final class SmackInitialization {
|
||||||
|
|
||||||
public static void processConfigFile(InputStream cfgFileStream,
|
public static void processConfigFile(InputStream cfgFileStream,
|
||||||
Collection<Exception> exceptions, ClassLoader classLoader) throws Exception {
|
Collection<Exception> exceptions, ClassLoader classLoader) throws Exception {
|
||||||
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
|
XmlPullParser parser = PacketParserUtils.getParserFor(cfgFileStream);
|
||||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
XmlPullParser.Event eventType = parser.getEventType();
|
||||||
parser.setInput(cfgFileStream, "UTF-8");
|
|
||||||
int eventType = parser.getEventType();
|
|
||||||
do {
|
do {
|
||||||
if (eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.Event.START_ELEMENT) {
|
||||||
if (parser.getName().equals("startupClasses")) {
|
if (parser.getName().equals("startupClasses")) {
|
||||||
parseClassesToLoad(parser, false, exceptions, classLoader);
|
parseClassesToLoad(parser, false, exceptions, classLoader);
|
||||||
}
|
}
|
||||||
|
@ -156,7 +154,7 @@ public final class SmackInitialization {
|
||||||
}
|
}
|
||||||
eventType = parser.next();
|
eventType = parser.next();
|
||||||
}
|
}
|
||||||
while (eventType != XmlPullParser.END_DOCUMENT);
|
while (eventType != XmlPullParser.Event.END_DOCUMENT);
|
||||||
CloseableUtil.maybeClose(cfgFileStream, LOGGER);
|
CloseableUtil.maybeClose(cfgFileStream, LOGGER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,12 +162,10 @@ public final class SmackInitialization {
|
||||||
Collection<Exception> exceptions, ClassLoader classLoader)
|
Collection<Exception> exceptions, ClassLoader classLoader)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
final String startName = parser.getName();
|
final String startName = parser.getName();
|
||||||
int eventType;
|
XmlPullParser.Event eventType;
|
||||||
String name;
|
|
||||||
outerloop: do {
|
outerloop: do {
|
||||||
eventType = parser.next();
|
eventType = parser.next();
|
||||||
name = parser.getName();
|
if (eventType == XmlPullParser.Event.START_ELEMENT && "className".equals(parser.getName())) {
|
||||||
if (eventType == XmlPullParser.START_TAG && "className".equals(name)) {
|
|
||||||
String classToLoad = parser.nextText();
|
String classToLoad = parser.nextText();
|
||||||
if (SmackConfiguration.isDisabledSmackClass(classToLoad)) {
|
if (SmackConfiguration.isDisabledSmackClass(classToLoad)) {
|
||||||
continue outerloop;
|
continue outerloop;
|
||||||
|
@ -188,7 +184,7 @@ public final class SmackInitialization {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!(eventType == XmlPullParser.END_TAG && startName.equals(name)));
|
while (!(eventType == XmlPullParser.Event.END_ELEMENT && startName.equals(parser.getName())));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadSmackClass(String className, boolean optional, ClassLoader classLoader) throws Exception {
|
private static void loadSmackClass(String className, boolean optional, ClassLoader classLoader) throws Exception {
|
||||||
|
|
|
@ -149,9 +149,8 @@ public class SmackReactor {
|
||||||
long releaseTimeEpoch = System.currentTimeMillis() + unit.toMillis(delay);
|
long releaseTimeEpoch = System.currentTimeMillis() + unit.toMillis(delay);
|
||||||
Date releaseTimeDate = new Date(releaseTimeEpoch);
|
Date releaseTimeDate = new Date(releaseTimeEpoch);
|
||||||
ScheduledAction scheduledAction = new ScheduledAction(runnable, releaseTimeDate, this);
|
ScheduledAction scheduledAction = new ScheduledAction(runnable, releaseTimeDate, this);
|
||||||
synchronized (scheduledActions) {
|
scheduledActions.add(scheduledAction);
|
||||||
scheduledActions.add(scheduledAction);
|
selector.wakeup();
|
||||||
}
|
|
||||||
return scheduledAction;
|
return scheduledAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +208,8 @@ public class SmackReactor {
|
||||||
|
|
||||||
long selectWait;
|
long selectWait;
|
||||||
if (nextScheduledAction == null) {
|
if (nextScheduledAction == null) {
|
||||||
// There is no next scheduled action, wait indefinitely in select().
|
// There is no next scheduled action, wait indefinitely in select() or until another thread invokes
|
||||||
|
// selector.wakeup().
|
||||||
selectWait = 0;
|
selectWait = 0;
|
||||||
} else {
|
} else {
|
||||||
selectWait = nextScheduledAction.getTimeToDueMillis();
|
selectWait = nextScheduledAction.getTimeToDueMillis();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2003-2007 Jive Software, 2016-2018 Florian Schmaus.
|
* Copyright 2003-2007 Jive Software, 2016-2019 Florian Schmaus.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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)
|
* @see XMPPConnection#createStanzaCollector(StanzaFilter)
|
||||||
* @author Matt Tucker
|
* @author Matt Tucker
|
||||||
*/
|
*/
|
||||||
public class StanzaCollector implements AutoCloseable {
|
public final class StanzaCollector implements AutoCloseable {
|
||||||
|
|
||||||
private final StanzaFilter packetFilter;
|
private final StanzaFilter packetFilter;
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ public class StanzaCollector implements AutoCloseable {
|
||||||
* @param connection the connection the collector is tied to.
|
* @param connection the connection the collector is tied to.
|
||||||
* @param configuration the configuration used to construct this collector
|
* @param configuration the configuration used to construct this collector
|
||||||
*/
|
*/
|
||||||
protected StanzaCollector(XMPPConnection connection, Configuration configuration) {
|
StanzaCollector(XMPPConnection connection, Configuration configuration) {
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
this.packetFilter = configuration.packetFilter;
|
this.packetFilter = configuration.packetFilter;
|
||||||
this.resultQueue = new ArrayDeque<>(configuration.size);
|
this.resultQueue = new ArrayDeque<>(configuration.size);
|
||||||
|
@ -98,18 +98,6 @@ public 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
|
* Returns the stanza filter associated with this stanza collector. The stanza
|
||||||
* filter is used to determine what stanzas are queued as results.
|
* filter is used to determine what stanzas are queued as results.
|
||||||
|
@ -329,6 +317,21 @@ public class StanzaCollector implements AutoCloseable {
|
||||||
return resultQueue.size();
|
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) {
|
synchronized void notifyConnectionError(Exception exception) {
|
||||||
connectionException = exception;
|
connectionException = exception;
|
||||||
notifyAll();
|
notifyAll();
|
||||||
|
@ -380,19 +383,6 @@ public class StanzaCollector implements AutoCloseable {
|
||||||
private Configuration() {
|
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
|
* Set the stanza filter used by this collector. If <code>null</code>, then all stanzas will
|
||||||
* get collected by this collector.
|
* get collected by this collector.
|
||||||
|
|
|
@ -20,7 +20,7 @@ import org.jivesoftware.smack.compress.packet.Compressed;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
import org.jivesoftware.smack.provider.NonzaProvider;
|
import org.jivesoftware.smack.provider.NonzaProvider;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
|
||||||
public final class CompressedProvider extends NonzaProvider<Compressed> {
|
public final class CompressedProvider extends NonzaProvider<Compressed> {
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,8 @@ import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||||
import org.jivesoftware.smack.provider.NonzaProvider;
|
import org.jivesoftware.smack.provider.NonzaProvider;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
public final class FailureProvider extends NonzaProvider<Failure> {
|
public final class FailureProvider extends NonzaProvider<Failure> {
|
||||||
|
|
||||||
|
@ -46,9 +46,9 @@ public final class FailureProvider extends NonzaProvider<Failure> {
|
||||||
XmlEnvironment failureXmlEnvironment = XmlEnvironment.from(parser, xmlEnvironment);
|
XmlEnvironment failureXmlEnvironment = XmlEnvironment.from(parser, xmlEnvironment);
|
||||||
|
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
String namespace = parser.getNamespace();
|
String namespace = parser.getNamespace();
|
||||||
switch (namespace) {
|
switch (namespace) {
|
||||||
|
@ -72,11 +72,12 @@ public final class FailureProvider extends NonzaProvider<Failure> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
if (parser.getDepth() == initialDepth) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default: // fall out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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;
|
|
@ -57,10 +57,10 @@ import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Challenge;
|
||||||
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Success;
|
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.Success;
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.Objects;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
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.jxmpp.jid.parts.Resourcepart;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
public abstract class AbstractXmppStateMachineConnection extends AbstractXMPPConnection {
|
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.
|
// Skip the enclosing stream open what is guaranteed to be there.
|
||||||
parser.next();
|
parser.next();
|
||||||
|
|
||||||
int event = parser.getEventType();
|
XmlPullParser.Event event = parser.getEventType();
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
final String name = parser.getName();
|
final String name = parser.getName();
|
||||||
// Note that we don't handle "stream" here as it's done in the splitter.
|
// Note that we don't handle "stream" here as it's done in the splitter.
|
||||||
switch (name) {
|
switch (name) {
|
||||||
|
@ -353,8 +353,9 @@ public abstract class AbstractXmppStateMachineConnection extends AbstractXMPPCon
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_DOCUMENT:
|
case END_DOCUMENT:
|
||||||
break outerloop;
|
break outerloop;
|
||||||
|
default: // fall out
|
||||||
}
|
}
|
||||||
event = parser.next();
|
event = parser.next();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2015 Florian Schmaus
|
* Copyright 2015-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,6 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.iqrequest;
|
package org.jivesoftware.smack.iqrequest;
|
||||||
|
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.IQ;
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,4 +52,8 @@ public interface IQRequestHandler {
|
||||||
String getElement();
|
String getElement();
|
||||||
|
|
||||||
String getNamespace();
|
String getNamespace();
|
||||||
|
|
||||||
|
default QName getQName() {
|
||||||
|
return new QName(getNamespace(), getElement());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class DefaultExtensionElement implements ExtensionElement {
|
||||||
|
|
||||||
private String elementName;
|
private String elementName;
|
||||||
private String namespace;
|
private String namespace;
|
||||||
private Map<String,String> map;
|
private Map<String, String> map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new generic stanza extension.
|
* Creates a new generic stanza extension.
|
||||||
|
@ -107,7 +107,7 @@ public class DefaultExtensionElement implements ExtensionElement {
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
return Collections.emptySet();
|
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) {
|
public synchronized void setValue(String name, String value) {
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
map = new HashMap<String,String>();
|
map = new HashMap<String, String>();
|
||||||
}
|
}
|
||||||
map.put(name, value);
|
map.put(name, value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2018 Florian Schmaus
|
* Copyright 2018-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,6 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.packet;
|
package org.jivesoftware.smack.packet;
|
||||||
|
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
public interface FullyQualifiedElement extends NamedElement {
|
public interface FullyQualifiedElement extends NamedElement {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,4 +27,9 @@ public interface FullyQualifiedElement extends NamedElement {
|
||||||
*/
|
*/
|
||||||
String getNamespace();
|
String getNamespace();
|
||||||
|
|
||||||
|
default QName getQName() {
|
||||||
|
String namespaceURI = getNamespace();
|
||||||
|
String localPart = getElementName();
|
||||||
|
return new QName(namespaceURI, localPart);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ package org.jivesoftware.smack.packet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.Objects;
|
||||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
|
|
||||||
|
@ -46,6 +48,7 @@ public abstract class IQ extends Stanza {
|
||||||
public static final String IQ_ELEMENT = "iq";
|
public static final String IQ_ELEMENT = "iq";
|
||||||
public static final String QUERY_ELEMENT = "query";
|
public static final String QUERY_ELEMENT = "query";
|
||||||
|
|
||||||
|
private final QName childElementQName;
|
||||||
private final String childElementName;
|
private final String childElementName;
|
||||||
private final String childElementNamespace;
|
private final String childElementNamespace;
|
||||||
|
|
||||||
|
@ -56,6 +59,7 @@ public abstract class IQ extends Stanza {
|
||||||
type = iq.getType();
|
type = iq.getType();
|
||||||
this.childElementName = iq.childElementName;
|
this.childElementName = iq.childElementName;
|
||||||
this.childElementNamespace = iq.childElementNamespace;
|
this.childElementNamespace = iq.childElementNamespace;
|
||||||
|
this.childElementQName = iq.childElementQName;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IQ(String childElementName) {
|
protected IQ(String childElementName) {
|
||||||
|
@ -65,6 +69,11 @@ public abstract class IQ extends Stanza {
|
||||||
protected IQ(String childElementName, String childElementNamespace) {
|
protected IQ(String childElementName, String childElementNamespace) {
|
||||||
this.childElementName = childElementName;
|
this.childElementName = childElementName;
|
||||||
this.childElementNamespace = childElementNamespace;
|
this.childElementNamespace = childElementNamespace;
|
||||||
|
if (childElementName == null) {
|
||||||
|
childElementQName = null;
|
||||||
|
} else {
|
||||||
|
childElementQName = new QName(childElementNamespace, childElementName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -115,6 +124,10 @@ public abstract class IQ extends Stanza {
|
||||||
return !isRequestIQ();
|
return !isRequestIQ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final QName getChildElementQName() {
|
||||||
|
return childElementQName;
|
||||||
|
}
|
||||||
|
|
||||||
public final String getChildElementName() {
|
public final String getChildElementName() {
|
||||||
return childElementName;
|
return childElementName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,8 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
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.Objects;
|
||||||
import org.jivesoftware.smack.util.TypedCloneable;
|
import org.jivesoftware.smack.util.TypedCloneable;
|
||||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
|
@ -561,32 +563,22 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
|
||||||
return subject;
|
return subject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final HashCode.Cache hashCodeCache = new HashCode.Cache();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
return hashCodeCache.getHashCode(c ->
|
||||||
int result = 1;
|
c.append(language)
|
||||||
if (language != null) {
|
.append(subject)
|
||||||
result = prime * result + this.language.hashCode();
|
);
|
||||||
}
|
|
||||||
result = prime * result + this.subject.hashCode();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) {
|
return EqualsUtil.equals(this, obj, (e, o) ->
|
||||||
return true;
|
e.append(language, o.language)
|
||||||
}
|
.append(subject, o.subject)
|
||||||
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
|
@Override
|
||||||
|
@ -670,31 +662,22 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final HashCode.Cache hashCodeCache = new HashCode.Cache();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
return hashCodeCache.getHashCode(c ->
|
||||||
int result = 1;
|
c.append(language)
|
||||||
if (language != null) {
|
.append(message)
|
||||||
result = prime * result + this.language.hashCode();
|
);
|
||||||
}
|
|
||||||
result = prime * result + this.message.hashCode();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) {
|
return EqualsUtil.equals(this, obj, (e, o) ->
|
||||||
return true;
|
e.append(language, o.language)
|
||||||
}
|
.append(message, o.message)
|
||||||
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
|
@Override
|
||||||
|
|
|
@ -150,7 +150,7 @@ public interface Packet extends TopLevelStreamElement {
|
||||||
/**
|
/**
|
||||||
* Returns the first extension of this stanza that has the given namespace.
|
* Returns the first extension of this stanza that has the given namespace.
|
||||||
* <p>
|
* <p>
|
||||||
* When possible, use {@link #getExtension(String,String)} instead.
|
* When possible, use {@link #getExtension(String, String)} instead.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param namespace the namespace of the extension that is desired.
|
* @param namespace the namespace of the extension that is desired.
|
||||||
|
|
|
@ -68,12 +68,12 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
|
||||||
private String status = null;
|
private String status = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The priority of the presence. The magic value {@link Integer#MIN_VALUE} is used to indicate that the original
|
* The priority of the presence. It is <code>null</code> to indicate that the original
|
||||||
* presence stanza did not had an explicit priority set. In which case the priority defaults to 0.
|
* 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>
|
* @see <a href="https://tools.ietf.org/html/rfc6121#section-4.7.2.3">RFC 6121 § 4.7.2.3.</a>
|
||||||
*/
|
*/
|
||||||
private int priority = Integer.MIN_VALUE;
|
private Byte priority;
|
||||||
|
|
||||||
private Mode mode = null;
|
private Mode mode = null;
|
||||||
|
|
||||||
|
@ -203,13 +203,13 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the priority of the presence, or Integer.MIN_VALUE if no priority has been set.
|
* Returns the priority of the presence.
|
||||||
*
|
*
|
||||||
* @return the priority.
|
* @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>
|
* @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() {
|
public int getPriority() {
|
||||||
if (priority == Integer.MIN_VALUE) {
|
if (priority == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return priority;
|
return priority;
|
||||||
|
@ -227,6 +227,10 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
|
||||||
throw new IllegalArgumentException("Priority value " + priority +
|
throw new IllegalArgumentException("Priority value " + priority +
|
||||||
" is not valid. Valid range is -128 through 127.");
|
" is not valid. Valid range is -128 through 127.");
|
||||||
}
|
}
|
||||||
|
setPriority((byte) priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPriority(byte priority) {
|
||||||
this.priority = priority;
|
this.priority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +268,7 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
|
||||||
if (!StringUtils.isNullOrEmpty(status)) {
|
if (!StringUtils.isNullOrEmpty(status)) {
|
||||||
sb.append("status=").append(status).append(',');
|
sb.append("status=").append(status).append(',');
|
||||||
}
|
}
|
||||||
if (priority != Integer.MIN_VALUE) {
|
if (priority != null) {
|
||||||
sb.append("prio=").append(priority).append(',');
|
sb.append("prio=").append(priority).append(',');
|
||||||
}
|
}
|
||||||
sb.append(']');
|
sb.append(']');
|
||||||
|
@ -282,9 +286,7 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
|
||||||
buf.rightAngleBracket();
|
buf.rightAngleBracket();
|
||||||
|
|
||||||
buf.optElement("status", status);
|
buf.optElement("status", status);
|
||||||
if (priority != Integer.MIN_VALUE) {
|
buf.optElement("priority", priority);
|
||||||
buf.element("priority", Integer.toString(priority));
|
|
||||||
}
|
|
||||||
if (mode != null && mode != Mode.available) {
|
if (mode != null && mode != Mode.available) {
|
||||||
buf.element("show", mode);
|
buf.element("show", mode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2015 Florian Schmaus.
|
* Copyright 2015-2019 Florian Schmaus.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.jivesoftware.smack.util.MultiMap;
|
import org.jivesoftware.smack.util.MultiMap;
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.Objects;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
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
|
* An {@link ExtensionElement} modeling the often required and used XML features when using XMPP. It
|
||||||
* is therefore suitable for most use cases. Use
|
* is therefore suitable for most use cases. Use
|
||||||
|
@ -47,7 +47,7 @@ public final class StandardExtensionElement implements ExtensionElement {
|
||||||
private final String namespace;
|
private final String namespace;
|
||||||
private final Map<String, String> attributes;
|
private final Map<String, String> attributes;
|
||||||
private final String text;
|
private final String text;
|
||||||
private final MultiMap<String, StandardExtensionElement> elements;
|
private final MultiMap<QName, StandardExtensionElement> elements;
|
||||||
|
|
||||||
private XmlStringBuilder xmlCache;
|
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,
|
private StandardExtensionElement(String name, String namespace, Map<String, String> attributes, String text,
|
||||||
MultiMap<String, StandardExtensionElement> elements) {
|
MultiMap<QName, StandardExtensionElement> elements) {
|
||||||
this.name = StringUtils.requireNotNullNorEmpty(name, "Name must not be null nor empty");
|
this.name = StringUtils.requireNotNullNorEmpty(name, "Name must not be null nor empty");
|
||||||
this.namespace = StringUtils.requireNotNullNorEmpty(namespace, "Namespace must not be null nor empty");
|
this.namespace = StringUtils.requireNotNullNorEmpty(namespace, "Namespace must not be null nor empty");
|
||||||
if (attributes == null) {
|
if (attributes == null) {
|
||||||
|
@ -100,7 +100,7 @@ public final class StandardExtensionElement implements ExtensionElement {
|
||||||
if (elements == null) {
|
if (elements == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String key = XmppStringUtils.generateKey(element, namespace);
|
QName key = new QName(namespace, element);
|
||||||
return elements.getFirst(key);
|
return elements.getFirst(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ public final class StandardExtensionElement implements ExtensionElement {
|
||||||
if (elements == null) {
|
if (elements == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String key = XmppStringUtils.generateKey(element, namespace);
|
QName key = new QName(namespace, element);
|
||||||
return elements.getAll(key);
|
return elements.getAll(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ public final class StandardExtensionElement implements ExtensionElement {
|
||||||
xml.optEscape(text);
|
xml.optEscape(text);
|
||||||
|
|
||||||
if (elements != null) {
|
if (elements != null) {
|
||||||
for (Map.Entry<String, StandardExtensionElement> entry : elements.entrySet()) {
|
for (Map.Entry<QName, StandardExtensionElement> entry : elements.entrySet()) {
|
||||||
xml.append(entry.getValue().toXML(getNamespace()));
|
xml.append(entry.getValue().toXML(getNamespace()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ public final class StandardExtensionElement implements ExtensionElement {
|
||||||
|
|
||||||
private Map<String, String> attributes;
|
private Map<String, String> attributes;
|
||||||
private String text;
|
private String text;
|
||||||
private MultiMap<String, StandardExtensionElement> elements;
|
private MultiMap<QName, StandardExtensionElement> elements;
|
||||||
|
|
||||||
private Builder(String name, String namespace) {
|
private Builder(String name, String namespace) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -200,7 +200,8 @@ public final class StandardExtensionElement implements ExtensionElement {
|
||||||
if (elements == null) {
|
if (elements == null) {
|
||||||
elements = new MultiMap<>();
|
elements = new MultiMap<>();
|
||||||
}
|
}
|
||||||
String key = XmppStringUtils.generateKey(element.getElementName(), element.getNamespace());
|
|
||||||
|
QName key = element.getQName();
|
||||||
elements.put(key, element);
|
elements.put(key, element);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.id.StanzaIdUtil;
|
import org.jivesoftware.smack.packet.id.StanzaIdUtil;
|
||||||
import org.jivesoftware.smack.util.MultiMap;
|
import org.jivesoftware.smack.util.MultiMap;
|
||||||
import org.jivesoftware.smack.util.PacketUtil;
|
import org.jivesoftware.smack.util.PacketUtil;
|
||||||
|
@ -31,7 +33,6 @@ import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
import org.jxmpp.jid.Jid;
|
import org.jxmpp.jid.Jid;
|
||||||
import org.jxmpp.jid.impl.JidCreate;
|
import org.jxmpp.jid.impl.JidCreate;
|
||||||
import org.jxmpp.stringprep.XmppStringprepException;
|
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. < 4.1).
|
* Base class for XMPP Stanzas, which are called Stanza in older versions of Smack (i.e. < 4.1).
|
||||||
|
@ -56,7 +57,7 @@ public abstract class Stanza implements TopLevelStreamElement {
|
||||||
protected static final String DEFAULT_LANGUAGE =
|
protected static final String DEFAULT_LANGUAGE =
|
||||||
java.util.Locale.getDefault().getLanguage().toLowerCase(Locale.US);
|
java.util.Locale.getDefault().getLanguage().toLowerCase(Locale.US);
|
||||||
|
|
||||||
private final MultiMap<String, ExtensionElement> packetExtensions = new MultiMap<>();
|
private final MultiMap<QName, ExtensionElement> extensionElements = new MultiMap<>();
|
||||||
|
|
||||||
private String id = null;
|
private String id = null;
|
||||||
private Jid to;
|
private Jid to;
|
||||||
|
@ -306,9 +307,9 @@ public abstract class Stanza implements TopLevelStreamElement {
|
||||||
* @return a list of all extension elements of this stanza.
|
* @return a list of all extension elements of this stanza.
|
||||||
*/
|
*/
|
||||||
public List<ExtensionElement> getExtensions() {
|
public List<ExtensionElement> getExtensions() {
|
||||||
synchronized (packetExtensions) {
|
synchronized (extensionElements) {
|
||||||
// No need to create a new list, values() will already create a new one for us
|
// No need to create a new list, values() will already create a new one for us
|
||||||
return packetExtensions.values();
|
return extensionElements.values();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,14 +327,14 @@ public abstract class Stanza implements TopLevelStreamElement {
|
||||||
public List<ExtensionElement> getExtensions(String elementName, String namespace) {
|
public List<ExtensionElement> getExtensions(String elementName, String namespace) {
|
||||||
requireNotNullNorEmpty(elementName, "elementName must not be null nor empty");
|
requireNotNullNorEmpty(elementName, "elementName must not be null nor empty");
|
||||||
requireNotNullNorEmpty(namespace, "namespace must not be null nor empty");
|
requireNotNullNorEmpty(namespace, "namespace must not be null nor empty");
|
||||||
String key = XmppStringUtils.generateKey(elementName, namespace);
|
QName key = new QName(namespace, elementName);
|
||||||
return packetExtensions.getAll(key);
|
return extensionElements.getAll(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the first extension of this stanza that has the given namespace.
|
* Returns the first extension of this stanza that has the given namespace.
|
||||||
* <p>
|
* <p>
|
||||||
* When possible, use {@link #getExtension(String,String)} instead.
|
* When possible, use {@link #getExtension(String, String)} instead.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param namespace the namespace of the extension that is desired.
|
* @param namespace the namespace of the extension that is desired.
|
||||||
|
@ -359,10 +360,10 @@ public abstract class Stanza implements TopLevelStreamElement {
|
||||||
if (namespace == null) {
|
if (namespace == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String key = XmppStringUtils.generateKey(elementName, namespace);
|
QName key = new QName(namespace, elementName);
|
||||||
ExtensionElement packetExtension;
|
ExtensionElement packetExtension;
|
||||||
synchronized (packetExtensions) {
|
synchronized (extensionElements) {
|
||||||
packetExtension = packetExtensions.getFirst(key);
|
packetExtension = extensionElements.getFirst(key);
|
||||||
}
|
}
|
||||||
if (packetExtension == null) {
|
if (packetExtension == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -377,9 +378,9 @@ public abstract class Stanza implements TopLevelStreamElement {
|
||||||
*/
|
*/
|
||||||
public void addExtension(ExtensionElement extension) {
|
public void addExtension(ExtensionElement extension) {
|
||||||
if (extension == null) return;
|
if (extension == null) return;
|
||||||
String key = XmppStringUtils.generateKey(extension.getElementName(), extension.getNamespace());
|
QName key = extension.getQName();
|
||||||
synchronized (packetExtensions) {
|
synchronized (extensionElements) {
|
||||||
packetExtensions.put(key, extension);
|
extensionElements.put(key, extension);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,7 +394,7 @@ public abstract class Stanza implements TopLevelStreamElement {
|
||||||
*/
|
*/
|
||||||
public ExtensionElement overrideExtension(ExtensionElement extension) {
|
public ExtensionElement overrideExtension(ExtensionElement extension) {
|
||||||
if (extension == null) return null;
|
if (extension == null) return null;
|
||||||
synchronized (packetExtensions) {
|
synchronized (extensionElements) {
|
||||||
// Note that we need to use removeExtension(String, String) here. If would use
|
// 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
|
// removeExtension(ExtensionElement) then we would remove based on the equality of ExtensionElement, which
|
||||||
// is not what we want in this case.
|
// is not what we want in this case.
|
||||||
|
@ -429,9 +430,9 @@ public abstract class Stanza implements TopLevelStreamElement {
|
||||||
if (elementName == null) {
|
if (elementName == null) {
|
||||||
return hasExtension(namespace);
|
return hasExtension(namespace);
|
||||||
}
|
}
|
||||||
String key = XmppStringUtils.generateKey(elementName, namespace);
|
QName key = new QName(namespace, elementName);
|
||||||
synchronized (packetExtensions) {
|
synchronized (extensionElements) {
|
||||||
return packetExtensions.containsKey(key);
|
return extensionElements.containsKey(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,8 +443,8 @@ public abstract class Stanza implements TopLevelStreamElement {
|
||||||
* @return true if a stanza extension exists, false otherwise.
|
* @return true if a stanza extension exists, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean hasExtension(String namespace) {
|
public boolean hasExtension(String namespace) {
|
||||||
synchronized (packetExtensions) {
|
synchronized (extensionElements) {
|
||||||
for (ExtensionElement packetExtension : packetExtensions.values()) {
|
for (ExtensionElement packetExtension : extensionElements.values()) {
|
||||||
if (packetExtension.getNamespace().equals(namespace)) {
|
if (packetExtension.getNamespace().equals(namespace)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -460,9 +461,9 @@ public abstract class Stanza implements TopLevelStreamElement {
|
||||||
* @return the removed stanza extension or null.
|
* @return the removed stanza extension or null.
|
||||||
*/
|
*/
|
||||||
public ExtensionElement removeExtension(String elementName, String namespace) {
|
public ExtensionElement removeExtension(String elementName, String namespace) {
|
||||||
String key = XmppStringUtils.generateKey(elementName, namespace);
|
QName key = new QName(namespace, elementName);
|
||||||
synchronized (packetExtensions) {
|
synchronized (extensionElements) {
|
||||||
return packetExtensions.remove(key);
|
return extensionElements.remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,9 +474,9 @@ public abstract class Stanza implements TopLevelStreamElement {
|
||||||
* @return the removed stanza extension or null.
|
* @return the removed stanza extension or null.
|
||||||
*/
|
*/
|
||||||
public ExtensionElement removeExtension(ExtensionElement extension) {
|
public ExtensionElement removeExtension(ExtensionElement extension) {
|
||||||
String key = XmppStringUtils.generateKey(extension.getElementName(), extension.getNamespace());
|
QName key = extension.getQName();
|
||||||
synchronized (packetExtensions) {
|
synchronized (extensionElements) {
|
||||||
List<ExtensionElement> list = packetExtensions.getAll(key);
|
List<ExtensionElement> list = extensionElements.getAll(key);
|
||||||
boolean removed = list.remove(extension);
|
boolean removed = list.remove(extension);
|
||||||
if (removed) {
|
if (removed) {
|
||||||
return extension;
|
return extension;
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.jivesoftware.smack.packet;
|
||||||
import org.jivesoftware.smack.util.ParserUtils;
|
import org.jivesoftware.smack.util.ParserUtils;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
|
||||||
public class XmlEnvironment {
|
public class XmlEnvironment {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2015 Florian Schmaus.
|
* Copyright 2015-2019 Florian Schmaus.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.ParserUtils;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parser for {@link StandardExtensionElement}s.
|
* The parser for {@link StandardExtensionElement}s.
|
||||||
|
@ -47,7 +47,7 @@ public class StandardExtensionElementProvider extends ExtensionElementProvider<S
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
String namespace = parser.getNamespace();
|
String namespace = parser.getNamespace();
|
||||||
StandardExtensionElement.Builder builder = StandardExtensionElement.builder(name, namespace);
|
StandardExtensionElement.Builder builder = StandardExtensionElement.builder(name, namespace);
|
||||||
final int namespaceCount = parser.getNamespaceCount(initialDepth);
|
final int namespaceCount = parser.getNamespaceCount();
|
||||||
final int attributeCount = parser.getAttributeCount();
|
final int attributeCount = parser.getAttributeCount();
|
||||||
final Map<String, String> attributes = new LinkedHashMap<>(namespaceCount + attributeCount);
|
final Map<String, String> attributes = new LinkedHashMap<>(namespaceCount + attributeCount);
|
||||||
for (int i = 0; i < namespaceCount; i++) {
|
for (int i = 0; i < namespaceCount; i++) {
|
||||||
|
@ -77,19 +77,22 @@ public class StandardExtensionElementProvider extends ExtensionElementProvider<S
|
||||||
builder.addAttributes(attributes);
|
builder.addAttributes(attributes);
|
||||||
|
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int event = parser.next();
|
XmlPullParser.Event event = parser.next();
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
builder.addElement(parse(parser, parser.getDepth(), xmlEnvironment));
|
builder.addElement(parse(parser, parser.getDepth(), xmlEnvironment));
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.TEXT:
|
case TEXT_CHARACTERS:
|
||||||
builder.setText(parser.getText());
|
builder.setText(parser.getText());
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
if (initialDepth == parser.getDepth()) {
|
if (initialDepth == parser.getDepth()) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,12 @@ import java.io.IOException;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.Bind;
|
import org.jivesoftware.smack.packet.Bind;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
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.EntityFullJid;
|
||||||
import org.jxmpp.jid.impl.JidCreate;
|
import org.jxmpp.jid.impl.JidCreate;
|
||||||
import org.jxmpp.jid.parts.Resourcepart;
|
import org.jxmpp.jid.parts.Resourcepart;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
public class BindIQProvider extends IQProvider<Bind> {
|
public class BindIQProvider extends IQProvider<Bind> {
|
||||||
|
|
||||||
|
@ -34,9 +34,9 @@ public class BindIQProvider extends IQProvider<Bind> {
|
||||||
String name;
|
String name;
|
||||||
Bind bind = null;
|
Bind bind = null;
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
name = parser.getName();
|
name = parser.getName();
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "resource":
|
case "resource":
|
||||||
|
@ -49,11 +49,14 @@ public class BindIQProvider extends IQProvider<Bind> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
if (parser.getDepth() == initialDepth) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bind;
|
return bind;
|
||||||
|
|
|
@ -24,8 +24,8 @@ import org.jivesoftware.smack.packet.Message;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
import org.jivesoftware.smack.util.ParserUtils;
|
import org.jivesoftware.smack.util.ParserUtils;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
public class BodyElementProvider extends ExtensionElementProvider<Message.Body> {
|
public class BodyElementProvider extends ExtensionElementProvider<Message.Body> {
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,8 @@ import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
import org.jivesoftware.smack.parsing.SmackParsingException;
|
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -97,14 +97,14 @@ public abstract class EmbeddedExtensionProvider<PE extends ExtensionElement> ext
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ExtensionElement> extensions = new ArrayList<>();
|
List<ExtensionElement> extensions = new ArrayList<>();
|
||||||
int event;
|
XmlPullParser.Event event;
|
||||||
do {
|
do {
|
||||||
event = parser.next();
|
event = parser.next();
|
||||||
|
|
||||||
if (event == XmlPullParser.START_TAG)
|
if (event == XmlPullParser.Event.START_ELEMENT)
|
||||||
PacketParserUtils.addExtensionElement(extensions, parser, xmlEnvironment);
|
PacketParserUtils.addExtensionElement(extensions, parser, xmlEnvironment);
|
||||||
}
|
}
|
||||||
while (!(event == XmlPullParser.END_TAG && parser.getDepth() == initialDepth));
|
while (!(event == XmlPullParser.Event.END_ELEMENT && parser.getDepth() == initialDepth));
|
||||||
|
|
||||||
return createReturnExtension(name, namespace, attMap, extensions);
|
return createReturnExtension(name, namespace, attMap, extensions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,8 @@ import org.jivesoftware.smack.packet.IQ;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
import org.jivesoftware.smack.util.ParserUtils;
|
import org.jivesoftware.smack.util.ParserUtils;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
public class IntrospectionProvider{
|
public class IntrospectionProvider{
|
||||||
|
|
||||||
|
@ -81,9 +81,9 @@ public class IntrospectionProvider{
|
||||||
ParserUtils.assertAtStartTag(parser);
|
ParserUtils.assertAtStartTag(parser);
|
||||||
Object object = objectClass.getConstructor().newInstance();
|
Object object = objectClass.getConstructor().newInstance();
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
String stringValue = parser.nextText();
|
String stringValue = parser.nextText();
|
||||||
Class<?> propertyType = object.getClass().getMethod(
|
Class<?> propertyType = object.getClass().getMethod(
|
||||||
|
@ -97,11 +97,14 @@ public class IntrospectionProvider{
|
||||||
propertyType).invoke(object, value);
|
propertyType).invoke(object, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
if (parser.getDepth() == initialDepth) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ParserUtils.assertAtEndTag(parser);
|
ParserUtils.assertAtEndTag(parser);
|
||||||
|
|
|
@ -26,8 +26,8 @@ import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
import org.jivesoftware.smack.parsing.SmackParsingException;
|
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||||
import org.jivesoftware.smack.util.ParserUtils;
|
import org.jivesoftware.smack.util.ParserUtils;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Smack provider are the parsers used to deserialize raw XMPP into the according Java {@link Element}s.
|
* Smack provider are the parsers used to deserialize raw XMPP into the according Java {@link Element}s.
|
||||||
|
|
|
@ -26,9 +26,8 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||||
import org.jivesoftware.smack.packet.IQ;
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the {@link IQProvider} and {@link ExtensionElementProvider} information from a standard provider file in preparation
|
* Loads the {@link IQProvider} and {@link ExtensionElementProvider} information from a standard provider file in preparation
|
||||||
|
@ -54,12 +53,10 @@ public class ProviderFileLoader implements ProviderLoader {
|
||||||
public ProviderFileLoader(InputStream providerStream, ClassLoader classLoader) {
|
public ProviderFileLoader(InputStream providerStream, ClassLoader classLoader) {
|
||||||
// Load processing providers.
|
// Load processing providers.
|
||||||
try (InputStream is = providerStream) {
|
try (InputStream is = providerStream) {
|
||||||
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
|
XmlPullParser parser = PacketParserUtils.getParserFor(is);
|
||||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
XmlPullParser.Event eventType = parser.getEventType();
|
||||||
parser.setInput(is, "UTF-8");
|
|
||||||
int eventType = parser.getEventType();
|
|
||||||
do {
|
do {
|
||||||
if (eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.Event.START_ELEMENT) {
|
||||||
final String typeName = parser.getName();
|
final String typeName = parser.getName();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -134,7 +131,7 @@ public class ProviderFileLoader implements ProviderLoader {
|
||||||
}
|
}
|
||||||
eventType = parser.next();
|
eventType = parser.next();
|
||||||
}
|
}
|
||||||
while (eventType != XmlPullParser.END_DOCUMENT);
|
while (eventType != XmlPullParser.Event.END_DOCUMENT);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
LOGGER.log(Level.SEVERE, "Unknown error occurred while parsing provider file", e);
|
LOGGER.log(Level.SEVERE, "Unknown error occurred while parsing provider file", e);
|
||||||
|
|
|
@ -22,6 +22,8 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackConfiguration;
|
import org.jivesoftware.smack.SmackConfiguration;
|
||||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||||
import org.jivesoftware.smack.packet.IQ;
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
|
@ -29,8 +31,6 @@ import org.jivesoftware.smack.packet.Nonza;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smack.util.XmppElementUtil;
|
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
|
* Manages providers for parsing custom XML sub-documents of XMPP packets. Two types of
|
||||||
* providers exist:<ul>
|
* providers exist:<ul>
|
||||||
|
@ -112,10 +112,10 @@ import org.jxmpp.util.XmppStringUtils;
|
||||||
*/
|
*/
|
||||||
public final class ProviderManager {
|
public final class ProviderManager {
|
||||||
|
|
||||||
private static final Map<String, ExtensionElementProvider<ExtensionElement>> extensionProviders = new ConcurrentHashMap<String, ExtensionElementProvider<ExtensionElement>>();
|
private static final Map<QName, ExtensionElementProvider<ExtensionElement>> extensionProviders = new ConcurrentHashMap<>();
|
||||||
private static final Map<String, IQProvider<IQ>> iqProviders = new ConcurrentHashMap<String, IQProvider<IQ>>();
|
private static final Map<QName, IQProvider<IQ>> iqProviders = new ConcurrentHashMap<>();
|
||||||
private static final Map<String, ExtensionElementProvider<ExtensionElement>> streamFeatureProviders = new ConcurrentHashMap<String, ExtensionElementProvider<ExtensionElement>>();
|
private static final Map<QName, ExtensionElementProvider<ExtensionElement>> streamFeatureProviders = new ConcurrentHashMap<>();
|
||||||
private static final Map<String, NonzaProvider<? extends Nonza>> nonzaProviders = new ConcurrentHashMap<>();
|
private static final Map<QName, NonzaProvider<? extends Nonza>> nonzaProviders = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// Ensure that Smack is initialized by calling getVersion, so that user
|
// Ensure that Smack is initialized by calling getVersion, so that user
|
||||||
|
@ -168,7 +168,7 @@ public final class ProviderManager {
|
||||||
* @return the IQ provider.
|
* @return the IQ provider.
|
||||||
*/
|
*/
|
||||||
public static IQProvider<IQ> getIQProvider(String elementName, String namespace) {
|
public static IQProvider<IQ> getIQProvider(String elementName, String namespace) {
|
||||||
String key = getKey(elementName, namespace);
|
QName key = getQName(elementName, namespace);
|
||||||
return iqProviders.get(key);
|
return iqProviders.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ public final class ProviderManager {
|
||||||
Object provider) {
|
Object provider) {
|
||||||
validate(elementName, namespace);
|
validate(elementName, namespace);
|
||||||
// First remove existing providers
|
// First remove existing providers
|
||||||
String key = removeIQProvider(elementName, namespace);
|
QName key = removeIQProvider(elementName, namespace);
|
||||||
if (provider instanceof IQProvider) {
|
if (provider instanceof IQProvider) {
|
||||||
iqProviders.put(key, (IQProvider<IQ>) provider);
|
iqProviders.put(key, (IQProvider<IQ>) provider);
|
||||||
} else {
|
} else {
|
||||||
|
@ -214,10 +214,10 @@ public final class ProviderManager {
|
||||||
*
|
*
|
||||||
* @param elementName the XML element name.
|
* @param elementName the XML element name.
|
||||||
* @param namespace the XML namespace.
|
* @param namespace the XML namespace.
|
||||||
* @return the key of the removed IQ Provider
|
* @return the QName of the removed provider
|
||||||
*/
|
*/
|
||||||
public static String removeIQProvider(String elementName, String namespace) {
|
public static QName removeIQProvider(String elementName, String namespace) {
|
||||||
String key = getKey(elementName, namespace);
|
QName key = getQName(elementName, namespace);
|
||||||
iqProviders.remove(key);
|
iqProviders.remove(key);
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ public final class ProviderManager {
|
||||||
* @return the extension provider.
|
* @return the extension provider.
|
||||||
*/
|
*/
|
||||||
public static ExtensionElementProvider<ExtensionElement> getExtensionProvider(String elementName, String namespace) {
|
public static ExtensionElementProvider<ExtensionElement> getExtensionProvider(String elementName, String namespace) {
|
||||||
String key = getKey(elementName, namespace);
|
QName key = getQName(elementName, namespace);
|
||||||
return extensionProviders.get(key);
|
return extensionProviders.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +260,7 @@ public final class ProviderManager {
|
||||||
Object provider) {
|
Object provider) {
|
||||||
validate(elementName, namespace);
|
validate(elementName, namespace);
|
||||||
// First remove existing providers
|
// First remove existing providers
|
||||||
String key = removeExtensionProvider(elementName, namespace);
|
QName key = removeExtensionProvider(elementName, namespace);
|
||||||
if (provider instanceof ExtensionElementProvider) {
|
if (provider instanceof ExtensionElementProvider) {
|
||||||
extensionProviders.put(key, (ExtensionElementProvider<ExtensionElement>) provider);
|
extensionProviders.put(key, (ExtensionElementProvider<ExtensionElement>) provider);
|
||||||
} else {
|
} else {
|
||||||
|
@ -275,10 +275,10 @@ public final class ProviderManager {
|
||||||
*
|
*
|
||||||
* @param elementName the XML element name.
|
* @param elementName the XML element name.
|
||||||
* @param namespace the XML namespace.
|
* @param namespace the XML namespace.
|
||||||
* @return the key of the removed stanza extension provider
|
* @return the QName of the removed stanza extension provider
|
||||||
*/
|
*/
|
||||||
public static String removeExtensionProvider(String elementName, String namespace) {
|
public static QName removeExtensionProvider(String elementName, String namespace) {
|
||||||
String key = getKey(elementName, namespace);
|
QName key = getQName(elementName, namespace);
|
||||||
extensionProviders.remove(key);
|
extensionProviders.remove(key);
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
@ -297,48 +297,48 @@ public final class ProviderManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExtensionElementProvider<ExtensionElement> getStreamFeatureProvider(String elementName, String namespace) {
|
public static ExtensionElementProvider<ExtensionElement> getStreamFeatureProvider(String elementName, String namespace) {
|
||||||
String key = getKey(elementName, namespace);
|
QName key = getQName(elementName, namespace);
|
||||||
return streamFeatureProviders.get(key);
|
return streamFeatureProviders.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addStreamFeatureProvider(String elementName, String namespace, ExtensionElementProvider<ExtensionElement> provider) {
|
public static void addStreamFeatureProvider(String elementName, String namespace, ExtensionElementProvider<ExtensionElement> provider) {
|
||||||
validate(elementName, namespace);
|
validate(elementName, namespace);
|
||||||
String key = getKey(elementName, namespace);
|
QName key = getQName(elementName, namespace);
|
||||||
streamFeatureProviders.put(key, provider);
|
streamFeatureProviders.put(key, provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeStreamFeatureProvider(String elementName, String namespace) {
|
public static void removeStreamFeatureProvider(String elementName, String namespace) {
|
||||||
String key = getKey(elementName, namespace);
|
QName key = getQName(elementName, namespace);
|
||||||
streamFeatureProviders.remove(key);
|
streamFeatureProviders.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NonzaProvider<? extends Nonza> getNonzaProvider(String elementName, String namespace) {
|
public static NonzaProvider<? extends Nonza> getNonzaProvider(String elementName, String namespace) {
|
||||||
String key = getKey(elementName, namespace);
|
QName key = getQName(elementName, namespace);
|
||||||
return getNonzaProvider(key);
|
return getNonzaProvider(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NonzaProvider<? extends Nonza> getNonzaProvider(String key) {
|
public static NonzaProvider<? extends Nonza> getNonzaProvider(QName key) {
|
||||||
return nonzaProviders.get(key);
|
return nonzaProviders.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addNonzaProvider(NonzaProvider<? extends Nonza> nonzaProvider) {
|
public static void addNonzaProvider(NonzaProvider<? extends Nonza> nonzaProvider) {
|
||||||
Class<? extends Nonza> nonzaClass = nonzaProvider.getElementClass();
|
Class<? extends Nonza> nonzaClass = nonzaProvider.getElementClass();
|
||||||
String key = XmppElementUtil.getKeyFor(nonzaClass);
|
QName key = XmppElementUtil.getQNameFor(nonzaClass);
|
||||||
nonzaProviders.put(key, nonzaProvider);
|
nonzaProviders.put(key, nonzaProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeNonzaProvider(Class<? extends Nonza> nonzaClass) {
|
public static void removeNonzaProvider(Class<? extends Nonza> nonzaClass) {
|
||||||
String key = XmppElementUtil.getKeyFor(nonzaClass);
|
QName key = XmppElementUtil.getQNameFor(nonzaClass);
|
||||||
nonzaProviders.remove(key);
|
nonzaProviders.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeNonzaProvider(String elementName, String namespace) {
|
public static void removeNonzaProvider(String elementName, String namespace) {
|
||||||
String key = getKey(elementName, namespace);
|
QName key = getQName(elementName, namespace);
|
||||||
nonzaProviders.remove(key);
|
nonzaProviders.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getKey(String elementName, String namespace) {
|
private static QName getQName(String elementName, String namespace) {
|
||||||
return XmppStringUtils.generateKey(elementName, namespace);
|
return new QName(namespace, elementName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void validate(String elementName, String namespace) {
|
private static void validate(String elementName, String namespace) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.jivesoftware.smack.provider;
|
||||||
import org.jivesoftware.smack.packet.TlsProceed;
|
import org.jivesoftware.smack.packet.TlsProceed;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
|
||||||
public final class TlsFailureProvider extends NonzaProvider<TlsProceed> {
|
public final class TlsFailureProvider extends NonzaProvider<TlsProceed> {
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.jivesoftware.smack.provider;
|
||||||
import org.jivesoftware.smack.packet.TlsFailure;
|
import org.jivesoftware.smack.packet.TlsFailure;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
|
||||||
public final class TlsProceedProvider extends NonzaProvider<TlsFailure> {
|
public final class TlsProceedProvider extends NonzaProvider<TlsFailure> {
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,7 @@ import java.io.OutputStream;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Socket factory for socks4 proxy.
|
* Socket factory for socks4 proxy.
|
||||||
|
@ -73,7 +72,6 @@ public class Socks4ProxySocketConnection implements ProxySocketConnection {
|
||||||
of all zero bits.
|
of all zero bits.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
index = 0;
|
|
||||||
buf[index++] = 4;
|
buf[index++] = 4;
|
||||||
buf[index++] = 1;
|
buf[index++] = 1;
|
||||||
|
|
||||||
|
@ -87,7 +85,7 @@ public class Socks4ProxySocketConnection implements ProxySocketConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
byte[] userBytes = user.getBytes(StringUtils.UTF8);
|
byte[] userBytes = user.getBytes(StandardCharsets.UTF_8);
|
||||||
System.arraycopy(userBytes, 0, buf, index, user.length());
|
System.arraycopy(userBytes, 0, buf, index, user.length());
|
||||||
index += user.length();
|
index += user.length();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,10 @@ import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.jivesoftware.smack.util.CloseableUtil;
|
import org.jivesoftware.smack.util.CloseableUtil;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Socket factory for Socks5 proxy.
|
* Socket factory for Socks5 proxy.
|
||||||
|
@ -133,11 +133,11 @@ public class Socks5ProxySocketConnection implements ProxySocketConnection {
|
||||||
index = 0;
|
index = 0;
|
||||||
buf[index++] = 1;
|
buf[index++] = 1;
|
||||||
buf[index++] = (byte) user.length();
|
buf[index++] = (byte) user.length();
|
||||||
byte[] userBytes = user.getBytes(StringUtils.UTF8);
|
byte[] userBytes = user.getBytes(StandardCharsets.UTF_8);
|
||||||
System.arraycopy(userBytes, 0, buf, index,
|
System.arraycopy(userBytes, 0, buf, index,
|
||||||
user.length());
|
user.length());
|
||||||
index += user.length();
|
index += user.length();
|
||||||
byte[] passwordBytes = passwd.getBytes(StringUtils.UTF8);
|
byte[] passwordBytes = passwd.getBytes(StandardCharsets.UTF_8);
|
||||||
buf[index++] = (byte) passwordBytes.length;
|
buf[index++] = (byte) passwordBytes.length;
|
||||||
System.arraycopy(passwordBytes, 0, buf, index,
|
System.arraycopy(passwordBytes, 0, buf, index,
|
||||||
passwd.length());
|
passwd.length());
|
||||||
|
@ -204,7 +204,7 @@ public class Socks5ProxySocketConnection implements ProxySocketConnection {
|
||||||
buf[index++] = 1; // CONNECT
|
buf[index++] = 1; // CONNECT
|
||||||
buf[index++] = 0;
|
buf[index++] = 0;
|
||||||
|
|
||||||
byte[] hostb = host.getBytes(StringUtils.UTF8);
|
byte[] hostb = host.getBytes(StandardCharsets.UTF_8);
|
||||||
int len = hostb.length;
|
int len = hostb.length;
|
||||||
buf[index++] = 3; // DOMAINNAME
|
buf[index++] = 3; // DOMAINNAME
|
||||||
buf[index++] = (byte) len;
|
buf[index++] = (byte) len;
|
||||||
|
|
|
@ -31,13 +31,13 @@ public class SASLErrorException extends XMPPException {
|
||||||
|
|
||||||
private final SASLFailure saslFailure;
|
private final SASLFailure saslFailure;
|
||||||
private final String mechanism;
|
private final String mechanism;
|
||||||
private final Map<String,String> texts;
|
private final Map<String, String> texts;
|
||||||
|
|
||||||
public SASLErrorException(String mechanism, SASLFailure saslFailure) {
|
public SASLErrorException(String mechanism, SASLFailure saslFailure) {
|
||||||
this(mechanism, saslFailure, new HashMap<String, String>());
|
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());
|
super("SASLError using " + mechanism + ": " + saslFailure.getSASLErrorString());
|
||||||
this.mechanism = mechanism;
|
this.mechanism = mechanism;
|
||||||
this.saslFailure = saslFailure;
|
this.saslFailure = saslFailure;
|
||||||
|
@ -52,7 +52,7 @@ public class SASLErrorException extends XMPPException {
|
||||||
return mechanism;
|
return mechanism;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String,String> getTexts() {
|
public Map<String, String> getTexts() {
|
||||||
return texts;
|
return texts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.sasl.core;
|
package org.jivesoftware.smack.sasl.core;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -114,14 +114,8 @@ public abstract class ScramMechanism extends SASLMechanism {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected byte[] evaluateChallenge(byte[] challenge) throws SmackSaslException {
|
protected byte[] evaluateChallenge(byte[] challenge) throws SmackSaslException {
|
||||||
String challengeString;
|
// TODO: Where is it specified that this is an UTF-8 encoded string?
|
||||||
try {
|
String challengeString = new String(challenge, StandardCharsets.UTF_8);
|
||||||
// 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) {
|
switch (state) {
|
||||||
case AUTH_TEXT_SENT:
|
case AUTH_TEXT_SENT:
|
||||||
|
@ -386,14 +380,9 @@ public abstract class ScramMechanism extends SASLMechanism {
|
||||||
* @throws SmackSaslException if a SASL related error occurs.
|
* @throws SmackSaslException if a SASL related error occurs.
|
||||||
*/
|
*/
|
||||||
private byte[] hi(String normalizedPassword, byte[] salt, int iterations) throws SmackSaslException {
|
private byte[] hi(String normalizedPassword, byte[] salt, int iterations) throws SmackSaslException {
|
||||||
byte[] key;
|
// According to RFC 5802 § 2.2, the resulting string of the normalization is also in UTF-8.
|
||||||
try {
|
byte[] key = normalizedPassword.getBytes(StandardCharsets.UTF_8);
|
||||||
// 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))
|
// U1 := HMAC(str, salt + INT(1))
|
||||||
byte[] u = hmac(key, ByteUtils.concat(salt, ONE));
|
byte[] u = hmac(key, ByteUtils.concat(salt, ONE));
|
||||||
byte[] res = u.clone();
|
byte[] res = u.clone();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2014-2018 Florian Schmaus
|
* Copyright 2014-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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 {
|
private void checkNotShutdown() throws InterruptedException {
|
||||||
if (isShutdown) {
|
if (isShutdown) {
|
||||||
throw new InterruptedException();
|
throw new InterruptedException("Queue was already shut down");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.util;
|
package org.jivesoftware.smack.util;
|
||||||
|
|
||||||
public interface CallbackRecipient<V,E> {
|
public interface CallbackRecipient<V, E> {
|
||||||
|
|
||||||
CallbackRecipient<V, E> onSuccess(SuccessCallback<V> successCallback);
|
CallbackRecipient<V, E> onSuccess(SuccessCallback<V> successCallback);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2018 Florian Schmaus
|
* Copyright 2018-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -23,6 +23,10 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
public class CloseableUtil {
|
public class CloseableUtil {
|
||||||
|
|
||||||
|
public static void maybeClose(Closeable closable) {
|
||||||
|
maybeClose(closable, null);
|
||||||
|
}
|
||||||
|
|
||||||
public static void maybeClose(Closeable closable, Logger logger) {
|
public static void maybeClose(Closeable closable, Logger logger) {
|
||||||
if (closable == null) {
|
if (closable == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -31,7 +35,9 @@ public class CloseableUtil {
|
||||||
try {
|
try {
|
||||||
closable.close();
|
closable.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.log(Level.WARNING, "Could not close " + closable, e);
|
if (logger != null) {
|
||||||
|
logger.log(Level.WARNING, "Could not close " + closable, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2015-2018 Florian Schmaus
|
* Copyright 2015-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -49,4 +49,10 @@ public class CollectionUtil {
|
||||||
public interface Predicate<T> {
|
public interface Predicate<T> {
|
||||||
boolean test(T 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,243 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -34,7 +34,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
*/
|
*/
|
||||||
public class EventManger<K, R, E extends Exception> {
|
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.
|
* Perform an action and wait for an event.
|
||||||
|
|
|
@ -30,6 +30,7 @@ import java.io.Reader;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -90,7 +91,7 @@ public final class FileUtils {
|
||||||
public static boolean addLines(String uriString, Set<String> set) throws MalformedURLException, IOException {
|
public static boolean addLines(String uriString, Set<String> set) throws MalformedURLException, IOException {
|
||||||
URI uri = URI.create(uriString);
|
URI uri = URI.create(uriString);
|
||||||
InputStream is = getStreamForUri(uri, null);
|
InputStream is = getStreamForUri(uri, null);
|
||||||
InputStreamReader sr = new InputStreamReader(is, StringUtils.UTF8);
|
InputStreamReader sr = new InputStreamReader(is, StandardCharsets.UTF_8);
|
||||||
BufferedReader br = new BufferedReader(sr);
|
BufferedReader br = new BufferedReader(sr);
|
||||||
try {
|
try {
|
||||||
String line;
|
String line;
|
||||||
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,213 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,7 +34,7 @@ import java.util.Set;
|
||||||
* @param <K> the type of the keys the map uses.
|
* @param <K> the type of the keys the map uses.
|
||||||
* @param <V> the type of the values 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}.
|
* The constant value {@value}.
|
||||||
|
@ -57,7 +58,11 @@ public class MultiMap<K,V> {
|
||||||
* @param size the initial capacity.
|
* @param size the initial capacity.
|
||||||
*/
|
*/
|
||||||
public MultiMap(int size) {
|
public MultiMap(int size) {
|
||||||
map = new LinkedHashMap<>(size);
|
this(new LinkedHashMap<>(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
private MultiMap(Map<K, List<V>> map) {
|
||||||
|
this.map = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
|
@ -72,11 +77,11 @@ public class MultiMap<K,V> {
|
||||||
return map.isEmpty();
|
return map.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsKey(Object key) {
|
public boolean containsKey(K key) {
|
||||||
return map.containsKey(key);
|
return map.containsKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsValue(Object value) {
|
public boolean containsValue(V value) {
|
||||||
for (List<V> list : map.values()) {
|
for (List<V> list : map.values()) {
|
||||||
if (list.contains(value)) {
|
if (list.contains(value)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -91,7 +96,7 @@ public class MultiMap<K,V> {
|
||||||
* @param key
|
* @param key
|
||||||
* @return the first value or null.
|
* @return the first value or null.
|
||||||
*/
|
*/
|
||||||
public V getFirst(Object key) {
|
public V getFirst(K key) {
|
||||||
List<V> res = getAll(key);
|
List<V> res = getAll(key);
|
||||||
if (res.isEmpty()) {
|
if (res.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -109,7 +114,7 @@ public class MultiMap<K,V> {
|
||||||
* @param key
|
* @param key
|
||||||
* @return all values for the given key.
|
* @return all values for the given key.
|
||||||
*/
|
*/
|
||||||
public List<V> getAll(Object key) {
|
public List<V> getAll(K key) {
|
||||||
List<V> res = map.get(key);
|
List<V> res = map.get(key);
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
res = Collections.emptyList();
|
res = Collections.emptyList();
|
||||||
|
@ -138,7 +143,7 @@ public class MultiMap<K,V> {
|
||||||
* @param key
|
* @param key
|
||||||
* @return the first value of the given key or null.
|
* @return the first value of the given key or null.
|
||||||
*/
|
*/
|
||||||
public V remove(Object key) {
|
public V remove(K key) {
|
||||||
List<V> res = map.remove(key);
|
List<V> res = map.remove(key);
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -157,7 +162,7 @@ public class MultiMap<K,V> {
|
||||||
* @param value
|
* @param value
|
||||||
* @return true if the mapping was removed, false otherwise.
|
* @return true if the mapping was removed, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean removeOne(Object key, V value) {
|
public boolean removeOne(K key, V value) {
|
||||||
List<V> list = map.get(key);
|
List<V> list = map.get(key);
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -235,6 +240,18 @@ public class MultiMap<K,V> {
|
||||||
return entrySet;
|
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 static final class SimpleMapEntry<K, V> implements Map.Entry<K, V> {
|
||||||
|
|
||||||
private final K key;
|
private final K key;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright © 2015 Florian Schmaus
|
* Copyright © 2015-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -22,13 +22,41 @@ public class NumberUtil {
|
||||||
* Checks if the given long is within the range of an unsigned 32-bit integer, the XML type "xs:unsignedInt".
|
* Checks if the given long is within the range of an unsigned 32-bit integer, the XML type "xs:unsignedInt".
|
||||||
*
|
*
|
||||||
* @param value
|
* @param value
|
||||||
|
* @deprecated use {@link #requireUInt32(long)} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
|
// TODO: Remove in Smack 4.5.
|
||||||
public static void checkIfInUInt32Range(long value) {
|
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) {
|
if (value < 0) {
|
||||||
throw new IllegalArgumentException("unsigned 32-bit integers can't be negative");
|
throw new IllegalArgumentException("unsigned 32-bit integers can't be negative");
|
||||||
}
|
}
|
||||||
if (value > ((1L << 32) - 1)) {
|
if (value > ((1L << 32) - 1)) {
|
||||||
throw new IllegalArgumentException("unsigned 32-bit integers can't be greater then 2^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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2015-2018 Florian Schmaus
|
* Copyright 2015-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -20,9 +20,26 @@ import java.util.Collection;
|
||||||
|
|
||||||
public class Objects {
|
public class Objects {
|
||||||
|
|
||||||
public static <T> T requireNonNull(T obj, String message) {
|
/**
|
||||||
|
* 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 {
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
throw new NullPointerException(message);
|
if (message == null) {
|
||||||
|
message = "Can not provide null argument";
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(message);
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,18 +17,19 @@
|
||||||
package org.jivesoftware.smack.util;
|
package org.jivesoftware.smack.util;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackConfiguration;
|
|
||||||
import org.jivesoftware.smack.compress.packet.Compress;
|
import org.jivesoftware.smack.compress.packet.Compress;
|
||||||
import org.jivesoftware.smack.packet.EmptyResultIQ;
|
import org.jivesoftware.smack.packet.EmptyResultIQ;
|
||||||
import org.jivesoftware.smack.packet.ErrorIQ;
|
import org.jivesoftware.smack.packet.ErrorIQ;
|
||||||
|
@ -49,11 +50,12 @@ import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
||||||
import org.jivesoftware.smack.provider.IQProvider;
|
import org.jivesoftware.smack.provider.IQProvider;
|
||||||
import org.jivesoftware.smack.provider.ProviderManager;
|
import org.jivesoftware.smack.provider.ProviderManager;
|
||||||
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.SASLFailure;
|
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.jid.Jid;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.jxmpp.stringprep.XmppStringprepException;
|
||||||
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
|
* Utility class that helps to parse packets. Any parsing packets method that must be shared
|
||||||
|
@ -64,51 +66,22 @@ import org.xmlpull.v1.XmlPullParserFactory;
|
||||||
public class PacketParserUtils {
|
public class PacketParserUtils {
|
||||||
private static final Logger LOGGER = Logger.getLogger(PacketParserUtils.class.getName());
|
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'.
|
// TODO: Rename argument name from 'stanza' to 'element'.
|
||||||
public static XmlPullParser getParserFor(String stanza) throws XmlPullParserException, IOException {
|
public static XmlPullParser getParserFor(String stanza) throws XmlPullParserException, IOException {
|
||||||
return getParserFor(new StringReader(stanza));
|
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 {
|
public static XmlPullParser getParserFor(Reader reader) throws XmlPullParserException, IOException {
|
||||||
XmlPullParser parser = newXmppParser(reader);
|
XmlPullParser parser = SmackXmlParser.newXmlParser(reader);
|
||||||
// Wind the parser forward to the first start tag
|
// Wind the parser forward to the first start tag
|
||||||
int event = parser.getEventType();
|
XmlPullParser.Event event = parser.getEventType();
|
||||||
while (event != XmlPullParser.START_TAG) {
|
while (event != XmlPullParser.Event.START_ELEMENT) {
|
||||||
if (event == XmlPullParser.END_DOCUMENT) {
|
if (event == XmlPullParser.Event.END_DOCUMENT) {
|
||||||
throw new IllegalArgumentException("Document contains no start tag");
|
throw new IllegalArgumentException("Document contains no start tag");
|
||||||
}
|
}
|
||||||
event = parser.next();
|
event = parser.next();
|
||||||
|
@ -116,28 +89,8 @@ public class PacketParserUtils {
|
||||||
return parser;
|
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")
|
@SuppressWarnings("unchecked")
|
||||||
public static <S extends Stanza> S parseStanza(String stanza) throws Exception {
|
public static <S extends Stanza> S parseStanza(String stanza) throws XmlPullParserException, SmackParsingException, IOException {
|
||||||
return (S) parseStanza(getParserFor(stanza), null);
|
return (S) parseStanza(getParserFor(stanza), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,9 +102,11 @@ public class PacketParserUtils {
|
||||||
* @param parser
|
* @param parser
|
||||||
* @param outerXmlEnvironment the outer XML environment (optional).
|
* @param outerXmlEnvironment the outer XML environment (optional).
|
||||||
* @return a stanza which is either a Message, IQ or Presence.
|
* @return a stanza which is either a Message, IQ or Presence.
|
||||||
* @throws Exception
|
* @throws XmlPullParserException
|
||||||
|
* @throws SmackParsingException
|
||||||
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static Stanza parseStanza(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws Exception {
|
public static Stanza parseStanza(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, SmackParsingException, IOException {
|
||||||
ParserUtils.assertAtStartTag(parser);
|
ParserUtils.assertAtStartTag(parser);
|
||||||
final String name = parser.getName();
|
final String name = parser.getName();
|
||||||
switch (name) {
|
switch (name) {
|
||||||
|
@ -166,53 +121,6 @@ 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 {
|
public static Message parseMessage(XmlPullParser parser) throws XmlPullParserException, IOException, SmackParsingException {
|
||||||
return parseMessage(parser, null);
|
return parseMessage(parser, null);
|
||||||
}
|
}
|
||||||
|
@ -249,9 +157,9 @@ public class PacketParserUtils {
|
||||||
// in arbitrary sub-elements.
|
// in arbitrary sub-elements.
|
||||||
String thread = null;
|
String thread = null;
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
String elementName = parser.getName();
|
String elementName = parser.getName();
|
||||||
String namespace = parser.getNamespace();
|
String namespace = parser.getNamespace();
|
||||||
switch (elementName) {
|
switch (elementName) {
|
||||||
|
@ -276,11 +184,12 @@ public class PacketParserUtils {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
if (parser.getDepth() == initialDepth) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default: // fall out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,9 +204,9 @@ public class PacketParserUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the textual content of an element as String. After this method returns the parser
|
* Returns the textual content of an element as String. After this method returns the parser
|
||||||
* position will be END_TAG, following the established pull parser calling convention.
|
* position will be END_ELEMENT, following the established pull parser calling convention.
|
||||||
* <p>
|
* <p>
|
||||||
* The parser must be positioned on a START_TAG of an element which MUST NOT contain Mixed
|
* The parser must be positioned on a START_ELEMENT of an element which MUST NOT contain Mixed
|
||||||
* Content (as defined in XML 3.2.2), or else an XmlPullParserException will be thrown.
|
* Content (as defined in XML 3.2.2), or else an XmlPullParserException will be thrown.
|
||||||
* </p>
|
* </p>
|
||||||
* This method is used for the parts where the XMPP specification requires elements that contain
|
* This method is used for the parts where the XMPP specification requires elements that contain
|
||||||
|
@ -309,41 +218,36 @@ public class PacketParserUtils {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static String parseElementText(XmlPullParser parser) throws XmlPullParserException, IOException {
|
public static String parseElementText(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||||
assert (parser.getEventType() == XmlPullParser.START_TAG);
|
assert (parser.getEventType() == XmlPullParser.Event.START_ELEMENT);
|
||||||
String res;
|
String res;
|
||||||
if (parser.isEmptyElementTag()) {
|
// Advance to the text of the Element
|
||||||
res = "";
|
XmlPullParser.Event event = parser.next();
|
||||||
}
|
if (event != XmlPullParser.Event.TEXT_CHARACTERS) {
|
||||||
else {
|
if (event == XmlPullParser.Event.END_ELEMENT) {
|
||||||
// Advance to the text of the Element
|
// Assume this is the end tag of the start tag at the
|
||||||
int event = parser.next();
|
// beginning of this method. Typical examples where this
|
||||||
if (event != XmlPullParser.TEXT) {
|
// happens are body elements containing the empty string,
|
||||||
if (event == XmlPullParser.END_TAG) {
|
// ie. <body></body>, which appears to be valid XMPP, or a
|
||||||
// Assume this is the end tag of the start tag at the
|
// least it's not explicitly forbidden by RFC 6121 5.2.3
|
||||||
// beginning of this method. Typical examples where this
|
return "";
|
||||||
// happens are body elements containing the empty string,
|
} else {
|
||||||
// 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(
|
throw new XmlPullParserException(
|
||||||
"Non-empty element tag contains child-elements, while Mixed Content (XML 3.2.2) is disallowed");
|
"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.Event.END_ELEMENT) {
|
||||||
|
throw new XmlPullParserException(
|
||||||
|
"Non-empty element tag contains child-elements, while Mixed Content (XML 3.2.2) is disallowed");
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current element as string.
|
* Returns the current element as string.
|
||||||
* <p>
|
* <p>
|
||||||
* The parser must be positioned on START_TAG.
|
* The parser must be positioned on START_ELEMENT.
|
||||||
* </p>
|
* </p>
|
||||||
* Note that only the outermost namespace attributes ("xmlns") will be returned, not nested ones.
|
* Note that only the outermost namespace attributes ("xmlns") will be returned, not nested ones.
|
||||||
*
|
*
|
||||||
|
@ -359,37 +263,10 @@ public class PacketParserUtils {
|
||||||
public static CharSequence parseElement(XmlPullParser parser,
|
public static CharSequence parseElement(XmlPullParser parser,
|
||||||
boolean fullNamespaces) throws XmlPullParserException,
|
boolean fullNamespaces) throws XmlPullParserException,
|
||||||
IOException {
|
IOException {
|
||||||
assert (parser.getEventType() == XmlPullParser.START_TAG);
|
assert (parser.getEventType() == XmlPullParser.Event.START_ELEMENT);
|
||||||
return parseContentDepth(parser, parser.getDepth(), fullNamespaces);
|
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)
|
public static CharSequence parseContentDepth(XmlPullParser parser, int depth)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
return parseContentDepth(parser, depth, false);
|
return parseContentDepth(parser, depth, false);
|
||||||
|
@ -402,7 +279,7 @@ public class PacketParserUtils {
|
||||||
* parent elements will be added to child elements that don't define a different namespace.
|
* parent elements will be added to child elements that don't define a different namespace.
|
||||||
* <p>
|
* <p>
|
||||||
* This method is able to parse the content with MX- and KXmlParser. KXmlParser does not support
|
* 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_TAG and END_TAG. We check for the
|
* xml-roundtrip. i.e. return a String on getText() on START_ELEMENT and END_ELEMENT. We check for the
|
||||||
* XML_ROUNDTRIP feature. If it's not found we are required to work around this limitation, which
|
* 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
|
* 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.
|
* elements will be included in the resulting String, if <code>fullNamespaces</code> is set to false.
|
||||||
|
@ -419,7 +296,7 @@ public class PacketParserUtils {
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static CharSequence parseContentDepth(XmlPullParser parser, int depth, boolean fullNamespaces) throws XmlPullParserException, IOException {
|
public static CharSequence parseContentDepth(XmlPullParser parser, int depth, boolean fullNamespaces) throws XmlPullParserException, IOException {
|
||||||
if (parser.getFeature(FEATURE_XML_ROUNDTRIP)) {
|
if (parser.supportsRoundtrip()) {
|
||||||
return parseContentDepthWithRoundtrip(parser, depth, fullNamespaces);
|
return parseContentDepthWithRoundtrip(parser, depth, fullNamespaces);
|
||||||
} else {
|
} else {
|
||||||
return parseContentDepthWithoutRoundtrip(parser, depth, fullNamespaces);
|
return parseContentDepthWithoutRoundtrip(parser, depth, fullNamespaces);
|
||||||
|
@ -429,15 +306,21 @@ public class PacketParserUtils {
|
||||||
private static CharSequence parseContentDepthWithoutRoundtrip(XmlPullParser parser, int depth,
|
private static CharSequence parseContentDepthWithoutRoundtrip(XmlPullParser parser, int depth,
|
||||||
boolean fullNamespaces) throws XmlPullParserException, IOException {
|
boolean fullNamespaces) throws XmlPullParserException, IOException {
|
||||||
XmlStringBuilder xml = new XmlStringBuilder();
|
XmlStringBuilder xml = new XmlStringBuilder();
|
||||||
int event = parser.getEventType();
|
XmlPullParser.Event event = parser.getEventType();
|
||||||
boolean isEmptyElement = false;
|
|
||||||
// XmlPullParser reports namespaces in nested elements even if *only* the outer ones defines
|
// 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
|
// 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.
|
// in a nested element. It's an ugly workaround that has the potential to break things.
|
||||||
String namespaceElement = null;
|
String namespaceElement = null;
|
||||||
|
boolean startElementJustSeen = false;
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
|
if (startElementJustSeen) {
|
||||||
|
xml.rightAngleBracket();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
startElementJustSeen = true;
|
||||||
|
}
|
||||||
xml.halfOpenElement(parser.getName());
|
xml.halfOpenElement(parser.getName());
|
||||||
if (namespaceElement == null || fullNamespaces) {
|
if (namespaceElement == null || fullNamespaces) {
|
||||||
String namespace = parser.getNamespace();
|
String namespace = parser.getNamespace();
|
||||||
|
@ -449,18 +332,11 @@ public class PacketParserUtils {
|
||||||
for (int i = 0; i < parser.getAttributeCount(); i++) {
|
for (int i = 0; i < parser.getAttributeCount(); i++) {
|
||||||
xml.attribute(parser.getAttributeName(i), parser.getAttributeValue(i));
|
xml.attribute(parser.getAttributeName(i), parser.getAttributeValue(i));
|
||||||
}
|
}
|
||||||
if (parser.isEmptyElementTag()) {
|
|
||||||
xml.closeEmptyElement();
|
|
||||||
isEmptyElement = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
xml.rightAngleBracket();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
if (isEmptyElement) {
|
if (startElementJustSeen) {
|
||||||
// Do nothing as the element was already closed, just reset the flag
|
xml.closeEmptyElement();
|
||||||
isEmptyElement = false;
|
startElementJustSeen = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
xml.closeElement(parser.getName());
|
xml.closeElement(parser.getName());
|
||||||
|
@ -474,31 +350,58 @@ public class PacketParserUtils {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.TEXT:
|
case TEXT_CHARACTERS:
|
||||||
|
if (startElementJustSeen) {
|
||||||
|
startElementJustSeen = false;
|
||||||
|
xml.rightAngleBracket();
|
||||||
|
}
|
||||||
xml.escape(parser.getText());
|
xml.escape(parser.getText());
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
event = parser.next();
|
event = parser.next();
|
||||||
}
|
}
|
||||||
return xml;
|
return xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("UnusedVariable")
|
||||||
private static CharSequence parseContentDepthWithRoundtrip(XmlPullParser parser, int depth, boolean fullNamespaces)
|
private static CharSequence parseContentDepthWithRoundtrip(XmlPullParser parser, int depth, boolean fullNamespaces)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
StringBuilder sb = new StringBuilder();
|
XmlStringBuilder sb = new XmlStringBuilder();
|
||||||
int event = parser.getEventType();
|
XmlPullParser.Event event = parser.getEventType();
|
||||||
|
boolean startElementJustSeen = false;
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
// Only append the text if the parser is not on on an empty element' start tag. Empty elements are reported
|
switch (event) {
|
||||||
// twice, so in order to prevent duplication we only add their text when we are on their end tag.
|
case START_ELEMENT:
|
||||||
if (!(event == XmlPullParser.START_TAG && parser.isEmptyElementTag())) {
|
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;
|
||||||
CharSequence text = parser.getText();
|
CharSequence text = parser.getText();
|
||||||
if (event == XmlPullParser.TEXT) {
|
if (event == XmlPullParser.Event.TEXT_CHARACTERS) {
|
||||||
text = StringUtils.escapeForXmlText(text);
|
text = StringUtils.escapeForXml(text);
|
||||||
}
|
}
|
||||||
sb.append(text);
|
sb.append(text);
|
||||||
}
|
break;
|
||||||
if (event == XmlPullParser.END_TAG && parser.getDepth() <= depth) {
|
|
||||||
break outerloop;
|
|
||||||
}
|
}
|
||||||
event = parser.next();
|
event = parser.next();
|
||||||
}
|
}
|
||||||
|
@ -536,16 +439,14 @@ public class PacketParserUtils {
|
||||||
|
|
||||||
String language = ParserUtils.getXmlLang(parser);
|
String language = ParserUtils.getXmlLang(parser);
|
||||||
if (language != null && !"".equals(language.trim())) {
|
if (language != null && !"".equals(language.trim())) {
|
||||||
// CHECKSTYLE:OFF
|
presence.setLanguage(language);
|
||||||
presence.setLanguage(language);
|
|
||||||
// CHECKSTYLE:ON
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse sub-elements
|
// Parse sub-elements
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
String elementName = parser.getName();
|
String elementName = parser.getName();
|
||||||
String namespace = parser.getNamespace();
|
String namespace = parser.getNamespace();
|
||||||
switch (elementName) {
|
switch (elementName) {
|
||||||
|
@ -553,7 +454,7 @@ public class PacketParserUtils {
|
||||||
presence.setStatus(parser.nextText());
|
presence.setStatus(parser.nextText());
|
||||||
break;
|
break;
|
||||||
case "priority":
|
case "priority":
|
||||||
int priority = Integer.parseInt(parser.nextText());
|
Byte priority = ParserUtils.getByteAttributeFromNextText(parser);
|
||||||
presence.setPriority(priority);
|
presence.setPriority(priority);
|
||||||
break;
|
break;
|
||||||
case "show":
|
case "show":
|
||||||
|
@ -587,11 +488,14 @@ public class PacketParserUtils {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
if (parser.getDepth() == initialDepth) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return presence;
|
return presence;
|
||||||
|
@ -607,9 +511,12 @@ public class PacketParserUtils {
|
||||||
* @param parser the XML parser, positioned at the start of an IQ packet.
|
* @param parser the XML parser, positioned at the start of an IQ packet.
|
||||||
* @param outerXmlEnvironment the outer XML environment (optional).
|
* @param outerXmlEnvironment the outer XML environment (optional).
|
||||||
* @return an IQ object.
|
* @return an IQ object.
|
||||||
* @throws Exception
|
* @throws XmlPullParserException
|
||||||
|
* @throws XmppStringprepException
|
||||||
|
* @throws IOException
|
||||||
|
* @throws SmackParsingException
|
||||||
*/
|
*/
|
||||||
public static IQ parseIQ(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws Exception {
|
public static IQ parseIQ(XmlPullParser parser, XmlEnvironment outerXmlEnvironment) throws XmlPullParserException, XmppStringprepException, IOException, SmackParsingException {
|
||||||
ParserUtils.assertAtStartTag(parser);
|
ParserUtils.assertAtStartTag(parser);
|
||||||
final int initialDepth = parser.getDepth();
|
final int initialDepth = parser.getDepth();
|
||||||
XmlEnvironment iqXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment);
|
XmlEnvironment iqXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment);
|
||||||
|
@ -622,10 +529,10 @@ public class PacketParserUtils {
|
||||||
final IQ.Type type = IQ.Type.fromString(parser.getAttributeValue("", "type"));
|
final IQ.Type type = IQ.Type.fromString(parser.getAttributeValue("", "type"));
|
||||||
|
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
|
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
String elementName = parser.getName();
|
String elementName = parser.getName();
|
||||||
String namespace = parser.getNamespace();
|
String namespace = parser.getNamespace();
|
||||||
switch (elementName) {
|
switch (elementName) {
|
||||||
|
@ -640,7 +547,7 @@ public class PacketParserUtils {
|
||||||
iqPacket = provider.parse(parser, outerXmlEnvironment);
|
iqPacket = provider.parse(parser, outerXmlEnvironment);
|
||||||
}
|
}
|
||||||
// Note that if we reach this code, it is guranteed that the result IQ contained a child element
|
// 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_TAG first.
|
// (RFC 6120 § 8.2.3 6) because otherwhise we would have reached the END_ELEMENT first.
|
||||||
else {
|
else {
|
||||||
// No Provider found for the IQ stanza, parse it to an UnparsedIQ instance
|
// 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
|
// so that the content of the IQ can be examined later on
|
||||||
|
@ -649,11 +556,14 @@ public class PacketParserUtils {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
if (parser.getDepth() == initialDepth) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Decide what to do when an IQ packet was not understood
|
// Decide what to do when an IQ packet was not understood
|
||||||
|
@ -694,15 +604,15 @@ public class PacketParserUtils {
|
||||||
List<String> mechanisms = new ArrayList<String>();
|
List<String> mechanisms = new ArrayList<String>();
|
||||||
boolean done = false;
|
boolean done = false;
|
||||||
while (!done) {
|
while (!done) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
|
|
||||||
if (eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.Event.START_ELEMENT) {
|
||||||
String elementName = parser.getName();
|
String elementName = parser.getName();
|
||||||
if (elementName.equals("mechanism")) {
|
if (elementName.equals("mechanism")) {
|
||||||
mechanisms.add(parser.nextText());
|
mechanisms.add(parser.nextText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (eventType == XmlPullParser.END_TAG) {
|
else if (eventType == XmlPullParser.Event.END_ELEMENT) {
|
||||||
if (parser.getName().equals("mechanisms")) {
|
if (parser.getName().equals("mechanisms")) {
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
@ -721,14 +631,14 @@ public class PacketParserUtils {
|
||||||
*/
|
*/
|
||||||
public static Compress.Feature parseCompressionFeature(XmlPullParser parser)
|
public static Compress.Feature parseCompressionFeature(XmlPullParser parser)
|
||||||
throws IOException, XmlPullParserException {
|
throws IOException, XmlPullParserException {
|
||||||
assert (parser.getEventType() == XmlPullParser.START_TAG);
|
assert (parser.getEventType() == XmlPullParser.Event.START_ELEMENT);
|
||||||
String name;
|
String name;
|
||||||
final int initialDepth = parser.getDepth();
|
final int initialDepth = parser.getDepth();
|
||||||
List<String> methods = new LinkedList<>();
|
List<String> methods = new LinkedList<>();
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
name = parser.getName();
|
name = parser.getName();
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "method":
|
case "method":
|
||||||
|
@ -736,7 +646,7 @@ public class PacketParserUtils {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
name = parser.getName();
|
name = parser.getName();
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case Compress.Feature.ELEMENT:
|
case Compress.Feature.ELEMENT:
|
||||||
|
@ -744,9 +654,13 @@ public class PacketParserUtils {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert (parser.getEventType() == XmlPullParser.END_TAG);
|
assert (parser.getEventType() == XmlPullParser.Event.END_ELEMENT);
|
||||||
assert (parser.getDepth() == initialDepth);
|
assert (parser.getDepth() == initialDepth);
|
||||||
return new Compress.Feature(methods);
|
return new Compress.Feature(methods);
|
||||||
}
|
}
|
||||||
|
@ -782,9 +696,9 @@ public class PacketParserUtils {
|
||||||
String condition = null;
|
String condition = null;
|
||||||
Map<String, String> descriptiveTexts = null;
|
Map<String, String> descriptiveTexts = null;
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
if (name.equals("text")) {
|
if (name.equals("text")) {
|
||||||
descriptiveTexts = parseDescriptiveTexts(parser, descriptiveTexts);
|
descriptiveTexts = parseDescriptiveTexts(parser, descriptiveTexts);
|
||||||
|
@ -794,11 +708,14 @@ public class PacketParserUtils {
|
||||||
condition = parser.getName();
|
condition = parser.getName();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
if (parser.getDepth() == initialDepth) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new SASLFailure(condition, descriptiveTexts);
|
return new SASLFailure(condition, descriptiveTexts);
|
||||||
|
@ -826,9 +743,9 @@ public class PacketParserUtils {
|
||||||
String conditionText = null;
|
String conditionText = null;
|
||||||
XmlEnvironment streamErrorXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment);
|
XmlEnvironment streamErrorXmlEnvironment = XmlEnvironment.from(parser, outerXmlEnvironment);
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
String namespace = parser.getNamespace();
|
String namespace = parser.getNamespace();
|
||||||
switch (namespace) {
|
switch (namespace) {
|
||||||
|
@ -841,8 +758,9 @@ public class PacketParserUtils {
|
||||||
// If it's not a text element, that is qualified by the StreamError.NAMESPACE,
|
// If it's not a text element, that is qualified by the StreamError.NAMESPACE,
|
||||||
// then it has to be the stream error code
|
// then it has to be the stream error code
|
||||||
condition = StreamError.Condition.fromString(name);
|
condition = StreamError.Condition.fromString(name);
|
||||||
if (!parser.isEmptyElementTag()) {
|
conditionText = parser.nextText();
|
||||||
conditionText = parser.nextText();
|
if (conditionText.isEmpty()) {
|
||||||
|
conditionText = null;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -852,11 +770,14 @@ public class PacketParserUtils {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
if (parser.getDepth() == initialDepth) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new StreamError(condition, conditionText, descriptiveTexts, extensions);
|
return new StreamError(condition, conditionText, descriptiveTexts, extensions);
|
||||||
|
@ -888,9 +809,9 @@ public class PacketParserUtils {
|
||||||
builder.setErrorGenerator(parser.getAttributeValue("", "by"));
|
builder.setErrorGenerator(parser.getAttributeValue("", "by"));
|
||||||
|
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
String namespace = parser.getNamespace();
|
String namespace = parser.getNamespace();
|
||||||
switch (namespace) {
|
switch (namespace) {
|
||||||
|
@ -901,8 +822,9 @@ public class PacketParserUtils {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
builder.setCondition(StanzaError.Condition.fromString(name));
|
builder.setCondition(StanzaError.Condition.fromString(name));
|
||||||
if (!parser.isEmptyElementTag()) {
|
String conditionText = parser.nextText();
|
||||||
builder.setConditionText(parser.nextText());
|
if (!conditionText.isEmpty()) {
|
||||||
|
builder.setConditionText(conditionText);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -911,10 +833,14 @@ public class PacketParserUtils {
|
||||||
PacketParserUtils.addExtensionElement(extensions, parser, name, namespace, stanzaErrorXmlEnvironment);
|
PacketParserUtils.addExtensionElement(extensions, parser, name, namespace, stanzaErrorXmlEnvironment);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
if (parser.getDepth() == initialDepth) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder.setExtensions(extensions).setDescriptiveTexts(descriptiveTexts);
|
builder.setExtensions(extensions).setDescriptiveTexts(descriptiveTexts);
|
||||||
|
@ -949,14 +875,14 @@ public class PacketParserUtils {
|
||||||
|
|
||||||
public static StartTls parseStartTlsFeature(XmlPullParser parser)
|
public static StartTls parseStartTlsFeature(XmlPullParser parser)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
assert (parser.getEventType() == XmlPullParser.START_TAG);
|
assert (parser.getEventType() == XmlPullParser.Event.START_ELEMENT);
|
||||||
assert (parser.getNamespace().equals(StartTls.NAMESPACE));
|
assert (parser.getNamespace().equals(StartTls.NAMESPACE));
|
||||||
int initalDepth = parser.getDepth();
|
int initalDepth = parser.getDepth();
|
||||||
boolean required = false;
|
boolean required = false;
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int event = parser.next();
|
XmlPullParser.Event event = parser.next();
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "required":
|
case "required":
|
||||||
|
@ -964,13 +890,17 @@ public class PacketParserUtils {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
if (parser.getDepth() == initalDepth) {
|
if (parser.getDepth() == initalDepth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert (parser.getEventType() == XmlPullParser.END_TAG);
|
assert (parser.getEventType() == XmlPullParser.Event.END_ELEMENT);
|
||||||
return new StartTls(required);
|
return new StartTls(required);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -978,14 +908,11 @@ public class PacketParserUtils {
|
||||||
ParserUtils.assertAtStartTag(parser);
|
ParserUtils.assertAtStartTag(parser);
|
||||||
final int initialDepth = parser.getDepth();
|
final int initialDepth = parser.getDepth();
|
||||||
boolean optional = false;
|
boolean optional = false;
|
||||||
if (parser.isEmptyElementTag()) {
|
|
||||||
return new Session.Feature(optional);
|
|
||||||
}
|
|
||||||
|
|
||||||
outerloop: while (true) {
|
outerloop: while (true) {
|
||||||
int event = parser.next();
|
XmlPullParser.Event event = parser.next();
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case XmlPullParser.START_TAG:
|
case START_ELEMENT:
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case Session.Feature.OPTIONAL_ELEMENT:
|
case Session.Feature.OPTIONAL_ELEMENT:
|
||||||
|
@ -993,10 +920,14 @@ public class PacketParserUtils {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XmlPullParser.END_TAG:
|
case END_ELEMENT:
|
||||||
if (parser.getDepth() == initialDepth) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
break outerloop;
|
break outerloop;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,15 @@ import java.text.ParseException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.xml.XMLConstants;
|
|
||||||
import javax.xml.namespace.QName;
|
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;
|
||||||
import org.jivesoftware.smack.parsing.SmackParsingException.SmackTextParseException;
|
import org.jivesoftware.smack.parsing.SmackParsingException.SmackTextParseException;
|
||||||
import org.jivesoftware.smack.parsing.SmackParsingException.SmackUriSyntaxParsingException;
|
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.EntityBareJid;
|
||||||
import org.jxmpp.jid.EntityFullJid;
|
import org.jxmpp.jid.EntityFullJid;
|
||||||
|
@ -38,8 +41,6 @@ import org.jxmpp.jid.impl.JidCreate;
|
||||||
import org.jxmpp.jid.parts.Resourcepart;
|
import org.jxmpp.jid.parts.Resourcepart;
|
||||||
import org.jxmpp.stringprep.XmppStringprepException;
|
import org.jxmpp.stringprep.XmppStringprepException;
|
||||||
import org.jxmpp.util.XmppDateTime;
|
import org.jxmpp.util.XmppDateTime;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
public class ParserUtils {
|
public class ParserUtils {
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ public class ParserUtils {
|
||||||
public static final String JID = "jid";
|
public static final String JID = "jid";
|
||||||
|
|
||||||
public static void assertAtStartTag(XmlPullParser parser) throws XmlPullParserException {
|
public static void assertAtStartTag(XmlPullParser parser) throws XmlPullParserException {
|
||||||
assert (parser.getEventType() == XmlPullParser.START_TAG);
|
assert (parser.getEventType() == XmlPullParser.Event.START_ELEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertAtStartTag(XmlPullParser parser, String name) throws XmlPullParserException {
|
public static void assertAtStartTag(XmlPullParser parser, String name) throws XmlPullParserException {
|
||||||
|
@ -58,13 +59,13 @@ public class ParserUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertAtEndTag(XmlPullParser parser) throws XmlPullParserException {
|
public static void assertAtEndTag(XmlPullParser parser) throws XmlPullParserException {
|
||||||
assert (parser.getEventType() == XmlPullParser.END_TAG);
|
assert (parser.getEventType() == XmlPullParser.Event.END_ELEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void forwardToEndTagOfDepth(XmlPullParser parser, int depth)
|
public static void forwardToEndTagOfDepth(XmlPullParser parser, int depth)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
int event = parser.getEventType();
|
XmlPullParser.Event event = parser.getEventType();
|
||||||
while (!(event == XmlPullParser.END_TAG && parser.getDepth() == depth)) {
|
while (!(event == XmlPullParser.Event.END_ELEMENT && parser.getDepth() == depth)) {
|
||||||
event = parser.next();
|
event = parser.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,6 +179,11 @@ 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)
|
public static int getIntegerAttributeOrThrow(XmlPullParser parser, String name, String throwMessage)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
Integer res = getIntegerAttribute(parser, name);
|
Integer res = getIntegerAttribute(parser, name);
|
||||||
|
@ -205,6 +211,14 @@ 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 {
|
public static int getIntegerFromNextText(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||||
String intString = parser.nextText();
|
String intString = parser.nextText();
|
||||||
return Integer.valueOf(intString);
|
return Integer.valueOf(intString);
|
||||||
|
@ -227,6 +241,14 @@ 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 {
|
public static double getDoubleFromNextText(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||||
String doubleString = parser.nextText();
|
String doubleString = parser.nextText();
|
||||||
return Double.valueOf(doubleString);
|
return Double.valueOf(doubleString);
|
||||||
|
@ -323,13 +345,16 @@ public class ParserUtils {
|
||||||
return parser.getAttributeValue("http://www.w3.org/XML/1998/namespace", "lang");
|
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) {
|
public static QName getQName(XmlPullParser parser) {
|
||||||
String elementName = parser.getName();
|
return parser.getQName();
|
||||||
String prefix = parser.getPrefix();
|
|
||||||
if (prefix == null) {
|
|
||||||
prefix = XMLConstants.DEFAULT_NS_PREFIX;
|
|
||||||
}
|
|
||||||
String namespace = parser.getNamespace();
|
|
||||||
return new QName(namespace, elementName, prefix);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
|
|
||||||
package org.jivesoftware.smack.util;
|
package org.jivesoftware.smack.util;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.IOException;
|
||||||
|
import java.nio.CharBuffer;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
@ -29,7 +31,23 @@ public class StringUtils {
|
||||||
|
|
||||||
public static final String MD5 = "MD5";
|
public static final String MD5 = "MD5";
|
||||||
public static final String SHA1 = "SHA-1";
|
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";
|
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 USASCII = "US-ASCII";
|
||||||
|
|
||||||
public static final String QUOTE_ENCODE = """;
|
public static final String QUOTE_ENCODE = """;
|
||||||
|
@ -244,22 +262,13 @@ public class StringUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] toUtf8Bytes(String string) {
|
public static byte[] toUtf8Bytes(String string) {
|
||||||
try {
|
return string.getBytes(StandardCharsets.UTF_8);
|
||||||
return string.getBytes(StringUtils.UTF8);
|
|
||||||
}
|
|
||||||
catch (UnsupportedEncodingException e) {
|
|
||||||
throw new IllegalStateException("UTF-8 encoding not supported by platform", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of numbers and letters of mixed case. Numbers appear in the list
|
* 24 upper case characters from the latin alphabet and numbers without '0' and 'O'.
|
||||||
* 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[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" +
|
private static final char[] UNAMBIGUOUS_NUMBERS_AND_LETTER = "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ".toCharArray();
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a random String of numbers and letters (lower and upper case)
|
* Returns a random String of numbers and letters (lower and upper case)
|
||||||
|
@ -278,6 +287,74 @@ public class StringUtils {
|
||||||
return randomString(length, RandomUtil.RANDOM.get());
|
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) {
|
public static String randomString(final int length) {
|
||||||
return randomString(length, RandomUtil.SECURE_RANDOM.get());
|
return randomString(length, RandomUtil.SECURE_RANDOM.get());
|
||||||
}
|
}
|
||||||
|
@ -287,24 +364,14 @@ public class StringUtils {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] randomBytes = new byte[length];
|
|
||||||
random.nextBytes(randomBytes);
|
|
||||||
char[] randomChars = new char[length];
|
char[] randomChars = new char[length];
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
randomChars[i] = getPrintableChar(randomBytes[i]);
|
int index = random.nextInt(UNAMBIGUOUS_NUMBERS_AND_LETTER.length);
|
||||||
|
randomChars[i] = UNAMBIGUOUS_NUMBERS_AND_LETTER[index];
|
||||||
}
|
}
|
||||||
return new String(randomChars);
|
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.
|
* Returns true if CharSequence is not null and is not empty, false otherwise.
|
||||||
* Examples:
|
* Examples:
|
||||||
|
|
|
@ -64,7 +64,7 @@ public class TLSUtils {
|
||||||
*
|
*
|
||||||
* @return the given builder
|
* @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 });
|
builder.setEnabledSSLProtocols(new String[] { PROTO_TLSV1_2, PROTO_TLSV1_1, PROTO_TLSV1 });
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ public class TLSUtils {
|
||||||
*
|
*
|
||||||
* @return the given builder
|
* @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 });
|
builder.setEnabledSSLProtocols(new String[] { PROTO_TLSV1_2, PROTO_TLSV1_1, PROTO_TLSV1, PROTO_SSL3 });
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ public class TLSUtils {
|
||||||
* @throws KeyManagementException
|
* @throws KeyManagementException
|
||||||
* @return the given builder.
|
* @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);
|
SSLContext context = SSLContext.getInstance(TLS);
|
||||||
context.init(null, new TrustManager[] { new AcceptAllTrustManager() }, new SecureRandom());
|
context.init(null, new TrustManager[] { new AcceptAllTrustManager() }, new SecureRandom());
|
||||||
builder.setCustomSSLContext(context);
|
builder.setCustomSSLContext(context);
|
||||||
|
@ -130,7 +130,7 @@ public class TLSUtils {
|
||||||
* @param <B> Type of the ConnectionConfiguration builder.
|
* @param <B> Type of the ConnectionConfiguration builder.
|
||||||
* @return the given 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);
|
builder.setHostnameVerifier(DOES_NOT_VERIFY_VERIFIER);
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,10 +269,20 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element {
|
||||||
|
|
||||||
public XmlStringBuilder attribute(String name, Enum<?> value) {
|
public XmlStringBuilder attribute(String name, Enum<?> value) {
|
||||||
assert value != null;
|
assert value != null;
|
||||||
|
// TODO: Should use toString() instead of name().
|
||||||
attribute(name, value.name());
|
attribute(name, value.name());
|
||||||
return this;
|
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) {
|
public XmlStringBuilder attribute(String name, int value) {
|
||||||
assert name != null;
|
assert name != null;
|
||||||
return attribute(name, String.valueOf(value));
|
return attribute(name, String.valueOf(value));
|
||||||
|
@ -327,6 +337,13 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element {
|
||||||
return this;
|
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}.
|
* Add the given attribute if {@code value => 0}.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2018 Florian Schmaus
|
* Copyright 2018-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +16,13 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.util;
|
package org.jivesoftware.smack.util;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.FullyQualifiedElement;
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.jxmpp.util.XmppStringUtils;
|
import org.jivesoftware.smack.packet.FullyQualifiedElement;
|
||||||
|
|
||||||
public class XmppElementUtil {
|
public class XmppElementUtil {
|
||||||
|
|
||||||
public static String getKeyFor(Class<? extends FullyQualifiedElement> fullyQualifiedElement) {
|
public static QName getQNameFor(Class<? extends FullyQualifiedElement> fullyQualifiedElement) {
|
||||||
String element, namespace;
|
String element, namespace;
|
||||||
try {
|
try {
|
||||||
element = (String) fullyQualifiedElement.getField("ELEMENT").get(null);
|
element = (String) fullyQualifiedElement.getField("ELEMENT").get(null);
|
||||||
|
@ -32,14 +32,7 @@ public class XmppElementUtil {
|
||||||
throw new IllegalArgumentException(e);
|
throw new IllegalArgumentException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
String key = XmppStringUtils.generateKey(element, namespace);
|
return new QName(namespace, element);
|
||||||
return key;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getKeyFor(FullyQualifiedElement fullyQualifiedElement) {
|
|
||||||
String element = fullyQualifiedElement.getElementName();
|
|
||||||
String namespace = fullyQualifiedElement.getNamespace();
|
|
||||||
String key = XmppStringUtils.generateKey(element, namespace);
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,7 @@ package org.jivesoftware.smack.util.stringencoder;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base32 string encoding is useful for when filenames case-insensitive filesystems are encoded.
|
* Base32 string encoding is useful for when filenames case-insensitive filesystems are encoded.
|
||||||
|
@ -55,13 +53,8 @@ public class Base32 {
|
||||||
|
|
||||||
public static String decode(String str) {
|
public static String decode(String str) {
|
||||||
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
||||||
byte[] raw;
|
byte[] raw = str.getBytes(StandardCharsets.UTF_8);
|
||||||
try {
|
|
||||||
raw = str.getBytes(StringUtils.UTF8);
|
|
||||||
}
|
|
||||||
catch (UnsupportedEncodingException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < raw.length; i++) {
|
for (int i = 0; i < raw.length; i++) {
|
||||||
char c = (char) raw[i];
|
char c = (char) raw[i];
|
||||||
if (!Character.isWhitespace(c)) {
|
if (!Character.isWhitespace(c)) {
|
||||||
|
@ -114,24 +107,12 @@ public class Base32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String res;
|
String res = new String(bs.toByteArray(), StandardCharsets.UTF_8);
|
||||||
try {
|
|
||||||
res = new String(bs.toByteArray(), StringUtils.UTF8);
|
|
||||||
}
|
|
||||||
catch (UnsupportedEncodingException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String encode(String str) {
|
public static String encode(String str) {
|
||||||
byte[] b;
|
byte[] b = str.getBytes(StandardCharsets.UTF_8);
|
||||||
try {
|
|
||||||
b = str.getBytes(StringUtils.UTF8);
|
|
||||||
}
|
|
||||||
catch (UnsupportedEncodingException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
|
||||||
for (int i = 0; i < (b.length + 4) / 5; i++) {
|
for (int i = 0; i < (b.length + 4) / 5; i++) {
|
||||||
|
@ -174,13 +155,7 @@ public class Base32 {
|
||||||
os.write(c);
|
os.write(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String res;
|
String res = new String(os.toByteArray(), StandardCharsets.UTF_8);
|
||||||
try {
|
|
||||||
res = new String(os.toByteArray(), StringUtils.UTF8);
|
|
||||||
}
|
|
||||||
catch (UnsupportedEncodingException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,9 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.util.stringencoder;
|
package org.jivesoftware.smack.util.stringencoder;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.Objects;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
|
||||||
|
|
||||||
public class Base64 {
|
public class Base64 {
|
||||||
|
|
||||||
|
@ -31,11 +30,7 @@ public class Base64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String encode(String string) {
|
public static final String encode(String string) {
|
||||||
try {
|
return encodeToString(string.getBytes(StandardCharsets.UTF_8));
|
||||||
return encodeToString(string.getBytes(StringUtils.UTF8));
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new IllegalStateException("UTF-8 not supported", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String encodeToString(byte[] input) {
|
public static final String encodeToString(byte[] input) {
|
||||||
|
@ -56,11 +51,7 @@ public class Base64 {
|
||||||
|
|
||||||
public static final String decodeToString(String string) {
|
public static final String decodeToString(String string) {
|
||||||
byte[] bytes = decode(string);
|
byte[] bytes = decode(string);
|
||||||
try {
|
return new String(bytes, StandardCharsets.UTF_8);
|
||||||
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
|
// TODO: We really should not mask the IllegalArgumentException. But some unit test depend on this behavior, like
|
||||||
|
@ -74,12 +65,7 @@ public class Base64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final byte[] decode(byte[] input) {
|
public static final byte[] decode(byte[] input) {
|
||||||
String string;
|
String string = new String(input, StandardCharsets.US_ASCII);
|
||||||
try {
|
|
||||||
string = new String(input, StringUtils.USASCII);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
return decode(string);
|
return decode(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class StanzaCollectorTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void verifyRollover() throws InterruptedException {
|
public void verifyRollover() throws InterruptedException {
|
||||||
TestStanzaCollector collector = new TestStanzaCollector(null, new OKEverything(), 5);
|
StanzaCollector collector = createTestStanzaCollector(null, new OKEverything(), 5);
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
Stanza testPacket = new TestPacket(i);
|
Stanza testPacket = new TestPacket(i);
|
||||||
|
@ -70,7 +70,7 @@ public class StanzaCollectorTest {
|
||||||
@Test
|
@Test
|
||||||
public void verifyThreadSafety() throws InterruptedException {
|
public void verifyThreadSafety() throws InterruptedException {
|
||||||
final int insertCount = 500;
|
final int insertCount = 500;
|
||||||
final TestStanzaCollector collector = new TestStanzaCollector(null, new OKEverything(), insertCount);
|
final StanzaCollector collector = createTestStanzaCollector(null, new OKEverything(), insertCount);
|
||||||
|
|
||||||
final AtomicInteger consumer1Dequeued = new AtomicInteger();
|
final AtomicInteger consumer1Dequeued = new AtomicInteger();
|
||||||
final AtomicInteger consumer2Dequeued = new AtomicInteger();
|
final AtomicInteger consumer2Dequeued = new AtomicInteger();
|
||||||
|
@ -170,10 +170,8 @@ public class StanzaCollectorTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TestStanzaCollector extends StanzaCollector {
|
private static StanzaCollector createTestStanzaCollector(XMPPConnection connection, StanzaFilter packetFilter, int size) {
|
||||||
protected TestStanzaCollector(XMPPConnection conection, StanzaFilter packetFilter, int size) {
|
return new StanzaCollector(connection, StanzaCollector.newConfiguration().setStanzaFilter(packetFilter).setSize(size));
|
||||||
super(conection, StanzaCollector.newConfiguration().setStanzaFilter(packetFilter).setSize(size));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TestPacket extends Stanza {
|
static class TestPacket extends Stanza {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.compress.packet;
|
package org.jivesoftware.smack.compress.packet;
|
||||||
|
|
||||||
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
|
import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public class FailureTest {
|
||||||
|
|
||||||
final String expectedXml = "<failure xmlns='http://jabber.org/protocol/compress'><processing-failed/></failure>";
|
final String expectedXml = "<failure xmlns='http://jabber.org/protocol/compress'><processing-failed/></failure>";
|
||||||
|
|
||||||
assertXMLEqual(expectedXml, xml.toString());
|
assertXmlSimilar(expectedXml, xml.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -53,6 +53,6 @@ public class FailureTest {
|
||||||
+ "</error>"
|
+ "</error>"
|
||||||
+ "</failure>";
|
+ "</failure>";
|
||||||
|
|
||||||
assertXMLEqual(expectedXml, xml.toString());
|
assertXmlSimilar(expectedXml, xml.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2018 Florian Schmaus
|
* Copyright 2018-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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;
|
||||||
import org.jivesoftware.smack.packet.StanzaError.Condition;
|
import org.jivesoftware.smack.packet.StanzaError.Condition;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
|
|
||||||
public class FailureProviderTest {
|
public class FailureProviderTest {
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.packet;
|
package org.jivesoftware.smack.packet;
|
||||||
|
|
||||||
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
|
import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
@ -26,8 +26,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jivesoftware.smack.test.util.XmlUnitUtils;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
@ -49,7 +47,7 @@ public class MessageTest {
|
||||||
Message messageTypeInConstructor = new Message(null, Message.Type.chat);
|
Message messageTypeInConstructor = new Message(null, Message.Type.chat);
|
||||||
messageTypeInConstructor.setStanzaId(null);
|
messageTypeInConstructor.setStanzaId(null);
|
||||||
assertEquals(type, messageTypeInConstructor.getType());
|
assertEquals(type, messageTypeInConstructor.getType());
|
||||||
assertXMLEqual(control, messageTypeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, messageTypeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
controlBuilder = new StringBuilder();
|
controlBuilder = new StringBuilder();
|
||||||
controlBuilder.append("<message")
|
controlBuilder.append("<message")
|
||||||
|
@ -62,7 +60,7 @@ public class MessageTest {
|
||||||
Message messageTypeSet = getNewMessage();
|
Message messageTypeSet = getNewMessage();
|
||||||
messageTypeSet.setType(type2);
|
messageTypeSet.setType(type2);
|
||||||
assertEquals(type2, messageTypeSet.getType());
|
assertEquals(type2, messageTypeSet.getType());
|
||||||
assertXMLEqual(control, messageTypeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, messageTypeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
@Test(expected = NullPointerException.class)
|
||||||
|
@ -87,7 +85,7 @@ public class MessageTest {
|
||||||
message.setSubject(messageSubject);
|
message.setSubject(messageSubject);
|
||||||
|
|
||||||
assertEquals(messageSubject, message.getSubject());
|
assertEquals(messageSubject, message.getSubject());
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -106,7 +104,7 @@ public class MessageTest {
|
||||||
message.setBody(messageBody);
|
message.setBody(messageBody);
|
||||||
|
|
||||||
assertEquals(messageBody, message.getBody());
|
assertEquals(messageBody, message.getBody());
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -139,7 +137,7 @@ public class MessageTest {
|
||||||
message.addBody(null, messageBody1);
|
message.addBody(null, messageBody1);
|
||||||
message.addBody(lang2, messageBody2);
|
message.addBody(lang2, messageBody2);
|
||||||
message.addBody(lang3, messageBody3);
|
message.addBody(lang3, messageBody3);
|
||||||
XmlUnitUtils.assertSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE));
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE));
|
||||||
|
|
||||||
Collection<String> languages = message.getBodyLanguages();
|
Collection<String> languages = message.getBodyLanguages();
|
||||||
List<String> controlLanguages = new ArrayList<>();
|
List<String> controlLanguages = new ArrayList<>();
|
||||||
|
@ -183,7 +181,7 @@ public class MessageTest {
|
||||||
message.setThread(messageThread);
|
message.setThread(messageThread);
|
||||||
|
|
||||||
assertEquals(messageThread, message.getThread());
|
assertEquals(messageThread, message.getThread());
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -201,7 +199,7 @@ public class MessageTest {
|
||||||
Message message = getNewMessage();
|
Message message = getNewMessage();
|
||||||
message.setLanguage(lang);
|
message.setLanguage(lang);
|
||||||
|
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Message getNewMessage() {
|
private static Message getNewMessage() {
|
||||||
|
|
|
@ -16,14 +16,15 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.packet;
|
package org.jivesoftware.smack.packet;
|
||||||
|
|
||||||
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
|
import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
public class PresenceTest {
|
public class PresenceTest {
|
||||||
|
@ -43,7 +44,7 @@ public class PresenceTest {
|
||||||
Presence presenceTypeInConstructor = new Presence(type);
|
Presence presenceTypeInConstructor = new Presence(type);
|
||||||
presenceTypeInConstructor.setStanzaId(null);
|
presenceTypeInConstructor.setStanzaId(null);
|
||||||
assertEquals(type, presenceTypeInConstructor.getType());
|
assertEquals(type, presenceTypeInConstructor.getType());
|
||||||
assertXMLEqual(control, presenceTypeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, presenceTypeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
controlBuilder = new StringBuilder();
|
controlBuilder = new StringBuilder();
|
||||||
controlBuilder.append("<presence")
|
controlBuilder.append("<presence")
|
||||||
|
@ -56,12 +57,14 @@ public class PresenceTest {
|
||||||
Presence presenceTypeSet = getNewPresence();
|
Presence presenceTypeSet = getNewPresence();
|
||||||
presenceTypeSet.setType(type2);
|
presenceTypeSet.setType(type2);
|
||||||
assertEquals(type2, presenceTypeSet.getType());
|
assertEquals(type2, presenceTypeSet.getType());
|
||||||
assertXMLEqual(control, presenceTypeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, presenceTypeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
@Test
|
||||||
public void setNullPresenceTypeTest() {
|
public void setNullPresenceTypeTest() {
|
||||||
getNewPresence().setType(null);
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
getNewPresence().setType(null)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -90,7 +93,7 @@ public class PresenceTest {
|
||||||
presence.setStatus(status);
|
presence.setStatus(status);
|
||||||
|
|
||||||
assertEquals(status, presence.getStatus());
|
assertEquals(status, presence.getStatus());
|
||||||
assertXMLEqual(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -109,12 +112,14 @@ public class PresenceTest {
|
||||||
presence.setPriority(priority);
|
presence.setPriority(priority);
|
||||||
|
|
||||||
assertEquals(priority, presence.getPriority());
|
assertEquals(priority, presence.getPriority());
|
||||||
assertXMLEqual(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
public void setIllegalPriorityTest() {
|
public void setIllegalPriorityTest() {
|
||||||
getNewPresence().setPriority(Integer.MIN_VALUE);
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
getNewPresence().setPriority(Integer.MIN_VALUE)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -142,7 +147,7 @@ public class PresenceTest {
|
||||||
mode1);
|
mode1);
|
||||||
presenceModeInConstructor.setStanzaId(null);
|
presenceModeInConstructor.setStanzaId(null);
|
||||||
assertEquals(mode1, presenceModeInConstructor.getMode());
|
assertEquals(mode1, presenceModeInConstructor.getMode());
|
||||||
assertXMLEqual(control, presenceModeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, presenceModeInConstructor.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
controlBuilder = new StringBuilder();
|
controlBuilder = new StringBuilder();
|
||||||
controlBuilder.append("<presence>")
|
controlBuilder.append("<presence>")
|
||||||
|
@ -155,7 +160,7 @@ public class PresenceTest {
|
||||||
Presence presenceModeSet = getNewPresence();
|
Presence presenceModeSet = getNewPresence();
|
||||||
presenceModeSet.setMode(mode2);
|
presenceModeSet.setMode(mode2);
|
||||||
assertEquals(mode2, presenceModeSet.getMode());
|
assertEquals(mode2, presenceModeSet.getMode());
|
||||||
assertXMLEqual(control, presenceModeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, presenceModeSet.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -183,7 +188,7 @@ public class PresenceTest {
|
||||||
Presence presence = getNewPresence();
|
Presence presence = getNewPresence();
|
||||||
presence.setLanguage(lang);
|
presence.setLanguage(lang);
|
||||||
|
|
||||||
assertXMLEqual(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Presence getNewPresence() {
|
private static Presence getNewPresence() {
|
||||||
|
|
|
@ -18,19 +18,25 @@ package org.jivesoftware.smack.packet;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.StreamError.Condition;
|
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.util.PacketParserUtils;
|
||||||
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.junit.jupiter.params.provider.EnumSource;
|
||||||
|
|
||||||
public class StreamErrorTest {
|
public class StreamErrorTest {
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testParsingOfSimpleStreamError() {
|
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
|
||||||
StreamError error = null;
|
public void testParsingOfSimpleStreamError(SmackTestUtil.XmlPullParserKind parserKind)
|
||||||
|
throws XmlPullParserException, IOException, SmackParsingException {
|
||||||
final String xml =
|
final String xml =
|
||||||
// Usually the stream:stream element has more attributes (to, version, ...)
|
// Usually the stream:stream element has more attributes (to, version, ...)
|
||||||
// We omit those, since they are not relevant for testing
|
// We omit those, since they are not relevant for testing
|
||||||
|
@ -39,19 +45,17 @@ public class StreamErrorTest {
|
||||||
"<conflict xmlns='urn:ietf:params:xml:ns:xmpp-streams' /> +" +
|
"<conflict xmlns='urn:ietf:params:xml:ns:xmpp-streams' /> +" +
|
||||||
"</stream:error>" +
|
"</stream:error>" +
|
||||||
"</stream:stream>";
|
"</stream:stream>";
|
||||||
try {
|
|
||||||
XmlPullParser parser = PacketParserUtils.getParserFor(xml, "error");
|
XmlPullParser parser = SmackTestUtil.getParserFor(xml, "error", parserKind);
|
||||||
error = PacketParserUtils.parseStreamError(parser);
|
StreamError error = PacketParserUtils.parseStreamError(parser);
|
||||||
} catch (Exception e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
assertNotNull(error);
|
assertNotNull(error);
|
||||||
assertEquals(Condition.conflict, error.getCondition());
|
assertEquals(Condition.conflict, error.getCondition());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testParsingOfStreamErrorWithText() {
|
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
|
||||||
StreamError error = null;
|
public void testParsingOfStreamErrorWithText(SmackTestUtil.XmlPullParserKind parserKind) throws XmlPullParserException, IOException, SmackParsingException {
|
||||||
final String xml =
|
final String xml =
|
||||||
// Usually the stream:stream element has more attributes (to, version, ...)
|
// Usually the stream:stream element has more attributes (to, version, ...)
|
||||||
// We omit those, since they are not relevant for testing
|
// We omit those, since they are not relevant for testing
|
||||||
|
@ -63,20 +67,19 @@ public class StreamErrorTest {
|
||||||
"</text>" +
|
"</text>" +
|
||||||
"</stream:error>" +
|
"</stream:error>" +
|
||||||
"</stream:stream>";
|
"</stream:stream>";
|
||||||
try {
|
|
||||||
XmlPullParser parser = PacketParserUtils.getParserFor(xml, "error");
|
XmlPullParser parser = SmackTestUtil.getParserFor(xml, "error", parserKind);
|
||||||
error = PacketParserUtils.parseStreamError(parser);
|
StreamError error = PacketParserUtils.parseStreamError(parser);
|
||||||
} catch (Exception e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
assertNotNull(error);
|
assertNotNull(error);
|
||||||
assertEquals(Condition.conflict, error.getCondition());
|
assertEquals(Condition.conflict, error.getCondition());
|
||||||
assertEquals("Replaced by new connection", error.getDescriptiveText());
|
assertEquals("Replaced by new connection", error.getDescriptiveText());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testParsingOfStreamErrorWithTextAndOptionalElement() {
|
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
|
||||||
StreamError error = null;
|
public void testParsingOfStreamErrorWithTextAndOptionalElement(SmackTestUtil.XmlPullParserKind parserKind)
|
||||||
|
throws XmlPullParserException, IOException, SmackParsingException {
|
||||||
final String xml =
|
final String xml =
|
||||||
// Usually the stream:stream element has more attributes (to, version, ...)
|
// Usually the stream:stream element has more attributes (to, version, ...)
|
||||||
// We omit those, since they are not relevant for testing
|
// We omit those, since they are not relevant for testing
|
||||||
|
@ -91,12 +94,10 @@ public class StreamErrorTest {
|
||||||
"</appSpecificElement>" +
|
"</appSpecificElement>" +
|
||||||
"</stream:error>" +
|
"</stream:error>" +
|
||||||
"</stream:stream>";
|
"</stream:stream>";
|
||||||
try {
|
|
||||||
XmlPullParser parser = PacketParserUtils.getParserFor(xml, "error");
|
XmlPullParser parser = SmackTestUtil.getParserFor(xml, "error", parserKind);
|
||||||
error = PacketParserUtils.parseStreamError(parser);
|
StreamError error = PacketParserUtils.parseStreamError(parser);
|
||||||
} catch (Exception e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
assertNotNull(error);
|
assertNotNull(error);
|
||||||
assertEquals(Condition.conflict, error.getCondition());
|
assertEquals(Condition.conflict, error.getCondition());
|
||||||
assertEquals("Replaced by new connection", error.getDescriptiveText());
|
assertEquals("Replaced by new connection", error.getDescriptiveText());
|
||||||
|
@ -104,21 +105,20 @@ public class StreamErrorTest {
|
||||||
assertNotNull(appSpecificElement);
|
assertNotNull(appSpecificElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testStreamErrorXmlNotWellFormed() {
|
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
|
||||||
StreamError error = null;
|
public void testStreamErrorXmlNotWellFormed(SmackTestUtil.XmlPullParserKind parserKind)
|
||||||
|
throws XmlPullParserException, IOException, SmackParsingException {
|
||||||
final String xml =
|
final String xml =
|
||||||
// Usually the stream:stream element has more attributes (to, version, ...)
|
// Usually the stream:stream element has more attributes (to, version, ...)
|
||||||
// We omit those, since they are not relevant for testing
|
// 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: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:error><xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/></stream:error>" +
|
||||||
"</stream:stream>";
|
"</stream:stream>";
|
||||||
try {
|
|
||||||
XmlPullParser parser = PacketParserUtils.getParserFor(xml, "error");
|
XmlPullParser parser = SmackTestUtil.getParserFor(xml, "error", parserKind);
|
||||||
error = PacketParserUtils.parseStreamError(parser);
|
StreamError error = PacketParserUtils.parseStreamError(parser);
|
||||||
} catch (Exception e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
assertNotNull(error);
|
assertNotNull(error);
|
||||||
assertEquals(Condition.not_well_formed, error.getCondition());
|
assertEquals(Condition.not_well_formed, error.getCondition());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright © 2014 Florian Schmaus
|
* Copyright © 2014-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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 class TestIQ extends SimpleIQ {
|
||||||
|
|
||||||
public TestIQ() {
|
public TestIQ() {
|
||||||
this(null, null);
|
this("https://igniterealtime.org/projects/smack", "test-iq");
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestIQ(String element, String namespace) {
|
public TestIQ(String element, String namespace) {
|
||||||
|
|
|
@ -27,11 +27,11 @@ import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
||||||
import org.jivesoftware.smack.provider.ProviderManager;
|
import org.jivesoftware.smack.provider.ProviderManager;
|
||||||
import org.jivesoftware.smack.test.util.TestUtils;
|
import org.jivesoftware.smack.test.util.TestUtils;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
|
|
||||||
public class ParsingExceptionTest {
|
public class ParsingExceptionTest {
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ public class ParsingExceptionTest {
|
||||||
"<extension2 xmlns='namespace'>" +
|
"<extension2 xmlns='namespace'>" +
|
||||||
"<bar node='testNode'>" +
|
"<bar node='testNode'>" +
|
||||||
"<i id='testid1'>" +
|
"<i id='testid1'>" +
|
||||||
|
"text content" +
|
||||||
"</i>" +
|
"</i>" +
|
||||||
"</bar>" +
|
"</bar>" +
|
||||||
"</extension2>";
|
"</extension2>";
|
||||||
|
@ -57,8 +58,7 @@ public class ParsingExceptionTest {
|
||||||
public void consumeUnparsedInput() throws Exception {
|
public void consumeUnparsedInput() throws Exception {
|
||||||
final String MESSAGE_EXCEPTION_ELEMENT =
|
final String MESSAGE_EXCEPTION_ELEMENT =
|
||||||
"<" + ThrowException.ELEMENT + " xmlns='" + ThrowException.NAMESPACE + "'>" +
|
"<" + ThrowException.ELEMENT + " xmlns='" + ThrowException.NAMESPACE + "'>" +
|
||||||
"<nothingInHere>" +
|
"<nothingInHere/>" +
|
||||||
"</nothingInHere>" +
|
|
||||||
"</" + ThrowException.ELEMENT + ">";
|
"</" + ThrowException.ELEMENT + ">";
|
||||||
XmlPullParser parser = TestUtils.getMessageParser(
|
XmlPullParser parser = TestUtils.getMessageParser(
|
||||||
"<message from='user@server.example' to='francisco@denmark.lit' id='foo'>" +
|
"<message from='user@server.example' to='francisco@denmark.lit' id='foo'>" +
|
||||||
|
|
|
@ -22,10 +22,10 @@ import java.util.Collection;
|
||||||
import org.jivesoftware.smack.packet.IQ;
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
import org.jivesoftware.smack.util.FileUtils;
|
import org.jivesoftware.smack.util.FileUtils;
|
||||||
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
|
|
||||||
public class ProviderConfigTest {
|
public class ProviderConfigTest {
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,9 @@ import static org.junit.Assert.assertTrue;
|
||||||
import org.jivesoftware.smack.SmackConfiguration;
|
import org.jivesoftware.smack.SmackConfiguration;
|
||||||
import org.jivesoftware.smack.packet.IQ;
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
|
|
||||||
public class ProviderManagerTest {
|
public class ProviderManagerTest {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright © 2014-2017 Florian Schmaus
|
* Copyright © 2014-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,10 +16,10 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.sasl;
|
package org.jivesoftware.smack.sasl;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -39,14 +39,14 @@ public class DigestMd5SaslTest extends AbstractSaslTest {
|
||||||
super(saslMechanism);
|
super(saslMechanism);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void runTest(boolean useAuthzid) throws SmackException, InterruptedException, XmppStringprepException, UnsupportedEncodingException {
|
protected void runTest(boolean useAuthzid) throws SmackException, InterruptedException, XmppStringprepException {
|
||||||
EntityBareJid authzid = null;
|
EntityBareJid authzid = null;
|
||||||
if (useAuthzid) {
|
if (useAuthzid) {
|
||||||
authzid = JidCreate.entityBareFrom("shazbat@xmpp.org");
|
authzid = JidCreate.entityBareFrom("shazbat@xmpp.org");
|
||||||
}
|
}
|
||||||
saslMechanism.authenticate("florian", "irrelevant", JidCreate.domainBareFrom("xmpp.org"), "secret", authzid, null);
|
saslMechanism.authenticate("florian", "irrelevant", JidCreate.domainBareFrom("xmpp.org"), "secret", authzid, null);
|
||||||
byte[] response = saslMechanism.evaluateChallenge(challengeBytes);
|
byte[] response = saslMechanism.evaluateChallenge(challengeBytes);
|
||||||
String responseString = new String(response, StringUtils.UTF8);
|
String responseString = new String(response, StandardCharsets.UTF_8);
|
||||||
String[] responseParts = responseString.split(",");
|
String[] responseParts = responseString.split(",");
|
||||||
Map<String, String> responsePairs = new HashMap<String, String>();
|
Map<String, String> responsePairs = new HashMap<String, String>();
|
||||||
for (String part : responseParts) {
|
for (String part : responseParts) {
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.jivesoftware.smack.test.util;
|
||||||
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.SmackConfiguration;
|
||||||
import org.jivesoftware.smack.util.stringencoder.Base64.Encoder;
|
import org.jivesoftware.smack.util.stringencoder.Base64.Encoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,6 +28,7 @@ import org.jivesoftware.smack.util.stringencoder.Base64.Encoder;
|
||||||
public class SmackTestSuite {
|
public class SmackTestSuite {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
SmackConfiguration.getVersion();
|
||||||
org.jivesoftware.smack.util.stringencoder.Base64.setEncoder(new Encoder() {
|
org.jivesoftware.smack.util.stringencoder.Base64.setEncoder(new Encoder() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,14 +20,11 @@ import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
import org.jivesoftware.smack.xml.SmackXmlParser;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
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 {
|
public final class TestUtils {
|
||||||
private TestUtils() {
|
private TestUtils() {
|
||||||
}
|
}
|
||||||
|
@ -52,12 +49,12 @@ public final class TestUtils {
|
||||||
return getParser(new StringReader(string), startTag);
|
return getParser(new StringReader(string), startTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static XmlPullParser getParser(Reader reader, String startTag) {
|
private static XmlPullParser getParser(Reader reader, String startTag) {
|
||||||
XmlPullParser parser;
|
XmlPullParser parser;
|
||||||
try {
|
try {
|
||||||
parser = PacketParserUtils.newXmppParser(reader);
|
parser = SmackXmlParser.newXmlParser(reader);
|
||||||
if (startTag == null) {
|
if (startTag == null) {
|
||||||
while (parser.getEventType() != XmlPullParser.START_TAG) {
|
while (parser.getEventType() != XmlPullParser.Event.START_ELEMENT) {
|
||||||
parser.next();
|
parser.next();
|
||||||
}
|
}
|
||||||
return parser;
|
return parser;
|
||||||
|
@ -65,7 +62,7 @@ public final class TestUtils {
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
|
|
||||||
while (!found) {
|
while (!found) {
|
||||||
if ((parser.next() == XmlPullParser.START_TAG) && parser.getName().equals(startTag))
|
if ((parser.next() == XmlPullParser.Event.START_ELEMENT) && parser.getName().equals(startTag))
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,17 +76,4 @@ public final class TestUtils {
|
||||||
return parser;
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2014-2018 Florian Schmaus
|
* Copyright 2014-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,24 +16,36 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.test.util;
|
package org.jivesoftware.smack.test.util;
|
||||||
|
|
||||||
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
|
import java.io.StringReader;
|
||||||
|
|
||||||
import java.io.IOException;
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
|
||||||
import org.custommonkey.xmlunit.Diff;
|
import org.xmlunit.assertj.CompareAssert;
|
||||||
import org.custommonkey.xmlunit.examples.RecursiveElementNameAndTextQualifier;
|
import org.xmlunit.assertj.XmlAssert;
|
||||||
import org.xml.sax.SAXException;
|
import org.xmlunit.diff.DefaultNodeMatcher;
|
||||||
|
import org.xmlunit.diff.ElementSelectors;
|
||||||
|
import org.xmlunit.input.NormalizedSource;
|
||||||
|
|
||||||
|
// TODO: Rename this class to XmlAssertUtil
|
||||||
public class XmlUnitUtils {
|
public class XmlUnitUtils {
|
||||||
|
|
||||||
// TOOD: Remove this method.
|
public static void assertXmlNotSimilar(CharSequence xmlOne, CharSequence xmlTwo) {
|
||||||
public static void assertSimilar(CharSequence expected, CharSequence actual) throws SAXException, IOException {
|
normalizedCompare(xmlOne, xmlTwo).areNotSimilar();
|
||||||
assertXmlSimilar(expected, actual);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertXmlSimilar(CharSequence expected, CharSequence actual) throws SAXException, IOException {
|
public static void assertXmlSimilar(CharSequence expected, CharSequence actual) {
|
||||||
Diff diff = new Diff(expected.toString(), actual.toString());
|
normalizedCompare(expected, actual).areSimilar();
|
||||||
diff.overrideElementQualifier(new RecursiveElementNameAndTextQualifier());
|
}
|
||||||
assertXMLEqual(diff, true);
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.util;
|
package org.jivesoftware.smack.util;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
import java.lang.ref.PhantomReference;
|
import java.lang.ref.PhantomReference;
|
||||||
import java.lang.ref.Reference;
|
import java.lang.ref.Reference;
|
||||||
|
@ -51,6 +51,7 @@ public class MemoryLeakTestUtil {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(MemoryLeakTestUtil.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(MemoryLeakTestUtil.class.getName());
|
||||||
|
|
||||||
|
@SuppressWarnings("UnusedVariable")
|
||||||
public static <M extends Manager> void noResourceLeakTest(Function<DummyConnection, M> managerSupplier)
|
public static <M extends Manager> void noResourceLeakTest(Function<DummyConnection, M> managerSupplier)
|
||||||
throws XmppStringprepException, IllegalArgumentException, InterruptedException {
|
throws XmppStringprepException, IllegalArgumentException, InterruptedException {
|
||||||
final int numConnections = 10;
|
final int numConnections = 10;
|
||||||
|
@ -103,10 +104,27 @@ public class MemoryLeakTestUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assertReferencesQueueSize(ReferenceQueue<?> referenceQueue, int expectedSize) throws IllegalArgumentException, InterruptedException {
|
private static void assertReferencesQueueSize(ReferenceQueue<?> referenceQueue, int expectedSize) throws IllegalArgumentException, InterruptedException {
|
||||||
final int timeout = 60000;
|
final int timeout = 120000;
|
||||||
|
final int maxAttempts = 3;
|
||||||
for (int itemsRemoved = 0; itemsRemoved < expectedSize; ++itemsRemoved) {
|
for (int itemsRemoved = 0; itemsRemoved < expectedSize; ++itemsRemoved) {
|
||||||
Reference<?> reference = referenceQueue.remove(timeout);
|
int attempt = 0;
|
||||||
assertNotNull("No reference found after " + timeout + "ms", reference);
|
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.clear();
|
reference.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +137,7 @@ public class MemoryLeakTestUtil {
|
||||||
assertNull(reference);
|
assertNull(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("UnusedVariable")
|
||||||
private static void triggerGarbageCollection() {
|
private static void triggerGarbageCollection() {
|
||||||
Object object = new Object();
|
Object object = new Object();
|
||||||
WeakReference<Object> weakReference = new WeakReference<>(object);
|
WeakReference<Object> weakReference = new WeakReference<>(object);
|
||||||
|
@ -130,6 +149,8 @@ public class MemoryLeakTestUtil {
|
||||||
throw new AssertionError("No observed gargabe collection after " + gcCalls + " calls of System.gc()");
|
throw new AssertionError("No observed gargabe collection after " + gcCalls + " calls of System.gc()");
|
||||||
}
|
}
|
||||||
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++;
|
gcCalls++;
|
||||||
} while (weakReference.get() != null);
|
} while (weakReference.get() != null);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2016 Florian Schmaus
|
* Copyright 2016-2019 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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());
|
private static final Logger LOGGER = Logger.getLogger(NetworkUtil.class.getName());
|
||||||
|
|
||||||
public static ServerSocket getSocketOnLoopback() {
|
public static ServerSocket getSocketOnLoopback() throws IOException {
|
||||||
final InetAddress loopbackAddress = InetAddress.getLoopbackAddress();
|
final InetAddress loopbackAddress = InetAddress.getLoopbackAddress();
|
||||||
final int portMin = 1024;
|
final int portMin = 1024;
|
||||||
final int portMax = (1 << 16) - 1;
|
final int portMax = (1 << 16) - 1;
|
||||||
|
@ -40,13 +40,12 @@ public class NetworkUtil {
|
||||||
break;
|
break;
|
||||||
} catch (BindException e) {
|
} catch (BindException e) {
|
||||||
LOGGER.log(Level.FINEST, "Could not bind port " + port + ", trying next", e);
|
LOGGER.log(Level.FINEST, "Could not bind port " + port + ", trying next", e);
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverSocket == null) {
|
if (serverSocket == null) {
|
||||||
throw new IllegalStateException();
|
throw new IOException("Could not bind any port between " + portMin + " and " + portMax
|
||||||
|
+ " on loopback address" + loopbackAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
return serverSocket;
|
return serverSocket;
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.util;
|
package org.jivesoftware.smack.util;
|
||||||
|
|
||||||
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
|
import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlNotSimilar;
|
||||||
import static org.custommonkey.xmlunit.XMLAssert.assertXMLNotEqual;
|
import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
@ -29,6 +29,8 @@ import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.xml.parsers.FactoryConfigurationError;
|
import javax.xml.parsers.FactoryConfigurationError;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
@ -42,15 +44,17 @@ import org.jivesoftware.smack.packet.StreamOpen;
|
||||||
import org.jivesoftware.smack.sasl.SASLError;
|
import org.jivesoftware.smack.sasl.SASLError;
|
||||||
import org.jivesoftware.smack.sasl.packet.SaslStreamElements;
|
import org.jivesoftware.smack.sasl.packet.SaslStreamElements;
|
||||||
import org.jivesoftware.smack.sasl.packet.SaslStreamElements.SASLFailure;
|
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.test.util.TestUtils;
|
||||||
import org.jivesoftware.smack.test.util.XmlUnitUtils;
|
import org.jivesoftware.smack.xml.XmlPullParser;
|
||||||
|
import org.jivesoftware.smack.xml.XmlPullParserException;
|
||||||
|
|
||||||
import com.jamesmurty.utils.XMLBuilder;
|
import com.jamesmurty.utils.XMLBuilder;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.EnumSource;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
public class PacketParserUtilsTest {
|
public class PacketParserUtilsTest {
|
||||||
|
|
||||||
|
@ -59,8 +63,9 @@ public class PacketParserUtilsTest {
|
||||||
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
|
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void singleMessageBodyTest() throws Exception {
|
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
|
||||||
|
public void singleMessageBodyTest(SmackTestUtil.XmlPullParserKind parserKind) throws Exception {
|
||||||
String defaultLanguage = Stanza.getDefaultLanguage();
|
String defaultLanguage = Stanza.getDefaultLanguage();
|
||||||
String otherLanguage = determineNonDefaultLanguage();
|
String otherLanguage = determineNonDefaultLanguage();
|
||||||
|
|
||||||
|
@ -79,13 +84,13 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
Message message = PacketParserUtils
|
Message message = PacketParserUtils
|
||||||
.parseMessage(PacketParserUtils.getParserFor(control));
|
.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getBody());
|
assertEquals(defaultLanguage, message.getBody());
|
||||||
assertTrue(message.getBodyLanguages().isEmpty());
|
assertTrue(message.getBodyLanguages().isEmpty());
|
||||||
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
||||||
assertNull(message.getBody(otherLanguage));
|
assertNull(message.getBody(otherLanguage));
|
||||||
assertXMLEqual(control, message.toXML().toString());
|
assertXmlSimilar(control, message.toXML().toString());
|
||||||
|
|
||||||
// message has non-default language, body has no language
|
// message has non-default language, body has no language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -99,13 +104,13 @@ public class PacketParserUtilsTest {
|
||||||
.t(otherLanguage)
|
.t(otherLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
|
message = PacketParserUtils.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
|
||||||
|
|
||||||
assertEquals(otherLanguage, message.getBody());
|
assertEquals(otherLanguage, message.getBody());
|
||||||
assertTrue(message.getBodyLanguages().isEmpty());
|
assertTrue(message.getBodyLanguages().isEmpty());
|
||||||
assertEquals(otherLanguage, message.getBody(otherLanguage));
|
assertEquals(otherLanguage, message.getBody(otherLanguage));
|
||||||
assertNull(message.getBody(defaultLanguage));
|
assertNull(message.getBody(defaultLanguage));
|
||||||
assertXMLEqual(control, message.toXML().toString());
|
assertXmlSimilar(control, message.toXML().toString());
|
||||||
|
|
||||||
// message has no language, body has no language
|
// message has no language, body has no language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -118,13 +123,13 @@ public class PacketParserUtilsTest {
|
||||||
.t(defaultLanguage)
|
.t(defaultLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
|
message = PacketParserUtils.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getBody());
|
assertEquals(defaultLanguage, message.getBody());
|
||||||
assertTrue(message.getBodyLanguages().isEmpty());
|
assertTrue(message.getBodyLanguages().isEmpty());
|
||||||
assertEquals(defaultLanguage, message.getBody(null));
|
assertEquals(defaultLanguage, message.getBody(null));
|
||||||
assertNull(message.getBody(otherLanguage));
|
assertNull(message.getBody(otherLanguage));
|
||||||
assertXMLEqual(control, message.toXML().toString());
|
assertXmlSimilar(control, message.toXML().toString());
|
||||||
|
|
||||||
// message has no language, body has default language
|
// message has no language, body has default language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -138,14 +143,14 @@ public class PacketParserUtilsTest {
|
||||||
.t(defaultLanguage)
|
.t(defaultLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
|
message = PacketParserUtils.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
|
||||||
|
|
||||||
assertNull(message.getBody());
|
assertNull(message.getBody());
|
||||||
assertFalse(message.getBodyLanguages().isEmpty());
|
assertFalse(message.getBodyLanguages().isEmpty());
|
||||||
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
||||||
assertNull(message.getBody(otherLanguage));
|
assertNull(message.getBody(otherLanguage));
|
||||||
|
|
||||||
assertXMLEqual(control, message.toXML().toString());
|
assertXmlSimilar(control, message.toXML().toString());
|
||||||
|
|
||||||
// message has no language, body has non-default language
|
// message has no language, body has non-default language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -159,14 +164,14 @@ public class PacketParserUtilsTest {
|
||||||
.t(otherLanguage)
|
.t(otherLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
|
message = PacketParserUtils.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
|
||||||
|
|
||||||
assertNull(message.getBody());
|
assertNull(message.getBody());
|
||||||
assertFalse(message.getBodyLanguages().isEmpty());
|
assertFalse(message.getBodyLanguages().isEmpty());
|
||||||
assertTrue(message.getBodyLanguages().contains(otherLanguage));
|
assertTrue(message.getBodyLanguages().contains(otherLanguage));
|
||||||
assertEquals(otherLanguage, message.getBody(otherLanguage));
|
assertEquals(otherLanguage, message.getBody(otherLanguage));
|
||||||
assertNull(message.getBody(defaultLanguage));
|
assertNull(message.getBody(defaultLanguage));
|
||||||
assertXMLEqual(control, message.toXML().toString());
|
assertXmlSimilar(control, message.toXML().toString());
|
||||||
|
|
||||||
// message has default language, body has non-default language
|
// message has default language, body has non-default language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -181,14 +186,14 @@ public class PacketParserUtilsTest {
|
||||||
.t(otherLanguage)
|
.t(otherLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
|
message = PacketParserUtils.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
|
||||||
|
|
||||||
assertNull(message.getBody());
|
assertNull(message.getBody());
|
||||||
assertFalse(message.getBodyLanguages().isEmpty());
|
assertFalse(message.getBodyLanguages().isEmpty());
|
||||||
assertTrue(message.getBodyLanguages().contains(otherLanguage));
|
assertTrue(message.getBodyLanguages().contains(otherLanguage));
|
||||||
assertEquals(otherLanguage, message.getBody(otherLanguage));
|
assertEquals(otherLanguage, message.getBody(otherLanguage));
|
||||||
assertNull(message.getBody(defaultLanguage));
|
assertNull(message.getBody(defaultLanguage));
|
||||||
assertXMLEqual(control, message.toXML().toString());
|
assertXmlSimilar(control, message.toXML().toString());
|
||||||
|
|
||||||
// message has non-default language, body has default language
|
// message has non-default language, body has default language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -203,14 +208,14 @@ public class PacketParserUtilsTest {
|
||||||
.t(defaultLanguage)
|
.t(defaultLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(control));
|
message = PacketParserUtils.parseMessage(SmackTestUtil.getParserFor(control, parserKind));
|
||||||
|
|
||||||
assertNull(message.getBody());
|
assertNull(message.getBody());
|
||||||
assertFalse(message.getBodyLanguages().isEmpty());
|
assertFalse(message.getBodyLanguages().isEmpty());
|
||||||
assertTrue(message.getBodyLanguages().contains(defaultLanguage));
|
assertTrue(message.getBodyLanguages().contains(defaultLanguage));
|
||||||
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
||||||
assertNull(message.getBody(otherLanguage));
|
assertNull(message.getBody(otherLanguage));
|
||||||
assertXMLEqual(control, message.toXML().toString());
|
assertXmlSimilar(control, message.toXML().toString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +244,7 @@ public class PacketParserUtilsTest {
|
||||||
assertTrue(message.getSubjectLanguages().isEmpty());
|
assertTrue(message.getSubjectLanguages().isEmpty());
|
||||||
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
||||||
assertNull(message.getSubject(otherLanguage));
|
assertNull(message.getSubject(otherLanguage));
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
// message has non-default language, subject has no language
|
// message has non-default language, subject has no language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -258,7 +263,7 @@ public class PacketParserUtilsTest {
|
||||||
assertTrue(message.getSubjectLanguages().isEmpty());
|
assertTrue(message.getSubjectLanguages().isEmpty());
|
||||||
assertEquals(otherLanguage, message.getSubject(otherLanguage));
|
assertEquals(otherLanguage, message.getSubject(otherLanguage));
|
||||||
assertNull(message.getSubject(defaultLanguage));
|
assertNull(message.getSubject(defaultLanguage));
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
// message has no language, subject has no language
|
// message has no language, subject has no language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -276,7 +281,7 @@ public class PacketParserUtilsTest {
|
||||||
assertTrue(message.getSubjectLanguages().isEmpty());
|
assertTrue(message.getSubjectLanguages().isEmpty());
|
||||||
assertEquals(defaultLanguage, message.getSubject(null));
|
assertEquals(defaultLanguage, message.getSubject(null));
|
||||||
assertNull(message.getSubject(otherLanguage));
|
assertNull(message.getSubject(otherLanguage));
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
// message has no language, subject has default language
|
// message has no language, subject has default language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -295,7 +300,7 @@ public class PacketParserUtilsTest {
|
||||||
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
||||||
assertNull(message.getSubject(otherLanguage));
|
assertNull(message.getSubject(otherLanguage));
|
||||||
|
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
// message has no language, subject has non-default language
|
// message has no language, subject has non-default language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -315,7 +320,7 @@ public class PacketParserUtilsTest {
|
||||||
assertTrue(message.getSubjectLanguages().contains(otherLanguage));
|
assertTrue(message.getSubjectLanguages().contains(otherLanguage));
|
||||||
assertEquals(otherLanguage, message.getSubject(otherLanguage));
|
assertEquals(otherLanguage, message.getSubject(otherLanguage));
|
||||||
assertNull(message.getSubject(defaultLanguage));
|
assertNull(message.getSubject(defaultLanguage));
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
// message has default language, subject has non-default language
|
// message has default language, subject has non-default language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -336,7 +341,7 @@ public class PacketParserUtilsTest {
|
||||||
assertTrue(message.getSubjectLanguages().contains(otherLanguage));
|
assertTrue(message.getSubjectLanguages().contains(otherLanguage));
|
||||||
assertEquals(otherLanguage, message.getSubject(otherLanguage));
|
assertEquals(otherLanguage, message.getSubject(otherLanguage));
|
||||||
assertNull(message.getSubject(defaultLanguage));
|
assertNull(message.getSubject(defaultLanguage));
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
// message has non-default language, subject has default language
|
// message has non-default language, subject has default language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -357,7 +362,7 @@ public class PacketParserUtilsTest {
|
||||||
assertTrue(message.getSubjectLanguages().contains(defaultLanguage));
|
assertTrue(message.getSubjectLanguages().contains(defaultLanguage));
|
||||||
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
||||||
assertNull(message.getSubject(otherLanguage));
|
assertNull(message.getSubject(otherLanguage));
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,7 +398,7 @@ public class PacketParserUtilsTest {
|
||||||
assertEquals(2, message.getBodies().size());
|
assertEquals(2, message.getBodies().size());
|
||||||
assertEquals(1, message.getBodyLanguages().size());
|
assertEquals(1, message.getBodyLanguages().size());
|
||||||
assertTrue(message.getBodyLanguages().contains(otherLanguage));
|
assertTrue(message.getBodyLanguages().contains(otherLanguage));
|
||||||
assertXMLEqual(control, message.toXML().toString());
|
assertXmlSimilar(control, message.toXML().toString());
|
||||||
|
|
||||||
// message has non-default language, first body no language, second body default language
|
// message has non-default language, first body no language, second body default language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -419,7 +424,7 @@ public class PacketParserUtilsTest {
|
||||||
assertEquals(2, message.getBodies().size());
|
assertEquals(2, message.getBodies().size());
|
||||||
assertEquals(1, message.getBodyLanguages().size());
|
assertEquals(1, message.getBodyLanguages().size());
|
||||||
assertTrue(message.getBodyLanguages().contains(defaultLanguage));
|
assertTrue(message.getBodyLanguages().contains(defaultLanguage));
|
||||||
assertXMLEqual(control, message.toXML().toString());
|
assertXmlSimilar(control, message.toXML().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Re-enable once we throw an exception on duplicate body elements.
|
// TODO: Re-enable once we throw an exception on duplicate body elements.
|
||||||
|
@ -452,7 +457,7 @@ public class PacketParserUtilsTest {
|
||||||
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
||||||
assertEquals(1, message.getBodies().size());
|
assertEquals(1, message.getBodies().size());
|
||||||
assertEquals(0, message.getBodyLanguages().size());
|
assertEquals(0, message.getBodyLanguages().size());
|
||||||
assertXMLNotEqual(control, message.toXML().toString());
|
assertXmlNotSimilar(control, message.toXML().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
|
@ -510,7 +515,7 @@ public class PacketParserUtilsTest {
|
||||||
assertEquals(otherLanguage, message.getBody(otherLanguage));
|
assertEquals(otherLanguage, message.getBody(otherLanguage));
|
||||||
assertEquals(2, message.getBodies().size());
|
assertEquals(2, message.getBodies().size());
|
||||||
assertEquals(1, message.getBodyLanguages().size());
|
assertEquals(1, message.getBodyLanguages().size());
|
||||||
assertXMLEqual(control, message.toXML().toString());
|
assertXmlSimilar(control, message.toXML().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -544,7 +549,7 @@ public class PacketParserUtilsTest {
|
||||||
assertEquals(2, message.getSubjects().size());
|
assertEquals(2, message.getSubjects().size());
|
||||||
assertEquals(1, message.getSubjectLanguages().size());
|
assertEquals(1, message.getSubjectLanguages().size());
|
||||||
assertTrue(message.getSubjectLanguages().contains(otherLanguage));
|
assertTrue(message.getSubjectLanguages().contains(otherLanguage));
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
// message has default language, first subject no language, second subject default language
|
// message has default language, first subject no language, second subject default language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -568,7 +573,7 @@ public class PacketParserUtilsTest {
|
||||||
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
||||||
assertEquals(1, message.getSubjects().size());
|
assertEquals(1, message.getSubjects().size());
|
||||||
assertEquals(0, message.getSubjectLanguages().size());
|
assertEquals(0, message.getSubjectLanguages().size());
|
||||||
assertXMLNotEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlNotSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
// message has non-default language, first subject no language, second subject default language
|
// message has non-default language, first subject no language, second subject default language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -593,7 +598,7 @@ public class PacketParserUtilsTest {
|
||||||
assertEquals(2, message.getSubjects().size());
|
assertEquals(2, message.getSubjects().size());
|
||||||
assertEquals(1, message.getSubjectLanguages().size());
|
assertEquals(1, message.getSubjectLanguages().size());
|
||||||
assertTrue(message.getSubjectLanguages().contains(defaultLanguage));
|
assertTrue(message.getSubjectLanguages().contains(defaultLanguage));
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// message has no language, first subject no language, second subject default language
|
// message has no language, first subject no language, second subject default language
|
||||||
|
@ -641,7 +646,7 @@ public class PacketParserUtilsTest {
|
||||||
assertEquals(otherLanguage, message.getSubject(otherLanguage));
|
assertEquals(otherLanguage, message.getSubject(otherLanguage));
|
||||||
assertEquals(2, message.getSubjects().size());
|
assertEquals(2, message.getSubjects().size());
|
||||||
assertEquals(1, message.getSubjectLanguages().size());
|
assertEquals(1, message.getSubjectLanguages().size());
|
||||||
assertXMLEqual(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(control, message.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
|
|
||||||
// message has no language, first subject no language, second subject no language
|
// message has no language, first subject no language, second subject no language
|
||||||
control = XMLBuilder.create("message")
|
control = XMLBuilder.create("message")
|
||||||
|
@ -708,13 +713,18 @@ public class PacketParserUtilsTest {
|
||||||
.t("Good Message Body")
|
.t("Good Message Body")
|
||||||
.asString(outputProperties);
|
.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");
|
String invalidControl = validControl.replace("Good Message Body", "Bad </span> Body");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(invalidControl));
|
PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(invalidControl));
|
||||||
fail("Exception should be thrown");
|
fail("Exception should be thrown");
|
||||||
} catch (XmlPullParserException e) {
|
} catch (XmlPullParserException e) {
|
||||||
assertTrue(e.getMessage().contains("end tag name </span>"));
|
String exceptionMessage = e.getMessage();
|
||||||
|
boolean expectedContentFound = expectedContentOfExceptionMessage.get().anyMatch((expected) -> exceptionMessage.contains(expected));
|
||||||
|
assertTrue(expectedContentFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidControl = validControl.replace("Good Message Body", "Bad </body> Body");
|
invalidControl = validControl.replace("Good Message Body", "Bad </body> Body");
|
||||||
|
@ -723,7 +733,9 @@ public class PacketParserUtilsTest {
|
||||||
PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(invalidControl));
|
PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(invalidControl));
|
||||||
fail("Exception should be thrown");
|
fail("Exception should be thrown");
|
||||||
} catch (XmlPullParserException e) {
|
} catch (XmlPullParserException e) {
|
||||||
assertTrue(e.getMessage().contains("end tag name </body>"));
|
String exceptionMessage = e.getMessage();
|
||||||
|
boolean expectedContentFound = expectedContentOfExceptionMessage.get().anyMatch((expected) -> exceptionMessage.contains(expected));
|
||||||
|
assertTrue(expectedContentFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidControl = validControl.replace("Good Message Body", "Bad </message> Body");
|
invalidControl = validControl.replace("Good Message Body", "Bad </message> Body");
|
||||||
|
@ -732,9 +744,10 @@ public class PacketParserUtilsTest {
|
||||||
PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(invalidControl));
|
PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(invalidControl));
|
||||||
fail("Exception should be thrown");
|
fail("Exception should be thrown");
|
||||||
} catch (XmlPullParserException e) {
|
} catch (XmlPullParserException e) {
|
||||||
assertTrue(e.getMessage().contains("end tag name </message>"));
|
String exceptionMessage = e.getMessage();
|
||||||
|
boolean expectedContentFound = expectedContentOfExceptionMessage.get().anyMatch((expected) -> exceptionMessage.contains(expected));
|
||||||
|
assertTrue(expectedContentFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -763,58 +776,52 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
Stanza message = PacketParserUtils.parseStanza(control);
|
Stanza message = PacketParserUtils.parseStanza(control);
|
||||||
XmlUnitUtils.assertSimilar(control, message.toXML());
|
assertXmlSimilar(control, message.toXML());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateSimplePresence() throws Exception {
|
public void validateSimplePresence() throws Exception {
|
||||||
// CHECKSTYLE:OFF
|
String stanza = "<presence from='juliet@example.com/balcony' to='romeo@example.net'/>";
|
||||||
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));
|
||||||
|
|
||||||
assertXMLEqual(stanza, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(stanza, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
// CHECKSTYLE:ON
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validatePresenceProbe() throws Exception {
|
public void validatePresenceProbe() throws Exception {
|
||||||
// CHECKSTYLE:OFF
|
String stanza = "<presence from='mercutio@example.com' id='xv291f38' to='juliet@example.com' type='unsubscribed'/>";
|
||||||
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));
|
||||||
|
|
||||||
assertXMLEqual(stanza, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(stanza, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
assertEquals(Presence.Type.unsubscribed, presence.getType());
|
assertEquals(Presence.Type.unsubscribed, presence.getType());
|
||||||
// CHECKSTYLE:ON
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validatePresenceOptionalElements() throws Exception {
|
public void validatePresenceOptionalElements() throws Exception {
|
||||||
// CHECKSTYLE:OFF
|
String stanza = "<presence xml:lang='en' type='unsubscribed'>"
|
||||||
String stanza = "<presence xml:lang='en' type='unsubscribed'>"
|
+ "<show>dnd</show>"
|
||||||
+ "<show>dnd</show>"
|
+ "<status>Wooing Juliet</status>"
|
||||||
+ "<status>Wooing Juliet</status>"
|
+ "<priority>1</priority>"
|
||||||
+ "<priority>1</priority>"
|
+ "</presence>";
|
||||||
+ "</presence>";
|
|
||||||
|
|
||||||
Presence presence = PacketParserUtils.parsePresence(PacketParserUtils.getParserFor(stanza));
|
Presence presence = PacketParserUtils.parsePresence(PacketParserUtils.getParserFor(stanza));
|
||||||
assertXMLEqual(stanza, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
assertXmlSimilar(stanza, presence.toXML(StreamOpen.CLIENT_NAMESPACE).toString());
|
||||||
assertEquals(Presence.Type.unsubscribed, presence.getType());
|
assertEquals(Presence.Type.unsubscribed, presence.getType());
|
||||||
assertEquals("dnd", presence.getMode().name());
|
assertEquals("dnd", presence.getMode().name());
|
||||||
assertEquals("en", presence.getLanguage());
|
assertEquals("en", presence.getLanguage());
|
||||||
assertEquals("Wooing Juliet", presence.getStatus());
|
assertEquals("Wooing Juliet", presence.getStatus());
|
||||||
assertEquals(1, presence.getPriority());
|
assertEquals(1, presence.getPriority());
|
||||||
// CHECKSTYLE:ON
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
// @Test
|
||||||
public void parseContentDepthTest() throws Exception {
|
// public void parseContentDepthTest() throws Exception {
|
||||||
final String stanza = "<iq type='result' to='foo@bar.com' from='baz.com' id='42'/>";
|
// final String stanza = "<iq type='result' to='foo@bar.com' from='baz.com' id='42'/>";
|
||||||
XmlPullParser parser = TestUtils.getParser(stanza, "iq");
|
// XmlPullParser parser = TestUtils.getParser(stanza, "iq");
|
||||||
CharSequence content = PacketParserUtils.parseContent(parser);
|
// CharSequence content = PacketParserUtils.parseContent(parser);
|
||||||
assertEquals("", content.toString());
|
// assertEquals("", content.toString());
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseElementMultipleNamespace()
|
public void parseElementMultipleNamespace()
|
||||||
|
@ -830,7 +837,7 @@ public class PacketParserUtilsTest {
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
XmlPullParser parser = TestUtils.getParser(stanza, "outer");
|
XmlPullParser parser = TestUtils.getParser(stanza, "outer");
|
||||||
CharSequence result = PacketParserUtils.parseElement(parser, true);
|
CharSequence result = PacketParserUtils.parseElement(parser, true);
|
||||||
assertXMLEqual(stanza, result.toString());
|
assertXmlSimilar(stanza, result.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -843,7 +850,7 @@ public class PacketParserUtilsTest {
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
XmlPullParser parser = TestUtils.getParser(saslFailureString, SASLFailure.ELEMENT);
|
XmlPullParser parser = TestUtils.getParser(saslFailureString, SASLFailure.ELEMENT);
|
||||||
SASLFailure saslFailure = PacketParserUtils.parseSASLFailure(parser);
|
SASLFailure saslFailure = PacketParserUtils.parseSASLFailure(parser);
|
||||||
assertXMLEqual(saslFailureString, saslFailure.toString());
|
assertXmlSimilar(saslFailureString, saslFailure.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -865,7 +872,7 @@ public class PacketParserUtilsTest {
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
XmlPullParser parser = TestUtils.getParser(saslFailureString, SASLFailure.ELEMENT);
|
XmlPullParser parser = TestUtils.getParser(saslFailureString, SASLFailure.ELEMENT);
|
||||||
SASLFailure saslFailure = PacketParserUtils.parseSASLFailure(parser);
|
SASLFailure saslFailure = PacketParserUtils.parseSASLFailure(parser);
|
||||||
XmlUnitUtils.assertSimilar(saslFailureString, saslFailure.toXML(StreamOpen.CLIENT_NAMESPACE));
|
assertXmlSimilar(saslFailureString, saslFailure.toXML(StreamOpen.CLIENT_NAMESPACE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ReferenceEquality")
|
@SuppressWarnings("ReferenceEquality")
|
||||||
|
@ -909,7 +916,7 @@ public class PacketParserUtilsTest {
|
||||||
.element("internal-server-error", StanzaError.ERROR_CONDITION_AND_TEXT_NAMESPACE).up()
|
.element("internal-server-error", StanzaError.ERROR_CONDITION_AND_TEXT_NAMESPACE).up()
|
||||||
.element("text", StanzaError.ERROR_CONDITION_AND_TEXT_NAMESPACE).t(text).up()
|
.element("text", StanzaError.ERROR_CONDITION_AND_TEXT_NAMESPACE).t(text).up()
|
||||||
.asString();
|
.asString();
|
||||||
XmlUnitUtils.assertSimilar(errorXml, error.toXML(StreamOpen.CLIENT_NAMESPACE));
|
assertXmlSimilar(errorXml, error.toXML(StreamOpen.CLIENT_NAMESPACE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -21,7 +21,7 @@ import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -31,11 +31,9 @@ import org.junit.Test;
|
||||||
public class StringUtilsTest {
|
public class StringUtilsTest {
|
||||||
@Test
|
@Test
|
||||||
public void testEscapeForXml() {
|
public void testEscapeForXml() {
|
||||||
String input = null;
|
|
||||||
|
|
||||||
assertNull(StringUtils.escapeForXml(null));
|
assertNull(StringUtils.escapeForXml(null));
|
||||||
|
|
||||||
input = "<b>";
|
String input = "<b>";
|
||||||
assertCharSequenceEquals("<b>", StringUtils.escapeForXml(input));
|
assertCharSequenceEquals("<b>", StringUtils.escapeForXml(input));
|
||||||
|
|
||||||
input = "\"";
|
input = "\"";
|
||||||
|
@ -74,15 +72,15 @@ public class StringUtilsTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeHex() throws UnsupportedEncodingException {
|
public void testEncodeHex() {
|
||||||
String input = "";
|
String input = "";
|
||||||
String output = "";
|
String output = "";
|
||||||
assertEquals(new String(StringUtils.encodeHex(input.getBytes(StringUtils.UTF8))),
|
assertEquals(new String(StringUtils.encodeHex(input.getBytes(StandardCharsets.UTF_8))),
|
||||||
output);
|
output);
|
||||||
|
|
||||||
input = "foo bar 123";
|
input = "foo bar 123";
|
||||||
output = "666f6f2062617220313233";
|
output = "666f6f2062617220313233";
|
||||||
assertEquals(new String(StringUtils.encodeHex(input.getBytes(StringUtils.UTF8))),
|
assertEquals(new String(StringUtils.encodeHex(input.getBytes(StandardCharsets.UTF_8))),
|
||||||
output);
|
output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,231 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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 ' 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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -257,11 +257,9 @@ public class EnhancedDebugger extends SmackDebugger {
|
||||||
new DefaultTableModel(
|
new DefaultTableModel(
|
||||||
new Object[] {"Hide", "Timestamp", "", "", "Message", "Id", "Type", "To", "From"},
|
new Object[] {"Hide", "Timestamp", "", "", "Message", "Id", "Type", "To", "From"},
|
||||||
0) {
|
0) {
|
||||||
// CHECKSTYLE:OFF
|
private static final long serialVersionUID = 8136121224474217264L;
|
||||||
private static final long serialVersionUID = 8136121224474217264L;
|
@Override
|
||||||
@Override
|
|
||||||
public boolean isCellEditable(int rowIndex, int mColIndex) {
|
public boolean isCellEditable(int rowIndex, int mColIndex) {
|
||||||
// CHECKSTYLE:ON
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,11 +687,9 @@ public class EnhancedDebugger extends SmackDebugger {
|
||||||
new DefaultTableModel(new Object[][] { {"IQ", 0, 0}, {"Message", 0, 0},
|
new DefaultTableModel(new Object[][] { {"IQ", 0, 0}, {"Message", 0, 0},
|
||||||
{"Presence", 0, 0}, {"Other", 0, 0}, {"Total", 0, 0}},
|
{"Presence", 0, 0}, {"Other", 0, 0}, {"Total", 0, 0}},
|
||||||
new Object[] {"Type", "Received", "Sent"}) {
|
new Object[] {"Type", "Received", "Sent"}) {
|
||||||
// CHECKSTYLE:OFF
|
private static final long serialVersionUID = -6793886085109589269L;
|
||||||
private static final long serialVersionUID = -6793886085109589269L;
|
@Override
|
||||||
@Override
|
|
||||||
public boolean isCellEditable(int rowIndex, int mColIndex) {
|
public boolean isCellEditable(int rowIndex, int mColIndex) {
|
||||||
// CHECKSTYLE:ON
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -346,6 +346,7 @@ public final class EnhancedDebuggerWindow {
|
||||||
*
|
*
|
||||||
* @param evt the event that indicates that the root window is closing
|
* @param evt the event that indicates that the root window is closing
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("UnusedVariable")
|
||||||
private synchronized void rootWindowClosing(WindowEvent evt) {
|
private synchronized void rootWindowClosing(WindowEvent evt) {
|
||||||
// Notify to all the debuggers to stop debugging
|
// Notify to all the debuggers to stop debugging
|
||||||
for (EnhancedDebugger debugger : debuggers) {
|
for (EnhancedDebugger debugger : debuggers) {
|
||||||
|
|
|
@ -21,15 +21,14 @@ import java.io.IOException;
|
||||||
import org.jivesoftware.smack.packet.XmlEnvironment;
|
import org.jivesoftware.smack.packet.XmlEnvironment;
|
||||||
import org.jivesoftware.smack.parsing.SmackParsingException;
|
import org.jivesoftware.smack.parsing.SmackParsingException;
|
||||||
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
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;
|
||||||
import org.jivesoftware.smackx.carbons.packet.CarbonExtension.Direction;
|
import org.jivesoftware.smackx.carbons.packet.CarbonExtension.Direction;
|
||||||
import org.jivesoftware.smackx.forward.packet.Forwarded;
|
import org.jivesoftware.smackx.forward.packet.Forwarded;
|
||||||
import org.jivesoftware.smackx.forward.provider.ForwardedProvider;
|
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
|
* This class implements the {@link ExtensionElementProvider} to parse
|
||||||
* carbon copied messages from a packet. It will return a {@link CarbonExtension} stanza extension.
|
* carbon copied messages from a packet. It will return a {@link CarbonExtension} stanza extension.
|
||||||
|
@ -48,11 +47,11 @@ public class CarbonManagerProvider extends ExtensionElementProvider<CarbonExtens
|
||||||
|
|
||||||
boolean done = false;
|
boolean done = false;
|
||||||
while (!done) {
|
while (!done) {
|
||||||
int eventType = parser.next();
|
XmlPullParser.Event eventType = parser.next();
|
||||||
if (eventType == XmlPullParser.START_TAG && parser.getName().equals("forwarded")) {
|
if (eventType == XmlPullParser.Event.START_ELEMENT && parser.getName().equals("forwarded")) {
|
||||||
fwd = FORWARDED_PROVIDER.parse(parser);
|
fwd = FORWARDED_PROVIDER.parse(parser);
|
||||||
}
|
}
|
||||||
else if (eventType == XmlPullParser.END_TAG && dir == Direction.valueOf(parser.getName()))
|
else if (eventType == XmlPullParser.Event.END_ELEMENT && dir == Direction.valueOf(parser.getName()))
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
if (fwd == null) {
|
if (fwd == null) {
|
||||||
|
|
|
@ -42,6 +42,7 @@ import org.jivesoftware.smack.filter.StanzaExtensionFilter;
|
||||||
import org.jivesoftware.smack.filter.StanzaFilter;
|
import org.jivesoftware.smack.filter.StanzaFilter;
|
||||||
import org.jivesoftware.smack.packet.Message;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
import org.jivesoftware.smack.packet.Stanza;
|
import org.jivesoftware.smack.packet.Stanza;
|
||||||
|
|
||||||
import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements;
|
import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements;
|
||||||
import org.jivesoftware.smackx.chat_markers.filter.ChatMarkersFilter;
|
import org.jivesoftware.smackx.chat_markers.filter.ChatMarkersFilter;
|
||||||
import org.jivesoftware.smackx.chat_markers.filter.EligibleForChatMarkerFilter;
|
import org.jivesoftware.smackx.chat_markers.filter.EligibleForChatMarkerFilter;
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.jivesoftware.smack.packet.ExtensionElement;
|
||||||
import org.jivesoftware.smack.packet.Message;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
|
|
||||||
import org.jivesoftware.smackx.chat_markers.ChatMarkersState;
|
import org.jivesoftware.smackx.chat_markers.ChatMarkersState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.jivesoftware.smackx.chat_markers.filter;
|
||||||
|
|
||||||
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
|
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
|
||||||
import org.jivesoftware.smack.filter.StanzaFilter;
|
import org.jivesoftware.smack.filter.StanzaFilter;
|
||||||
|
|
||||||
import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements;
|
import org.jivesoftware.smackx.chat_markers.element.ChatMarkersElements;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.jivesoftware.smackx.chat_markers.filter;
|
||||||
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
|
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
|
||||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||||
import org.jivesoftware.smack.packet.Stanza;
|
import org.jivesoftware.smack.packet.Stanza;
|
||||||
|
|
||||||
import org.jivesoftware.smackx.chatstates.ChatState;
|
import org.jivesoftware.smackx.chatstates.ChatState;
|
||||||
import org.jivesoftware.smackx.chatstates.ChatStateManager;
|
import org.jivesoftware.smackx.chatstates.ChatStateManager;
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue