diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa9bb447a..2fb93a48c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,14 +6,13 @@ jobs: build: name: Build Smack - runs-on: ubuntu-24.04 + runs-on: ubuntu-22.04 strategy: matrix: java: - - 17 - - 21 + - 11 env: - PRIMARY_JAVA_VERSION: 21 + PRIMARY_JAVA_VERSION: 11 steps: - name: Checkout @@ -53,10 +52,10 @@ jobs: - name: Install GraphViz run: sudo apt update && sudo apt install graphviz - name: Install Android SDK Manager - uses: android-actions/setup-android@v3 + uses: android-actions/setup-android@v2 - name: Install Android SDK run: | - sdkmanager "platforms;android-23" + sdkmanager "platforms;android-19" # Testing - name: Gradle Check @@ -72,22 +71,15 @@ jobs: run: ./gradlew javadocAll --stacktrace # Test Coverage Report - - name: Aggregated Jacoco Test Coverage Report + - name: Jacoco Test Coverage if: ${{ matrix.java == env.PRIMARY_JAVA_VERSION }} - run: | - ./gradlew smack-java11-full:testCodeCoverageReport - - # Coveralls - - name: Report coverage stats to Coveralls - if: ${{ matrix.java == env.PRIMARY_JAVA_VERSION }} - uses: coverallsapp/github-action@v2 - with: - format: jacoco - file: smack-java11-full/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml + run: ./gradlew jacocoRootReport coveralls + env: + COVERALLS_REPO_TOKEN: S2ecSJja2cKJa9yv45C8ZFPohXuRrTXKd # Upload build artifacts - name: Upload build artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v2 with: name: smack-java-${{ matrix.java }} path: | diff --git a/.gitignore b/.gitignore index ec8037f60..2739029bb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ *.iml *.ipr *.iws -!.idea/icon.svg # Mac OS X .DS_Store @@ -12,6 +11,7 @@ .project .settings .gradle +gradle.properties build/ core/build/ diff --git a/.idea/icon.svg b/.idea/icon.svg deleted file mode 100644 index 1d9b3fb6f..000000000 --- a/.idea/icon.svg +++ /dev/null @@ -1,89 +0,0 @@ - -image/svg+xml \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b413e7f75..93592bbc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,31 +1,5 @@ # Smack Changelog -# 4.4.8 -- 2024-04-02 - -### Improvement - -[SMACK-941](https://igniterealtime.atlassian.net/browse/SMACK-941) Suppress "roster not loaded while processing presence" warning if its caused by the reflected self-presence - -### Bug - -[SMACK-938](https://igniterealtime.atlassian.net/browse/SMACK-938) Busy loop in SmackReactor - -[SMACK-940](https://igniterealtime.atlassian.net/browse/SMACK-940) Ignore IPv6 Zone IDs in incoming streamhost candidates - -# 4.4.7 -- 2023-11-25 - -### Improvement - -- [SMACK-929](https://igniterealtime.atlassian.net/browse/SMACK-929) Ignore IPv6 Zone IDs in incoming Jingle candidates -- [SMACK-934](https://igniterealtime.atlassian.net/browse/SMACK-934) Deprecate and remove ChatMarkersManager.isSupportedByServer\(\) -- [SMACK-937](https://igniterealtime.atlassian.net/browse/SMACK-937) Avoid unnecessary feature lookups by making the EntityCaps listener synchronous - -### Bug - -- [SMACK-927](https://igniterealtime.atlassian.net/browse/SMACK-927) Deadlock due to recveive listeners may be invoked after AbstractXMPPConnection.invokeStanzaCollectorsAndNotifyRecvListeners\(\) returned -- [SMACK-930](https://igniterealtime.atlassian.net/browse/SMACK-930) Rename ELEMENT 'candidate-activated' to 'activated' per XEP-0260 -- [SMACK-931](https://igniterealtime.atlassian.net/browse/SMACK-931) IQ error stanza generation does not allow adding of an extension element - # 4.4.6 -- 2022-06-29 ### Bug diff --git a/Makefile b/Makefile deleted file mode 100644 index 4689ef8af..000000000 --- a/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -GRADLE ?= ./gradlew - -.PHONY: all -all: check jacocoRootReport javadocAll sinttest - -.PHONY: codecov -codecov: - $(GRADLE) smack-java11-full:testCodeCoverageReport - echo "Report available at smack-java11-full/build/reports/jacoco/testCodeCoverageReport/html/index.html" - -.PHONY: check -check: - $(GRADLE) $@ - -.PHONY: eclipse -eclipse: - $(GRADLE) $@ - -.PHONY: sinttest -sinttest: - $(GRADLE) $@ - -.PHONY: jacocoRootReport -jacocoRootReport: - $(GRADLE) $@ - -.PHONY: javadocAll -javadocAll: - $(GRADLE) $@ - echo "Smack javadoc available at build/javadoc/index.html" diff --git a/build-logic/build.gradle b/build-logic/build.gradle deleted file mode 100644 index 7b02d03a7..000000000 --- a/build-logic/build.gradle +++ /dev/null @@ -1,14 +0,0 @@ -plugins { - id 'groovy-gradle-plugin' -} - -repositories { - gradlePluginPortal() -} - -dependencies { - implementation "biz.aQute.bnd:biz.aQute.bnd.gradle:7.0.0" - implementation "me.champeau.jmh:jmh-gradle-plugin:0.7.2" - implementation "net.ltgt.gradle:gradle-errorprone-plugin:4.0.1" - implementation "ru.vyarus:gradle-animalsniffer-plugin:1.7.1" -} diff --git a/build-logic/settings.gradle b/build-logic/settings.gradle deleted file mode 100644 index d082ce7e0..000000000 --- a/build-logic/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'smack-build-logic' diff --git a/build-logic/src/main/groovy/org.igniterealtime.smack.android-boot-classpath-conventions.gradle b/build-logic/src/main/groovy/org.igniterealtime.smack.android-boot-classpath-conventions.gradle deleted file mode 100644 index c14cb3199..000000000 --- a/build-logic/src/main/groovy/org.igniterealtime.smack.android-boot-classpath-conventions.gradle +++ /dev/null @@ -1,6 +0,0 @@ -compileJava { - options.bootstrapClasspath = files(androidBootClasspath) -} -javadoc { - classpath += files(androidBootClasspath) -} diff --git a/build-logic/src/main/groovy/org.igniterealtime.smack.android-conventions.gradle b/build-logic/src/main/groovy/org.igniterealtime.smack.android-conventions.gradle deleted file mode 100644 index 94beb432c..000000000 --- a/build-logic/src/main/groovy/org.igniterealtime.smack.android-conventions.gradle +++ /dev/null @@ -1,10 +0,0 @@ -plugins { - id 'ru.vyarus.animalsniffer' - id 'org.igniterealtime.smack.global-conventions' -} -dependencies { - signature "net.sf.androidscents.signature:android-api-level-${smackMinAndroidSdk}:6.0_r3@signature" -} -animalsniffer { - sourceSets = [sourceSets.main] -} diff --git a/build-logic/src/main/groovy/org.igniterealtime.smack.application-conventions.gradle b/build-logic/src/main/groovy/org.igniterealtime.smack.application-conventions.gradle deleted file mode 100644 index fa4c7011e..000000000 --- a/build-logic/src/main/groovy/org.igniterealtime.smack.application-conventions.gradle +++ /dev/null @@ -1,12 +0,0 @@ -plugins { - id 'application' -} - -application { - applicationDefaultJvmArgs = ["-enableassertions"] -} - -run { - // Pass all system properties down to the "application" run - systemProperties System.getProperties() -} diff --git a/build-logic/src/main/groovy/org.igniterealtime.smack.global-conventions.gradle b/build-logic/src/main/groovy/org.igniterealtime.smack.global-conventions.gradle deleted file mode 100644 index 5bd92c7ee..000000000 --- a/build-logic/src/main/groovy/org.igniterealtime.smack.global-conventions.gradle +++ /dev/null @@ -1,37 +0,0 @@ -ext { - javaVersion = JavaVersion.VERSION_11 - javaMajor = javaVersion.getMajorVersion() - smackMinAndroidSdk = 23 - - androidBootClasspath = { getAndroidRuntimeJar() } -} - -repositories { - mavenLocal() - mavenCentral() -} - -def getAndroidRuntimeJar() { - def androidApiLevel = ext.smackMinAndroidSdk - def androidHome = getAndroidHome() - def androidJar = new File("$androidHome/platforms/android-${androidApiLevel}/android.jar") - if (androidJar.isFile()) { - return androidJar - } else { - throw new Exception("Can't find android.jar for API level ${androidApiLevel}. Please install corresponding SDK platform package") - } -} -def getAndroidJavadocOffline() { - def androidHome = getAndroidHome() - return androidHome.toString() + "/docs/reference" -} - -def getAndroidHome() { - def androidHomeEnv = System.getenv("ANDROID_HOME") - if (androidHomeEnv == null) { - throw new Exception("ANDROID_HOME environment variable is not set") - } - def androidHome = new File(androidHomeEnv) - if (!androidHome.isDirectory()) throw new Exception("Environment variable ANDROID_HOME is not pointing to a directory") - return androidHome -} diff --git a/build-logic/src/main/groovy/org.igniterealtime.smack.java-common-conventions.gradle b/build-logic/src/main/groovy/org.igniterealtime.smack.java-common-conventions.gradle deleted file mode 100644 index 598fdfa67..000000000 --- a/build-logic/src/main/groovy/org.igniterealtime.smack.java-common-conventions.gradle +++ /dev/null @@ -1,367 +0,0 @@ -plugins { - id 'biz.aQute.bnd.builder' - id 'checkstyle' - id 'eclipse' - id 'idea' - id 'jacoco' - id 'java' - id 'java-library' - id 'java-test-fixtures' - id 'maven-publish' - id 'net.ltgt.errorprone' - id 'signing' - - id 'jacoco-report-aggregation' - id 'test-report-aggregation' - - id 'org.igniterealtime.smack.global-conventions' - id 'org.igniterealtime.smack.javadoc-conventions' -} - -version readVersionFile() - -ext { - isSnapshot = version.endsWith('-SNAPSHOT') - gitCommit = getGitCommit() - rootConfigDir = new File(rootDir, 'config') - sonatypeCredentialsAvailable = project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword') - isReleaseVersion = !isSnapshot - isContinuousIntegrationEnvironment = Boolean.parseBoolean(System.getenv('CI')) - signingRequired = !(isSnapshot || isContinuousIntegrationEnvironment) - sonatypeSnapshotUrl = 'https://oss.sonatype.org/content/repositories/snapshots' - sonatypeStagingUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2' - builtDate = (new java.text.SimpleDateFormat("yyyy-MM-dd")).format(new Date()) - oneLineDesc = 'An Open Source XMPP (Jabber) client library' - - jxmppVersion = '[1.1.0-beta1, 1.1.999]' - miniDnsVersion = '[1.1.0-alpha3, 1.1.999]' - junitVersion = '5.9.2' - commonsIoVersion = '2.6' - bouncyCastleVersion = '1.73' - guavaVersion = '30.1-jre' - mockitoVersion = '5.13.0' - orgReflectionsVersion = '0.9.11' - - if (project.hasProperty("useSonatype")) { - useSonatype = project.getProperty("useSonatype").toBoolean() - } else { - // Default to true - useSonatype = true - } - - gplLicensedProjects = [ - ':smack-examples', - ':smack-omemo-signal', - ':smack-omemo-signal-integration-test', - ':smack-repl' - ].collect{ project(it) } -} - -group = 'org.igniterealtime.smack' - -java { - sourceCompatibility = javaVersion - targetCompatibility = sourceCompatibility -} - -eclipse { - classpath { - downloadJavadoc = true - } -} - -// Make all project's 'test' target depend on javadoc, so that -// javadoc is also linted. -test.dependsOn javadoc - -tasks.withType(JavaCompile) { - // Some systems may not have set their platform default - // converter to 'utf8', but we use unicode in our source - // files. Therefore ensure that javac uses unicode - options.encoding = "utf8" - options.compilerArgs = [ - '-Xlint:all', - // Set '-options' because a non-java7 javac will emit a - // warning if source/target is set to 1.7 and - // bootclasspath is *not* set. - '-Xlint:-options', - // TODO: Enable xlint serial - '-Xlint:-serial', - '-Werror', - ] -} -if (JavaVersion.current().isJava8Compatible()) { - tasks.withType(Javadoc) { - // The '-quiet' as second argument is actually a hack, - // since the one parameter addStringOption doesn't seem to - // work, we extra add '-quiet', which is added anyway by - // gradle. - // We disable 'missing' as we do most of javadoc checking via checkstyle. - options.addStringOption('Xdoclint:all,-missing', '-quiet') - // 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') - } -} - -if (JavaVersion.current().isJava9Compatible()) { - tasks.withType(JavaCompile) { - options.compilerArgs.addAll([ - '--release', javaMajor, - ]) - } -} - -jacoco { - toolVersion = "0.8.12" -} - -jacocoTestReport { - dependsOn test - reports { - xml.required = true - } -} - -dependencies { - testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion" - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" - - testFixturesApi "org.junit.jupiter:junit-jupiter-api:$junitVersion" - testImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion" - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" - // https://stackoverflow.com/a/77274251/194894 - testRuntimeOnly "org.junit.platform:junit-platform-launcher:1.11.0" - - // The smack-extensions subproject uses mockito in its fest - // fixtures, and we want to have mockito also available in - // test, so we use API here. - testFixturesApi "org.mockito:mockito-core:${mockitoVersion}" - - testImplementation 'com.jamesmurty.utils:java-xmlbuilder:1.2' - - errorprone 'com.google.errorprone:error_prone_core:2.32.0' -} - -test { - useJUnitPlatform() - - maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 - - // Enable full stacktraces of failed tests. Especially handy - // for CI environments. - testLogging { - events "failed" - exceptionFormat "full" - } -} - -jar { - manifest { - attributes( - 'Implementation-Version': version, - 'Implementation-GitRevision': gitCommit, - 'Built-JDK': System.getProperty('java.version'), - 'Built-Gradle': gradle.gradleVersion, - 'Built-By': System.getProperty('user.name') - ) - } - - bundle { - bnd( - '-removeheaders': 'Tool, Bnd-*', - '-exportcontents': '*', - ) - } -} - -checkstyle { - toolVersion = '8.27' - - if (project in gplLicensedProjects) { - configProperties.checkstyleLicenseHeader = "${project.name}-gplv3-license-header" - } else { - configProperties.checkstyleLicenseHeader = "header" - } -} -task sourcesJar(type: Jar, dependsOn: classes) { - archiveClassifier = 'sources' - from sourceSets.main.allSource -} -task javadocJar(type: Jar, dependsOn: javadoc) { - archiveClassifier = 'javadoc' - from javadoc.destinationDir -} -task testsJar(type: Jar) { - archiveClassifier = 'tests' - from sourceSets.test.output -} -configurations { - testRuntime -} -artifacts { - // Add a 'testRuntime' configuration including the tests so that - // it can be consumed by other projects (smack-omemo-signal for - // example). See http://stackoverflow.com/a/21946676/194894 - testRuntime testsJar -} - -publishing { - publications { - mavenJava(MavenPublication) { - from components.java - artifact sourcesJar - artifact javadocJar - artifact testsJar - pom { - name = 'Smack' - packaging = 'jar' - inceptionYear = '2003' - url = 'http://www.igniterealtime.org/projects/jxmpp/' - afterEvaluate { - description = project.description - } - - issueManagement { - system = 'JIRA' - url = 'http://issues.igniterealtime.org/browse/SMACK' - } - - scm { - url = 'https://github.com/igniterealtime/Smack' - connection = 'scm:git:https://github.com/igniterealtime/Smack.git' - developerConnection = 'scm:git:https://github.com/igniterealtime/Smack.git' - } - - licenses { - if (project in gplLicensedProjects) { - license { - name = 'GNU General Public License, version 3 or any later version' - url = 'https://www.gnu.org/licenses/gpl.txt' - distribution = 'repo' - } - } else { - license { - name = 'The Apache Software License, Version 2.0' - url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' - distribution = 'repo' - } - } - } - - developers { - developer { - id = 'flow' - name = 'Florian Schmaus' - email = 'flow@igniterealtime.org' - } - } - } - } - } - repositories { - if (sonatypeCredentialsAvailable && useSonatype) { - maven { - url isSnapshot ? sonatypeSnapshotUrl : sonatypeStagingUrl - credentials { - username = sonatypeUsername - password = sonatypePassword - } - } - } - // Use - // gradle publish -P customRepoUrl=https://www.igniterealtime.org/archiva/repository/maven -P customRepoUsername=bamboo -P customRepoPassword=hidden -P useSonatype=false - // to deploy to this repo. - if (project.hasProperty("customRepoUrl")) { - maven { - name 'customRepo' - url customRepoUrl - if (project.hasProperty("customRepoUsername")) { - credentials { - username customRepoUsername - password customRepoPassword - } - } - } - } - } -} - -// Workaround for gpg signatory not supporting the 'required' option -// See https://github.com/gradle/gradle/issues/5064#issuecomment-381924984 -// Note what we use 'signing.gnupg.keyName' instead of 'signing.keyId'. -tasks.withType(Sign) { - onlyIf { - project.hasProperty('signing.gnupg.keyName') - } -} -signing { - required { signingRequired } - useGpgCmd() - sign publishing.publications.mavenJava -} - -tasks.withType(JavaCompile) { - options.errorprone { - disableWarningsInGeneratedCode = true - excludedPaths = ".*/jmh_generated/.*" - error( - "UnusedVariable", - "UnusedMethod", - "MethodCanBeStatic", - ) - errorproneArgs = [ - // Disable MissingCasesInEnumSwitch error prone check - // because this check is already done by javac as incomplete-switch. - '-Xep:MissingCasesInEnumSwitch:OFF', - '-Xep:StringSplitter:OFF', - '-Xep:JavaTimeDefaultTimeZone:OFF', - '-Xep:InlineMeSuggester:OFF', - ] - } -} - -// Work around https://github.com/gradle/gradle/issues/4046 -task copyJavadocDocFiles(type: Copy) { - from('src/javadoc') - into 'build/docs/javadoc' - include '**/doc-files/*.*' -} -javadoc.dependsOn copyJavadocDocFiles - -def getGitCommit() { - def projectDirFile = new File("$projectDir") - - def cmd = 'git describe --always --tags --dirty=+' - def proc = cmd.execute(null, projectDirFile) - - def exitStatus = proc.waitFor() - if (exitStatus != 0) return "non-git build" - - def gitCommit = proc.text.trim() - assert !gitCommit.isEmpty() - gitCommit -} - -def getAndroidRuntimeJar() { - def androidHome = new File("$System.env.ANDROID_HOME") - if (!androidHome.isDirectory()) throw new Exception("ANDROID_HOME not found or set") - def androidJar = new File("$androidHome/platforms/android-$smackMinAndroidSdk/android.jar") - if (androidJar.isFile()) { - return androidJar - } else { - throw new Exception("Can't find android.jar for $smackMinAndroidSdk API. Please install corresponding SDK platform package") - } -} - -def readVersionFile() { - def versionFile = new File(rootDir, 'version') - if (!versionFile.isFile()) { - throw new Exception("Could not find version file") - } - if (versionFile.text.isEmpty()) { - throw new Exception("Version file does not contain a version") - } - versionFile.text.trim() -} diff --git a/build-logic/src/main/groovy/org.igniterealtime.smack.javadoc-conventions.gradle b/build-logic/src/main/groovy/org.igniterealtime.smack.javadoc-conventions.gradle deleted file mode 100644 index 61cb8f3c6..000000000 --- a/build-logic/src/main/groovy/org.igniterealtime.smack.javadoc-conventions.gradle +++ /dev/null @@ -1,30 +0,0 @@ -plugins { - // Javadoc linking requires repositories to bet configured. And - // those are declared in global-conventions, hence we add it here. - id 'org.igniterealtime.smack.global-conventions' -} - -if (JavaVersion.current().isJava8Compatible()) { - tasks.withType(Javadoc) { - // The '-quiet' as second argument is actually a hack, - // since the one parameter addStringOption doesn't seem to - // work, we extra add '-quiet', which is added anyway by - // gradle. - // We disable 'missing' as we do most of javadoc checking via checkstyle. - options.addStringOption('Xdoclint:all,-missing', '-quiet') - // 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') - } -} - -if (JavaVersion.current().isJava9Compatible()) { - tasks.withType(Javadoc) { - options.addStringOption('-release', javaMajor) - } -} - -tasks.withType(Javadoc) { - options.charSet = "UTF-8" -} diff --git a/build.gradle b/build.gradle index 13f9b12d7..eda9ed85c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,20 +1,347 @@ -plugins { - // The scalastyle plugin of smack-repl wants the root project to - // have a ideaProject task, so let's add one. - id 'idea' +buildscript { + repositories { + jcenter() + maven { url 'https://plugins.gradle.org/m2/' } + maven { url 'https://dl.bintray.com/content/aalmiray/kordamp' } + } + dependencies { + classpath 'org.kordamp.gradle:clirr-gradle-plugin:0.2.2' + classpath "biz.aQute.bnd:biz.aQute.bnd.gradle:6.0.0" + } +} - id 'org.igniterealtime.smack.javadoc-conventions' +plugins { + id 'ru.vyarus.animalsniffer' version '1.5.0' + id 'net.ltgt.errorprone' version '1.3.0' + // Use e.g. "gradle taskTree" to show its dependency tree. + id 'com.dorongold.task-tree' version '1.5' + id 'com.github.kt3k.coveralls' version '2.10.2' } ext { - javadocAllDir = new File(buildDir, 'javadoc') - integrationTestProjects = [ + java11Projects = [ ':smack-integration-test', ':smack-omemo-signal-integration-test', - ].collect{ project(it) } - javadocAllProjects = subprojects - integrationTestProjects + ':smack-repl', + ':smack-websocket-java11', + ].collect { project(it) } + java11Projects += getRootProject() + java8Projects = allprojects - java11Projects } +configure (java8Projects) { + ext { + javaCompatilibity = JavaVersion.VERSION_1_8 + } +} + +configure (java11Projects) { + ext { + javaCompatilibity = JavaVersion.VERSION_11 + } +} + +allprojects { + apply plugin: 'java-library' + apply plugin: 'java-test-fixtures' + apply plugin: 'eclipse' + apply plugin: 'idea' + apply plugin: 'jacoco' + apply plugin: 'net.ltgt.errorprone' + + version readVersionFile() + + ext { + isSnapshot = version.endsWith('-SNAPSHOT') + gitCommit = getGitCommit() + javadocAllDir = new File(buildDir, 'javadoc') + documentationDir = new File(projectDir, 'documentation') + releasedocsDir = new File(buildDir, 'releasedocs') + rootConfigDir = new File(rootDir, 'config') + sonatypeCredentialsAvailable = project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword') + isReleaseVersion = !isSnapshot + isContinuousIntegrationEnvironment = Boolean.parseBoolean(System.getenv('CI')) + signingRequired = !(isSnapshot || isContinuousIntegrationEnvironment) + sonatypeSnapshotUrl = 'https://oss.sonatype.org/content/repositories/snapshots' + sonatypeStagingUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2' + // Returns only the date in yyyy-MM-dd format, as otherwise, with + // hh:mm:ss information, the manifest files would change with every + // build, causing unnecessary rebuilds. + builtDate = (new java.text.SimpleDateFormat("yyyy-MM-dd")).format(new Date()) + oneLineDesc = 'An Open Source XMPP (Jabber) client library' + integrationTestProjects = [ + ':smack-integration-test', + ':smack-omemo-signal-integration-test', + ].collect{ project(it) } + javadocAllProjects = subprojects - integrationTestProjects + // A dirty hack used for Gradle's jacoco plugin, since is not + // hable to handle the case when a (sub)project has no unit + // tests. :-( + projectsWithoutUnitTests = [ + ':smack-android', + ':smack-android-extensions', + ':smack-bosh', + ':smack-debug', + ':smack-debug-slf4j', + ':smack-java8', + ':smack-jingle-old', + ':smack-resolver-dnsjava', + ':smack-resolver-javax', + ':smack-resolver-minidns', + ':smack-omemo-signal-integration-test', + ].collect{ project(it) } + projectsWithUnitTests = subprojects - projectsWithoutUnitTests + androidProjects = [ + ':smack-tcp', + ':smack-bosh', + ':smack-core', + ':smack-im', + ':smack-resolver-minidns', + ':smack-sasl-provided', + ':smack-extensions', + ':smack-experimental', + ':smack-omemo', + ':smack-omemo-signal', + ':smack-openpgp', + ':smack-xmlparser', + ':smack-xmlparser-xpp3', + ].collect{ project(it) } + androidBootClasspathProjects = [ + ':smack-android', + ':smack-android-extensions', + ].collect{ project(it) } + androidOptionalProjects = [ + ':smack-tcp', + ':smack-extensions', + ':smack-experimental', + ':smack-bosh', + ':smack-omemo', + ':smack-omemo-signal', + ].collect{ project(it) } + gplLicensedProjects = [ + ':smack-omemo-signal', + ':smack-omemo-signal-integration-test', + ':smack-repl' + ].collect{ project(it) } + // Lazily evaluate the Android bootClasspath and offline + // Javadoc using a closure, so that targets which do not + // require it are still able to succeed without an Android + // SDK. + androidBootClasspath = { getAndroidRuntimeJar() } + androidJavadocOffline = { getAndroidJavadocOffline() } + junit4Projects = [ + ':smack-core', + ':smack-im', + ':smack-omemo', + ':smack-omemo-signal', + ':smack-openpgp', + ].collect { project(it) } + + // When using dynamic versions for those, do *not* use [1.0, + // 2.0), since this will also pull in 2.0-alpha1. Instead use + // [1.0, 1.0.99]. + // See also: + // - https://issues.apache.org/jira/browse/MNG-6232 + // - https://issues.igniterealtime.org/browse/SMACK-858 + jxmppVersion = '[1.0.0, 1.0.999]' + miniDnsVersion = '[1.0.0, 1.0.999]' + smackMinAndroidSdk = 19 + junitVersion = '5.7.1' + commonsIoVersion = '2.6' + bouncyCastleVersion = '1.71' + guavaVersion = '30.1-jre' + mockitoVersion = '3.7.7' + orgReflectionsVersion = '0.9.11' + + if (project.hasProperty("useSonatype")) { + useSonatype = project.getProperty("useSonatype").toBoolean() + } else { + // Default to true + useSonatype = true + } + javaMajor = javaCompatilibity.getMajorVersion() + } + group = 'org.igniterealtime.smack' + sourceCompatibility = javaCompatilibity + targetCompatibility = sourceCompatibility + + test { + useJUnitPlatform() + + maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 + + // Enable full stacktraces of failed tests. Especially handy + // for environments like Travis. + testLogging { + events "failed" + exceptionFormat "full" + } + } + + ext.sharedManifest = manifest { + attributes('Implementation-Version': version, + 'Implementation-GitRevision': ext.gitCommit, + 'Built-Date': ext.builtDate, + 'Built-JDK': System.getProperty('java.version'), + 'Built-Gradle': gradle.gradleVersion, + 'Built-By': System.getProperty('user.name') + ) + } + + eclipse { + classpath { + downloadJavadoc = true + } + } + + repositories { + mavenLocal() + mavenCentral() + } + + tasks.withType(JavaCompile) { + // Some systems may not have set their platform default + // converter to 'utf8', but we use unicode in our source + // files. Therefore ensure that javac uses unicode + options.encoding = 'UTF-8' + options.compilerArgs = [ + '-Xlint:all', + // Set '-options' because a non-java7 javac will emit a + // warning if source/traget is set to 1.7 and + // bootclasspath is *not* set. + // TODO implement a sound heuristic to determine a java7 + // rt.jar on the build host. And if none is found, + // fallback to using a environment variable, + // e.g. JAVA7_HOME. See SMACK-651. + '-Xlint:-options', + '-Werror', + ] + options.errorprone { + error( + "UnusedVariable", + "UnusedMethod", + "MethodCanBeStatic", + ) + errorproneArgs = [ + // Disable errorprone checks + '-Xep:TypeParameterUnusedInFormals:OFF', + // Disable errorpone StringSplitter check, as it + // recommends using Splitter from Guava, which we don't + // have (nor want to use in Smack). + '-Xep:StringSplitter:OFF', + '-Xep:JdkObsolete:OFF', + // Disabled because sinttest re-uses BeforeClass from junit. + // TODO: change sinttest so that it has it's own + // BeforeClass and re-enable this check. + '-Xep:JUnit4ClassAnnotationNonStatic:OFF', + // Disabled but should be re-enabled at some point + //'-Xep:InconsistentCapitalization:OFF', + '-Xep:MixedMutabilityReturnType:OFF', + // TODO: Re-enable once Smack's minimum Android SDK level is 26 or higher. + '-Xep:JavaUtilDate:OFF', + ] + } + } + + tasks.withType(ScalaCompile) { + scalaCompileOptions.additionalParameters = [ + '-Xfatal-warnings', + '-feature', + ] + } + + jacoco { + toolVersion = "0.8.6" + } + + jacocoTestReport { + dependsOn test + getSourceDirectories().setFrom(project.files(sourceSets.main.allSource.srcDirs)) + getClassDirectories().setFrom(project.files(sourceSets.main.output)) + reports { + xml.enabled true + } + } + + if (JavaVersion.current().isJava8Compatible()) { + tasks.withType(Javadoc) { + // The '-quiet' as second argument is actually a hack, + // since the one paramater addStringOption doesn't seem to + // work, we extra add '-quiet', which is added anyway by + // gradle. + // TODO: This enables all doclint check but + // 'missing'. Re-enable 'missing' once every public API in + // Smack has a javadoc comment. + options.addStringOption('Xdoclint:accessibility,html,reference,syntax', '-quiet') + + // Treat warnings as errors. + // See also https://bugs.openjdk.java.net/browse/JDK-8200363 + options.addStringOption('Xwerror', '-quiet') + } + } + + if (JavaVersion.current().isJava9Compatible()) { + tasks.withType(Javadoc) { + options.addStringOption('-release', javaMajor) + + // The -no-modules-directories javadoc option was removed in Java 13 + // See https://bugs.openjdk.java.net/browse/JDK-8215582 + if (JavaVersion.current() < JavaVersion.VERSION_13) { + // Fix for javadoc search. If not set, the search result would direct to + // javadoc/undefined/org/jivesoftware/smack/altconnections/HttpLookupMethod.html + // instead of + // javadoc/org/jivesoftware/smack/altconnections/HttpLookupMethod.html + // https://stackoverflow.com/a/53732633/194894 + options.addBooleanOption("-no-module-directories", true) + } + } + tasks.withType(JavaCompile) { + options.compilerArgs.addAll([ + '--release', javaMajor, + ]) + } + } + +tasks.withType(Javadoc) { + options.charSet = "UTF-8" + options.encoding = 'UTF-8' + } + + dependencies { + testFixturesApi "org.junit.jupiter:junit-jupiter-api:$junitVersion" + testImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" + + // The smack-extensions subproject uses mockito in its fest + // fixtures, and we want to have mockito also available in + // test, so we use API here. + testFixturesApi "org.mockito:mockito-core:${mockitoVersion}" + + // To mock final classes + testImplementation "org.mockito:mockito-inline:${mockitoVersion}" + testImplementation 'com.jamesmurty.utils:java-xmlbuilder:1.2' + + errorprone 'com.google.errorprone:error_prone_core:2.5.1' + errorproneJavac('com.google.errorprone:javac:9+181-r4173-1') + } + + // Make all project's 'test' target depend on javadoc, so that + // javadoc is also linted. + test { dependsOn javadoc } +} + +configure (junit4Projects) { + dependencies { + testImplementation "org.junit.vintage:junit-vintage-engine:$junitVersion" + } +} + +// We need to evaluate the child projects first because +// - javadocAll needs the smack-core child to have already resolved +// the jXMPP/MiniDNS dependencies, so that we can the resovled +// version to link to those project's javadoc. +// - We use the child's project description as description for the +// Maven POM. evaluationDependsOnChildren() task javadocAll(type: Javadoc) { source javadocAllProjects.collect {project -> @@ -63,6 +390,315 @@ task javadocAll(type: Javadoc) { } } +import org.apache.tools.ant.filters.ReplaceTokens +task prepareReleasedocs(type: Copy) { + from 'resources/releasedocs' + into releasedocsDir + filter(ReplaceTokens, tokens: [version: version, releasedate: builtDate, targetCompatibility: targetCompatibility.toString()]) +} + +task distributionZip(type: Zip, dependsOn: [javadocAll, prepareReleasedocs]) { + classifier builtDate + into ('javadoc') { + from(javadocAllDir) + } + into ('releasedocs') { + from(releasedocsDir) + } + into ('releasedocs/documentation') { + from(documentationDir) + } +} + +task maybeCheckForSnapshotDependencies { + // Don't check for Snapshot dependencies if this is a snapshot. + onlyIf { isReleaseVersion } + // Run in the execution phase, not in configuration phase, as the + // 'each' forces the runtime configuration to be resovled, which + // causes "Cannot change dependencies of configuration after it + // has been included in dependency resolution." errors. + // See https://discuss.gradle.org/t/23153 + doLast { + allprojects { project -> + project.configurations.runtime.each { + if (it.toString().contains("-SNAPSHOT")) + throw new Exception("Release build contains snapshot dependencies: " + it) + } + } + } +} + +test { dependsOn maybeCheckForSnapshotDependencies } + +jar { + // Root project should not create empty jar artifact + enabled = false +} + +// Disable upload archives for the root project +uploadArchives.enabled = false + +description = """\ +Smack ${version} +${oneLineDesc}.""" + +subprojects { + apply plugin: 'maven-publish' + apply plugin: 'signing' + apply plugin: 'checkstyle' + apply plugin: 'org.kordamp.gradle.clirr' + apply plugin: 'biz.aQute.bnd.builder' + + checkstyle { + toolVersion = '8.27' + } + task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource + } + task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir + } + task testsJar(type: Jar, dependsOn: testClasses) { + classifier = 'tests' + from sourceSets.test.output + } + + artifacts { + // See http://stackoverflow.com/a/21946676/194894 + testRuntime testsJar + } + + publishing { + publications { + mavenJava(MavenPublication) { + from components.java + artifact sourcesJar + artifact javadocJar + artifact testsJar + pom { + name = 'Smack' + packaging = 'jar' + inceptionYear = '2003' + url = 'http://www.igniterealtime.org/projects/smack/' + description = project.description + + issueManagement { + system = 'JIRA' + url = 'https://igniterealtime.org/issues/browse/SMACK' + } + + scm { + url = 'https://github.com/igniterealtime/Smack' + connection = 'scm:git:https://github.com/igniterealtime/Smack.git' + developerConnection = 'scm:git:https://github.com/igniterealtime/Smack.git' + } + + developers { + developer { + id = 'flow' + name = 'Florian Schmaus' + email = 'flow@igniterealtime.org' + } + } + } + } + } + repositories { + if (sonatypeCredentialsAvailable && useSonatype) { + maven { + url isSnapshot ? sonatypeSnapshotUrl : sonatypeStagingUrl + credentials { + username = sonatypeUsername + password = sonatypePassword + } + } + } + // Use + // gradle publish -P customRepoUrl=https://www.igniterealtime.org/archiva/repository/maven -P customRepoUsername=bamboo -P customRepoPassword=hidden -P useSonatype=false + // to deploy to this repo. + if (project.hasProperty("customRepoUrl")) { + maven { + name 'customRepo' + url customRepoUrl + if (project.hasProperty("customRepoUsername")) { + credentials { + username customRepoUsername + password customRepoPassword + } + } + } + } + } + } + rootProject.distributionZip { + dependsOn build + from(buildDir) { + include "$libsDirName/*${version}.jar" + include "$libsDirName/*${version}-javadoc.jar" + include "$libsDirName/*${version}-sources.jar" + } + } + + // Workaround for gpg signatory not supporting the 'required' option + // See https://github.com/gradle/gradle/issues/5064#issuecomment-381924984 + // Note what we use 'signing.gnupg.keyName' instead of 'signing.keyId'. + tasks.withType(Sign) { + onlyIf { + project.hasProperty('signing.gnupg.keyName') + } + } + signing { + useGpgCmd() + required { signingRequired } + sign publishing.publications.mavenJava + } + + clirr { + // 2018-08-14: Disabled Clirr because + // - It reports an breaking change in android.jar (seems right, but there is nothing we can do about it) + // - Only the first smack-* projects are correctly checked, + // the other ones have the output of a clirr report from a previous project + // (Look at the clirr reports). + enabled false + semver false + } + + // Work around https://github.com/gradle/gradle/issues/4046 + task copyJavadocDocFiles(type: Copy) { + from('src/javadoc') + into 'build/docs/javadoc' + include '**/doc-files/*.*' + } + javadoc.dependsOn copyJavadocDocFiles + + // Make sure root projects 'javadocAll' depends on the + // subproject's javadoc, to ensure that all all doc-files/ are + // generated and up-to-date. Obviously this means that the + // javadocAll task will also create the individual javadoc's of the + // subprojects. + javadocAll.dependsOn javadoc +} + +// The smack-java8-full project generates the dot and png files of the +// current state graph. Ensure they are generated before copied. +configure (project(':smack-java8-full')) { + copyJavadocDocFiles.dependsOn convertModularXmppClientToServerConnectionStateGraphDotToPng +} + +configure (androidProjects + androidBootClasspathProjects) { + apply plugin: 'ru.vyarus.animalsniffer' + dependencies { + signature "net.sf.androidscents.signature:android-api-level-${smackMinAndroidSdk}:4.4.2_r4@signature" + } + animalsniffer { + sourceSets = [sourceSets.main] + } +} + +// There is no need to ever clirr integration test projects and the +// smack-repl project. +configure(integrationTestProjects + project(':smack-repl')) { + clirr { + enabled false + } +} + +// Disable clirr on omemo modules +project(':smack-omemo').clirr.enabled = false +project(':smack-omemo-signal').clirr.enabled = false + +subprojects*.jar { + manifest { + from sharedManifest + } + bundle { + bnd( + '-removeheaders': 'Tool, Bnd-*', + '-exportcontents': '*', + ) + } +} + +configure(subprojects - gplLicensedProjects) { + checkstyle { + configProperties.checkstyleLicenseHeader = "header" + } + publishing { + publications { + mavenJava(MavenPublication) { + pom { + licenses { + license { + name = 'The Apache Software License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + distribution = 'repo' + } + } + } + } + } + } +} + +configure(gplLicensedProjects) { + checkstyle { + configProperties.checkstyleLicenseHeader = "${project.name}-gplv3-license-header" + } + publishing { + publications { + mavenJava(MavenPublication) { + pom { + licenses { + license { + name = 'GNU General Public License, version 3 or any later version' + url = 'https://www.gnu.org/licenses/gpl.txt' + distribution = 'repo' + } + } + } + } + } + } +} + +configure(androidBootClasspathProjects) { + compileJava { + options.bootstrapClasspath = files(androidBootClasspath) + } + javadoc { + classpath += files(androidBootClasspath) + } +} + +apply plugin: "com.github.kt3k.coveralls" +coveralls { + sourceDirs = files(subprojects.sourceSets.main.allSource.srcDirs).files.absolutePath +} + +task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) { + dependsOn = projectsWithUnitTests.jacocoTestReport + getSourceDirectories().setFrom(files(projectsWithUnitTests.sourceSets.main.allSource.srcDirs)) + getClassDirectories().setFrom(files(projectsWithUnitTests.sourceSets.main.output)) + getExecutionData().setFrom(files(projectsWithUnitTests.jacocoTestReport.executionData)) + reports { + xml.enabled true + xml.destination file("${buildDir}/reports/jacoco/test/jacocoTestReport.xml") + } + // We could remove the following setOnlyIf line, but then + // jacocoRootReport would silently be SKIPPED if something with + // the projectsWithUnitTests is wrong (e.g. a project is missing + // in there). + setOnlyIf { true } +} + +// Important to specify this task after the subprojects block +task clirrRootReport(type: org.kordamp.gradle.clirr.ClirrReportTask) { + dependsOn = subprojects.tasks.clirr + reports = files((subprojects.findAll { it.clirr.enabled == true }).tasks.clirr.xmlReport) +} + task integrationTest { description 'Verify correct functionality of Smack by running some integration tests.' dependsOn project(':smack-integration-test').tasks.run @@ -70,7 +706,7 @@ task integrationTest { task omemoSignalIntTest { description 'Run integration tests of the smack-omemo module in combination with smack-omemo-signal.' - dependsOn 'smack-omemo-signal-integration-test:run' + dependsOn project(':smack-omemo-signal-integration-test').tasks.run } task sinttestAll { @@ -81,6 +717,70 @@ task sinttestAll { ]} } +def getGitCommit() { + def projectDirFile = new File("$projectDir") + def dotGit = new File(projectDirFile, ".git") + if (!dotGit.isDirectory()) return 'non-git build' + + def cmd = 'git describe --always --tags --dirty=+' + def proc = cmd.execute(null, projectDirFile) + proc.waitForOrKill(10 * 1000) + + def gitCommit = proc.text.trim() + assert !gitCommit.isEmpty() + + def srCmd = 'git symbolic-ref --short HEAD' + def srProc = srCmd.execute(null, projectDirFile) + srProc.waitForOrKill(10 * 1000) + if (srProc.exitValue() == 0) { + // Only add the information if the git command was + // successful. There may be no symbolic reference for HEAD if + // e.g. in detached mode. + def symbolicReference = srProc.text.trim() + assert !symbolicReference.isEmpty() + gitCommit += "-$symbolicReference" + } + + gitCommit +} + +def getAndroidRuntimeJar() { + def androidApiLevel = ext.smackMinAndroidSdk + def androidHome = getAndroidHome() + def androidJar = new File("$androidHome/platforms/android-${androidApiLevel}/android.jar") + if (androidJar.isFile()) { + return androidJar + } else { + throw new Exception("Can't find android.jar for API level ${androidApiLevel}. Please install corresponding SDK platform package") + } +} + +def getAndroidJavadocOffline() { + def androidHome = getAndroidHome() + return androidHome.toString() + "/docs/reference" +} + +def getAndroidHome() { + def androidHomeEnv = System.getenv("ANDROID_HOME") + if (androidHomeEnv == null) { + throw new Exception("ANDROID_HOME environment variable is not set") + } + def androidHome = new File(androidHomeEnv) + if (!androidHome.isDirectory()) throw new Exception("Environment variable ANDROID_HOME is not pointing to a directory") + return androidHome +} + +def readVersionFile() { + def versionFile = new File(rootDir, 'version') + if (!versionFile.isFile()) { + throw new Exception("Could not find version file") + } + if (versionFile.text.isEmpty()) { + throw new Exception("Version file does not contain a version") + } + versionFile.text.trim() +} + def getResolvedVersion(queriedProject = 'smack-core', component) { def configuration = project(queriedProject) .configurations @@ -91,7 +791,7 @@ def getResolvedVersion(queriedProject = 'smack-core', component) { .resolvedArtifacts .findAll { // 'it' is of type ResolvedArtifact, 'id' of - // Component*Artifact*Identifier, and we check the + // Component*Artifcat*Identifier, and we check the // ComponentIdentifier. it.id.getComponentIdentifier() instanceof org.gradle.api.artifacts.component.ModuleComponentIdentifier } diff --git a/config/checkstyle/smack-examples-gplv3-license-header.txt b/config/checkstyle/smack-examples-gplv3-license-header.txt deleted file mode 100644 index 3d9d392c4..000000000 --- a/config/checkstyle/smack-examples-gplv3-license-header.txt +++ /dev/null @@ -1,20 +0,0 @@ -/** - * - * Copyright 20XX John Doe - * - * This file is part of smack-examples. - * - * smack-examples is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index 671a138d8..000000000 --- a/gradle.properties +++ /dev/null @@ -1,5 +0,0 @@ -# Workaround for https://github.com/CycloneDX/cyclonedx-gradle-plugin/issues/349 -# suggested at https://docs.gradle.org/current/userguide/upgrading_version_8.html#xml_parsing_now_requires_recent_parsers -systemProp.javax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl -systemProp.javax.xml.transform.TransformerFactory=com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl -systemProp.javax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b953..e708b1c02 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index df97d72b8..442d9132e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip -networkTimeout=10000 -validateDistributionUrl=true +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index f5feea6d6..4f906e0c8 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/bin/sh +#!/usr/bin/env sh # -# Copyright © 2015-2021 the original authors. +# Copyright 2015 the original author or authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,104 +15,69 @@ # See the License for the specific language governing permissions and # limitations under the License. # -# SPDX-License-Identifier: Apache-2.0 -# ############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# +## +## Gradle start up script for UN*X +## ############################################################################## # Attempt to set APP_HOME - # Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum +MAX_FD="maximum" warn () { echo "$*" -} >&2 +} die () { echo echo "$*" echo exit 1 -} >&2 +} # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -122,9 +87,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java + JAVACMD="$JAVA_HOME/jre/sh/java" else - JAVACMD=$JAVA_HOME/bin/java + JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -133,120 +98,88 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." - fi fi # Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi fi -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi # For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=$( cygpath --unix "$JAVACMD" ) + JAVACMD=`cygpath --unix "$JAVACMD"` - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac fi +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 9b42019c7..ac1b06f93 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,10 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem -@if "%DEBUG%"=="" @echo off +@if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -27,8 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused +if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -43,13 +40,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute +if "%ERRORLEVEL%" == "0" goto execute -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. goto fail @@ -59,11 +56,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. goto fail @@ -78,15 +75,13 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd +if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/repl b/repl index e31926a9d..c6014bbb4 100755 --- a/repl +++ b/repl @@ -1,5 +1,7 @@ #!/usr/bin/env bash -set -euo pipefail +set -e +set -u +set -o pipefail JDWP=false JDWP_PORT=8000 @@ -35,13 +37,12 @@ echo "Compiling and computing classpath (May take a while)" # /smack/smack-repl/build/classes/main:/smack/smack-repl/build/ # resources/main:/smack/smack-tcp/build/libs/smack-tcp-4.2.0-alpha4-SNAPSHOT.jar # So perform a "tail -n1" on the output of gradle -GRADLE_CLASSPATH="$(${GRADLE_BIN:-./gradlew} :smack-repl:printClasspath --quiet |\ +GRADLE_CLASSPATH="$(gradle :smack-repl:printClasspath --quiet |\ tail -n1)" echo "Finished, starting REPL" -exec java \ - "${EXTRA_JAVA_ARGS[@]}" \ +java "${EXTRA_JAVA_ARGS[@]}" \ -Dscala.usejavacp=true \ -classpath "${GRADLE_CLASSPATH}" \ ammonite.Main \ - --predef smack-repl/scala.repl + --predef "smack-repl/scala.repl" diff --git a/resources/fix-a-javadoc.sh b/resources/fix-a-javadoc.sh index a300a1a59..94e8f31fd 100755 --- a/resources/fix-a-javadoc.sh +++ b/resources/fix-a-javadoc.sh @@ -29,7 +29,7 @@ SMACK_EXCEPTIONS[SmackException]="if Smack detected an exceptional situation." SMACK_EXCEPTIONS[XMPPException]="if an XMPP protocol error was received." SMACK_EXCEPTIONS[SmackSaslException]="if a SASL specific error occurred." SMACK_EXCEPTIONS[SASLErrorException]="if a SASL protocol error was returned." -SMACK_EXCEPTIONS[NotAMucServiceException]="if the entity is not a MUC service." +SMACK_EXCEPTIONS[NotAMucServiceException]="if the entity is not a MUC serivce." SMACK_EXCEPTIONS[NoSuchAlgorithmException]="if no such algorithm is available." SMACK_EXCEPTIONS[KeyManagementException]="if there was a key mangement error." SMACK_EXCEPTIONS[XmppStringprepException]="if the provided string is invalid." @@ -53,7 +53,7 @@ SMACK_EXCEPTIONS[Exception]="if an exception occurred." SMACK_EXCEPTIONS[TestNotPossibleException]="if the test is not possible." SMACK_EXCEPTIONS[TimeoutException]="if there was a timeout." SMACK_EXCEPTIONS[IllegalStateException]="if an illegal state was encountered" -SMACK_EXCEPTIONS[NoSuchPaddingException]="if the requested padding mechanism is not available." +SMACK_EXCEPTIONS[NoSuchPaddingException]="if the requested padding mechanism is not availble." SMACK_EXCEPTIONS[BadPaddingException]="if the input data is not padded properly." SMACK_EXCEPTIONS[InvalidKeyException]="if the key is invalid." SMACK_EXCEPTIONS[IllegalBlockSizeException]="if the input data length is incorrect." diff --git a/resources/getCopyright.sh b/resources/getCopyright.sh index fdde88b0f..c34fd87da 100755 --- a/resources/getCopyright.sh +++ b/resources/getCopyright.sh @@ -15,7 +15,7 @@ for p in $SUBPROJECTS; do sort | \ # Remove duplicates uniq | \ - # Split multi Copyright statements, e.g. "2001-2013 FooBar, 2014 Baz" + # Split multi Copyright statemtents, e.g. "2001-2013 FooBar, 2014 Baz" tr ',' '\n' | \ # Remove whitespaces resulting from the previous split sed "s/^[ \t]*//" | \ diff --git a/resources/releasedocs/README.html b/resources/releasedocs/README.html new file mode 100644 index 000000000..d25eaf624 --- /dev/null +++ b/resources/releasedocs/README.html @@ -0,0 +1,221 @@ + + + + + Smack Readme + + + + +
+ + + + +
+ +

+ + + + + + + + + +
version:@version@
released:@releasedate@
+ +

+Thank you for downloading Smack! This version of Smack is compatible +with JVMs @targetCompatibility@ or higher. Using a build system which +is able to consume Maven artifacts, like gradle or Maven, is highly +recommended when using Smack. +

+ +

+ This is not the real README. Please visit +

+ https://www.igniterealtime.org/projects/smack/readme +
+ for the README of the current stable Smack version. +

+ +

+ Smack tries to depend on as few as possible libraries. The only + requirement is jXMPP. For DNS + resolution we recommend to + use MiniDNS. +

+ +

+Start off by viewing the documentation +that can be found in the "documentation" directory included with this distribution. +

+Further information can be found on the +Smack website. If you need help using or would like to make contributions or +fixes to the code, please visit the +online forum. +

+ +

Changelog and Upgrading

+ +View the changelog for a list of changes since the +last release. + +

License Agreements

+

    +
  • Use of the Smack source code is governed by the Apache License Version 2.0: +
    + Copyright 2002-2008 Jive Software.
    +
    + 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.
    + 
  • + +
  • Smack contains icons and images licensed from INCORS GmbH. You are not licensed +to use these icons outside of Smack.
  • + +
  • Third-party source code is licensed as noted in their source files. + +
+
+
+ + diff --git a/settings.gradle b/settings.gradle index d433b95d3..91c403b77 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,3 @@ -pluginManagement { - includeBuild('build-logic') -} - // The name of the root project. // If we would not set the name, then gradle would use the directory // name of the root directory @@ -10,7 +6,6 @@ rootProject.name = 'Smack' include 'smack-core', 'smack-im', 'smack-tcp', - 'smack-examples', 'smack-extensions', 'smack-experimental', 'smack-debug', @@ -27,8 +22,8 @@ include 'smack-core', 'smack-bosh', 'smack-android', 'smack-android-extensions', - 'smack-java11', - 'smack-java11-full', + 'smack-java8', + 'smack-java8-full', 'smack-integration-test', 'smack-omemo', 'smack-omemo-signal', diff --git a/smack-android-extensions/build.gradle b/smack-android-extensions/build.gradle index ce9a40fc4..0cdad8bda 100644 --- a/smack-android-extensions/build.gradle +++ b/smack-android-extensions/build.gradle @@ -1,9 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' - id 'org.igniterealtime.smack.android-boot-classpath-conventions' -} - description = """\ Extra Smack extensions for Android.""" @@ -14,5 +8,5 @@ dependencies { api project(':smack-extensions') // Add the Android jar to the Eclipse .classpath. - implementation files(androidBootClasspath) + compileClasspath files(androidBootClasspath) } diff --git a/smack-android-extensions/src/main/java/org/jivesoftware/smackx/package-info.java b/smack-android-extensions/src/main/java/org/jivesoftware/smackx/package-info.java index bce3b6064..7ebe86244 120000 --- a/smack-android-extensions/src/main/java/org/jivesoftware/smackx/package-info.java +++ b/smack-android-extensions/src/main/java/org/jivesoftware/smackx/package-info.java @@ -1 +1 @@ -../../../../../../../smack-java11-full/src/main/java/org/jivesoftware/smackx/package-info.java \ No newline at end of file +../../../../../../../smack-java8-full/src/main/java/org/jivesoftware/smackx/package-info.java \ No newline at end of file diff --git a/smack-android-extensions/src/main/java/org/jivesoftware/smackx/ping/android/ServerPingWithAlarmManager.java b/smack-android-extensions/src/main/java/org/jivesoftware/smackx/ping/android/ServerPingWithAlarmManager.java index 0315629c8..a81f51ade 100644 --- a/smack-android-extensions/src/main/java/org/jivesoftware/smackx/ping/android/ServerPingWithAlarmManager.java +++ b/smack-android-extensions/src/main/java/org/jivesoftware/smackx/ping/android/ServerPingWithAlarmManager.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014-2024 Florian Schmaus + * Copyright © 2014-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.os.Build; import android.os.SystemClock; /** @@ -122,7 +121,6 @@ public final class ServerPingWithAlarmManager extends Manager { private static final BroadcastReceiver ALARM_BROADCAST_RECEIVER = new BroadcastReceiver() { @Override - @SuppressWarnings("LockOnNonEnclosingClassLiteral") public void onReceive(Context context, Intent intent) { LOGGER.fine("Ping Alarm broadcast received"); Set> managers; @@ -165,7 +163,7 @@ public final class ServerPingWithAlarmManager extends Manager { private static AlarmManager sAlarmManager; /** - * Register a pending intent with the AlarmManager to be broadcast every half hour and + * Register a pending intent with the AlarmManager to be broadcasted every half hour and * register the alarm broadcast receiver to receive this intent. The receiver will check all * known questions if a ping is Necessary when invoked by the alarm intent. * @@ -175,11 +173,7 @@ public final class ServerPingWithAlarmManager extends Manager { sContext = context; context.registerReceiver(ALARM_BROADCAST_RECEIVER, new IntentFilter(PING_ALARM_ACTION)); sAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - int pendingIntentFlags = 0; - if (Build.VERSION.SDK_INT >= 23) { - pendingIntentFlags |= PendingIntent.FLAG_IMMUTABLE; - } - sPendingIntent = PendingIntent.getBroadcast(context, 0, new Intent(PING_ALARM_ACTION), pendingIntentFlags); + sPendingIntent = PendingIntent.getBroadcast(context, 0, new Intent(PING_ALARM_ACTION), 0); sAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR, AlarmManager.INTERVAL_HALF_HOUR, sPendingIntent); diff --git a/smack-android/build.gradle b/smack-android/build.gradle index ef158e137..556a526eb 100644 --- a/smack-android/build.gradle +++ b/smack-android/build.gradle @@ -1,9 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' - id 'org.igniterealtime.smack.android-boot-classpath-conventions' -} - description = """\ Smack for Android. All the required dependencies to run Smack on Android. @@ -22,13 +16,13 @@ dependencies { // used in non-Android projects. implementation "org.minidns:minidns-android21:$miniDnsVersion" - api project(':smack-core') - api project(':smack-im') - api project(':smack-resolver-minidns') - api project(':smack-sasl-provided') - api project(':smack-xmlparser') - api project(':smack-xmlparser-xpp3') + // androidProjects lists all projects that are checked to compile against android.jar + // Filter out the optional Smack dependencies from androidProjects + (androidProjects - androidOptionalProjects) + .each { project -> + api project + } // Add the Android jar to the Eclipse .classpath. - implementation files(androidBootClasspath) + compileClasspath files(androidBootClasspath) } diff --git a/smack-android/src/main/java/org/jivesoftware/smack/android/AndroidSmackInitializer.java b/smack-android/src/main/java/org/jivesoftware/smack/android/AndroidSmackInitializer.java index b66b56462..a34fb1776 100644 --- a/smack-android/src/main/java/org/jivesoftware/smack/android/AndroidSmackInitializer.java +++ b/smack-android/src/main/java/org/jivesoftware/smack/android/AndroidSmackInitializer.java @@ -37,8 +37,6 @@ import org.minidns.dnsserverlookup.android21.AndroidUsingLinkProperties; public class AndroidSmackInitializer implements SmackInitializer { @Override - // Android deprecated StrictHostnameVerifier in API level 22 - @SuppressWarnings("deprecation") public List initialize() { SmackConfiguration.setDefaultHostnameVerifier(new StrictHostnameVerifier()); Base64.setEncoder(AndroidBase64Encoder.INSTANCE); diff --git a/smack-android/src/main/java/org/jivesoftware/smackx/debugger/android/AndroidDebugger.java b/smack-android/src/main/java/org/jivesoftware/smackx/debugger/android/AndroidDebugger.java index 930fb9195..068dab202 100644 --- a/smack-android/src/main/java/org/jivesoftware/smackx/debugger/android/AndroidDebugger.java +++ b/smack-android/src/main/java/org/jivesoftware/smackx/debugger/android/AndroidDebugger.java @@ -28,7 +28,7 @@ import android.util.Log; * implementation, therefore {@link org.jivesoftware.smack.debugger.JulDebugger} is preferred. *

* It is possible to not only print the raw sent and received stanzas but also the interpreted - * packets by Smack. By default,interpreted packets won't be printed. To enable this feature + * packets by Smack. By default interpreted packets won't be printed. To enable this feature * just change the printInterpreted static variable to true. * */ diff --git a/smack-android/src/main/java/org/jivesoftware/smackx/package-info.java b/smack-android/src/main/java/org/jivesoftware/smackx/package-info.java index bce3b6064..7ebe86244 120000 --- a/smack-android/src/main/java/org/jivesoftware/smackx/package-info.java +++ b/smack-android/src/main/java/org/jivesoftware/smackx/package-info.java @@ -1 +1 @@ -../../../../../../../smack-java11-full/src/main/java/org/jivesoftware/smackx/package-info.java \ No newline at end of file +../../../../../../../smack-java8-full/src/main/java/org/jivesoftware/smackx/package-info.java \ No newline at end of file diff --git a/smack-bosh/build.gradle b/smack-bosh/build.gradle index d939a9e46..fcd3d5896 100644 --- a/smack-bosh/build.gradle +++ b/smack-bosh/build.gradle @@ -1,8 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} - description = """\ Smack BOSH API. This API is considered beta quality.""" diff --git a/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java b/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java index f1c0b9015..14d7c0e90 100644 --- a/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java +++ b/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java @@ -172,15 +172,14 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection { client = BOSHClient.create(cfgBuilder.build()); - // Initialize the debugger before addBOSHClientResponseListener(new BOSHPacketReader()); - // BOSHPacketReader may hold and send response prior to display of the request i.e. before + client.addBOSHClientConnListener(new BOSHConnectionListener()); + client.addBOSHClientResponseListener(new BOSHPacketReader()); + + // Initialize the debugger if (debugger != null) { initDebugger(); } - client.addBOSHClientConnListener(new BOSHConnectionListener()); - client.addBOSHClientResponseListener(new BOSHPacketReader()); - // Send the session creation request client.send(ComposableBody.builder() .setNamespaceDefinition("xmpp", XMPP_BOSH_NS) @@ -360,11 +359,10 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection { CloseableUtil.maybeClose(reader, LOGGER); CloseableUtil.maybeClose(writer, LOGGER); - // set readerConsumer = null before reader to avoid NPE reference - readerConsumer = null; readerPipe = null; reader = null; writer = null; + readerConsumer = null; } /** @@ -442,8 +440,6 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection { if (event.getBody() != null) { try { writer.write(event.getBody().toXML()); - // Fix all BOSH sent debug messages not shown - writer.flush(); } catch (Exception e) { // Ignore } diff --git a/smack-core/build.gradle b/smack-core/build.gradle index 1ffb92eb7..f449ec5b7 100644 --- a/smack-core/build.gradle +++ b/smack-core/build.gradle @@ -1,7 +1,7 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} +// Note that this is also declared in the main build.gradle for +// subprojects, but since evaluationDependsOnChildren is enabled we +// need to declare it here too to have bundle{bnd{...}} available +apply plugin: 'biz.aQute.bnd.builder' description = """\ Smack core components.""" @@ -16,9 +16,6 @@ dependencies { api "org.jxmpp:jxmpp-jid:$jxmppVersion" api "org.minidns:minidns-core:$miniDnsVersion" - // TODO: Migrate Junit4 tests to Junit5. - testImplementation "org.junit.vintage:junit-vintage-engine:$junitVersion" - testFixturesImplementation project(':smack-xmlparser-stax') testFixturesImplementation project(':smack-xmlparser-xpp3') @@ -31,7 +28,7 @@ dependencies { testFixturesApi "org.jxmpp:jxmpp-jid:$jxmppVersion:tests" testFixturesApi "org.xmlunit:xmlunit-core:$xmlUnitVersion" - // Explicitly add assertj-core which is a dependency of + // Explictily add assertj-core which is a dependency of // xmlunit-assertj, but gradle fails to resolves it with: // Execution failed for task ':smack-core:compileTestJava'. // > Could not resolve all files for configuration ':smack-core:testCompileClasspath'. @@ -62,7 +59,7 @@ task createVersionResource(type: CreateFileTask) { outputFile = new File(projectDir, 'src/main/resources/org.jivesoftware.smack/version') } -processResources.dependsOn(createVersionResource) +compileJava.dependsOn(createVersionResource) jar { bundle { diff --git a/smack-core/src/integration-test/java/org/jivesoftware/smack/MessageTest.java b/smack-core/src/integration-test/java/org/jivesoftware/smack/MessageTest.java index bcded200c..75b4f6915 100644 --- a/smack-core/src/integration-test/java/org/jivesoftware/smack/MessageTest.java +++ b/smack-core/src/integration-test/java/org/jivesoftware/smack/MessageTest.java @@ -60,7 +60,7 @@ public class MessageTest extends SmackTestCase { } Message message = (Message) collector.nextResult(2500); - assertNotNull("Message not received from remote user", message); + assertNotNull("Message not recieved from remote user", message); } /** diff --git a/smack-core/src/integration-test/java/org/jivesoftware/smack/test/SmackTestCase.java b/smack-core/src/integration-test/java/org/jivesoftware/smack/test/SmackTestCase.java index ae25506ba..601540abe 100644 --- a/smack-core/src/integration-test/java/org/jivesoftware/smack/test/SmackTestCase.java +++ b/smack-core/src/integration-test/java/org/jivesoftware/smack/test/SmackTestCase.java @@ -487,7 +487,7 @@ public abstract class SmackTestCase extends TestCase { } /** - * Returns the name of the configuration file related to this test case. By default,all + * Returns the name of the configuration file related to this test case. By default all * the test cases will use the same configuration file. However, it's possible to override the * default configuration by providing a file of the form .xml * (e.g. RosterTest.xml). diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AbstractConnectionListener.java b/smack-core/src/main/java/org/jivesoftware/smack/AbstractConnectionListener.java new file mode 100644 index 000000000..f4a6749b9 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractConnectionListener.java @@ -0,0 +1,51 @@ +/** + * + * Copyright 2009 the original author or authors + * + * 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; + +/** + * The AbstractConnectionListener class provides an empty implementation for all + * methods defined by the {@link ConnectionListener} interface. This is a + * convenience class which should be used in case you do not need to implement + * all methods. + * + * @author Henning Staib + * @deprecated use {@link ConnectionListener} instead. + */ +// TODO: Remove in Smack 4.5. +@Deprecated +public class AbstractConnectionListener implements ConnectionListener { + @Override + public void connected(XMPPConnection connection) { + // do nothing + } + + @Override + public void authenticated(XMPPConnection connection, boolean resumed) { + // do nothing + } + + @Override + public void connectionClosed() { + // do nothing + } + + @Override + public void connectionClosedOnError(Exception e) { + // do nothing + } + +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java index a3fc2f941..2b2dd5ee8 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -1,6 +1,6 @@ /** * - * Copyright 2009 Jive Software, 2018-2024 Florian Schmaus. + * Copyright 2009 Jive Software, 2018-2022 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ package org.jivesoftware.smack; import java.io.IOException; import java.io.Reader; import java.io.Writer; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; @@ -129,7 +128,7 @@ import org.jxmpp.stringprep.XmppStringprepException; import org.jxmpp.util.XmppStringUtils; /** - * This abstract class is commonly used as super class for XMPP connection mechanisms like TCP and BOSH. Hence, it + * This abstract class is commonly used as super class for XMPP connection mechanisms like TCP and BOSH. Hence it * provides the methods for connection state management, like {@link #connect()}, {@link #login()} and * {@link #disconnect()} (which are deliberately not provided by the {@link XMPPConnection} interface). *

@@ -388,7 +387,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { * * @param configuration The configuration which is used to establish the connection. */ - @SuppressWarnings("this-escape") protected AbstractXMPPConnection(ConnectionConfiguration configuration) { saslAuthentication = new SASLAuthentication(this, configuration); config = configuration; @@ -1069,7 +1067,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } @Override - @SuppressWarnings("TypeParameterUnusedInFormals") public I sendIqRequestAndWaitForResponse(IQ request) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { StanzaCollector collector = createStanzaCollectorAndSend(request); @@ -1217,7 +1214,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } Stanza packet = (Stanza) sendTopLevelStreamElement; - final List listenersToNotify = new ArrayList<>(); + final List listenersToNotify = new LinkedList<>(); synchronized (sendListeners) { for (ListenerWrapper listenerWrapper : sendListeners.values()) { if (listenerWrapper.filterMatches(packet)) { @@ -1245,6 +1242,27 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { }); } + @Deprecated + @Override + public void addStanzaInterceptor(StanzaListener packetInterceptor, + StanzaFilter packetFilter) { + if (packetInterceptor == null) { + throw new NullPointerException("Packet interceptor is null."); + } + InterceptorWrapper interceptorWrapper = new InterceptorWrapper(packetInterceptor, packetFilter); + synchronized (interceptors) { + interceptors.put(packetInterceptor, interceptorWrapper); + } + } + + @Deprecated + @Override + public void removeStanzaInterceptor(StanzaListener packetInterceptor) { + synchronized (interceptors) { + interceptors.remove(packetInterceptor); + } + } + private static , MP extends MessageOrPresence> void addInterceptor( Map, GenericInterceptorWrapper> interceptors, Consumer interceptor, Predicate filter) { @@ -1287,7 +1305,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { private static , MP extends MessageOrPresence> MP fireMessageOrPresenceInterceptors( MP messageOrPresence, Map, GenericInterceptorWrapper> interceptors) { - List> interceptorsToInvoke = new ArrayList<>(); + List> interceptorsToInvoke = new LinkedList<>(); synchronized (interceptors) { for (GenericInterceptorWrapper interceptorWrapper : interceptors.values()) { if (interceptorWrapper.filterMatches(messageOrPresence)) { @@ -1322,7 +1340,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { * @return the, potentially modified stanza, after the interceptors are run. */ private Stanza firePacketInterceptors(Stanza packet) { - List interceptorsToInvoke = new ArrayList<>(); + List interceptorsToInvoke = new LinkedList<>(); synchronized (interceptors) { for (InterceptorWrapper interceptorWrapper : interceptors.values()) { if (interceptorWrapper.filterMatches(packet)) { @@ -1607,7 +1625,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { // First handle the async recv listeners. Note that this code is very similar to what follows a few lines below, // the only difference is that asyncRecvListeners is used here and that the packet listeners are started in // their own thread. - final Collection listenersToNotify = new ArrayList<>(); + final Collection listenersToNotify = new LinkedList<>(); extractMatchingListeners(packet, asyncRecvListeners, listenersToNotify); for (final StanzaListener listener : listenersToNotify) { asyncGoLimited(new Runnable() { @@ -1933,7 +1951,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { // Default implementation does nothing } - @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) + @SuppressWarnings("unchecked") @Override public F getFeature(QName qname) { return (F) streamFeatures.get(qname); @@ -2178,7 +2196,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { * {@link #maxAsyncRunnables}. Note that we use a {@code LinkedList} in order to avoid space blowups in case the * list ever becomes very big and shrinks again. */ - @SuppressWarnings("JdkObsolete") private final Queue deferredAsyncRunnables = new LinkedList<>(); private int deferredAsyncRunnablesCount; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AsyncButOrdered.java b/smack-core/src/main/java/org/jivesoftware/smack/AsyncButOrdered.java index 5788370ff..526e3cd2e 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AsyncButOrdered.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AsyncButOrdered.java @@ -53,14 +53,14 @@ import java.util.concurrent.Executor; public class AsyncButOrdered { /** - * A map with the currently pending runnables for a given key. Note that this is a weak hash map, so we do not have - * to take care of removing the keys ourselves from the map. + * A map with the currently pending runnables for a given key. Note that this is a weak hash map so we do not have + * to take care of removing the keys ourselfs from the map. */ private final Map> pendingRunnables = new WeakHashMap<>(); /** * A marker map if there is an active thread for the given key. Holds the responsible handler thread if one is - * active, otherwise the key is non-existent in the map. + * active, otherwise the key is non-existend in the map. */ private final Map threadActiveMap = new HashMap<>(); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java index e9d8afe45..9561a158d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2017-2024 Florian Schmaus. + * Copyright 2003-2007 Jive Software, 2017-2022 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -88,7 +88,7 @@ import org.minidns.util.InetAddressUtil; /** * The connection configuration used for XMPP client-to-server connections. A well configured XMPP service will * typically only require you to provide two parameters: The XMPP address, also known as the JID, of the user and the - * password. All other configuration parameters could ideally be determined automatically by Smack. Hence, it is often + * password. All other configuration parameters could ideally be determined automatically by Smack. Hence it is often * enough to call {@link Builder#setXmppAddressAndPassword(CharSequence, String)}. *

* Technically there are typically at least two parameters required: Some kind of credentials for authentication. And @@ -248,7 +248,7 @@ public abstract class ConnectionConfiguration { stanzaIdSourceFactory = builder.stanzaIdSourceFactory; - // If the enabledSaslMechanisms are set, then they must not be empty + // If the enabledSaslmechanisms are set, then they must not be empty assert enabledSaslMechanisms == null || !enabledSaslMechanisms.isEmpty(); } @@ -267,7 +267,7 @@ public abstract class ConnectionConfiguration { context = SSLContext.getInstance("TLS"); } - // TODO: Remove the block below once we removed setKeystorePath(), setKeystoreType(), setCallbackHandler() and + // TODO: Remove the block below once we removed setKeystorePath(), setKeystoreType(), setCallbackHanlder() and // setPKCS11Library() in the builder, and all related fields and the parameters of this function. if (keyManagers == null) { keyManagers = Builder.getKeyManagersFrom(keystoreType, keystorePath, callbackHandler, pkcs11Library); @@ -534,7 +534,7 @@ public abstract class ConnectionConfiguration { /** * Returns the stream language to use when connecting to the server. * - * @return the stream language to use when connecting to the server or null. + * @return the stream language to use when connecting to the server. */ public Locale getLanguage() { return language; @@ -544,21 +544,19 @@ public abstract class ConnectionConfiguration { * Returns the xml:lang string of the stream language to use when connecting to the server. * *

If the developer sets the language to null, this will also return null, leading to - * the removal of the xml:lang tag from the stream.

+ * the removal of the xml:lang tag from the stream. If a Locale("") is configured, this will + * return "", which can be used as an override.

* - * @return the stream language to use when connecting to the server or null. + * @return the stream language to use when connecting to the server. */ public String getXmlLang() { - if (language == null) { - return null; - } - - String languageTag = language.toLanguageTag(); - if (languageTag.equals("und")) { - return null; - } - - return languageTag; + // TODO: Change to Locale.toLanguageTag() once Smack's minimum Android API level is 21 or higher. + // This will need a workaround for new Locale("").getLanguageTag() returning "und". Expected + // behavior of this function: + // - returns null if language is null + // - returns "" if language.getLanguage() returns the empty string + // - returns language.toLanguageTag() otherwise + return language != null ? language.toString().replace("_", "-") : null; } /** @@ -585,7 +583,7 @@ public abstract class ConnectionConfiguration { * Returns true if the connection is going to use stream compression. Stream compression * will be requested after TLS was established (if TLS was enabled) and only if the server * offered stream compression. With stream compression network traffic can be reduced - * up to 90%. By default,compression is disabled. + * up to 90%. By default compression is disabled. * * @return true if the connection is going to use stream compression. */ @@ -594,7 +592,7 @@ public abstract class ConnectionConfiguration { } /** - * Check if the given SASL mechanism is enabled in this connection configuration. + * Check if the given SASL mechansism is enabled in this connection configuration. * * @param saslMechanism TODO javadoc me please * @return true if the given SASL mechanism is enabled, false otherwise. @@ -609,7 +607,7 @@ public abstract class ConnectionConfiguration { /** * Return the explicitly enabled SASL mechanisms. May return null if no SASL mechanisms where - * explicitly enabled, i.e. all SASL mechanisms supported and announced by the service will be considered. + * explicitly enabled, i.e. all SALS mechanisms supported and announced by the service will be considered. * * @return the enabled SASL mechanisms or null. */ @@ -672,7 +670,6 @@ public abstract class ConnectionConfiguration { private boolean compressionEnabled = false; private StanzaIdSourceFactory stanzaIdSourceFactory = new StandardStanzaIdSource.Factory(); - @SuppressWarnings("this-escape") protected Builder() { if (SmackConfiguration.DEBUG) { enableDefaultDebugger(); @@ -860,6 +857,22 @@ public abstract class ConnectionConfiguration { return getThis(); } + /** + * Set the host to connect to by either its fully qualified domain name (FQDN) or its IP. + * + * @param fqdnOrIp a CharSequence either representing the FQDN or the IP of the host. + * @return a reference to this builder. + * @see #setHost(DnsName) + * @see #setHostAddress(InetAddress) + * @since 4.3.2 + * @deprecated use {@link #setHost(CharSequence)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public B setHostAddressByNameOrIp(CharSequence fqdnOrIp) { + return setHost(fqdnOrIp); + } + public B setPort(int port) { if (port < 0 || port > 65535) { throw new IllegalArgumentException( @@ -1008,6 +1021,25 @@ public abstract class ConnectionConfiguration { return getThis(); } + /** + * Sets a custom SSLContext for creating SSL sockets. + *

+ * For more information on how to create a SSLContext see Java Secure Socket Extension (JSEE) Reference Guide: Creating Your Own X509TrustManager + * + * @param context the custom SSLContext for new sockets. + * @return a reference to this builder. + * @deprecated use {@link #setSslContextFactory(SslContextFactory)} instead}. + */ + // TODO: Remove in Smack 4.5. + @Deprecated + public B setCustomSSLContext(SSLContext context) { + return setSslContextFactory(() -> { + return context; + }); + } + /** * Sets a custom SSLContext for creating SSL sockets. *

@@ -1058,7 +1090,8 @@ public abstract class ConnectionConfiguration { } /** - * Sets if an initial available presence will be sent to the server. By default, * an available presence will be sent to the server indicating that this presence + * Sets if an initial available presence will be sent to the server. By default + * an available presence will be sent to the server indicating that this presence * is not online and available to receive messages. If you want to log in without * being 'noticed' then pass a false value. * @@ -1154,9 +1187,7 @@ public abstract class ConnectionConfiguration { if (!SASLAuthentication.isSaslMechanismRegistered(SASLMechanism.EXTERNAL)) { throw new IllegalArgumentException("SASL " + SASLMechanism.EXTERNAL + " is not registered"); } - setSslContextFactory(() -> { - return sslContext; - }); + setCustomSSLContext(sslContext); throwIfEnabledSaslMechanismsSet(); allowEmptyOrNullUsernames(); @@ -1235,7 +1266,7 @@ public abstract class ConnectionConfiguration { * Sets if the connection is going to use compression (default false). * * Compression is only activated if the server offers compression. With compression network - * traffic can be reduced up to 90%. By default,compression is disabled. + * traffic can be reduced up to 90%. By default compression is disabled. * * @param compressionEnabled if the connection is going to use compression on the HTTP level. * @return a reference to this object. @@ -1293,7 +1324,7 @@ public abstract class ConnectionConfiguration { } else { InputStream stream = TLSUtils.getDefaultTruststoreStreamIfPossible(); try { - // Note that PKCS12 keystores need a password one some Java platforms. Hence, we try the famous + // Note that PKCS12 keystores need a password one some Java platforms. Hence we try the famous // 'changeit' here. See https://bugs.openjdk.java.net/browse/JDK-8194702 char[] password = "changeit".toCharArray(); try { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java b/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java index 7d545bb45..4685bf4af 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java @@ -53,7 +53,7 @@ import org.jxmpp.jid.EntityBareJid; * *

Once TLS has been negotiated (i.e. the connection has been secured) it is possible to * register with the server or authenticate using SASL. If the - * server supports SASL then Smack will try to authenticate using SASL.

+ * server supports SASL then Smack will try to authenticate using SASL..

* *

The server may support many SASL mechanisms to use for authenticating. Out of the box * Smack provides several SASL mechanisms, but it is possible to register new SASL Mechanisms. Use diff --git a/smack-core/src/main/java/org/jivesoftware/smack/ScheduledAction.java b/smack-core/src/main/java/org/jivesoftware/smack/ScheduledAction.java index def612a19..da0377fab 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/ScheduledAction.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/ScheduledAction.java @@ -1,6 +1,6 @@ /** * - * Copyright 2018-2024 Florian Schmaus + * Copyright 2018 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,13 +50,11 @@ public class ScheduledAction implements Delayed { return smackReactor.cancel(this); } - @SuppressWarnings("JavaUtilDate") public boolean isDue() { Date now = new Date(); return now.after(releaseTime); } - @SuppressWarnings("JavaUtilDate") public long getTimeToDueMillis() { long now = System.currentTimeMillis(); return releaseTime.getTime() - now; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/Smack.java b/smack-core/src/main/java/org/jivesoftware/smack/Smack.java index daa7a18b4..6608bba4b 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/Smack.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/Smack.java @@ -30,7 +30,7 @@ public class Smack { public static final String SMACK_PACKAGE = SMACK_ORG + ".smack"; /** - * Returns the Smack version information, e.g."1.3.0". + * Returns the Smack version information, eg "1.3.0". * * @return the Smack version information. */ diff --git a/smack-core/src/main/java/org/jivesoftware/smack/SmackConfiguration.java b/smack-core/src/main/java/org/jivesoftware/smack/SmackConfiguration.java index ef1101cff..f3316c8ed 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/SmackConfiguration.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/SmackConfiguration.java @@ -102,7 +102,7 @@ public final class SmackConfiguration { private static HostnameVerifier defaultHostnameVerififer; /** - * Returns the Smack version information, e.g."1.3.0". + * Returns the Smack version information, eg "1.3.0". * * @return the Smack version information. * @deprecated use {@link Smack#getVersion()} instead. diff --git a/smack-core/src/main/java/org/jivesoftware/smack/SmackInitialization.java b/smack-core/src/main/java/org/jivesoftware/smack/SmackInitialization.java index 82098094f..2a5b79c6a 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/SmackInitialization.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/SmackInitialization.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2014-2024 Florian Schmaus + * Copyright 2003-2007 Jive Software, 2014-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,7 +63,7 @@ public final class SmackInitialization { private static final Logger LOGGER = Logger.getLogger(SmackInitialization.class.getName()); - /* + /** * Loads the configuration from the smack-config.xml and system properties file. *

* So far this means that: diff --git a/smack-core/src/main/java/org/jivesoftware/smack/SmackReactor.java b/smack-core/src/main/java/org/jivesoftware/smack/SmackReactor.java index 8fc59ab3a..67e68f1fd 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/SmackReactor.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/SmackReactor.java @@ -1,6 +1,6 @@ /** * - * Copyright 2018-2024 Florian Schmaus + * Copyright 2018-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -144,7 +144,6 @@ public class SmackReactor { } } - @SuppressWarnings("JavaUtilDate") ScheduledAction schedule(Runnable runnable, long delay, TimeUnit unit, ScheduledAction.Kind scheduledActionKind) { long releaseTimeEpoch = System.currentTimeMillis() + unit.toMillis(delay); Date releaseTimeDate = new Date(releaseTimeEpoch); @@ -277,7 +276,8 @@ public class SmackReactor { setInterestOpsCancelledKeySafe(selectionKey, 0); } - selectedKeys = new ArrayList<>(selectedKeySet); + selectedKeys = new ArrayList<>(selectedKeySet.size()); + selectedKeys.addAll(selectedKeySet); selectedKeySet.clear(); } @@ -327,12 +327,6 @@ public class SmackReactor { int currentReactorThreadCount = reactorThreads.size(); int myKeyCount = pendingSelectionKeysSize / currentReactorThreadCount; - // The division could result in myKeyCount being zero, even though there are pending selection keys. - // Therefore, ensure that this thread tries to get at least one pending selection key by invoking poll(). - // Otherwise, it could happen that we end up in a busy loop, where myKeyCount is zero and this thread invokes - // selector.wakeup() below because pendingSelectionsKeys is not empty, but the woken up reactor thread wil - // end up with myKeyCount being zero again, restarting the busy-loop cycle. - if (myKeyCount == 0) myKeyCount = 1; Collection selectedKeys = new ArrayList<>(myKeyCount); for (int i = 0; i < myKeyCount; i++) { SelectionKey selectionKey = pendingSelectionKeys.poll(); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/StanzaCollector.java b/smack-core/src/main/java/org/jivesoftware/smack/StanzaCollector.java index dfa0ec7d2..2ceaaf19d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/StanzaCollector.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/StanzaCollector.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2016-2024 Florian Schmaus. + * Copyright 2003-2007 Jive Software, 2016-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. @@ -117,7 +117,7 @@ public final class StanzaCollector implements AutoCloseable { * @return the next stanza result, or null if there are no more * results. */ - @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) + @SuppressWarnings("unchecked") public synchronized

P pollResult() { return (P) resultQueue.poll(); } @@ -134,7 +134,6 @@ public final class StanzaCollector implements AutoCloseable { * @return the next available packet. * @throws XMPPErrorException in case an error response. */ - @SuppressWarnings("TypeParameterUnusedInFormals") public

P pollResultOrThrow() throws XMPPErrorException { P result = pollResult(); if (result != null) { @@ -151,7 +150,7 @@ public final class StanzaCollector implements AutoCloseable { * @return the next available packet. * @throws InterruptedException if the calling thread was interrupted. */ - @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) + @SuppressWarnings("unchecked") // TODO: Consider removing this method as it is hardly ever useful. public synchronized

P nextResultBlockForever() throws InterruptedException { throwIfCancelled(); @@ -176,7 +175,6 @@ public final class StanzaCollector implements AutoCloseable { * @return the next available packet. * @throws InterruptedException if the calling thread was interrupted. */ - @SuppressWarnings("TypeParameterUnusedInFormals") public

P nextResult() throws InterruptedException { return nextResult(connection.getReplyTimeout()); } @@ -193,7 +191,7 @@ public final class StanzaCollector implements AutoCloseable { * @return the next available stanza or null on timeout or connection error. * @throws InterruptedException if the calling thread was interrupted. */ - @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) + @SuppressWarnings("unchecked") public

P nextResult(long timeout) throws InterruptedException { throwIfCancelled(); P res = null; @@ -225,7 +223,6 @@ public final class StanzaCollector implements AutoCloseable { * @throws NotConnectedException if the XMPP connection is not connected. * @see #nextResultOrThrow(long) */ - @SuppressWarnings("TypeParameterUnusedInFormals") public

P nextResultOrThrow() throws NoResponseException, XMPPErrorException, InterruptedException, NotConnectedException { return nextResultOrThrow(connection.getReplyTimeout()); @@ -266,7 +263,6 @@ public final class StanzaCollector implements AutoCloseable { * @throws InterruptedException if the calling thread was interrupted. * @throws NotConnectedException if there was no response and the connection got disconnected. */ - @SuppressWarnings("TypeParameterUnusedInFormals") public

P nextResultOrThrow(long timeout) throws NoResponseException, XMPPErrorException, InterruptedException, NotConnectedException { P result; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/StanzaListener.java b/smack-core/src/main/java/org/jivesoftware/smack/StanzaListener.java index 786c5a8b0..52b3168c8 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/StanzaListener.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/StanzaListener.java @@ -27,6 +27,12 @@ import org.jivesoftware.smack.packet.Stanza; * the {@link #processStanza(Stanza)} method will be called. This is the * opposite approach to the functionality provided by a {@link StanzaCollector} * which lets you block while waiting for results. + *

+ * Additionally you are able to intercept Packets that are going to be send and + * make modifications to them. You can register a PacketListener as interceptor + * by using {@link XMPPConnection#addStanzaInterceptor(StanzaListener, + * org.jivesoftware.smack.filter.StanzaFilter)} + *

* * @see XMPPConnection#addAsyncStanzaListener(StanzaListener, org.jivesoftware.smack.filter.StanzaFilter) * @author Matt Tucker diff --git a/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java index 45cd8328f..0ef97910a 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java @@ -91,24 +91,23 @@ import org.jxmpp.jid.EntityFullJid; *

Incoming Stanza Listeners

* Most callbacks (listeners, handlers, …) than you can add to a connection come in three different variants: *
    - *
  • asynchronous - e.g., {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)}
  • - *
  • synchronous - e.g., {@link #addSyncStanzaListener(StanzaListener, StanzaFilter)}
  • - *
  • other - e.g., {@link #addStanzaListener(StanzaListener, StanzaFilter)}
  • + *
  • standard
  • + *
  • async (asynchronous)
  • + *
  • sync (synchronous)
  • *
*

- * Asynchronous callbacks are run decoupled from the connections main event loop. Hence, a callback triggered by + * Standard callbacks are invoked concurrently, but it is ensured that the same callback is never run concurrently. + * The callback's identity is used as key for that. The events delivered to the callback preserve the order of the + * causing events of the connection. + *

+ *

+ * Asynchronous callbacks are run decoupled from the connections main event loop. Hence a callback triggered by * stanza B may (appear to) invoked before a callback triggered by stanza A, even though stanza A arrived before B. *

*

- * Synchronous callbacks are invoked concurrently, but it is ensured that the same callback is never run concurrently - * and that they are executed in order. That is, if both stanza A and B trigger the same callback, and A arrives before - * B, then the callback will be invoked with A first, and then B. Furthermore, those callbacks are not executed within - * the main loop. However it is still advisable that those callbacks do not block or only block briefly. - *

- *

- * Other callbacks are run synchronous to the main event loop of a connection and are executed within the main loop. - * This means that if such a callback blocks, the main event loop also blocks, which can easily cause deadlocks. - * Therefore, you should avoid using those callbacks unless you know what you are doing. + * Synchronous callbacks are run synchronous to the main event loop of a connection. Hence they are invoked in the + * exact order of how events happen there, most importantly the arrival order of incoming stanzas. You should only + * use synchronous callbacks in rare situations. *

*

Stanza Filters

* Stanza filters allow you to define the predicates for which listeners or collectors should be invoked. For more @@ -242,7 +241,7 @@ public interface XMPPConnection { *

* * @param stanza the stanza to send. - * @return {@code true} if the stanza was successfully scheduled to be sent, {@code false} otherwise. + * @return {@code true} if the stanza was successfully scheduled to be send, {@code false} otherwise. * @throws NotConnectedException if the connection is not connected. * @since 4.4.0 * @deprecated use {@link #sendStanzaNonBlocking(Stanza)} instead. @@ -265,7 +264,7 @@ public interface XMPPConnection { * @param stanza the stanza to send. * @param timeout how long to wait before giving up, in units of {@code unit}. * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter. - * @return {@code true} if the stanza was successfully scheduled to be sent, {@code false} otherwise. + * @return {@code true} if the stanza was successfully scheduled to be send, {@code false} otherwise. * @throws NotConnectedException if the connection is not connected. * @throws InterruptedException if the calling thread was interrupted. * @since 4.4.0 @@ -318,7 +317,6 @@ public interface XMPPConnection { * @throws InterruptedException if the calling thread was interrupted. * @since 4.3 */ - @SuppressWarnings("TypeParameterUnusedInFormals") I sendIqRequestAndWaitForResponse(IQ request) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException; @@ -411,7 +409,7 @@ public interface XMPPConnection { boolean removeStanzaListener(StanzaListener stanzaListener); /** - * Registers a synchronous stanza listener with this connection. A stanza listener will be invoked only when + * Registers a synchronous stanza listener with this connection. A stanza listener will be invoked only when * an incoming stanza is received. A stanza filter determines which stanzas will be delivered to the listener. If * the same stanza listener is added again with a different filter, only the new filter will be used. *

@@ -424,6 +422,7 @@ public interface XMPPConnection { * * @param stanzaListener the stanza listener to notify of new received stanzas. * @param stanzaFilter the stanza filter to use. + * @see #addStanzaInterceptor(StanzaListener, StanzaFilter) * @since 4.1 */ void addSyncStanzaListener(StanzaListener stanzaListener, StanzaFilter stanzaFilter); @@ -449,6 +448,7 @@ public interface XMPPConnection { * * @param stanzaListener the stanza listener to notify of new received stanzas. * @param stanzaFilter the stanza filter to use. + * @see #addStanzaInterceptor(StanzaListener, StanzaFilter) * @since 4.1 */ void addAsyncStanzaListener(StanzaListener stanzaListener, StanzaFilter stanzaFilter); @@ -482,6 +482,34 @@ public interface XMPPConnection { */ void removeStanzaSendingListener(StanzaListener stanzaListener); + /** + * Registers a stanza interceptor with this connection. The interceptor will be + * invoked every time a stanza is about to be sent by this connection. Interceptors + * may modify the stanza to be sent. A stanza filter determines which stanzas + * will be delivered to the interceptor. + * + *

+ * NOTE: For a similar functionality on incoming stanzas, see {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)}. + *

+ * + * @param stanzaInterceptor the stanza interceptor to notify of stanzas about to be sent. + * @param stanzaFilter the stanza filter to use. + * @deprecated use {@link #addMessageInterceptor(Consumer, Predicate)} or {@link #addPresenceInterceptor(Consumer, Predicate)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + void addStanzaInterceptor(StanzaListener stanzaInterceptor, StanzaFilter stanzaFilter); + + /** + * Removes a stanza interceptor. + * + * @param stanzaInterceptor the stanza interceptor to remove. + * @deprecated use {@link #removeMessageInterceptor(Consumer)} or {@link #removePresenceInterceptor(Consumer)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + void removeStanzaInterceptor(StanzaListener stanzaInterceptor); + /** * Registers a stanza interceptor with this connection. The interceptor will be * invoked every time a stanza is about to be sent by this connection. Interceptors @@ -582,6 +610,23 @@ public interface XMPPConnection { */ FromMode getFromMode(); + /** + * Get the feature stanza extensions for a given stream feature of the + * server, or null if the server doesn't support that feature. + * + * @param {@link ExtensionElement} type of the feature. + * @param element TODO javadoc me please + * @param namespace TODO javadoc me please + * @return a stanza extensions of the feature or null + * @deprecated use {@link #getFeature(Class)} instead. + */ + // TODO: Remove in Smack 4.5. + @Deprecated + default F getFeature(String element, String namespace) { + QName qname = new QName(namespace, element); + return getFeature(qname); + } + /** * Get the feature stanza extensions for a given stream feature of the * server, or null if the server doesn't support that feature. @@ -591,7 +636,6 @@ public interface XMPPConnection { * @return a stanza extensions of the feature or null * @since 4.4 */ - @SuppressWarnings("TypeParameterUnusedInFormals") F getFeature(QName qname); /** diff --git a/smack-core/src/main/java/org/jivesoftware/smack/XmppInputOutputFilter.java b/smack-core/src/main/java/org/jivesoftware/smack/XmppInputOutputFilter.java index 4f0c68b0a..97fdff246 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/XmppInputOutputFilter.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/XmppInputOutputFilter.java @@ -57,8 +57,8 @@ public interface XmppInputOutputFilter { } /** - * The returned {@link ByteBuffer} is going to get flipped by the caller. The callee must not flip the buffer. - * @param inputData the data this method needs to process. + * The returned {@link ByteBuffer} is going to get fliped by the caller. The callee must not flip the buffer. + * @param inputData the data this methods needs to process. * @return a {@link ByteBuffer} or {@code null} if no data could be produced. * @throws IOException in case an I/O exception occurs. */ diff --git a/smack-core/src/main/java/org/jivesoftware/smack/c2s/ModularXmppClientToServerConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/c2s/ModularXmppClientToServerConnection.java index ca3de8190..b24b00704 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/c2s/ModularXmppClientToServerConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/c2s/ModularXmppClientToServerConnection.java @@ -301,7 +301,7 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne currentStateVertex = StateDescriptorGraph.convertToStateGraph(initialStateDescriptorVertex, connectionInternal); } - @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) + @SuppressWarnings("unchecked") public > CM getConnectionModuleFor( Class descriptorClass) { return (CM) connectionModules.get(descriptorClass); @@ -390,7 +390,7 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne // Ignore successorStateVertex if the only way to the final state is via the initial state. This happens // typically if we are in the ConnectedButUnauthenticated state on the way to ResourceboundAndAuthenticated, - // where we do not want to walk via InstantShutdown/Shutdown in a cycle over the initial state towards this + // where we do not want to walk via InstantShutdown/Shtudown in a cycle over the initial state towards this // state. if (walkStateGraphContext.wouldCauseCycle(successorStateVertex)) { // Ignore this successor. @@ -658,7 +658,6 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne updateOutgoingStreamXmlEnvironmentOnStreamOpen(streamOpen); } - @SuppressWarnings("this-escape") public static class DisconnectedStateDescriptor extends StateDescriptor { protected DisconnectedStateDescriptor() { super(DisconnectedState.class, StateDescriptor.Property.finalState); @@ -667,8 +666,7 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne } private final class DisconnectedState extends State { - // Invoked via reflection. - @SuppressWarnings("UnusedMethod") + private DisconnectedState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) { super(stateDescriptor, connectionInternal); @@ -709,8 +707,6 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne private final class LookupRemoteConnectionEndpointsState extends State { boolean outgoingElementsQueueWasShutdown; - // Invoked via reflection. - @SuppressWarnings("UnusedMethod") private LookupRemoteConnectionEndpointsState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) { super(stateDescriptor, connectionInternal); @@ -821,8 +817,6 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne } private final class ConnectedButUnauthenticatedState extends State { - // Invoked via reflection. - @SuppressWarnings("UnusedMethod") private ConnectedButUnauthenticatedState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) { super(stateDescriptor, connectionInternal); @@ -855,8 +849,6 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne } private final class SaslAuthenticationState extends State { - // Invoked via reflection. - @SuppressWarnings("UnusedMethod") private SaslAuthenticationState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) { super(stateDescriptor, connectionInternal); @@ -900,8 +892,6 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne } public static final class ResourceBindingStateDescriptor extends StateDescriptor { - // Invoked via reflection. - @SuppressWarnings("UnusedMethod") private ResourceBindingStateDescriptor() { super(ResourceBindingState.class, "RFC 6120 § 7"); addSuccessor(AuthenticatedAndResourceBoundStateDescriptor.class); @@ -909,8 +899,6 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne } private final class ResourceBindingState extends State { - // Invoked via reflection. - @SuppressWarnings("UnusedMethod") private ResourceBindingState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) { super(stateDescriptor, connectionInternal); @@ -966,8 +954,6 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne } private final class AuthenticatedAndResourceBoundState extends State { - // Invoked via reflection. - @SuppressWarnings("UnusedMethod") private AuthenticatedAndResourceBoundState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) { super(stateDescriptor, connectionInternal); @@ -1008,8 +994,6 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne } private final class ShutdownState extends State { - // Invoked via reflection. - @SuppressWarnings("UnusedMethod") private ShutdownState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) { super(stateDescriptor, connectionInternal); @@ -1072,8 +1056,6 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne } private static final class InstantShutdownState extends NoOpState { - // Invoked via reflection. - @SuppressWarnings("UnusedMethod") private InstantShutdownState(ModularXmppClientToServerConnection connection, StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) { super(connection, stateDescriptor, connectionInternal); @@ -1095,8 +1077,6 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne } private final class CloseConnectionState extends State { - // Invoked via reflection. - @SuppressWarnings("UnusedMethod") private CloseConnectionState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) { super(stateDescriptor, connectionInternal); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/compression/CompressionModuleDescriptor.java b/smack-core/src/main/java/org/jivesoftware/smack/compression/CompressionModuleDescriptor.java index 4fa0e6045..3cf43ee79 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/compression/CompressionModuleDescriptor.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/compression/CompressionModuleDescriptor.java @@ -1,6 +1,6 @@ /** * - * Copyright 2018-2024 Florian Schmaus + * Copyright 2018-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,8 +41,6 @@ public class CompressionModuleDescriptor extends ModularXmppClientToServerConnec public static final class Builder extends ModularXmppClientToServerConnectionModuleDescriptor.Builder { - // Invoked via reflection. - @SuppressWarnings("UnusedMethod") private Builder(ModularXmppClientToServerConnectionConfiguration.Builder connectionConfigurationBuilder) { super(connectionConfigurationBuilder); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/compression/zlib/ZlibXmppCompressionFactory.java b/smack-core/src/main/java/org/jivesoftware/smack/compression/zlib/ZlibXmppCompressionFactory.java index d851b0c44..096147931 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/compression/zlib/ZlibXmppCompressionFactory.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/compression/zlib/ZlibXmppCompressionFactory.java @@ -143,9 +143,7 @@ public final class ZlibXmppCompressionFactory extends XmppCompressionFactory { int bytesWritten = compressor.deflate(buffer, initialOutputBufferPosition, length, flushMode); int newOutputBufferPosition = initialOutputBufferPosition + bytesWritten; - // Workaround for Android API not matching Java >=9 API. - // See https://issuetracker.google.com/issues/369219141 - ((java.nio.Buffer) outputBuffer).position(newOutputBufferPosition); + outputBuffer.position(newOutputBufferPosition); totalBytesWritten += bytesWritten; @@ -158,9 +156,7 @@ public final class ZlibXmppCompressionFactory extends XmppCompressionFactory { increasedBufferSize = MINIMUM_OUTPUT_BUFFER_INCREASE; } ByteBuffer newCurrentOutputBuffer = ByteBuffer.allocate(increasedBufferSize); - // Workaround for Android API not matching Java >=9 API. - // See https://issuetracker.google.com/issues/369219141 - ((java.nio.Buffer) outputBuffer).flip(); + outputBuffer.flip(); newCurrentOutputBuffer.put(outputBuffer); outputBuffer = newCurrentOutputBuffer; } @@ -206,9 +202,7 @@ public final class ZlibXmppCompressionFactory extends XmppCompressionFactory { throw new IOException(e); } - // Workaround for Android API not matching Java >=9 API. - // See https://issuetracker.google.com/issues/369219141 - ((java.nio.Buffer) outputBuffer).position(inflateOutputBufferOffset + bytesInflated); + outputBuffer.position(inflateOutputBufferOffset + bytesInflated); decompressorOutBytes += bytesInflated; @@ -218,9 +212,7 @@ public final class ZlibXmppCompressionFactory extends XmppCompressionFactory { int increasedBufferSize = outputBuffer.capacity() * 2; ByteBuffer increasedOutputBuffer = ByteBuffer.allocate(increasedBufferSize); - // Workaround for Android API not matching Java >=9 API. - // See https://issuetracker.google.com/issues/369219141 - ((java.nio.Buffer) outputBuffer).flip(); + outputBuffer.flip(); increasedOutputBuffer.put(outputBuffer); outputBuffer = increasedOutputBuffer; } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/datatypes/UInt16.java b/smack-core/src/main/java/org/jivesoftware/smack/datatypes/UInt16.java index 8df4cd2f4..271de8cbc 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/datatypes/UInt16.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/datatypes/UInt16.java @@ -19,7 +19,7 @@ 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:unsignedShort". + * 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 implements Comparable { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/debugger/ConsoleDebugger.java b/smack-core/src/main/java/org/jivesoftware/smack/debugger/ConsoleDebugger.java index 95c339a5d..b026f7bb3 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/debugger/ConsoleDebugger.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/debugger/ConsoleDebugger.java @@ -28,20 +28,19 @@ import org.jivesoftware.smack.util.ExceptionUtil; * even block the thread since only one thread may print at a time. *

* It is possible to not only print the raw sent and received stanzas but also the interpreted - * packets by Smack. By default,interpreted packets won't be printed. To enable this feature + * packets by Smack. By default interpreted packets won't be printed. To enable this feature * just change the printInterpreted static variable to true. *

* * @author Gaston Dombiak */ public class ConsoleDebugger extends AbstractDebugger { - private final SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss.S"); + private final SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss"); public ConsoleDebugger(XMPPConnection connection) { super(connection); } - @SuppressWarnings("JavaUtilDate") @Override protected void log(String logMessage) { String formatedDate; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/debugger/JulDebugger.java b/smack-core/src/main/java/org/jivesoftware/smack/debugger/JulDebugger.java index 015bb813b..db0772271 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/debugger/JulDebugger.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/debugger/JulDebugger.java @@ -27,7 +27,7 @@ import org.jivesoftware.smack.XMPPConnection; * even block the thread since only one thread may print at a time. *

* It is possible to not only print the raw sent and received stanzas but also the interpreted - * packets by Smack. By default,interpreted packets won't be printed. To enable this feature + * packets by Smack. By default interpreted packets won't be printed. To enable this feature * just change the printInterpreted static variable to true. *

* diff --git a/smack-core/src/main/java/org/jivesoftware/smack/debugger/SmackDebugger.java b/smack-core/src/main/java/org/jivesoftware/smack/debugger/SmackDebugger.java index 4f936b72d..82ca10b62 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/debugger/SmackDebugger.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/debugger/SmackDebugger.java @@ -57,7 +57,7 @@ public abstract class SmackDebugger { * * @param user the user@host/resource that has just logged in */ - // TODO: Should be replaced with a connection listener authenticated(). + // TODO: Should be replaced with a connection listener authenticed(). public abstract void userHasLogged(EntityFullJid user); /** diff --git a/smack-core/src/main/java/org/jivesoftware/smack/filter/NotFilter.java b/smack-core/src/main/java/org/jivesoftware/smack/filter/NotFilter.java index 5589b2109..006b5f4f9 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/filter/NotFilter.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/filter/NotFilter.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2024 Florian Schmaus. + * Copyright 2003-2007 Jive Software. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package org.jivesoftware.smack.filter; -import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.util.Objects; @@ -44,9 +43,4 @@ public class NotFilter implements StanzaFilter { public boolean accept(Stanza packet) { return !filter.accept(packet); } - - public static NotFilter of(Class extensionElementClass) { - ExtensionElementFilter extensionElementFilter = new ExtensionElementFilter<>(extensionElementClass); - return new NotFilter(extensionElementFilter); - } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaIdFilter.java b/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaIdFilter.java index 8e5a5cc2c..c0d507e50 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaIdFilter.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/filter/StanzaIdFilter.java @@ -18,7 +18,6 @@ package org.jivesoftware.smack.filter; import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smack.packet.StanzaView; import org.jivesoftware.smack.util.StringUtils; /** @@ -35,7 +34,7 @@ public class StanzaIdFilter implements StanzaFilter { * * @param stanza the stanza which the ID is taken from. */ - public StanzaIdFilter(StanzaView stanza) { + public StanzaIdFilter(Stanza stanza) { this(stanza.getStanzaId()); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/filter/package-info.java b/smack-core/src/main/java/org/jivesoftware/smack/filter/package-info.java index c130b93ff..01f2e0461 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/filter/package-info.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/filter/package-info.java @@ -23,7 +23,7 @@ *
  • {@link StanzaIdFilter}: filters for stanzas with a particular stanza ID
  • *
  • {@link ToMatchesFilter}: filters for stanzas that are sent to a particular address
  • *
  • {@link FromMatchesFilter}: filters for stanzas that are sent from a particular address
  • - *
  • {@link ExtensionElementFilter}: filters for stanzas that have a particular stanza extension element
  • + *
  • {@link ExtensionElementFilter}: filters for stanzas that have a particular stanza exentsion element
  • *
  • {@link AndFilter}: implements the logical AND operation over two or more filters
  • *
  • {@link OrFilter}: implements the logical OR operation over two or more filters
  • *
  • {@link NotFilter}: implements the logical NOT operation on a filter
  • diff --git a/smack-core/src/main/java/org/jivesoftware/smack/fsm/StateDescriptor.java b/smack-core/src/main/java/org/jivesoftware/smack/fsm/StateDescriptor.java index 29c298c76..8f399480e 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/fsm/StateDescriptor.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/fsm/StateDescriptor.java @@ -118,7 +118,7 @@ public abstract class StateDescriptor { if (stateClassConstructor != null) { stateClassConstructor.setAccessible(true); } else { - // TODO: Add validation check that if stateClassConstructor is 'null' the constructState() method is overridden. + // TODO: Add validation check that if stateClassConstructor is 'null' the cosntructState() method is overriden. } String className = getClass().getSimpleName(); @@ -155,7 +155,7 @@ public abstract class StateDescriptor { clazz = Class.forName(clazzName); } catch (ClassNotFoundException e) { // The state descriptor class is not in classpath, which probably means that the smack module is not loaded - // into the classpath. Hence, we can silently ignore that. + // into the classpath. Hence we can silently ignore that. LOGGER.log(Level.FINEST, "Ignoring unknown state descriptor '" + clazzName + "'", e); return; } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/fsm/StateDescriptorGraph.java b/smack-core/src/main/java/org/jivesoftware/smack/fsm/StateDescriptorGraph.java index 45d23bb36..41bb29f59 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/fsm/StateDescriptorGraph.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/fsm/StateDescriptorGraph.java @@ -1,6 +1,6 @@ /** * - * Copyright 2018-2024 Florian Schmaus + * Copyright 2018-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -215,7 +215,7 @@ public class StateDescriptorGraph { inferredForwardEdges.put(predecessor, backwardsEdge); } } - // Ensure that the initial node has their successors inferred. + // Ensure that the intial node has their successors inferred. for (Class inferredSuccessorOfInitialStateDescriptor : inferredForwardEdges.getAll(initialStatedescriptorClass)) { initialNode.getElement().addSuccessor(inferredSuccessorOfInitialStateDescriptor); } @@ -368,7 +368,7 @@ public class StateDescriptorGraph { } } - public static void stateDescriptorGraphToDot(Collection> vertexes, + public static void stateDescriptorGraphToDot(Collection> vertexes, PrintWriter dotOut, boolean breakStateName) { dotOut.append("digraph {\n"); dfs(vertexes, diff --git a/smack-core/src/main/java/org/jivesoftware/smack/initializer/UrlInitializer.java b/smack-core/src/main/java/org/jivesoftware/smack/initializer/UrlInitializer.java index 33ced4f39..ec7b047e7 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/initializer/UrlInitializer.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/initializer/UrlInitializer.java @@ -1,6 +1,6 @@ /** * - * Copyright 2014-2024 Florian Schmaus + * Copyright 2014-2018 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ package org.jivesoftware.smack.initializer; import java.io.InputStream; import java.net.URI; -import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -42,7 +42,7 @@ public abstract class UrlInitializer implements SmackInitializer { public List initialize() { InputStream is = null; final ClassLoader classLoader = this.getClass().getClassLoader(); - final List exceptions = new ArrayList(); + final List exceptions = new LinkedList(); final String providerUriString = getProvidersUri(); if (providerUriString != null) { try { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/isr/InstantStreamResumptionModuleDescriptor.java b/smack-core/src/main/java/org/jivesoftware/smack/isr/InstantStreamResumptionModuleDescriptor.java index 3e8171076..d26703eec 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/isr/InstantStreamResumptionModuleDescriptor.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/isr/InstantStreamResumptionModuleDescriptor.java @@ -41,8 +41,6 @@ public class InstantStreamResumptionModuleDescriptor extends ModularXmppClientTo public static final class Builder extends ModularXmppClientToServerConnectionModuleDescriptor.Builder { - // Unfinished implementation. - @SuppressWarnings("UnusedMethod") private Builder(ModularXmppClientToServerConnectionConfiguration.Builder connectionConfigurationBuilder) { super(connectionConfigurationBuilder); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractError.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractError.java index 50067fc14..147b4f031 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractError.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractError.java @@ -1,6 +1,6 @@ /** * - * Copyright 2014-2024 Florian Schmaus + * Copyright 2014-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -108,7 +108,6 @@ public class AbstractError { * @param type of the ExtensionElement. * @return the extension, or null if it doesn't exist. */ - @SuppressWarnings("TypeParameterUnusedInFormals") public PE getExtension(String elementName, String namespace) { return PacketUtil.extensionElementFrom(extensions, elementName, namespace); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractTextElement.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractTextElement.java index 2f475fa06..00e82d704 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractTextElement.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractTextElement.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2017-2024 Florian Schmaus + * Copyright © 2017-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. @@ -54,4 +54,15 @@ public abstract class AbstractTextElement implements ExtensionElement { return lang; } + /** + * Deprecated. + * + * @return deprecated + * @deprecated use {@link #getLanguage()} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public final String getLang() { + return lang; + } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/EmptyResultIQ.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/EmptyResultIQ.java index 246e9de06..a4d977ac3 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/EmptyResultIQ.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/EmptyResultIQ.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014-2024 Florian Schmaus + * Copyright © 2014-2023 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,6 @@ public class EmptyResultIQ extends IQ { } // TODO: Deprecate when stanza builder and parsing logic is ready. - @SuppressWarnings("this-escape") public EmptyResultIQ() { super((String) null, null); setType(IQ.Type.result); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/ExtensionElement.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/ExtensionElement.java index 5f4ed1b6e..5a7f00650 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/ExtensionElement.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/ExtensionElement.java @@ -19,7 +19,7 @@ package org.jivesoftware.smack.packet; /** * Interface to represent XMPP extension elements. Unlike {@link XmlElement}, every non-abstract class that implements * {@link ExtensionElement} must have a static final QNAME member of the type {@link javax.xml.namespace.QName}. This - * allows type-safe functions like {@link StanzaView#getExtension(Class)}. Hence, this is a marker interface. + * allows type-safe functions like {@link StanzaView#getExtension(Class)}. Hence this is a marker interface. *

    * Use this class when implementing new extension elements when possible. This means that every instance of your * implemented class must represent an XML element of the same qualified name. diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/IQ.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/IQ.java index 98f9880f3..1881f4c23 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/IQ.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/IQ.java @@ -88,14 +88,14 @@ public abstract class IQ extends Stanza implements IqView { } @Override - public final Type getType() { + public Type getType() { return type; } /** * Sets the type of the IQ packet. *

    - * Since the type of an IQ must present, an IllegalArgumentException will be thrown when type is + * Since the type of an IQ must present, an IllegalArgmentException will be thrown when type is * null. *

    * @@ -182,7 +182,7 @@ public abstract class IQ extends Stanza implements IqView { // Add the query section if there is one. IQChildElementXmlStringBuilder iqChildElement = getIQChildElementBuilder( new IQChildElementXmlStringBuilder(getChildElementName(), getChildElementNamespace(), null, xml.getXmlEnvironment())); - // TODO: Document the cases where iqChildElement is null but childElementName not. And if there are none, change + // TOOD: Document the cases where iqChildElement is null but childElementName not. And if there are none, change // the logic. if (iqChildElement == null) { return; @@ -287,6 +287,20 @@ public abstract class IQ extends Stanza implements IqView { return ErrorIQ.createErrorResponse(request, error); } + /** + * Deprecated. + * + * @param request the request. + * @param error the error. + * @return an error IQ. + * @deprecated use {@link #createErrorResponse(IQ, StanzaError)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public static ErrorIQ createErrorResponse(final IQ request, final StanzaError.Builder error) { + return createErrorResponse(request, error.build()); + } + public static ErrorIQ createErrorResponse(final IQ request, final StanzaError.Condition condition) { return createErrorResponse(request, StanzaError.getBuilder(condition).build()); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Mechanisms.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Mechanisms.java index 2d36eb920..a981589ee 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Mechanisms.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Mechanisms.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014-2024 Florian Schmaus + * Copyright © 2014-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +16,9 @@ */ package org.jivesoftware.smack.packet; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.LinkedList; import java.util.List; import javax.xml.namespace.QName; @@ -31,7 +31,7 @@ public class Mechanisms implements ExtensionElement { public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-sasl"; public static final QName QNAME = new QName(NAMESPACE, ELEMENT); - public final List mechanisms = new ArrayList(); + public final List mechanisms = new LinkedList(); public Mechanisms(String mechanism) { mechanisms.add(mechanism); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java index 6063af13b..d47cafda7 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java @@ -17,6 +17,7 @@ package org.jivesoftware.smack.packet; +import java.util.List; import java.util.Locale; import javax.xml.namespace.QName; @@ -28,6 +29,10 @@ import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.XmlStringBuilder; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; + /** * Represents XMPP message packets. A message can be one of several types: * @@ -58,7 +63,85 @@ public final class Message extends MessageOrPresence public static final String ELEMENT = "message"; public static final String BODY = "body"; - private final Type type; + private Type type; + + /** + * Creates a new, "normal" message. + * @deprecated use {@link StanzaBuilder}, preferable via {@link StanzaFactory}, instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public Message() { + } + + /** + * Creates a new "normal" message to the specified recipient. + * + * @param to the recipient of the message. + * @deprecated use {@link StanzaBuilder}, preferable via {@link StanzaFactory}, instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public Message(Jid to) { + setTo(to); + } + + /** + * Creates a new message of the specified type to a recipient. + * + * @param to the user to send the message to. + * @param type the message type. + * @deprecated use {@link StanzaBuilder}, preferable via {@link StanzaFactory}, instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public Message(Jid to, Type type) { + this(to); + setType(type); + } + + /** + * Creates a new message to the specified recipient and with the specified body. + * + * @param to the user to send the message to. + * @param body the body of the message. + * @deprecated use {@link StanzaBuilder}, preferable via {@link StanzaFactory}, instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public Message(Jid to, String body) { + this(to); + setBody(body); + } + + /** + * Creates a new message to the specified recipient and with the specified body. + * + * @param to the user to send the message to. + * @param body the body of the message. + * @throws XmppStringprepException if 'to' is not a valid XMPP address. + * @deprecated use {@link StanzaBuilder}, preferable via {@link StanzaFactory}, instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public Message(String to, String body) throws XmppStringprepException { + this(JidCreate.from(to), body); + } + + /** + * Creates a new message with the specified recipient and extension element. + * + * @param to TODO javadoc me please + * @param extensionElement TODO javadoc me please + * @since 4.2 + * @deprecated use {@link StanzaBuilder}, preferable via {@link StanzaFactory}, instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public Message(Jid to, ExtensionElement extensionElement) { + this(to); + addExtension(extensionElement); + } Message(MessageBuilder messageBuilder) { super(messageBuilder); @@ -87,6 +170,197 @@ public final class Message extends MessageOrPresence return type; } + /** + * Sets the type of the message. + * + * @param type the type of the message. + * @deprecated use {@link StanzaBuilder} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void setType(Type type) { + this.type = type; + } + + /** + * Sets the subject of the message. The subject is a short description of + * message contents. + * + * @param subject the subject of the message. + * @deprecated use {@link StanzaBuilder} instead. + */ + @Deprecated + // TODO: Remove when stanza builder is ready. + public void setSubject(String subject) { + if (subject == null) { + removeSubject(""); // use empty string because #removeSubject(null) is ambiguous + return; + } + addSubject(null, subject); + } + + /** + * Adds a subject with a corresponding language. + * + * @param language the language of the subject being added. + * @param subject the subject being added to the message. + * @return the new {@link org.jivesoftware.smack.packet.Message.Subject} + * @throws NullPointerException if the subject is null, a null pointer exception is thrown + */ + @Deprecated + // TODO: Remove when stanza builder is ready. + public Subject addSubject(String language, String subject) { + language = Stanza.determineLanguage(this, language); + + List currentSubjects = getExtensions(Subject.class); + for (Subject currentSubject : currentSubjects) { + if (language.equals(currentSubject.getLanguage())) { + throw new IllegalArgumentException("Subject with the language " + language + " already exists"); + } + } + + Subject messageSubject = new Subject(language, subject); + addExtension(messageSubject); + return messageSubject; + } + + /** + * Removes the subject with the given language from the message. + * + * @param language the language of the subject which is to be removed + * @return true if a subject was removed and false if it was not. + */ + @Deprecated + // TODO: Remove when stanza builder is ready. + public boolean removeSubject(String language) { + language = Stanza.determineLanguage(this, language); + for (Subject subject : getExtensions(Subject.class)) { + if (language.equals(subject.language)) { + return removeSubject(subject); + } + } + return false; + } + + /** + * Removes the subject from the message and returns true if the subject was removed. + * + * @param subject the subject being removed from the message. + * @return true if the subject was successfully removed and false if it was not. + */ + @Deprecated + // TODO: Remove when stanza builder is ready. + public boolean removeSubject(Subject subject) { + return removeExtension(subject) != null; + } + + /** + * Sets the body of the message. + * + * @param body the body of the message. + * @see #setBody(String) + * @since 4.2 + * @deprecated use {@link StanzaBuilder} instead. + */ + @Deprecated + // TODO: Remove when stanza builder is ready. + public void setBody(CharSequence body) { + String bodyString; + if (body != null) { + bodyString = body.toString(); + } else { + bodyString = null; + } + setBody(bodyString); + } + + /** + * Sets the body of the message. The body is the main message contents. + * + * @param body the body of the message. + * @deprecated use {@link StanzaBuilder} instead. + */ + @Deprecated + // TODO: Remove when stanza builder is ready. + public void setBody(String body) { + if (body == null) { + removeBody(""); // use empty string because #removeBody(null) is ambiguous + return; + } + addBody(null, body); + } + + /** + * Adds a body with a corresponding language. + * + * @param language the language of the body being added. + * @param body the body being added to the message. + * @return the new {@link org.jivesoftware.smack.packet.Message.Body} + * @throws NullPointerException if the body is null, a null pointer exception is thrown + * @since 3.0.2 + * @deprecated use {@link StanzaBuilder} instead. + */ + @Deprecated + // TODO: Remove when stanza builder is ready. + public Body addBody(String language, String body) { + language = Stanza.determineLanguage(this, language); + + removeBody(language); + + Body messageBody = new Body(language, body); + addExtension(messageBody); + return messageBody; + } + + /** + * Removes the body with the given language from the message. + * + * @param language the language of the body which is to be removed + * @return true if a body was removed and false if it was not. + * @deprecated use {@link StanzaBuilder} instead. + */ + @Deprecated + // TODO: Remove when stanza builder is ready. + public boolean removeBody(String language) { + language = Stanza.determineLanguage(this, language); + for (Body body : getBodies()) { + String bodyLanguage = body.getLanguage(); + if (Objects.equals(bodyLanguage, language)) { + removeExtension(body); + return true; + } + } + return false; + } + + /** + * Removes the body from the message and returns true if the body was removed. + * + * @param body the body being removed from the message. + * @return true if the body was successfully removed and false if it was not. + * @since 3.0.2 + * @deprecated use {@link StanzaBuilder} instead. + */ + @Deprecated + // TODO: Remove when stanza builder is ready. + public boolean removeBody(Body body) { + XmlElement removedElement = removeExtension(body); + return removedElement != null; + } + + /** + * Sets the thread id of the message, which is a unique identifier for a sequence + * of "chat" messages. + * + * @param thread the thread id of the message. + * @deprecated use {@link StanzaBuilder} instead. + */ + @Deprecated + // TODO: Remove when stanza builder is ready. + public void setThread(String thread) { + addExtension(new Message.Thread(thread)); + } + @Override public String getElementName() { return ELEMENT; @@ -138,6 +412,22 @@ public final class Message extends MessageOrPresence return buf; } + /** + * Creates and returns a copy of this message stanza. + *

    + * This does not perform a deep clone, as extension elements are shared between the new and old + * instance. + *

    + * @return a clone of this message. + * @deprecated use {@link #asBuilder()} instead. + */ + // TODO: Remove in Smack 4.5. + @Deprecated + @Override + public Message clone() { + return new Message(this); + } + /** * Represents a message subject, its language and the content of the subject. */ diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresence.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresence.java index c3aa3d180..f48b794a0 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresence.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/MessageOrPresence.java @@ -20,6 +20,11 @@ import org.jivesoftware.smack.XMPPConnection; public abstract class MessageOrPresence> extends Stanza { + @Deprecated + // TODO: Remove in Smack 4.5. + protected MessageOrPresence() { + } + protected MessageOrPresence(StanzaBuilder stanzaBuilder) { super(stanzaBuilder); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Nonza.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Nonza.java index ece665543..a86a4e1db 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Nonza.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Nonza.java @@ -18,7 +18,7 @@ package org.jivesoftware.smack.packet; /** - * A Nonza, i.e. everything that is not a stanza as defined + * A Nonza, i.e everything that is not a stanza as defined * RFC 6120 8. Stanzas are {@link Message}, {@link Presence} and {@link IQ}. * Everything else should sublcass this class instead of {@link Stanza}. *

    diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java index caa3942dc..3490e1a23 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2020-2024 Florian Schmaus. + * Copyright 2003-2007 Jive Software, 2020-2021 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,9 +21,12 @@ import java.util.List; import java.util.Locale; import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.XmlStringBuilder; +import org.jxmpp.jid.Jid; + /** * Represents XMPP presence stanzas. Every presence stanza has a type, which is one of * the following values: @@ -75,6 +78,55 @@ public final class Presence extends MessageOrPresence private Mode mode = null; + /** + * Creates a new presence update. Status, priority, and mode are left un-set. + * + * @param type the type. + * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public Presence(Type type) { + // Ensure that the stanza ID is set by calling super(). + super(); + setType(type); + } + + /** + * Creates a new presence with the given type and using the given XMPP address as recipient. + * + * @param to the recipient. + * @param type the type. + * @since 4.2 + * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public Presence(Jid to, Type type) { + this(type); + setTo(to); + } + + /** + * Creates a new presence update with a specified status, priority, and mode. + * + * @param type the type. + * @param status a text message describing the presence update. + * @param priority the priority of this presence update. + * @param mode the mode type for this presence update. + * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public Presence(Type type, String status, int priority, Mode mode) { + // Ensure that the stanza ID is set by calling super(). + super(); + setType(type); + setStatus(status); + setPriority(priority); + setMode(mode); + } + Presence(PresenceBuilder presenceBuilder) { super(presenceBuilder); type = presenceBuilder.type; @@ -134,11 +186,36 @@ public final class Presence extends MessageOrPresence return type; } + /** + * Sets the type of the presence packet. + * + * @param type the type of the presence packet. + * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void setType(Type type) { + this.type = Objects.requireNonNull(type, "Type cannot be null"); + } + @Override public String getStatus() { return status; } + /** + * Sets the status message of the presence update. The status is free-form text + * describing a user's presence (i.e., "gone to lunch"). + * + * @param status the status message. + * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void setStatus(String status) { + this.status = status; + } + @Override public int getPriority() { return getPriorityByte(); @@ -156,11 +233,20 @@ public final class Presence extends MessageOrPresence * Sets the priority of the presence. The valid range is -128 through 127. * * @param priority the priority of the presence. + * @throws IllegalArgumentException if the priority is outside the valid range. * @see RFC 6121 § 4.7.2.3. Priority Element * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead. */ @Deprecated - // TODO: Remove in Smack 4.6. + // TODO: Remove in Smack 4.5. + public void setPriority(int priority) { + if (priority < -128 || priority > 127) { + throw new IllegalArgumentException("Priority value " + priority + + " is not valid. Valid range is -128 through 127."); + } + setPriority((byte) priority); + } + public void setPriority(byte priority) { this.priority = priority; } @@ -173,6 +259,19 @@ public final class Presence extends MessageOrPresence return mode; } + /** + * Sets the mode of the presence update. A null presence mode value is interpreted + * to be the same thing as {@link Presence.Mode#available}. + * + * @param mode the mode. + * @deprecated use {@link PresenceBuilder} or {@link org.jivesoftware.smack.XMPPConnection#getStanzaFactory} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void setMode(Mode mode) { + this.mode = mode; + } + @Override public String getElementName() { return ELEMENT; @@ -247,6 +346,37 @@ public final class Presence extends MessageOrPresence return buf; } + /** + * Creates and returns a copy of this presence stanza. + *

    + * This does not perform a deep clone, as extension elements are shared between the new and old + * instance. + *

    + * @return a clone of this presence. + * @deprecated use {@link #asBuilder()} instead. + */ + // TODO: Remove in Smack 4.5. + @Deprecated + @Override + public Presence clone() { + return new Presence(this); + } + + /** + * Clone this presence and set a newly generated stanza ID as the clone's ID. + * + * @return a "clone" of this presence with a different stanza ID. + * @since 4.1.2 + * @deprecated use {@link #asBuilder(XMPPConnection)} or {@link #asBuilder(String)}instead. + */ + // TODO: Remove in Smack 4.5. + @Deprecated + public Presence cloneWithNewId() { + Presence clone = clone(); + clone.setNewStanzaId(); + return clone; + } + /** * An enum to represent the presence type. Note that presence type is often confused * with presence mode. Generally, if a user is signed in to a server, they have a presence diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java index 7e6331bb8..48e0330c6 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java @@ -39,7 +39,6 @@ public class Session extends SimpleIQ { public static final String ELEMENT = "session"; public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-session"; - @SuppressWarnings("this-escape") public Session() { super(ELEMENT, NAMESPACE); setType(IQ.Type.set); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/StandardExtensionElement.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/StandardExtensionElement.java index 9f1959460..8ae1f5a7a 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/StandardExtensionElement.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StandardExtensionElement.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015-2024 Florian Schmaus. + * Copyright 2015-2021 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,7 +53,9 @@ public final class StandardExtensionElement implements XmlElement { /** * Constructs a new extension element with the given name and namespace and nothing else. + *

    * This is meant to construct extension elements used as simple flags in Stanzas. + *

    * * @param name the name of the extension element. * @param namespace the namespace of the extension element. diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Stanza.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Stanza.java index 88c30bbfa..7123e82f8 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Stanza.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Stanza.java @@ -98,7 +98,7 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement { protected Stanza(StanzaBuilder stanzaBuilder) { if (stanzaBuilder.stanzaIdSource != null) { id = stanzaBuilder.stanzaIdSource.getNewStanzaId(); - // Note that some stanza ID sources, e.g. StanzaBuilder.PresenceBuilder.EMPTY return null here. Hence, we + // Note that some stanza ID sources, e.g. StanzaBuilder.PresenceBuilder.EMPTY return null here. Hence we // only check that the returned string is not empty. assert StringUtils.isNullOrNotEmpty(id); usedStanzaIdSource = stanzaBuilder.stanzaIdSource; @@ -159,6 +159,22 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement { return id != null; } + /** + * Set the stanza id if none is set. + * + * @return the stanza id. + * @since 4.2 + * @deprecated use {@link StanzaBuilder} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public String setStanzaId() { + if (!hasStanzaIdSet()) { + setNewStanzaId(); + } + return getStanzaId(); + } + /** * Throws an {@link IllegalArgumentException} if this stanza has no stanza ID set. * @@ -203,7 +219,7 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement { * @param to who the packet is being sent to. */ // TODO: Mark this as deprecated once StanzaBuilder is ready and all call sites are gone. - public final void setTo(Jid to) { + public void setTo(Jid to) { this.to = to; } @@ -239,11 +255,34 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement { error = stanzaError; } + /** + * Deprecated. + * @param stanzaError the stanza error. + * @deprecated use {@link StanzaBuilder} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void setError(StanzaError.Builder stanzaError) { + setError(stanzaError.build()); + } + @Override public final String getLanguage() { return language; } + /** + * Sets the xml:lang of this Stanza. + * + * @param language the xml:lang of this Stanza. + * @deprecated use {@link StanzaBuilder#setLanguage(String)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void setLanguage(String language) { + this.language = language; + } + @Override public final List getExtensions() { synchronized (extensionElements) { @@ -335,6 +374,22 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement { return packetExtension; } + /** + * This method is deprecated. Use preferably {@link #getExtension(Class)} or {@link #getExtensionElement(String, String)}. + * + * @param the type to cast to. + * @param elementName the XML element name of the extension. (May be null) + * @param namespace the XML element namespace of the extension. + * @return the extension, or null if it doesn't exist. + * @deprecated use {@link #getExtension(Class)} or {@link #getExtensionElement(String, String)} instead. + */ + // TODO: Remove in Smack 4.5. + @SuppressWarnings("unchecked") + @Deprecated + public final E getExtension(String elementName, String namespace) { + return (E) getExtensionElement(elementName, namespace); + } + @Override public final XmlElement getExtension(QName qname) { synchronized (extensionElements) { @@ -446,6 +501,27 @@ public abstract class Stanza implements StanzaView, TopLevelStreamElement { } } + /** + * Removes a stanza extension from the packet. + * + * @param extension the stanza extension to remove. + * @return the removed stanza extension or null. + * @deprecated use {@link StanzaBuilder} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public final XmlElement removeExtension(XmlElement extension) { + QName key = extension.getQName(); + synchronized (extensionElements) { + List list = extensionElements.getAll(key); + boolean removed = list.remove(extension); + if (removed) { + return extension; + } + } + return null; + } + /** * Returns a short String describing the Stanza. This method is suited for log purposes. */ diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaBuilder.java index 2cc2a20ed..ec8bdac3c 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaBuilder.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaBuilder.java @@ -87,9 +87,9 @@ public abstract class StanzaBuilder> implements Stanz } /** - * Set the recipient address of the stanza. + * Set the recipent address of the stanza. * - * @param to whom the stanza is being sent. + * @param to whoe the stanza is being sent to. * @return a reference to this builder. * @throws XmppStringprepException if the provided character sequence is not a valid XMPP address. * @see #to(Jid) diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaView.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaView.java index e435d7159..85c4af1a9 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaView.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaView.java @@ -1,6 +1,6 @@ /** * - * Copyright 2019-2024 Florian Schmaus + * Copyright 2019-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,7 @@ public interface StanzaView extends XmlLangElement { /** * Returns who the stanza is being sent "to", or null if * the value is not set. The XMPP protocol often makes the "to" - * attribute optional, so it does not always need to be set. + * attribute optional, so it does not always need to be set.

    * * @return who the stanza is being sent to, or null if the * value has not been set. @@ -46,7 +46,7 @@ public interface StanzaView extends XmlLangElement { /** * Returns who the stanza is being sent "from" or null if * the value is not set. The XMPP protocol often makes the "from" - * attribute optional, so it does not always need to be set. + * attribute optional, so it does not always need to be set.

    * * @return who the stanza is being sent from, or null if the * value has not been set. diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/StreamError.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/StreamError.java index a58599de8..f034be9d3 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/StreamError.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StreamError.java @@ -58,9 +58,9 @@ import org.jivesoftware.smack.util.XmlStringBuilder; * stream has been authenticated * policy-violation the entity has violated some local service * policy. - * remote-connection-failed the server is unable to properly connect + * remote-connection-failed Rthe server is unable to properly connect * to a remote entity. - * resource-constraint the server lacks the system resources necessary + * resource-constraint Rthe server lacks the system resources necessary * to service the stream. * restricted-xml the entity has attempted to send restricted XML * features. diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/UnparsedIQ.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/UnparsedIQ.java index 8cd2146f8..e363d2e30 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/UnparsedIQ.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/UnparsedIQ.java @@ -16,8 +16,6 @@ */ package org.jivesoftware.smack.packet; -import org.jivesoftware.smack.util.StringUtils; - /** * An IQ stanzas that could not be parsed because no provider was found. */ @@ -36,12 +34,7 @@ public class UnparsedIQ extends IQ { @Override protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { - if (StringUtils.isEmpty(content)) { - xml.setEmptyElement(); - } else { - xml.rightAngleBracket(); - xml.escape(content); - } + xml.escape(content); return xml; } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderFileLoader.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderFileLoader.java index 2781fe0d9..11da95318 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderFileLoader.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderFileLoader.java @@ -17,9 +17,9 @@ package org.jivesoftware.smack.provider; import java.io.InputStream; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.LinkedList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -39,11 +39,11 @@ import org.jivesoftware.smack.xml.XmlPullParser; public class ProviderFileLoader implements ProviderLoader { private static final Logger LOGGER = Logger.getLogger(ProviderFileLoader.class.getName()); - private final Collection iqProviders = new ArrayList(); - private final Collection extProviders = new ArrayList(); - private final Collection sfProviders = new ArrayList(); + private final Collection iqProviders = new LinkedList(); + private final Collection extProviders = new LinkedList(); + private final Collection sfProviders = new LinkedList(); - private List exceptions = new ArrayList(); + private List exceptions = new LinkedList(); public ProviderFileLoader(InputStream providerStream) { this(providerStream, ProviderFileLoader.class.getClassLoader()); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderManager.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderManager.java index b2f08cc3a..0943f31d6 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderManager.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/ProviderManager.java @@ -97,7 +97,6 @@ import org.jivesoftware.smack.util.XmppElementUtil; * </extensionProvider> * </smackProviders> * - *

    * If multiple provider entries attempt to register to handle the same element name and namespace, * the first entry loaded from the classpath will take precedence. Whenever a stanza extension * is found in a packet, parsing will be passed to the correct provider. Each provider @@ -107,8 +106,7 @@ import org.jivesoftware.smack.util.XmppElementUtil; * set the properties of th class using the values in the stanza extension sub-element. When an * extension provider is not registered for an element name and namespace combination, Smack will * store all top-level elements of the sub-packet in DefaultPacketExtension object and then - * attach it to the packet. - *

    + * attach it to the packet.

    * * @author Matt Tucker */ diff --git a/smack-core/src/main/java/org/jivesoftware/smack/provider/package-info.java b/smack-core/src/main/java/org/jivesoftware/smack/provider/package-info.java index 21fafdfcb..5e40c5639 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/provider/package-info.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/provider/package-info.java @@ -16,7 +16,7 @@ */ /** - * The Smack provider architecture is a system for plugging in custom XML parsing of stanza extensions + * The Smack provider architecture is a system for plugging in custom XML parsing of staza extensions * ({@link org.jivesoftware.smack.packet.ExtensionElement}, {@link org.jivesoftware.smack.packet.IQ} stanzas and * {@link org.jivesoftware.smack.packet.Nonza}. Hence, there are the the following providers: *

      diff --git a/smack-core/src/main/java/org/jivesoftware/smack/proxy/HTTPProxySocketConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/proxy/HTTPProxySocketConnection.java index bdf0cf390..549406423 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/proxy/HTTPProxySocketConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/proxy/HTTPProxySocketConnection.java @@ -23,7 +23,6 @@ import java.io.StringReader; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.Socket; -import java.nio.charset.StandardCharsets; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -59,7 +58,7 @@ class HTTPProxySocketConnection implements ProxySocketConnection { proxyLine = "\r\nProxy-Authorization: Basic " + Base64.encode(username + ":" + password); } socket.getOutputStream().write((hostport + " HTTP/1.1\r\nHost: " - + host + ":" + port + proxyLine + "\r\n\r\n").getBytes(StandardCharsets.UTF_8)); + + host + ":" + port + proxyLine + "\r\n\r\n").getBytes("UTF-8")); InputStream in = socket.getInputStream(); StringBuilder got = new StringBuilder(100); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/proxy/ProxyInfo.java b/smack-core/src/main/java/org/jivesoftware/smack/proxy/ProxyInfo.java index 90433c5c8..402a106a4 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/proxy/ProxyInfo.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/proxy/ProxyInfo.java @@ -41,7 +41,6 @@ public class ProxyInfo { private ProxyType proxyType; private final ProxySocketConnection proxySocketConnection; - @SuppressWarnings("this-escape") public ProxyInfo(ProxyType pType, String pHost, int pPort, String pUser, String pPass) { this.proxyType = pType; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/sasl/SASLMechanism.java b/smack-core/src/main/java/org/jivesoftware/smack/sasl/SASLMechanism.java index 24330a6ac..f1c00ef19 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/sasl/SASLMechanism.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/sasl/SASLMechanism.java @@ -358,7 +358,7 @@ public abstract class SASLMechanism implements Comparable { * SASLprep the given String. The resulting String is in UTF-8. * * @param string the String to sasl prep. - * @return the given String SASL prepped + * @return the given String SASL preped * @see RFC 4013 - SASLprep: Stringprep Profile for User Names and Passwords */ protected static String saslPrep(String string) { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramMechanism.java b/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramMechanism.java index 6dc482ce3..8f4133c81 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramMechanism.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramMechanism.java @@ -271,7 +271,6 @@ public abstract class ScramMechanism extends SASLMechanism { return null; } - @SuppressWarnings("MixedMutabilityReturnType") private static Map parseAttributes(String string) throws SmackSaslException { if (string.length() == 0) { return Collections.emptyMap(); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/CollectionUtil.java b/smack-core/src/main/java/org/jivesoftware/smack/util/CollectionUtil.java index c3566c6c0..408e00bfd 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/CollectionUtil.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/CollectionUtil.java @@ -55,7 +55,6 @@ public class CollectionUtil { boolean test(T t); } - @SuppressWarnings("NonApiType") public static ArrayList newListWith(Collection collection) { if (collection == null) { return null; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/LazyStringBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/util/LazyStringBuilder.java index 6e0ded134..752fda1cf 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/LazyStringBuilder.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/LazyStringBuilder.java @@ -1,6 +1,6 @@ /** * - * Copyright 2014-2023 Florian Schmaus + * Copyright 2014-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. @@ -24,12 +24,10 @@ public class LazyStringBuilder implements Appendable, CharSequence { private final List list; - private transient String cache; - private int cachedLength = -1; + private String cache; private void invalidateCache() { cache = null; - cachedLength = -1; } public LazyStringBuilder() { @@ -67,10 +65,9 @@ public class LazyStringBuilder implements Appendable, CharSequence { @Override public int length() { - if (cachedLength >= 0) { - return cachedLength; + if (cache != null) { + return cache.length(); } - int length = 0; try { for (CharSequence csq : list) { @@ -81,8 +78,6 @@ public class LazyStringBuilder implements Appendable, CharSequence { StringBuilder sb = safeToStringBuilder(); throw new RuntimeException("The following LazyStringBuilder threw a NullPointerException: " + sb, npe); } - - cachedLength = length; return length; } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/MAC.java b/smack-core/src/main/java/org/jivesoftware/smack/util/MAC.java index df177204e..4d78d24f8 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/MAC.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/MAC.java @@ -33,7 +33,7 @@ public class MAC { HMAC_SHA1 = Mac.getInstance(HMACSHA1); } catch (NoSuchAlgorithmException e) { - // Smack won't be able to function normally if this exception is thrown, wrap it into + // Smack wont be able to function normally if this exception is thrown, wrap it into // an ISE and make the user aware of the problem. throw new IllegalStateException(e); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/MD5.java b/smack-core/src/main/java/org/jivesoftware/smack/util/MD5.java index d81c4de5a..26c0547fd 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/MD5.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/MD5.java @@ -31,7 +31,7 @@ public class MD5 { MD5_DIGEST = MessageDigest.getInstance(StringUtils.MD5); } catch (NoSuchAlgorithmException e) { - // Smack won't be able to function normally if this exception is thrown, wrap it into + // Smack wont be able to function normally if this exception is thrown, wrap it into // an ISE and make the user aware of the problem. throw new IllegalStateException(e); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/MultiMap.java b/smack-core/src/main/java/org/jivesoftware/smack/util/MultiMap.java index 7e9889e57..852e01bf7 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/MultiMap.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/MultiMap.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2015-2024 Florian Schmaus + * Copyright © 2015-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -184,14 +184,13 @@ public class MultiMap { } /** - * Remove the given number of values for a given key. May return less values than requested. + * Remove the given number of values for a given key. May return less values then requested. * * @param key the key to remove from. * @param num the number of values to remove. * @return a list of the removed values. * @since 4.4.0 */ - @SuppressWarnings("MixedMutabilityReturnType") public List remove(K key, int num) { List values = map.get(key); if (values == null) { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/NumberUtil.java b/smack-core/src/main/java/org/jivesoftware/smack/util/NumberUtil.java index 836796248..98635309d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/NumberUtil.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/NumberUtil.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2015-2024 Florian Schmaus + * Copyright © 2015-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,18 @@ package org.jivesoftware.smack.util; public class NumberUtil { + /** + * Checks if the given long is within the range of an unsigned 32-bit integer, the XML type "xs:unsignedInt". + * + * @param value TODO javadoc me please + * @deprecated use {@link #requireUInt32(long)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public static void checkIfInUInt32Range(long value) { + requireUInt32(value); + } + /** * Checks if the given long is within the range of an unsigned 32-bit integer, the XML type "xs:unsignedInt". * diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java index 69f0aaca2..042402299 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2019-2024 Florian Schmaus. + * Copyright 2003-2007 Jive Software, 2019-2023 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.logging.Level; @@ -86,7 +87,7 @@ public class PacketParserUtils { return parser; } - @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) + @SuppressWarnings("unchecked") public static S parseStanza(String stanza) throws XmlPullParserException, SmackParsingException, IOException { return (S) parseStanza(getParserFor(stanza), XmlEnvironment.EMPTY); } @@ -229,7 +230,7 @@ public class PacketParserUtils { // Assume this is the end tag of the start tag at the // beginning of this method. Typical examples where this // happens are body elements containing the empty string, - // i.e. , which appears to be valid XMPP, or a + // ie. , which appears to be valid XMPP, or a // least it's not explicitly forbidden by RFC 6121 5.2.3 return ""; } else { @@ -643,7 +644,7 @@ public class PacketParserUtils { assert parser.getEventType() == XmlPullParser.Event.START_ELEMENT; String name; final int initialDepth = parser.getDepth(); - List methods = new ArrayList<>(); + List methods = new LinkedList<>(); outerloop: while (true) { XmlPullParser.Event eventType = parser.next(); switch (eventType) { @@ -849,7 +850,7 @@ public class PacketParserUtils { throws XmlPullParserException, IOException { ParserUtils.assertAtStartTag(parser); assert parser.getNamespace().equals(StartTls.NAMESPACE); - int initialDepth = parser.getDepth(); + int initalDepth = parser.getDepth(); boolean required = false; outerloop: while (true) { XmlPullParser.Event event = parser.next(); @@ -863,7 +864,7 @@ public class PacketParserUtils { } break; case END_ELEMENT: - if (parser.getDepth() == initialDepth) { + if (parser.getDepth() == initalDepth) { break outerloop; } break; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketUtil.java b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketUtil.java index 40da6f4d6..a68e91dd0 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketUtil.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketUtil.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014-2024 Florian Schmaus + * Copyright © 2014-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ public class PacketUtil { * * @return the extension element */ - @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) + @SuppressWarnings("unchecked") public static PE extensionElementFrom(Collection collection, String element, String namespace) { for (XmlElement packetExtension : collection) { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/Pair.java b/smack-core/src/main/java/org/jivesoftware/smack/util/Pair.java index 13e65e881..08bf41234 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/Pair.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/Pair.java @@ -1,6 +1,6 @@ /** * - * Copyright 2020-2024 Florian Schmaus. + * Copyright 2020 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,12 +26,11 @@ public final class Pair { this.second = second; } - public static Pair create(F first, S second) { + public static Pair create(F first, S second) { return new Pair<>(first, second); } - @SuppressWarnings("ReturnValueIgnored") - public static Pair createAndInitHashCode(F first, S second) { + public static Pair createAndInitHashCode(F first, S second) { Pair pair = new Pair<>(first, second); pair.hashCode(); return pair; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/ParserUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/ParserUtils.java index 7c58f8a12..64c18a7fb 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/ParserUtils.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/ParserUtils.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014-2024 Florian Schmaus + * Copyright © 2014-2023 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,8 @@ import java.text.ParseException; import java.util.Date; import java.util.Locale; +import javax.xml.namespace.QName; + import org.jivesoftware.smack.datatypes.UInt16; import org.jivesoftware.smack.datatypes.UInt32; import org.jivesoftware.smack.packet.XmlEnvironment; @@ -144,7 +146,7 @@ public class ParserUtils { } /** - * Phrase a string to a boolean value as per "xs:boolean". Valid input strings are "true", "1" for true, and "false", "0" for false. + * Prase a string to a boolean value as per "xs:boolean". Valid input strings are "true", "1" for true, and "false", "0" for false. * * @param booleanString the input string. * @return the boolean representation of the input string @@ -365,6 +367,19 @@ public class ParserUtils { return parser.getAttributeValue("http://www.w3.org/XML/1998/namespace", "lang"); } + /** + * Get the QName of the current element. + * + * @param parser the parser. + * @return the Qname. + * @deprecated use {@link XmlPullParser#getQName()} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5 + public static QName getQName(XmlPullParser parser) { + return parser.getQName(); + } + public static InternetAddress getInternetAddressIngoringZoneIdAttribute(XmlPullParser parser, String attribute) { String inetAddressString = parser.getAttributeValue(attribute); if (inetAddressString == null) { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/SHA1.java b/smack-core/src/main/java/org/jivesoftware/smack/util/SHA1.java index 3c7d53ac4..89144530b 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/SHA1.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/SHA1.java @@ -31,7 +31,7 @@ public class SHA1 { SHA1_DIGEST = MessageDigest.getInstance(StringUtils.SHA1); } catch (NoSuchAlgorithmException e) { - // Smack won't be able to function normally if this exception is thrown, wrap it into + // Smack wont be able to function normally if this exception is thrown, wrap it into // an ISE and make the user aware of the problem. throw new IllegalStateException(e); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/SecurityUtil.java b/smack-core/src/main/java/org/jivesoftware/smack/util/SecurityUtil.java index c796ab23e..3521279df 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/SecurityUtil.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/SecurityUtil.java @@ -1,6 +1,6 @@ /** * - * Copyright 2019-2024 Florian Schmaus. + * 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. @@ -26,7 +26,6 @@ public class SecurityUtil { private static final LruCache, Void> INSERTED_PROVIDERS_CACHE = new LruCache<>(8); - @SuppressWarnings("LockOnNonEnclosingClassLiteral") public static void ensureProviderAtFirstPosition(Class providerClass) { if (INSERTED_PROVIDERS_CACHE.containsKey(providerClass)) { return; @@ -42,7 +41,7 @@ public class SecurityUtil { String providerName = provider.getName(); - int installedPosition; + int installedPosition ; synchronized (Security.class) { Security.removeProvider(providerName); installedPosition = Security.insertProviderAt(provider, 1); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java index 83c9f40bb..5ebe4c116 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/StringUtils.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2016-2024 Florian Schmaus. + * Copyright 2003-2007 Jive Software, 2016-2021 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,24 @@ public class StringUtils { public static final String MD5 = "MD5"; public static final String SHA1 = "SHA-1"; + /** + * Deprecated, do not use. + * + * @deprecated use StandardCharsets.UTF_8 instead. + */ + // TODO: Remove in Smack 4.5. + @Deprecated + public static final String UTF8 = "UTF-8"; + + /** + * Deprecated, do not use. + * + * @deprecated use StandardCharsets.US_ASCII instead. + */ + // TODO: Remove in Smack 4.5. + @Deprecated + public static final String USASCII = "US-ASCII"; + public static final String QUOTE_ENCODE = """; public static final String APOS_ENCODE = "'"; public static final String AMP_ENCODE = "&"; @@ -325,14 +343,11 @@ public class StringUtils { try { randomString(charBuffer, random, alphabet, numRandomChars); } catch (IOException e) { - // This should never happen if we calculate the buffer size correctly. + // This should never happen if we calcuate the buffer size correctly. throw new AssertionError(e); } - // Workaround for Android API not matching Java >=9 API. - // See https://issuetracker.google.com/issues/369219141 - ((java.nio.Buffer) charBuffer).flip(); - return charBuffer.toString(); + return charBuffer.flip().toString(); } private static void randomString(Appendable appendable, Random random, char[] alphabet, int numRandomChars) @@ -464,7 +479,7 @@ public class StringUtils { appendTo(collection, ", ", sb); } - public static void appendTo(Collection collection, StringBuilder sb, + public static void appendTo(Collection collection, StringBuilder sb, Consumer appendFunction) { appendTo(collection, ", ", sb, appendFunction); } @@ -473,7 +488,7 @@ public class StringUtils { appendTo(collection, delimiter, sb, o -> sb.append(o)); } - public static void appendTo(Collection collection, String delimiter, StringBuilder sb, + public static void appendTo(Collection collection, String delimiter, StringBuilder sb, Consumer appendFunction) { for (Iterator it = collection.iterator(); it.hasNext();) { O cs = it.next(); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/TLSUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/TLSUtils.java index 47469f721..c1af8ba61 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/TLSUtils.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/TLSUtils.java @@ -1,6 +1,6 @@ /** * - * Copyright 2014-2024 Florian Schmaus + * Copyright 2014-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -68,6 +68,52 @@ public class TLSUtils { return builder; } + /** + * Enable only TLS. Connections created with the given ConnectionConfiguration will only support TLS. + *

      + * According to the Encrypted + * XMPP Manifesto, TLSv1.2 shall be deployed, providing fallback support for SSLv3 and + * TLSv1.1. This method goes one step beyond and upgrades the handshake to use TLSv1 or better. + * This method requires the underlying OS to support all of TLSv1.2 , 1.1 and 1.0. + *

      + * + * @param builder the configuration builder to apply this setting to + * @param Type of the ConnectionConfiguration builder. + * + * @return the given builder + * @deprecated use {@link #setEnabledTlsProtocolsToRecommended(org.jivesoftware.smack.ConnectionConfiguration.Builder)} instead. + */ + // TODO: Remove in Smack 4.5. + @Deprecated + public static > B setTLSOnly(B builder) { + builder.setEnabledSSLProtocols(new String[] { PROTO_TLSV1_2, PROTO_TLSV1_1, PROTO_TLSV1 }); + return builder; + } + + /** + * Enable only TLS and SSLv3. Connections created with the given ConnectionConfiguration will + * only support TLS and SSLv3. + *

      + * According to the Encrypted + * XMPP Manifesto, TLSv1.2 shall be deployed, providing fallback support for SSLv3 and + * TLSv1.1. + *

      + * + * @param builder the configuration builder to apply this setting to + * @param Type of the ConnectionConfiguration builder. + * + * @return the given builder + * @deprecated use {@link #setEnabledTlsProtocolsToRecommended(org.jivesoftware.smack.ConnectionConfiguration.Builder)} instead. + */ + // TODO: Remove in Smack 4.5. + @Deprecated + public static > B setSSLv3AndTLSOnly(B builder) { + builder.setEnabledSSLProtocols(new String[] { PROTO_TLSV1_2, PROTO_TLSV1_1, PROTO_TLSV1, PROTO_SSL3 }); + return builder; + } + /** * Accept all TLS certificates. *

      diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java index 5c327157b..21b192b4c 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java @@ -1,6 +1,6 @@ /** * - * Copyright 2014-2024 Florian Schmaus + * Copyright 2014-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,6 @@ import org.jivesoftware.smack.packet.NamedElement; import org.jivesoftware.smack.packet.XmlElement; import org.jivesoftware.smack.packet.XmlEnvironment; -import org.jxmpp.jid.Jid; import org.jxmpp.util.XmppDateTime; public class XmlStringBuilder implements Appendable, CharSequence, Element { @@ -47,7 +46,6 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element { this(pe, null); } - @SuppressWarnings("this-escape") public XmlStringBuilder(NamedElement e) { this(); halfOpenElement(e.getElementName()); @@ -57,7 +55,6 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element { this(element.getElementName(), element.getNamespace(), element.getLanguage(), enclosingXmlEnvironment); } - @SuppressWarnings("this-escape") public XmlStringBuilder(String elementName, String xmlNs, String xmlLang, XmlEnvironment enclosingXmlEnvironment) { sb = new LazyStringBuilder(); halfOpenElement(elementName); @@ -140,6 +137,20 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element { return this; } + /** + * Deprecated. + * + * @param element deprecated. + * @return deprecated. + * @deprecated use {@link #append(Element)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public XmlStringBuilder element(Element element) { + assert element != null; + return append(element.toXML()); + } + public XmlStringBuilder optElement(String name, String content) { if (content != null) { element(name, content); @@ -300,18 +311,6 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element { return attribute(name, String.valueOf(value)); } - public XmlStringBuilder jidAttribute(Jid jid) { - assert jid != null; - return attribute("jid", jid); - } - - public XmlStringBuilder optJidAttribute(Jid jid) { - if (jid != null) { - attribute("jid", jid); - } - return this; - } - public XmlStringBuilder optAttribute(String name, String value) { if (value != null) { attribute(name, value); @@ -594,49 +593,10 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element { return this; } - enum AppendApproach { - /** - * Simply add the given CharSequence to this builder. - */ - SINGLE, - - /** - * If the given CharSequence is a {@link XmlStringBuilder} or {@link LazyStringBuilder}, then copy the - * references of the lazy strings parts into this builder. This approach flattens the string builders into one, - * yielding a different performance characteristic. - */ - FLAT, - } - - private static AppendApproach APPEND_APPROACH = AppendApproach.SINGLE; - - /** - * Set the builders approach on how to append new char sequences. - * - * @param appendApproach the append approach. - */ - public static void setAppendMethod(AppendApproach appendApproach) { - Objects.requireNonNull(appendApproach); - APPEND_APPROACH = appendApproach; - } - @Override public XmlStringBuilder append(CharSequence csq) { assert csq != null; - switch (APPEND_APPROACH) { - case SINGLE: - sb.append(csq); - break; - case FLAT: - if (csq instanceof XmlStringBuilder) { - sb.append(((XmlStringBuilder) csq).sb); - } else if (csq instanceof LazyStringBuilder) { - sb.append((LazyStringBuilder) csq); - } else { - sb.append(csq); - } - break; - } + sb.append(csq); return this; } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/XmppElementUtil.java b/smack-core/src/main/java/org/jivesoftware/smack/util/XmppElementUtil.java index 7ffe2f2eb..5639a7e5f 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/XmppElementUtil.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/XmppElementUtil.java @@ -71,7 +71,6 @@ public class XmppElementUtil { return qname; } - @SuppressWarnings("MixedMutabilityReturnType") public static List getElementsFrom( MultiMap elementMap, Class extensionElementClass) { QName qname = XmppElementUtil.getQNameFor(extensionElementClass); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/dns/package-info.java b/smack-core/src/main/java/org/jivesoftware/smack/util/dns/package-info.java index 1fb7e9b3b..f06cdab84 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/dns/package-info.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/dns/package-info.java @@ -61,8 +61,8 @@ *

      *

      Best Practices

      *

      - * We recommend that applications using Smack's DNSSEC API do not ask the user if DNSSEC is available. Instead they - * should check for DNSSEC support on every connection attempt. Once DNSSEC support has been discovered, the application + * We recommend that applications using Smack's DNSSEC API do not ask the user if DNSSEC is avaialble. Instead they + * should check for DNSSEC suport on every connection attempt. Once DNSSEC support has been discovered, the application * should use the `needsDnssec` mode for all future connection attempts. The same scheme can be applied when using DANE. * This approach is similar to the scheme established by to HTTP Strict * Transport Security" (HSTS, RFC 6797. diff --git a/smack-core/src/test/java/org/jivesoftware/smack/packet/IqTest.java b/smack-core/src/test/java/org/jivesoftware/smack/packet/IqTest.java index 2101daca4..b8f192bd7 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/packet/IqTest.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/packet/IqTest.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2023-2024 Florian Schmaus + * Copyright © 2023 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,13 +18,7 @@ package org.jivesoftware.smack.packet; import static org.jivesoftware.smack.test.util.XmlAssertUtil.assertXmlSimilar; -import org.jivesoftware.smack.test.util.SmackTestUtil; -import org.jivesoftware.smack.util.PacketParserUtils; -import org.jivesoftware.smack.xml.XmlPullParser; - import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; public class IqTest { @@ -41,36 +35,4 @@ public class IqTest { assertXmlSimilar(expected, errorIq.toXML()); } - @ParameterizedTest - @EnumSource(SmackTestUtil.XmlPullParserKind.class) - public void testIqWithXmlns(SmackTestUtil.XmlPullParserKind parserKind) throws Exception { - final String iqXml = "" + - "" + - "foo@tigase.mydomain.org/myresource" + - "" + - ""; - final String xml = - "" + - iqXml + - ""; - - XmlPullParser parser = SmackTestUtil.getParserFor(xml, "iq", parserKind); - IQ iq = PacketParserUtils.parseIQ(parser); - assertXmlSimilar(iqXml, iq.toXML()); - } - - @ParameterizedTest - @EnumSource(SmackTestUtil.XmlPullParserKind.class) - public void testUnparsedIq(SmackTestUtil.XmlPullParserKind parserKind) throws Exception { - final String iqXml = "" + - "" + - ""; - final String expected = "" - + "<query xmlns='jabber:iq:version'/>" - + ""; - - XmlPullParser parser = SmackTestUtil.getParserFor(iqXml, "iq", parserKind); - IQ iq = PacketParserUtils.parseIQ(parser); - assertXmlSimilar(expected, iq.toXML()); - } } diff --git a/smack-core/src/testFixtures/java/org/jivesoftware/smack/DummyConnection.java b/smack-core/src/testFixtures/java/org/jivesoftware/smack/DummyConnection.java index 320bb1f9e..7e105d58b 100644 --- a/smack-core/src/testFixtures/java/org/jivesoftware/smack/DummyConnection.java +++ b/smack-core/src/testFixtures/java/org/jivesoftware/smack/DummyConnection.java @@ -1,6 +1,6 @@ /** * - * Copyright 2010 Jive Software, 2022-2024 Florian Schmaus. + * Copyright 2010 Jive Software, 2022 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,9 +39,9 @@ import org.jxmpp.stringprep.XmppStringprepException; * A dummy implementation of {@link XMPPConnection}, intended to be used during * unit tests. * - * Instances store any packets that are delivered to be sent using the + * Instances store any packets that are delivered to be send using the * {@link #sendStanza(Stanza)} method in a blocking queue. The content of this queue - * can be inspected using {@link #getSentPacket()}. Typically, these queues are + * can be inspected using {@link #getSentPacket()}. Typically these queues are * used to retrieve a message that was generated by the client. * * Packets that should be processed by the client to simulate a received stanza @@ -82,7 +82,6 @@ public class DummyConnection extends AbstractXMPPConnection { } } - @SuppressWarnings("this-escape") public DummyConnection(DummyConnectionConfiguration configuration) { super(configuration); @@ -92,7 +91,6 @@ public class DummyConnection extends AbstractXMPPConnection { user = getUserJid(); } - @SuppressWarnings("JavaUtilDate") @Override protected void connectInternal() { connected = true; @@ -164,7 +162,6 @@ public class DummyConnection extends AbstractXMPPConnection { * @param

      the top level stream element class. * @return a sent packet. */ - @SuppressWarnings("TypeParameterUnusedInFormals") public

      P getSentPacket() { return getSentPacket(5 * 60); } @@ -179,7 +176,7 @@ public class DummyConnection extends AbstractXMPPConnection { * @param

      the top level stream element class. * @return a sent packet. */ - @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) + @SuppressWarnings("unchecked") public

      P getSentPacket(int wait) { try { return (P) queue.poll(wait, TimeUnit.SECONDS); diff --git a/smack-core/src/testFixtures/java/org/jivesoftware/smack/test/util/MemoryLeakTestUtil.java b/smack-core/src/testFixtures/java/org/jivesoftware/smack/test/util/MemoryLeakTestUtil.java index 1eccfd75a..6746e8f13 100644 --- a/smack-core/src/testFixtures/java/org/jivesoftware/smack/test/util/MemoryLeakTestUtil.java +++ b/smack-core/src/testFixtures/java/org/jivesoftware/smack/test/util/MemoryLeakTestUtil.java @@ -41,7 +41,7 @@ import org.jxmpp.stringprep.XmppStringprepException; * Note that this test is based on the assumption that it is possible to trigger a full garbage collection run, which is * not the case. See also this * stackoverflow - * question. Hence, the {@link #triggerGarbageCollection()} method defined in this class is not portable and depends + * question. Hence the {@link #triggerGarbageCollection()} method defined in this class is not portable and depends * on implementation depended Java Virtual Machine behavior. *

      * diff --git a/smack-debug-slf4j/build.gradle b/smack-debug-slf4j/build.gradle index 71eae05b4..9c2272729 100644 --- a/smack-debug-slf4j/build.gradle +++ b/smack-debug-slf4j/build.gradle @@ -1,7 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' -} - description = """\ Smack slf4j debugger. Inspect the exchanged XMPP stanzas. @@ -9,5 +5,5 @@ Connect your favourite slf4j backend of choice to get output inside of it""" dependencies { api project(':smack-core') - implementation 'org.slf4j:slf4j-api:[1.7,2.0)' + implementation 'org.slf4j:slf4j-api:[1.7,1.8)' } diff --git a/smack-debug-slf4j/src/main/java/org/jivesoftware/smackx/package-info.java b/smack-debug-slf4j/src/main/java/org/jivesoftware/smackx/package-info.java index bce3b6064..7ebe86244 120000 --- a/smack-debug-slf4j/src/main/java/org/jivesoftware/smackx/package-info.java +++ b/smack-debug-slf4j/src/main/java/org/jivesoftware/smackx/package-info.java @@ -1 +1 @@ -../../../../../../../smack-java11-full/src/main/java/org/jivesoftware/smackx/package-info.java \ No newline at end of file +../../../../../../../smack-java8-full/src/main/java/org/jivesoftware/smackx/package-info.java \ No newline at end of file diff --git a/smack-debug/build.gradle b/smack-debug/build.gradle index 7c9fdc0f1..959caff4f 100644 --- a/smack-debug/build.gradle +++ b/smack-debug/build.gradle @@ -1,7 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' -} - description = """\ Smack GUI debugger. Inspect the exchanged XMPP stanzas.""" diff --git a/smack-debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebugger.java b/smack-debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebugger.java index e57b4aaaa..40d2e5263 100644 --- a/smack-debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebugger.java +++ b/smack-debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebugger.java @@ -160,7 +160,6 @@ public class EnhancedDebugger extends SmackDebugger { private ReaderListener readerListener; private WriterListener writerListener; - @SuppressWarnings("JavaUtilDate") private Date creationTime = new Date(); // Statistics variables @@ -178,7 +177,6 @@ public class EnhancedDebugger extends SmackDebugger { JTabbedPane tabbedPane; - @SuppressWarnings("this-escape") public EnhancedDebugger(XMPPConnection connection) { super(connection); @@ -758,7 +756,6 @@ public class EnhancedDebugger extends SmackDebugger { * @param dateFormatter the SimpleDateFormat to use to format Dates * @param packet the read stanza to add to the table */ - @SuppressWarnings("JavaUtilDate") private void addReadPacketToTable(final SimpleDateFormat dateFormatter, final TopLevelStreamElement packet) { SwingUtilities.invokeLater(new Runnable() { @Override @@ -830,7 +827,6 @@ public class EnhancedDebugger extends SmackDebugger { * @param dateFormatter the SimpleDateFormat to use to format Dates * @param packet the sent stanza to add to the table */ - @SuppressWarnings("JavaUtilDate") private void addSentPacketToTable(final SimpleDateFormat dateFormatter, final TopLevelStreamElement packet) { SwingUtilities.invokeLater(new Runnable() { @Override diff --git a/smack-debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebuggerWindow.java b/smack-debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebuggerWindow.java index cadcb0b53..5755207d8 100644 --- a/smack-debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebuggerWindow.java +++ b/smack-debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebuggerWindow.java @@ -204,7 +204,7 @@ public final class EnhancedDebuggerWindow { * Creates the main debug window that provides information about Smack and also shows * a tab panel for each connection that is being debugged. */ - @SuppressWarnings({ "rawtypes", "unchecked", "JdkObsolete" }) + @SuppressWarnings({ "rawtypes", "unchecked" }) private void createDebug() { frame = new JFrame("Smack Debug Window"); diff --git a/smack-debug/src/main/java/org/jivesoftware/smackx/package-info.java b/smack-debug/src/main/java/org/jivesoftware/smackx/package-info.java index bce3b6064..7ebe86244 120000 --- a/smack-debug/src/main/java/org/jivesoftware/smackx/package-info.java +++ b/smack-debug/src/main/java/org/jivesoftware/smackx/package-info.java @@ -1 +1 @@ -../../../../../../../smack-java11-full/src/main/java/org/jivesoftware/smackx/package-info.java \ No newline at end of file +../../../../../../../smack-java8-full/src/main/java/org/jivesoftware/smackx/package-info.java \ No newline at end of file diff --git a/smack-examples/build.gradle b/smack-examples/build.gradle deleted file mode 100644 index 244040dd7..000000000 --- a/smack-examples/build.gradle +++ /dev/null @@ -1,14 +0,0 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' -} - -description = """\ -Examples and test applications for Smack""" - -dependencies { - // Smack's integration test framework (sintest) depends on - // smack-java*-full and since we may want to use parts of sinttest - // in smack-examples, we simply depend sinttest. - api project(':smack-integration-test') - api project(':smack-omemo-signal') -} diff --git a/smack-examples/src/main/java/org/igniterealtime/smack/examples/XmlStringBuilderTest.java b/smack-examples/src/main/java/org/igniterealtime/smack/examples/XmlStringBuilderTest.java deleted file mode 100644 index b02e5cf81..000000000 --- a/smack-examples/src/main/java/org/igniterealtime/smack/examples/XmlStringBuilderTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/** - * - * Copyright 2023 Florian Schmaus - * - * This file is part of smack-examples. - * - * smack-examples is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.igniterealtime.smack.examples; - -import java.util.function.Supplier; - -import org.jivesoftware.smack.util.XmlStringBuilder; - -public class XmlStringBuilderTest { - static int COUNT_OUTER = 500; - static int COUNT_INNER = 50; - - public static void main(String[] args) throws Exception { - test1(); - test2(); - test3(); - } - - public static void test1() throws Exception { - // CHECKSTYLE:OFF - System.out.println("Test 1"); - // CHECKSTYLE:ON - XmlStringBuilder parent = new XmlStringBuilder(); - XmlStringBuilder child = new XmlStringBuilder(); - XmlStringBuilder child2 = new XmlStringBuilder(); - - for (int i = 1; i < COUNT_OUTER; i++) { - XmlStringBuilder cs = new XmlStringBuilder(); - for (int j = 0; j < COUNT_INNER; j++) { - cs.append("abc"); - } - child2.append((CharSequence) cs); - } - - child.append((CharSequence) child2); - parent.append((CharSequence) child); - - time("test1: parent", () -> "len=" + parent.toString().length()); - time("test1: child", () -> "len=" + child.toString().length()); - time("test1: child2", () -> "len=" + child2.toString().length()); - } - - public static void test2() throws Exception { - // CHECKSTYLE:OFF - System.out.println("Test 2: evaluate children first"); - // CHECKSTYLE:ON - XmlStringBuilder parent = new XmlStringBuilder(); - XmlStringBuilder child = new XmlStringBuilder(); - XmlStringBuilder child2 = new XmlStringBuilder(); - - for (int i = 1; i < COUNT_OUTER; i++) { - XmlStringBuilder cs = new XmlStringBuilder(); - for (int j = 0; j < COUNT_INNER; j++) { - cs.append("abc"); - } - child2.append((CharSequence) cs); - } - - child.append((CharSequence) child2); - parent.append((CharSequence) child); - - time("test2: child2", () -> "len=" + child2.toString().length()); - time("test2: child", () -> "len=" + child.toString().length()); - time("test2: parent", () -> "len=" + parent.toString().length()); - } - - public static void test3() throws Exception { - // CHECKSTYLE:OFF - System.out.println("Test 3: use append(XmlStringBuilder)"); - // CHECKSTYLE:ON - XmlStringBuilder parent = new XmlStringBuilder(); - XmlStringBuilder child = new XmlStringBuilder(); - XmlStringBuilder child2 = new XmlStringBuilder(); - - for (int i = 1; i < COUNT_OUTER; i++) { - XmlStringBuilder cs = new XmlStringBuilder(); - for (int j = 0; j < COUNT_INNER; j++) { - cs.append("abc"); - } - child2.append(cs); - } - - child.append(child2); - parent.append(child); - - time("test3: parent", () -> "len=" + parent.toString().length()); - time("test3: child", () -> "len=" + child.toString().length()); - time("test3: child2", () -> "len=" + child2.toString().length()); - } - - static void time(String name, Supplier block) { - long start = System.currentTimeMillis(); - String result = block.get(); - long end = System.currentTimeMillis(); - - // CHECKSTYLE:OFF - System.out.println(name + " took " + (end - start) + "ms: " + result); - // CHECKSTYLE:ONy - } -} diff --git a/smack-examples/src/main/java/org/igniterealtime/smack/examples/XmppConnectionTool.java b/smack-examples/src/main/java/org/igniterealtime/smack/examples/XmppConnectionTool.java deleted file mode 100644 index c44adb157..000000000 --- a/smack-examples/src/main/java/org/igniterealtime/smack/examples/XmppConnectionTool.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * - * Copyright 2024 Florian Schmaus. - * - * This file is part of smack-examples. - * - * smack-examples is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.igniterealtime.smack.examples; - -import java.io.IOException; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.SmackException.NoResponseException; -import org.jivesoftware.smack.SmackException.NotConnectedException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.XMPPException.XMPPErrorException; -import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection; -import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnectionConfiguration; -import org.jivesoftware.smack.debugger.ConsoleDebugger; -import org.jivesoftware.smack.debugger.SmackDebuggerFactory; -import org.jivesoftware.smackx.omemo.util.OmemoConstants; -import org.jivesoftware.smackx.pep.PepManager; -import org.jivesoftware.smackx.pubsub.PubSubManager; - -import org.jxmpp.stringprep.XmppStringprepException; - -public class XmppConnectionTool { - - public final ModularXmppClientToServerConnection connection; - - public XmppConnectionTool(ModularXmppClientToServerConnection connection) { - this.connection = connection; - } - - public boolean purgeOmemoInformation() - throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - PepManager pepManager = PepManager.getInstanceFor(connection); - PubSubManager pepPubSubManager = pepManager.getPepPubSubManager(); - - // TODO: Also delete "bundles" nodes. - return pepPubSubManager.deleteNode(OmemoConstants.PEP_NODE_DEVICE_LIST); - } - - public static XmppConnectionTool of(String jid, String password, boolean debug) - throws XMPPException, SmackException, IOException, InterruptedException { - ModularXmppClientToServerConnection connection = createConnectionFor(jid, password, debug); - connection.connect().login(); - return new XmppConnectionTool(connection); - } - - public static ModularXmppClientToServerConnection createConnectionFor(String jid, String password, boolean debug) - throws XmppStringprepException { - - final SmackDebuggerFactory smackDebuggerFactory; - if (debug) { - smackDebuggerFactory = ConsoleDebugger.Factory.INSTANCE; - } else { - smackDebuggerFactory = null; - } - - ModularXmppClientToServerConnectionConfiguration.Builder configurationBuilder = ModularXmppClientToServerConnectionConfiguration - .builder().setXmppAddressAndPassword(jid, password).setDebuggerFactory(smackDebuggerFactory); - - ModularXmppClientToServerConnectionConfiguration configuration = configurationBuilder.build(); - - ModularXmppClientToServerConnection connection = new ModularXmppClientToServerConnection(configuration); - return connection; - } -} diff --git a/smack-examples/src/main/java/org/igniterealtime/smack/examples/package-info.java b/smack-examples/src/main/java/org/igniterealtime/smack/examples/package-info.java deleted file mode 100644 index ed3cf17e7..000000000 --- a/smack-examples/src/main/java/org/igniterealtime/smack/examples/package-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * - * Copyright 2023 Florian Schmaus - * - * This file is part of smack-examples. - * - * smack-examples is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * Examples and tests for Smack. - */ -package org.igniterealtime.smack.examples; diff --git a/smack-examples/src/test/java/org/igniterealtime/smack/examples/SmackExamplesTest.java b/smack-examples/src/test/java/org/igniterealtime/smack/examples/SmackExamplesTest.java deleted file mode 100644 index 35aa7190d..000000000 --- a/smack-examples/src/test/java/org/igniterealtime/smack/examples/SmackExamplesTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * - * Copyright 2023 Florian Schmaus - * - * This file is part of smack-examples. - * - * smack-examples is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -package org.igniterealtime.smack.examples; - -import org.junit.jupiter.api.Test; - -public class SmackExamplesTest { - /** - * Just here to ensure jacoco is not complaining. - */ - @Test - public void emptyTest() { - } - -} diff --git a/smack-experimental/build.gradle b/smack-experimental/build.gradle index 7484d56f8..9e945e0d5 100644 --- a/smack-experimental/build.gradle +++ b/smack-experimental/build.gradle @@ -1,8 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} - description = """\ Smack experimental extensions. Classes and methods for XEPs that are in status 'experimental' or that should diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/carbons/packet/Carbon.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/carbons/packet/Carbon.java index 77ef518f6..8f303cdff 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/carbons/packet/Carbon.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/carbons/packet/Carbon.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014-2024 Florian Schmaus + * Copyright © 2014 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,6 @@ public class Carbon { public static class Enable extends SimpleIQ { public static final String ELEMENT = "enable"; - @SuppressWarnings("this-escape") public Enable() { super(ELEMENT, NAMESPACE); setType(Type.set); @@ -38,7 +37,6 @@ public class Carbon { public static class Disable extends SimpleIQ { public static final String ELEMENT = "disable"; - @SuppressWarnings("this-escape") public Disable() { super(ELEMENT, NAMESPACE); setType(Type.set); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/chat_markers/ChatMarkersManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/chat_markers/ChatMarkersManager.java index 60b125742..b2f99bd76 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/chat_markers/ChatMarkersManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/chat_markers/ChatMarkersManager.java @@ -174,10 +174,7 @@ public final class ChatMarkersManager extends Manager { * @throws XMPPErrorException in case an error response was received. * @throws NoResponseException if no response was received. * @throws InterruptedException if the connection is interrupted. - * @deprecated This method serves no purpose, as servers do not announce this feature. */ - // TODO: Remove in Smack 4.6. - @Deprecated public boolean isSupportedByServer() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { return ServiceDiscoveryManager.getInstanceFor(connection()) diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/element/DnsIq.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/element/DnsIq.java index 590906549..77c626eae 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/element/DnsIq.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/dox/element/DnsIq.java @@ -1,6 +1,6 @@ /** * - * Copyright 2019-2024 Florian Schmaus + * 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. @@ -43,7 +43,6 @@ public class DnsIq extends IQ { this(new DnsMessage(dnsMessage)); } - @SuppressWarnings("this-escape") public DnsIq(DnsMessage dnsQuery, Jid to) { this(dnsQuery); setTo(to); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/element/FileMetadataElement.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/element/FileMetadataElement.java deleted file mode 100644 index e9f2976bb..000000000 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/element/FileMetadataElement.java +++ /dev/null @@ -1,312 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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.smackx.file_metadata.element; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.packet.XmlEnvironment; -import org.jivesoftware.smack.util.CollectionUtil; -import org.jivesoftware.smack.util.EqualsUtil; -import org.jivesoftware.smack.util.HashCode; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smack.util.XmlStringBuilder; -import org.jivesoftware.smackx.hashes.HashManager; -import org.jivesoftware.smackx.hashes.element.HashElement; -import org.jivesoftware.smackx.thumbnails.element.ThumbnailElement; - -/** - * File metadata element as defined in XEP-0446: File Metadata Element. - * This element is used in a generic way to provide information about files, e.g. during file sharing. - */ -public final class FileMetadataElement implements ExtensionElement { - - public static final String ELEMENT = "file"; - public static final String NAMESPACE = "urn:xmpp:file:metadata:0"; - public static final String ELEM_DATE = "date"; - public static final String ELEM_HEIGHT = "height"; - public static final String ELEM_WIDTH = "width"; - public static final String ELEM_DESC = "desc"; - public static final String ELEM_LENGTH = "length"; - public static final String ELEM_MEDIA_TYPE = "media-type"; - public static final String ELEM_NAME = "name"; - public static final String ELEM_SIZE = "size"; - - - private final Date date; - private final Integer height; - private final Integer width; - private final Map descriptions; - private final Map hashElements; - private final Long length; - private final String mediaType; - private final String name; - private final Long size; - private final List thumbnails; - - private FileMetadataElement(Date date, Integer height, Integer width, Map descriptions, - Map hashElements, Long length, - String mediaType, String name, Long size, - List thumbnails) { - this.date = date; - this.height = height; - this.width = width; - this.descriptions = CollectionUtil.cloneAndSeal(descriptions); - this.hashElements = CollectionUtil.cloneAndSeal(hashElements); - this.length = length; - this.mediaType = mediaType; - this.name = name; - this.size = size; - this.thumbnails = CollectionUtil.cloneAndSeal(thumbnails); - } - - @Override - public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) { - XmlStringBuilder sb = new XmlStringBuilder(this) - .rightAngleBracket() - .optElement(ELEM_DATE, date) - .optElement(ELEM_HEIGHT, height) - .optElement(ELEM_WIDTH, width); - for (String key : descriptions.keySet()) { - sb.halfOpenElement(ELEM_DESC) - .optXmlLangAttribute(key) - .rightAngleBracket() - .append(descriptions.get(key)) - .closeElement(ELEM_DESC); - } - sb.append(hashElements.values()) - .optElement(ELEM_LENGTH, length != null ? Long.toString(length) : null) - .optElement(ELEM_MEDIA_TYPE, mediaType) - .optElement(ELEM_NAME, name) - .optElement(ELEM_SIZE, size != null ? Long.toString(size) : null) - .append(thumbnails); - return sb.closeElement(this); - } - - @Override - public String getNamespace() { - return NAMESPACE; - } - - @Override - public String getElementName() { - return ELEMENT; - } - - public Date getDate() { - return date; - } - - public Integer getHeight() { - return height; - } - - public Integer getWidth() { - return width; - } - - public Map getDescriptions() { - return Collections.unmodifiableMap(descriptions); - } - - public String getDescription() { - return getDescription(getLanguage()); - } - - public String getDescription(String lang) { - return descriptions.get(lang != null ? lang : ""); - } - - public Map getHashElements() { - return Collections.unmodifiableMap(hashElements); - } - - public HashElement getHashElement(HashManager.ALGORITHM algorithm) { - return hashElements.get(algorithm); - } - - public Long getLength() { - return length; - } - - public String getMediaType() { - return mediaType; - } - - /** - * Return the name of the file. - * - * @return escaped name - */ - public String getName() { - if (name == null) { - return null; - } - try { - return URLEncoder.encode(name, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); // UTF-8 MUST be supported - } - } - - public String getRawName() { - return name; - } - - public Long getSize() { - return size; - } - - public List getThumbnails() { - return Collections.unmodifiableList(thumbnails); - } - - @Override - public int hashCode() { - return HashCode.builder() - .append(getElementName()) - .append(getNamespace()) - .append(getDate()) - .append(getDescriptions()) - .append(getHeight()) - .append(getWidth()) - .append(getHashElements()) - .append(getLength()) - .append(getMediaType()) - .append(getRawName()) - .append(getSize()) - .append(getThumbnails()) - .build(); - } - - @Override - public boolean equals(Object other) { - return EqualsUtil.equals(this, other, (equalsBuilder, o) -> equalsBuilder - .append(getElementName(), o.getElementName()) - .append(getNamespace(), o.getNamespace()) - .append(getDate(), o.getDate()) - .append(getDescriptions(), o.getDescriptions()) - .append(getHeight(), o.getHeight()) - .append(getWidth(), o.getWidth()) - .append(getHashElements(), o.getHashElements()) - .append(getLength(), o.getLength()) - .append(getMediaType(), o.getMediaType()) - .append(getRawName(), o.getRawName()) - .append(getSize(), o.getSize()) - .append(getThumbnails(), o.getThumbnails())); - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - - private Date date; - private Integer height; - private Integer width; - private Map descriptions = new HashMap<>(); - private Map hashElements = new HashMap<>(); - private Long length; - private String mediaType; - private String name; - private Long size; - private List thumbnails = new ArrayList<>(); - - public Builder setModificationDate(Date date) { - this.date = date; - return this; - } - - public Builder setDimensions(int width, int height) { - return setHeight(height).setWidth(width); - } - - public Builder setHeight(int height) { - if (height <= 0) { - throw new IllegalArgumentException("Height must be a positive number"); - } - this.height = height; - return this; - } - - public Builder setWidth(int width) { - if (width <= 0) { - throw new IllegalArgumentException("Width must be a positive number"); - } - this.width = width; - return this; - } - - public Builder addDescription(String description) { - return addDescription(description, null); - } - - public Builder addDescription(String description, String language) { - this.descriptions.put(language != null ? language : "", StringUtils.requireNotNullNorEmpty(description, "Description MUST NOT be null nor empty")); - return this; - } - - public Builder addHash(HashElement hashElement) { - hashElements.put(hashElement.getAlgorithm(), hashElement); - return this; - } - - public Builder setLength(long length) { - if (length < 0) { - throw new IllegalArgumentException("Length cannot be negative."); - } - this.length = length; - return this; - } - - public Builder setMediaType(String mediaType) { - this.mediaType = StringUtils.requireNotNullNorEmpty(mediaType, "Media-Type MUST NOT be null nor empty"); - return this; - } - - public Builder setName(String name) { - this.name = StringUtils.requireNotNullNorEmpty(name, "Name MUST NOT be null nor empty"); - return this; - } - - public Builder setSize(long size) { - if (size < 0) { - throw new IllegalArgumentException("Size MUST NOT be negative."); - } - this.size = size; - return this; - } - - public Builder addThumbnail(ThumbnailElement thumbnail) { - thumbnails.add(thumbnail); - return this; - } - - public FileMetadataElement build() { - return new FileMetadataElement(date, height, width, descriptions, hashElements, length, - mediaType, name, size, thumbnails); - } - } -} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/element/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/element/package-info.java deleted file mode 100644 index dbea97273..000000000 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/element/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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. - */ -/** - * Smacks implementation of XEP-0446: File Metadata Element. - */ -package org.jivesoftware.smackx.file_metadata.element; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/package-info.java deleted file mode 100644 index 8d9825d6c..000000000 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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. - */ -/** - * Smacks implementation of XEP-0446: File Metadata Element. - */ -package org.jivesoftware.smackx.file_metadata; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/provider/FileMetadataElementProvider.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/provider/FileMetadataElementProvider.java deleted file mode 100644 index e4212b0ce..000000000 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/provider/FileMetadataElementProvider.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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.smackx.file_metadata.provider; - -import java.io.IOException; -import java.text.ParseException; - -import org.jivesoftware.smack.packet.XmlEnvironment; -import org.jivesoftware.smack.parsing.SmackParsingException; -import org.jivesoftware.smack.provider.ExtensionElementProvider; -import org.jivesoftware.smack.util.ParserUtils; -import org.jivesoftware.smack.xml.XmlPullParser; -import org.jivesoftware.smack.xml.XmlPullParserException; -import org.jivesoftware.smackx.file_metadata.element.FileMetadataElement; -import org.jivesoftware.smackx.hashes.element.HashElement; -import org.jivesoftware.smackx.hashes.provider.HashElementProvider; -import org.jivesoftware.smackx.thumbnails.element.ThumbnailElement; -import org.jivesoftware.smackx.thumbnails.provider.ThumbnailElementProvider; - -public class FileMetadataElementProvider extends ExtensionElementProvider { - - @Override - public FileMetadataElement parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) - throws XmlPullParserException, IOException, SmackParsingException, ParseException { - FileMetadataElement.Builder builder = FileMetadataElement.builder(); - - outerloop: while (true) { - XmlPullParser.Event event = parser.next(); - switch (event) { - case START_ELEMENT: - String name = parser.getName(); - switch (name) { - case FileMetadataElement.ELEMENT: - parser.next(); - break; - case FileMetadataElement.ELEM_DATE: - builder.setModificationDate(ParserUtils.getDateFromNextText(parser)); - break; - case FileMetadataElement.ELEM_DESC: - String lang = ParserUtils.getXmlLang(parser); - builder.addDescription(ParserUtils.getRequiredNextText(parser), lang); - break; - case "dimensions": // was replaced with width and height - String dimensions = ParserUtils.getRequiredNextText(parser); - String[] split = dimensions.split("x"); - if (split.length != 2) { - throw new IllegalArgumentException("Invalid dimensions."); - } - builder.setWidth(Integer.parseInt(split[0])); - builder.setHeight(Integer.parseInt(split[1])); - break; - case FileMetadataElement.ELEM_WIDTH: - builder.setWidth(Integer.parseInt(ParserUtils.getRequiredNextText(parser))); - break; - case FileMetadataElement.ELEM_HEIGHT: - builder.setHeight(Integer.parseInt(ParserUtils.getRequiredNextText(parser))); - break; - case FileMetadataElement.ELEM_LENGTH: - builder.setLength(Long.parseLong(ParserUtils.getRequiredNextText(parser))); - break; - case FileMetadataElement.ELEM_MEDIA_TYPE: - builder.setMediaType(ParserUtils.getRequiredNextText(parser)); - break; - case FileMetadataElement.ELEM_NAME: - builder.setName(ParserUtils.getRequiredNextText(parser)); - break; - case FileMetadataElement.ELEM_SIZE: - builder.setSize(Long.parseLong(ParserUtils.getRequiredNextText(parser))); - break; - case HashElement.ELEMENT: - builder.addHash(HashElementProvider.INSTANCE.parse(parser, parser.getDepth(), xmlEnvironment)); - break; - case ThumbnailElement.ELEMENT: - ThumbnailElementProvider provider = new ThumbnailElementProvider(); - builder.addThumbnail(provider.parse(parser, parser.getDepth(), xmlEnvironment)); - } - break; - case END_ELEMENT: - if (parser.getDepth() == initialDepth) break outerloop; - break; - default: - // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement. - break; - } - } - return builder.build(); - } -} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/provider/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/provider/package-info.java deleted file mode 100644 index e28f0d94b..000000000 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/file_metadata/provider/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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. - */ -/** - * File metadata element provider. - */ -package org.jivesoftware.smackx.file_metadata.provider; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/hashes/HashManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/hashes/HashManager.java index 68aa79ba7..b3f0c3db4 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/hashes/HashManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/hashes/HashManager.java @@ -47,7 +47,7 @@ import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.hashes.element.HashElement; /** - * Manager that can be used to determine support for hash functions. By default,the Manager announces support for + * Manager that can be used to determine support for hash functions. By default the Manager announces support for * XEP-0300, as well as for the recommended set of hash algorithms. Those contain SHA256, SHA384, SHA512, SHA3-256, * SHA3-384, SHA3-512, BLAKE2B256, BLAKE2B384 and BLAKE2B512. Those algorithms got recommended here: * https://xmpp.org/extensions/xep-0300.html#recommendations. diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/package-info.java index 9ca583637..1b357afa8 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/package-info.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/package-info.java @@ -103,7 +103,7 @@ * AbstractHttpOverXmpp.Data data = new AbstractHttpOverXmpp.Data(child); * * // create request - * HttpOverXmppReq req = HttpOverXmppReq.builder() + * HttpOverXmppReq req = HttpOverXmppReq.buider() * .setMethod(HttpMethod.POST) * .setResource("/mailbox") * .setHeaders(headers) diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/element/Slot.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/element/Slot.java index 48c61bec7..274e59bc0 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/element/Slot.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/element/Slot.java @@ -46,7 +46,6 @@ public class Slot extends IQ { this(putUrl, getUrl, headers, NAMESPACE); } - @SuppressWarnings("this-escape") protected Slot(URL putUrl, URL getUrl, Map headers, String namespace) { super(ELEMENT, namespace); setType(Type.result); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/element/SlotRequest.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/element/SlotRequest.java index 0fa8b484c..961fc27e1 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/element/SlotRequest.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/element/SlotRequest.java @@ -53,7 +53,6 @@ public class SlotRequest extends IQ { this(uploadServiceAddress, filename, size, contentType, NAMESPACE); } - @SuppressWarnings("this-escape") protected SlotRequest(DomainBareJid uploadServiceAddress, String filename, long size, String contentType, String namespace) { super(ELEMENT, namespace); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/control/element/IoTSetRequest.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/control/element/IoTSetRequest.java index a3dad0268..cd6d0b553 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/control/element/IoTSetRequest.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/control/element/IoTSetRequest.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2016-2024 Florian Schmaus + * Copyright © 2016-2017 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,6 @@ public class IoTSetRequest extends IQ { private final Collection setData; - @SuppressWarnings("this-escape") public IoTSetRequest(Collection setData) { super(ELEMENT, NAMESPACE); setType(Type.set); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/element/IoTDataReadOutAccepted.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/element/IoTDataReadOutAccepted.java index 279476cd2..20d0a125d 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/element/IoTDataReadOutAccepted.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/element/IoTDataReadOutAccepted.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2016-2024 Florian Schmaus + * Copyright © 2016 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,6 @@ public class IoTDataReadOutAccepted extends IQ { private final boolean queued; - @SuppressWarnings("this-escape") public IoTDataReadOutAccepted(int seqNr, boolean queued) { super(ELEMENT, NAMESPACE); this.seqNr = seqNr; @@ -38,7 +37,6 @@ public class IoTDataReadOutAccepted extends IQ { setType(Type.result); } - @SuppressWarnings("this-escape") public IoTDataReadOutAccepted(IoTDataRequest dataRequest) { this(dataRequest.getSequenceNr(), false); setStanzaId(dataRequest.getStanzaId()); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/element/IoTFieldsExtension.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/element/IoTFieldsExtension.java index 721b1b657..cb280745f 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/element/IoTFieldsExtension.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/data/element/IoTFieldsExtension.java @@ -83,7 +83,6 @@ public class IoTFieldsExtension implements ExtensionElement { return xml; } - @SuppressWarnings("JavaUtilDate") public static IoTFieldsExtension buildFor(int seqNr, boolean done, NodeInfo nodeInfo, List data) { TimestampElement timestampElement = new TimestampElement(new Date(), data); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/discovery/element/IoTUnregister.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/discovery/element/IoTUnregister.java index 3b510e55f..bdc536f97 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/discovery/element/IoTUnregister.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/discovery/element/IoTUnregister.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016-2024 Florian Schmaus + * Copyright 2016 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,6 @@ public class IoTUnregister extends IQ { private final NodeInfo nodeInfo; - @SuppressWarnings("this-escape") public IoTUnregister(NodeInfo nodeInfo) { super(ELEMENT, NAMESPACE); this.nodeInfo = nodeInfo; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/package-info.java index c4b261a27..0b3803a4f 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/package-info.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/package-info.java @@ -146,7 +146,7 @@ *
        * 
        * IoTDiscoveryManager iotDiscoveryManager = IoTDiscoveryManager.getInstanceFor(connection);
      - * iotDiscoveryManager.registerThing(thing);
      + * iotDiscovyerManager.registerThing(thing);
        * 
        * 
      *

      @@ -162,7 +162,7 @@ * Things can usually only be used by other things if they are friends. Since a * thing normally can't decide on its own if an incoming friendship request * should be granted or not, we can delegate this decision to a provisioning - * service. Smack provides the `IoTProvisionManager` to deal with friendship and + * service. Smack provides the `IoTProvisinoManager` to deal with friendship and * provisioning. *

      *

      diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/element/ClearCache.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/element/ClearCache.java index d17e46c94..fe98b32b3 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/element/ClearCache.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/element/ClearCache.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2016-2024 Florian Schmaus + * Copyright © 2016 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,6 @@ public class ClearCache extends SimpleIQ { public static final String ELEMENT = "clearCache"; public static final String NAMESPACE = Constants.IOT_PROVISIONING_NAMESPACE; - @SuppressWarnings("this-escape") public ClearCache() { super(ELEMENT, NAMESPACE); // IQs are always of type 'get' (XEP-0324 § 3.5.1, see also the XEPs history remarks) diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/element/ClearCacheResponse.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/element/ClearCacheResponse.java index 1abfb731c..1c229d153 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/element/ClearCacheResponse.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/iot/provisioning/element/ClearCacheResponse.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2016-2024 Florian Schmaus + * Copyright © 2016 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,14 +23,12 @@ public class ClearCacheResponse extends SimpleIQ { public static final String ELEMENT = "clearCacheResponse"; public static final String NAMESPACE = Constants.IOT_PROVISIONING_NAMESPACE; - @SuppressWarnings("this-escape") public ClearCacheResponse() { super(ELEMENT, NAMESPACE); // IQs are always of type 'result' (XEP-0324 § 3.5.1, see also the XEPs history remarks) setType(Type.result); } - @SuppressWarnings("this-escape") public ClearCacheResponse(ClearCache clearCacheRequest) { this(); setStanzaId(clearCacheRequest.getStanzaId()); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/element/JingleFileTransferChild.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/element/JingleFileTransferChild.java index cab86e550..b4e9021ec 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/element/JingleFileTransferChild.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/element/JingleFileTransferChild.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017 Paul Schaub, 2019-2024 Florian Schmaus + * Copyright 2017 Paul Schaub, 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. @@ -167,7 +167,6 @@ public class JingleFileTransferChild implements JingleContentDescriptionChildEle return new JingleFileTransferChild(date, desc, hash, mediaType, name, size, range); } - @SuppressWarnings("JavaUtilDate") public Builder setFile(File file) { return setDate(new Date(file.lastModified())) .setName(file.getAbsolutePath().substring(file.getAbsolutePath().lastIndexOf("/") + 1)) diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/MamManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/MamManager.java index 6ce58bdea..94dfc2f07 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/MamManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/MamManager.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2017-2024 Florian Schmaus, 2016-2017 Fernando Ramirez + * Copyright © 2017-2020 Florian Schmaus, 2016-2017 Fernando Ramirez * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,8 +44,8 @@ import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.commands.AdHocCommand; import org.jivesoftware.smackx.commands.AdHocCommandManager; +import org.jivesoftware.smackx.commands.RemoteCommand; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; import org.jivesoftware.smackx.disco.packet.DiscoverItems; @@ -233,7 +233,7 @@ public final class MamManager extends Manager { super(connection); this.archiveAddress = archiveAddress; serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection); - adHocCommandManager = AdHocCommandManager.getInstance(connection); + adHocCommandManager = AdHocCommandManager.getAddHocCommandsManager(connection); } /** @@ -387,7 +387,6 @@ public final class MamManager extends Manager { return this; } - @SuppressWarnings("JavaUtilDate") public Builder limitResultsSince(Date start) { if (start == null) { return this; @@ -416,7 +415,6 @@ public final class MamManager extends Manager { return this; } - @SuppressWarnings("JavaUtilDate") public Builder limitResultsBefore(Date end) { if (end == null) { return this; @@ -761,7 +759,7 @@ public final class MamManager extends Manager { return false; } - public AdHocCommand getAdvancedConfigurationCommand() throws InterruptedException, XMPPException, SmackException { + public RemoteCommand getAdvancedConfigurationCommand() throws InterruptedException, XMPPException, SmackException { DiscoverItems discoverItems = adHocCommandManager.discoverCommands(archiveAddress); for (DiscoverItems.Item item : discoverItems.getItems()) { if (item.getNode().equals(ADVANCED_CONFIG_NODE)) diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/element/MamPrefsIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/element/MamPrefsIQ.java index 1a5535135..e5898f4c3 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/element/MamPrefsIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/element/MamPrefsIQ.java @@ -81,7 +81,6 @@ public class MamPrefsIQ extends IQ { * @param neverJids TODO javadoc me please * @param defaultBehavior TODO javadoc me please */ - @SuppressWarnings("this-escape") public MamPrefsIQ(MamVersion version, List alwaysJids, List neverJids, DefaultBehavior defaultBehavior) { super(ELEMENT, version.getNamespace()); setType(Type.set); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/element/MamQueryIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/element/MamQueryIQ.java index 17b8a5cae..3909b077c 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/element/MamQueryIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/mam/element/MamQueryIQ.java @@ -45,7 +45,6 @@ public class MamQueryIQ extends IQ { * @param version TODO javadoc me please * @param queryId TODO javadoc me please */ - @SuppressWarnings("this-escape") public MamQueryIQ(MamVersion version, String queryId) { this(version, queryId, null, null); setType(IQ.Type.get); @@ -80,7 +79,6 @@ public class MamQueryIQ extends IQ { * @param node TODO javadoc me please * @param dataForm TODO javadoc me please */ - @SuppressWarnings("this-escape") public MamQueryIQ(MamVersion version, String queryId, String node, DataForm dataForm) { super(ELEMENT, version.getNamespace()); this.queryId = queryId; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/message_markup/element/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/message_markup/element/package-info.java index f1d6e981e..5246c33ff 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/message_markup/element/package-info.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/message_markup/element/package-info.java @@ -21,7 +21,7 @@ *

      Usage

      *

      * The most important class is the {@link org.jivesoftware.smackx.message_markup.element.MarkupElement} class, which - * contains a Builder to construct message markup. + * contains a Builder to construct message markup.. *

      *

      * To start creating a Message Markup Extension, call diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MUCLightRoomConfiguration.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MUCLightRoomConfiguration.java index 7f0595871..aab822087 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MUCLightRoomConfiguration.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MUCLightRoomConfiguration.java @@ -16,7 +16,7 @@ */ package org.jivesoftware.smackx.muclight; -import java.util.Map; +import java.util.HashMap; /** * MUC Light room configuration class. @@ -28,7 +28,7 @@ public class MUCLightRoomConfiguration { private final String roomName; private final String subject; - private final Map customConfigs; + private final HashMap customConfigs; /** * MUC Light room configuration model constructor. @@ -37,7 +37,7 @@ public class MUCLightRoomConfiguration { * @param subject TODO javadoc me please * @param customConfigs TODO javadoc me please */ - public MUCLightRoomConfiguration(String roomName, String subject, Map customConfigs) { + public MUCLightRoomConfiguration(String roomName, String subject, HashMap customConfigs) { this.roomName = roomName; this.subject = subject; this.customConfigs = customConfigs; @@ -66,7 +66,7 @@ public class MUCLightRoomConfiguration { * * @return the custom configurations of the room. */ - public Map getCustomConfigs() { + public HashMap getCustomConfigs() { return customConfigs; } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MUCLightRoomInfo.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MUCLightRoomInfo.java index 532f64bf4..b41066d54 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MUCLightRoomInfo.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MUCLightRoomInfo.java @@ -16,7 +16,7 @@ */ package org.jivesoftware.smackx.muclight; -import java.util.Map; +import java.util.HashMap; import org.jxmpp.jid.Jid; @@ -30,7 +30,7 @@ public class MUCLightRoomInfo { private final String version; private final Jid room; private final MUCLightRoomConfiguration configuration; - private final Map occupants; + private final HashMap occupants; /** * MUC Light room info model constructor. @@ -41,7 +41,7 @@ public class MUCLightRoomInfo { * @param occupants TODO javadoc me please */ public MUCLightRoomInfo(String version, Jid roomJid, MUCLightRoomConfiguration configuration, - Map occupants) { + HashMap occupants) { this.version = version; this.room = roomJid; this.configuration = configuration; @@ -80,7 +80,7 @@ public class MUCLightRoomInfo { * * @return the occupants of the room. */ - public Map getOccupants() { + public HashMap getOccupants() { return occupants; } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MultiUserChatLight.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MultiUserChatLight.java index 58e5b367d..5ebd11197 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MultiUserChatLight.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MultiUserChatLight.java @@ -18,7 +18,6 @@ package org.jivesoftware.smackx.muclight; import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; @@ -182,6 +181,21 @@ public class MultiUserChatLight { ; } + /** + * Sends a Message to the chat room. + * + * @param message TODO javadoc me please + * the message. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + * @deprecated use {@link #sendMessage(MessageBuilder)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void sendMessage(Message message) throws NotConnectedException, InterruptedException { + sendMessage(message.asBuilder()); + } + /** * Sends a Message to the chat room. * @@ -280,7 +294,7 @@ public class MultiUserChatLight { * @param occupants TODO javadoc me please * @throws Exception TODO javadoc me please */ - public void create(String roomName, String subject, Map customConfigs, List occupants) + public void create(String roomName, String subject, HashMap customConfigs, List occupants) throws Exception { MUCLightCreateIQ createMUCLightIQ = new MUCLightCreateIQ(room, roomName, occupants); @@ -314,7 +328,7 @@ public class MultiUserChatLight { * @throws XMPPErrorException if there was an XMPP error returned. */ public void leave() throws NotConnectedException, InterruptedException, NoResponseException, XMPPErrorException { - Map affiliations = new HashMap<>(); + HashMap affiliations = new HashMap<>(); affiliations.put(connection.getUser(), MUCLightAffiliation.none); MUCLightChangeAffiliationsIQ changeAffiliationsIQ = new MUCLightChangeAffiliationsIQ(room, affiliations); @@ -403,7 +417,7 @@ public class MultiUserChatLight { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public Map getAffiliations(String version) + public HashMap getAffiliations(String version) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { MUCLightGetAffiliationsIQ mucLightGetAffiliationsIQ = new MUCLightGetAffiliationsIQ(room, version); @@ -422,7 +436,7 @@ public class MultiUserChatLight { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public Map getAffiliations() + public HashMap getAffiliations() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { return getAffiliations(null); } @@ -436,7 +450,7 @@ public class MultiUserChatLight { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void changeAffiliations(Map affiliations) + public void changeAffiliations(HashMap affiliations) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { MUCLightChangeAffiliationsIQ changeAffiliationsIQ = new MUCLightChangeAffiliationsIQ(room, affiliations); connection.sendIqRequestAndWaitForResponse(changeAffiliationsIQ); @@ -499,7 +513,7 @@ public class MultiUserChatLight { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void setRoomConfigs(Map customConfigs) + public void setRoomConfigs(HashMap customConfigs) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { setRoomConfigs(null, customConfigs); } @@ -514,7 +528,7 @@ public class MultiUserChatLight { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void setRoomConfigs(String roomName, Map customConfigs) + public void setRoomConfigs(String roomName, HashMap customConfigs) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { MUCLightSetConfigsIQ mucLightSetConfigIQ = new MUCLightSetConfigsIQ(room, roomName, customConfigs); connection.sendIqRequestAndWaitForResponse(mucLightSetConfigIQ); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MultiUserChatLightManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MultiUserChatLightManager.java index 58f030499..d153d499d 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MultiUserChatLightManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/MultiUserChatLightManager.java @@ -274,7 +274,7 @@ public final class MultiUserChatLightManager extends Manager { sendBlockRooms(mucLightService, rooms); } - private void sendBlockRooms(DomainBareJid mucLightService, Map rooms) + private void sendBlockRooms(DomainBareJid mucLightService, HashMap rooms) throws NoResponseException, XMPPErrorException, InterruptedException, NotConnectedException { MUCLightBlockingIQ mucLightBlockingIQ = new MUCLightBlockingIQ(rooms, null); mucLightBlockingIQ.setType(IQ.Type.set); @@ -318,7 +318,7 @@ public final class MultiUserChatLightManager extends Manager { sendBlockUsers(mucLightService, users); } - private void sendBlockUsers(DomainBareJid mucLightService, Map users) + private void sendBlockUsers(DomainBareJid mucLightService, HashMap users) throws NoResponseException, XMPPErrorException, InterruptedException, NotConnectedException { MUCLightBlockingIQ mucLightBlockingIQ = new MUCLightBlockingIQ(null, users); mucLightBlockingIQ.setType(IQ.Type.set); @@ -362,7 +362,7 @@ public final class MultiUserChatLightManager extends Manager { sendUnblockRooms(mucLightService, rooms); } - private void sendUnblockRooms(DomainBareJid mucLightService, Map rooms) + private void sendUnblockRooms(DomainBareJid mucLightService, HashMap rooms) throws NoResponseException, XMPPErrorException, InterruptedException, NotConnectedException { MUCLightBlockingIQ mucLightBlockingIQ = new MUCLightBlockingIQ(rooms, null); mucLightBlockingIQ.setType(IQ.Type.set); @@ -406,7 +406,7 @@ public final class MultiUserChatLightManager extends Manager { sendUnblockUsers(mucLightService, users); } - private void sendUnblockUsers(DomainBareJid mucLightService, Map users) + private void sendUnblockUsers(DomainBareJid mucLightService, HashMap users) throws NoResponseException, XMPPErrorException, InterruptedException, NotConnectedException { MUCLightBlockingIQ mucLightBlockingIQ = new MUCLightBlockingIQ(null, users); mucLightBlockingIQ.setType(IQ.Type.set); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightAffiliationsIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightAffiliationsIQ.java index 047c7af50..c9e0ead62 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightAffiliationsIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightAffiliationsIQ.java @@ -16,6 +16,7 @@ */ package org.jivesoftware.smackx.muclight.element; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -39,7 +40,7 @@ public class MUCLightAffiliationsIQ extends IQ { public static final String NAMESPACE = MultiUserChatLight.NAMESPACE + MultiUserChatLight.AFFILIATIONS; private final String version; - private Map affiliations; + private HashMap affiliations; /** * MUC Light affiliations response IQ constructor. @@ -47,8 +48,7 @@ public class MUCLightAffiliationsIQ extends IQ { * @param version TODO javadoc me please * @param affiliations TODO javadoc me please */ - @SuppressWarnings("this-escape") - public MUCLightAffiliationsIQ(String version, Map affiliations) { + public MUCLightAffiliationsIQ(String version, HashMap affiliations) { super(ELEMENT, NAMESPACE); this.version = version; this.affiliations = affiliations; @@ -82,7 +82,7 @@ public class MUCLightAffiliationsIQ extends IQ { * * @return the affiliations of the room */ - public Map getAffiliations() { + public HashMap getAffiliations() { return affiliations; } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightBlockingIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightBlockingIQ.java index fa6264ff0..f3334b651 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightBlockingIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightBlockingIQ.java @@ -16,6 +16,7 @@ */ package org.jivesoftware.smackx.muclight.element; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -37,8 +38,8 @@ public class MUCLightBlockingIQ extends IQ { public static final String ELEMENT = QUERY_ELEMENT; public static final String NAMESPACE = MultiUserChatLight.NAMESPACE + MultiUserChatLight.BLOCKING; - private final Map rooms; - private final Map users; + private final HashMap rooms; + private final HashMap users; /** * MUC Light blocking IQ constructor. @@ -46,7 +47,7 @@ public class MUCLightBlockingIQ extends IQ { * @param rooms TODO javadoc me please * @param users TODO javadoc me please */ - public MUCLightBlockingIQ(Map rooms, Map users) { + public MUCLightBlockingIQ(HashMap rooms, HashMap users) { super(ELEMENT, NAMESPACE); this.rooms = rooms; this.users = users; @@ -57,7 +58,7 @@ public class MUCLightBlockingIQ extends IQ { * * @return the rooms JIDs with booleans (true if allow, false if deny) */ - public Map getRooms() { + public HashMap getRooms() { return rooms; } @@ -66,7 +67,7 @@ public class MUCLightBlockingIQ extends IQ { * * @return the users JIDs with booleans (true if allow, false if deny) */ - public Map getUsers() { + public HashMap getUsers() { return users; } @@ -85,7 +86,7 @@ public class MUCLightBlockingIQ extends IQ { return xml; } - private static void parseBlocking(IQChildElementXmlStringBuilder xml, Map map, boolean isRoom) { + private static void parseBlocking(IQChildElementXmlStringBuilder xml, HashMap map, boolean isRoom) { Iterator> it = map.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = it.next(); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightChangeAffiliationsIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightChangeAffiliationsIQ.java index e472c84e1..494a7a4d7 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightChangeAffiliationsIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightChangeAffiliationsIQ.java @@ -16,6 +16,7 @@ */ package org.jivesoftware.smackx.muclight.element; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -38,7 +39,7 @@ public class MUCLightChangeAffiliationsIQ extends IQ { public static final String ELEMENT = QUERY_ELEMENT; public static final String NAMESPACE = MultiUserChatLight.NAMESPACE + MultiUserChatLight.AFFILIATIONS; - private Map affiliations; + private HashMap affiliations; /** * MUCLight change affiliations IQ constructor. @@ -46,8 +47,7 @@ public class MUCLightChangeAffiliationsIQ extends IQ { * @param room TODO javadoc me please * @param affiliations TODO javadoc me please */ - @SuppressWarnings("this-escape") - public MUCLightChangeAffiliationsIQ(Jid room, Map affiliations) { + public MUCLightChangeAffiliationsIQ(Jid room, HashMap affiliations) { super(ELEMENT, NAMESPACE); this.setType(Type.set); this.setTo(room); @@ -59,7 +59,7 @@ public class MUCLightChangeAffiliationsIQ extends IQ { * * @return the affiliations */ - public Map getAffiliations() { + public HashMap getAffiliations() { return affiliations; } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightCreateIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightCreateIQ.java index ea0db3b21..d15d47db5 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightCreateIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightCreateIQ.java @@ -18,7 +18,6 @@ package org.jivesoftware.smackx.muclight.element; import java.util.HashMap; import java.util.List; -import java.util.Map; import org.jivesoftware.smack.packet.IQ; @@ -43,7 +42,7 @@ public class MUCLightCreateIQ extends IQ { public static final String NAMESPACE = MultiUserChatLight.NAMESPACE + MultiUserChatLight.CREATE; private MUCLightRoomConfiguration configuration; - private final Map occupants; + private final HashMap occupants; /** * MUCLight create IQ constructor. @@ -54,8 +53,7 @@ public class MUCLightCreateIQ extends IQ { * @param customConfigs TODO javadoc me please * @param occupants TODO javadoc me please */ - @SuppressWarnings("this-escape") - public MUCLightCreateIQ(EntityJid room, String roomName, String subject, Map customConfigs, + public MUCLightCreateIQ(EntityJid room, String roomName, String subject, HashMap customConfigs, List occupants) { super(ELEMENT, NAMESPACE); this.configuration = new MUCLightRoomConfiguration(roomName, subject, customConfigs); @@ -94,7 +92,7 @@ public class MUCLightCreateIQ extends IQ { * * @return the room occupants */ - public Map getOccupants() { + public HashMap getOccupants() { return occupants; } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightDestroyIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightDestroyIQ.java index 6606ae035..8198007cf 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightDestroyIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightDestroyIQ.java @@ -38,7 +38,6 @@ public class MUCLightDestroyIQ extends IQ { * * @param roomJid TODO javadoc me please */ - @SuppressWarnings("this-escape") public MUCLightDestroyIQ(Jid roomJid) { super(ELEMENT, NAMESPACE); this.setType(Type.set); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightElements.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightElements.java index 27dcbd2e7..33861b29e 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightElements.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightElements.java @@ -16,6 +16,7 @@ */ package org.jivesoftware.smackx.muclight.element; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -47,11 +48,11 @@ public abstract class MUCLightElements { public static final String NAMESPACE = MultiUserChatLight.NAMESPACE + MultiUserChatLight.AFFILIATIONS; public static final QName QNAME = new QName(NAMESPACE, ELEMENT); - private final Map affiliations; + private final HashMap affiliations; private final String prevVersion; private final String version; - public AffiliationsChangeExtension(Map affiliations, String prevVersion, + public AffiliationsChangeExtension(HashMap affiliations, String prevVersion, String version) { this.affiliations = affiliations; this.prevVersion = prevVersion; @@ -73,7 +74,7 @@ public abstract class MUCLightElements { * * @return the affiliations */ - public Map getAffiliations() { + public HashMap getAffiliations() { return affiliations; } @@ -134,7 +135,7 @@ public abstract class MUCLightElements { private final String version; private final String roomName; private final String subject; - private final Map customConfigs; + private final HashMap customConfigs; /** * Configurations change extension constructor. @@ -146,7 +147,7 @@ public abstract class MUCLightElements { * @param customConfigs TODO javadoc me please */ public ConfigurationsChangeExtension(String prevVersion, String version, String roomName, String subject, - Map customConfigs) { + HashMap customConfigs) { this.prevVersion = prevVersion; this.version = version; this.roomName = roomName; @@ -205,7 +206,7 @@ public abstract class MUCLightElements { * * @return the room custom configurations */ - public Map getCustomConfigs() { + public HashMap getCustomConfigs() { return customConfigs; } @@ -286,14 +287,14 @@ public abstract class MUCLightElements { */ public static class OccupantsElement implements Element { - private Map occupants; + private HashMap occupants; /** * Occupants element constructor. * * @param occupants TODO javadoc me please */ - public OccupantsElement(Map occupants) { + public OccupantsElement(HashMap occupants) { this.occupants = occupants; } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightGetAffiliationsIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightGetAffiliationsIQ.java index 70249914c..67cd26481 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightGetAffiliationsIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightGetAffiliationsIQ.java @@ -41,7 +41,6 @@ public class MUCLightGetAffiliationsIQ extends IQ { * @param roomJid TODO javadoc me please * @param version TODO javadoc me please */ - @SuppressWarnings("this-escape") public MUCLightGetAffiliationsIQ(Jid roomJid, String version) { super(ELEMENT, NAMESPACE); this.version = version; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightGetConfigsIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightGetConfigsIQ.java index aff4283ee..15ce3e1f9 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightGetConfigsIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightGetConfigsIQ.java @@ -41,7 +41,6 @@ public class MUCLightGetConfigsIQ extends IQ { * @param roomJid TODO javadoc me please * @param version TODO javadoc me please */ - @SuppressWarnings("this-escape") public MUCLightGetConfigsIQ(Jid roomJid, String version) { super(ELEMENT, NAMESPACE); this.version = version; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightGetInfoIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightGetInfoIQ.java index 6e3d1daa0..112ec1935 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightGetInfoIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightGetInfoIQ.java @@ -41,7 +41,6 @@ public class MUCLightGetInfoIQ extends IQ { * @param roomJid TODO javadoc me please * @param version TODO javadoc me please */ - @SuppressWarnings("this-escape") public MUCLightGetInfoIQ(Jid roomJid, String version) { super(ELEMENT, NAMESPACE); this.version = version; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightInfoIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightInfoIQ.java index ef33d4b77..42a2b9308 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightInfoIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightInfoIQ.java @@ -16,7 +16,7 @@ */ package org.jivesoftware.smackx.muclight.element; -import java.util.Map; +import java.util.HashMap; import org.jivesoftware.smack.packet.IQ; @@ -41,7 +41,7 @@ public class MUCLightInfoIQ extends IQ { private final String version; private final MUCLightRoomConfiguration configuration; - private final Map occupants; + private final HashMap occupants; /** * MUCLight info response IQ constructor. @@ -51,7 +51,7 @@ public class MUCLightInfoIQ extends IQ { * @param occupants TODO javadoc me please */ public MUCLightInfoIQ(String version, MUCLightRoomConfiguration configuration, - Map occupants) { + HashMap occupants) { super(ELEMENT, NAMESPACE); this.version = version; this.configuration = configuration; @@ -90,7 +90,7 @@ public class MUCLightInfoIQ extends IQ { * * @return the occupants of the room */ - public Map getOccupants() { + public HashMap getOccupants() { return occupants; } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightSetConfigsIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightSetConfigsIQ.java index 3e332194a..0751b582f 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightSetConfigsIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/element/MUCLightSetConfigsIQ.java @@ -16,6 +16,7 @@ */ package org.jivesoftware.smackx.muclight.element; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -38,7 +39,7 @@ public class MUCLightSetConfigsIQ extends IQ { private String roomName; private String subject; - private Map customConfigs; + private HashMap customConfigs; /** * MUC Light set configuration IQ constructor. @@ -48,8 +49,7 @@ public class MUCLightSetConfigsIQ extends IQ { * @param subject TODO javadoc me please * @param customConfigs TODO javadoc me please */ - @SuppressWarnings("this-escape") - public MUCLightSetConfigsIQ(Jid roomJid, String roomName, String subject, Map customConfigs) { + public MUCLightSetConfigsIQ(Jid roomJid, String roomName, String subject, HashMap customConfigs) { super(ELEMENT, NAMESPACE); this.roomName = roomName; this.subject = subject; @@ -65,7 +65,7 @@ public class MUCLightSetConfigsIQ extends IQ { * @param roomName TODO javadoc me please * @param customConfigs TODO javadoc me please */ - public MUCLightSetConfigsIQ(Jid roomJid, String roomName, Map customConfigs) { + public MUCLightSetConfigsIQ(Jid roomJid, String roomName, HashMap customConfigs) { this(roomJid, roomName, null, customConfigs); } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/provider/MUCLightBlockingIQProvider.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/provider/MUCLightBlockingIQProvider.java index 1412b2900..b89dba5c8 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/provider/MUCLightBlockingIQProvider.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/provider/MUCLightBlockingIQProvider.java @@ -18,7 +18,6 @@ package org.jivesoftware.smackx.muclight.provider; import java.io.IOException; import java.util.HashMap; -import java.util.Map; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IqData; @@ -43,8 +42,8 @@ public class MUCLightBlockingIQProvider extends IqProvider { @Override public MUCLightBlockingIQ parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException { - Map rooms = null; - Map users = null; + HashMap rooms = null; + HashMap users = null; outerloop: while (true) { XmlPullParser.Event eventType = parser.next(); @@ -71,7 +70,7 @@ public class MUCLightBlockingIQProvider extends IqProvider { return mucLightBlockingIQ; } - private static Map parseBlocking(XmlPullParser parser, Map map) + private static HashMap parseBlocking(XmlPullParser parser, HashMap map) throws XmppStringprepException, XmlPullParserException, IOException { if (map == null) { map = new HashMap<>(); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/provider/MUCLightInfoIQProvider.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/provider/MUCLightInfoIQProvider.java index 50d30bca4..54d0a4218 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/provider/MUCLightInfoIQProvider.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/muclight/provider/MUCLightInfoIQProvider.java @@ -18,7 +18,6 @@ package org.jivesoftware.smackx.muclight.provider; import java.io.IOException; import java.util.HashMap; -import java.util.Map; import org.jivesoftware.smack.packet.IqData; import org.jivesoftware.smack.packet.XmlEnvironment; @@ -46,8 +45,8 @@ public class MUCLightInfoIQProvider extends IqProvider { String version = null; String roomName = null; String subject = null; - Map customConfigs = null; - Map occupants = new HashMap<>(); + HashMap customConfigs = null; + HashMap occupants = new HashMap<>(); outerloop: while (true) { XmlPullParser.Event eventType = parser.next(); @@ -98,8 +97,8 @@ public class MUCLightInfoIQProvider extends IqProvider { return new MUCLightInfoIQ(version, new MUCLightRoomConfiguration(roomName, subject, customConfigs), occupants); } - private static Map iterateOccupants(XmlPullParser parser) throws XmlPullParserException, IOException { - Map occupants = new HashMap<>(); + private static HashMap iterateOccupants(XmlPullParser parser) throws XmlPullParserException, IOException { + HashMap occupants = new HashMap<>(); int depth = parser.getDepth(); outerloop: while (true) { diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/PushNotificationsManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/PushNotificationsManager.java index 8615b4759..ff62d96eb 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/PushNotificationsManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/PushNotificationsManager.java @@ -16,6 +16,7 @@ */ package org.jivesoftware.smackx.push_notifications; +import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; @@ -121,7 +122,7 @@ public final class PushNotificationsManager extends Manager { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public boolean enable(Jid pushJid, String node, Map publishOptions) + public boolean enable(Jid pushJid, String node, HashMap publishOptions) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { EnablePushNotificationsIQ enablePushNotificationsIQ = new EnablePushNotificationsIQ(pushJid, node, publishOptions); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/element/DisablePushNotificationsIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/element/DisablePushNotificationsIQ.java index 08342811b..bedf8be02 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/element/DisablePushNotificationsIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/element/DisablePushNotificationsIQ.java @@ -43,7 +43,6 @@ public class DisablePushNotificationsIQ extends IQ { private final Jid jid; private final String node; - @SuppressWarnings("this-escape") public DisablePushNotificationsIQ(Jid jid, String node) { super(ELEMENT, NAMESPACE); this.jid = jid; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/element/EnablePushNotificationsIQ.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/element/EnablePushNotificationsIQ.java index c6f8199b4..428b41b67 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/element/EnablePushNotificationsIQ.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/push_notifications/element/EnablePushNotificationsIQ.java @@ -16,6 +16,7 @@ */ package org.jivesoftware.smackx.push_notifications.element; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -50,10 +51,9 @@ public class EnablePushNotificationsIQ extends IQ { private final Jid jid; private final String node; - private final Map publishOptions; + private final HashMap publishOptions; - @SuppressWarnings("this-escape") - public EnablePushNotificationsIQ(Jid jid, String node, Map publishOptions) { + public EnablePushNotificationsIQ(Jid jid, String node, HashMap publishOptions) { super(ELEMENT, NAMESPACE); this.jid = jid; this.node = node; @@ -88,7 +88,7 @@ public class EnablePushNotificationsIQ extends IQ { * * @return the publish options */ - public Map getPublishOptions() { + public HashMap getPublishOptions() { return publishOptions; } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/reference/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/reference/package-info.java index fc8f020be..821577179 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/reference/package-info.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/reference/package-info.java @@ -29,7 +29,7 @@ * *

        * 
      - * Message message = new Message("Alice is a really nice person.");
      + * Message message = new Message("Alice is a realy nice person.");
        * BareJid alice = JidCreate.bareFrom("alice@capulet.lit");
        * ReferenceManager.addMention(message, 0, 5, alice);
        * 
      diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java
      index f0766de8b..a50fd99e2 100644
      --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java
      +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/sid/element/OriginIdElement.java
      @@ -38,6 +38,28 @@ public class OriginIdElement extends StableAndUniqueIdElement {
               super(id);
           }
       
      +    /**
      +     * Add an origin-id element to a message and set the stanzas id to the same id as in the origin-id element.
      +     *
      +     * @param message message.
      +     * @return the added origin-id element.
      +     * @deprecated use {@link #addTo(MessageBuilder)} instead.
      +     */
      +    @Deprecated
      +    // TODO: Remove in Smack 4.5.
      +    public static OriginIdElement addOriginId(Message message) {
      +        OriginIdElement originId = message.getExtension(OriginIdElement.class);
      +        if (originId != null) {
      +            return originId;
      +        }
      +
      +        originId = new OriginIdElement();
      +        message.addExtension(originId);
      +        // TODO: Find solution to have both the originIds stanzaId and a nice to look at incremental stanzaID.
      +        // message.setStanzaId(originId.getId());
      +        return originId;
      +    }
      +
           /**
            * Add an origin-id element to a message and set the stanzas id to the same id as in the origin-id element.
            *
      diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/spoiler/element/SpoilerElement.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/spoiler/element/SpoilerElement.java
      index b18a5af5c..6d5c02fd6 100644
      --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/spoiler/element/SpoilerElement.java
      +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/spoiler/element/SpoilerElement.java
      @@ -114,7 +114,6 @@ public class SpoilerElement implements ExtensionElement {
            * @param message message
            * @return map of spoilers
            */
      -    @SuppressWarnings("MixedMutabilityReturnType")
           public static Map getSpoilers(Message message) {
               if (!containsSpoiler(message)) {
                   return Collections.emptyMap();
      diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/stanza_content_encryption/element/TimestampAffixElement.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/stanza_content_encryption/element/TimestampAffixElement.java
      index eee726085..0c48f7b7a 100644
      --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/stanza_content_encryption/element/TimestampAffixElement.java
      +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/stanza_content_encryption/element/TimestampAffixElement.java
      @@ -56,7 +56,6 @@ public class TimestampAffixElement implements NamedElement, AffixElement {
               return EqualsUtil.equals(this, obj, (e, o) -> e.append(getTimestamp(), o.getTimestamp()));
           }
       
      -    @SuppressWarnings("JavaUtilDate")
           @Override
           public int hashCode() {
               return timestamp.hashCode();
      diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/thumbnails/element/ThumbnailElement.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/thumbnails/element/ThumbnailElement.java
      deleted file mode 100644
      index 3bcd4b045..000000000
      --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/thumbnails/element/ThumbnailElement.java
      +++ /dev/null
      @@ -1,92 +0,0 @@
      -/**
      - *
      - * Copyright 2023 Paul Schaub
      - *
      - * 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.smackx.thumbnails.element;
      -
      -import org.jivesoftware.smack.packet.ExtensionElement;
      -import org.jivesoftware.smack.packet.XmlEnvironment;
      -import org.jivesoftware.smack.util.Objects;
      -import org.jivesoftware.smack.util.XmlStringBuilder;
      -
      -public class ThumbnailElement implements ExtensionElement {
      -
      -    public static final String ELEMENT = "thumbnail";
      -    public static final String NAMESPACE = "urn:xmpp:thumbs:1";
      -    public static final String ELEM_URI = "uri";
      -    public static final String ELEM_MEDIA_TYPE = "media-type";
      -    public static final String ELEM_WIDTH = "width";
      -    public static final String ELEM_HEIGHT = "height";
      -
      -    private final String uri;
      -    private final String mediaType;
      -    private final Integer width;
      -    private final Integer height;
      -
      -    public ThumbnailElement(String uri) {
      -        this(uri, null, null, null);
      -    }
      -
      -    public ThumbnailElement(String uri, String mediaType, Integer width, Integer height) {
      -        this.uri = Objects.requireNonNull(uri);
      -        this.mediaType = mediaType;
      -
      -        if (width != null && width < 0) {
      -            throw new IllegalArgumentException("Width cannot be negative.");
      -        }
      -        this.width = width;
      -
      -        if (height != null && height < 0) {
      -            throw new IllegalArgumentException("Height cannot be negative.");
      -        }
      -        this.height = height;
      -    }
      -
      -    public String getUri() {
      -        return uri;
      -    }
      -
      -    public String getMediaType() {
      -        return mediaType;
      -    }
      -
      -    public Integer getWidth() {
      -        return width;
      -    }
      -
      -    public Integer getHeight() {
      -        return height;
      -    }
      -
      -    @Override
      -    public CharSequence toXML(XmlEnvironment xmlEnvironment) {
      -        XmlStringBuilder sb = new XmlStringBuilder(this, xmlEnvironment);
      -        return sb.attribute(ELEM_URI, uri)
      -                .optAttribute(ELEM_MEDIA_TYPE, mediaType)
      -                .optAttribute(ELEM_WIDTH, width)
      -                .optAttribute(ELEM_HEIGHT, height)
      -                .closeEmptyElement();
      -    }
      -
      -    @Override
      -    public String getElementName() {
      -        return ELEMENT;
      -    }
      -
      -    @Override
      -    public String getNamespace() {
      -        return NAMESPACE;
      -    }
      -}
      diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/thumbnails/element/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/thumbnails/element/package-info.java
      deleted file mode 100644
      index a13671247..000000000
      --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/thumbnails/element/package-info.java
      +++ /dev/null
      @@ -1,20 +0,0 @@
      -/**
      - *
      - * Copyright 2023 Paul Schaub
      - *
      - * 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.
      - */
      -/**
      - * Smacks implementation of XEP-0264: Jingle Content Thumbnails.
      - */
      -package org.jivesoftware.smackx.thumbnails.element;
      diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/thumbnails/provider/ThumbnailElementProvider.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/thumbnails/provider/ThumbnailElementProvider.java
      deleted file mode 100644
      index 6fc174002..000000000
      --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/thumbnails/provider/ThumbnailElementProvider.java
      +++ /dev/null
      @@ -1,46 +0,0 @@
      -/**
      - *
      - * Copyright 2023 Paul Schaub
      - *
      - * 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.smackx.thumbnails.provider;
      -
      -import java.io.IOException;
      -import java.text.ParseException;
      -
      -import org.jivesoftware.smack.packet.XmlEnvironment;
      -import org.jivesoftware.smack.parsing.SmackParsingException;
      -import org.jivesoftware.smack.provider.ExtensionElementProvider;
      -import org.jivesoftware.smack.util.ParserUtils;
      -import org.jivesoftware.smack.xml.XmlPullParser;
      -import org.jivesoftware.smack.xml.XmlPullParserException;
      -import org.jivesoftware.smackx.thumbnails.element.ThumbnailElement;
      -
      -public class ThumbnailElementProvider extends ExtensionElementProvider {
      -    @Override
      -    public ThumbnailElement parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment)
      -            throws XmlPullParserException, IOException, SmackParsingException, ParseException {
      -        String uri = parser.getAttributeValue(ThumbnailElement.ELEM_URI);
      -        String mediaType = parser.getAttributeValue(ThumbnailElement.ELEM_MEDIA_TYPE);
      -        Integer width = ParserUtils.getIntegerAttribute(parser, ThumbnailElement.ELEM_WIDTH);
      -        Integer height = ParserUtils.getIntegerAttribute(parser, ThumbnailElement.ELEM_HEIGHT);
      -
      -        return new ThumbnailElement(
      -                uri,
      -                mediaType,
      -                width,
      -                height
      -        );
      -    }
      -}
      diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/thumbnails/provider/package-info.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/thumbnails/provider/package-info.java
      deleted file mode 100644
      index 20816c2ce..000000000
      --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/thumbnails/provider/package-info.java
      +++ /dev/null
      @@ -1,20 +0,0 @@
      -/**
      - *
      - * Copyright 2023 Paul Schaub
      - *
      - * 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.
      - */
      -/**
      - * Smacks implementation of XEP-0264: Jingle Content Thumbnails.
      - */
      -package org.jivesoftware.smackx.thumbnails.provider;
      diff --git a/smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers b/smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers
      index 822bc5837..eb0c1a45f 100644
      --- a/smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers
      +++ b/smack-experimental/src/main/resources/org.jivesoftware.smack.experimental/experimental.providers
      @@ -2,13 +2,6 @@
       
       
       
      -    
      -    
      -        thumbnail
      -        urn:xmpp:thumbs:1
      -        org.jivesoftware.smackx.thumbnails.provider.ThumbnailElementProvider
      -    
      -
           
           
               sent
      @@ -352,13 +345,6 @@
             org.jivesoftware.smackx.fallback_indication.provider.FallbackIndicationElementProvider
           
       
      -    
      -    
      -      file
      -      urn:xmpp:file:metadata:0
      -      org.jivesoftware.smackx.file_metadata.provider.FileMetadataElementProvider
      -    
      -
           
           
               query
      diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/eme/ExplicitMessageEncryptionElementTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/eme/ExplicitMessageEncryptionElementTest.java
      index b9364b01f..dc14db131 100644
      --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/eme/ExplicitMessageEncryptionElementTest.java
      +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/eme/ExplicitMessageEncryptionElementTest.java
      @@ -39,7 +39,7 @@ public class ExplicitMessageEncryptionElementTest extends SmackTestSuite {
           public void addToMessageTest() {
               Message message = StanzaBuilder.buildMessage().build();
       
      -        // Check initial state (no elements)
      +        // Check inital state (no elements)
               assertNull(ExplicitMessageEncryptionElement.from(message));
               assertFalse(ExplicitMessageEncryptionElement.hasProtocol(message,
                       ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.omemoVAxolotl));
      @@ -75,7 +75,7 @@ public class ExplicitMessageEncryptionElementTest extends SmackTestSuite {
               assertTrue(ExplicitMessageEncryptionElement.hasProtocol(message,
                       ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.omemoVAxolotl));
       
      -        // Check, if adding additional OMEMO won't add another element
      +        // Check, if adding additional OMEMO wont add another element
               ExplicitMessageEncryptionElement.set(messageBuilder,
                       ExplicitMessageEncryptionElement.ExplicitMessageEncryptionProtocol.omemoVAxolotl);
       
      diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/file_metadata/FileMetadataElementTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/file_metadata/FileMetadataElementTest.java
      deleted file mode 100644
      index 229581308..000000000
      --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/file_metadata/FileMetadataElementTest.java
      +++ /dev/null
      @@ -1,190 +0,0 @@
      -/**
      - *
      - * Copyright 2020 Paul Schaub
      - *
      - * 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.smackx.file_metadata;
      -
      -import static org.jivesoftware.smack.test.util.XmlAssertUtil.assertXmlSimilar;
      -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.text.ParseException;
      -import java.util.Date;
      -
      -import org.jivesoftware.smack.test.util.SmackTestSuite;
      -import org.jivesoftware.smack.test.util.SmackTestUtil;
      -import org.jivesoftware.smackx.file_metadata.element.FileMetadataElement;
      -import org.jivesoftware.smackx.file_metadata.provider.FileMetadataElementProvider;
      -import org.jivesoftware.smackx.hashes.HashManager;
      -import org.jivesoftware.smackx.hashes.element.HashElement;
      -
      -import org.junit.jupiter.api.Test;
      -import org.junit.jupiter.params.ParameterizedTest;
      -import org.junit.jupiter.params.provider.EnumSource;
      -import org.jxmpp.util.XmppDateTime;
      -
      -public class FileMetadataElementTest extends SmackTestSuite {
      -
      -    private static final Date date;
      -    static {
      -        try {
      -            date = XmppDateTime.parseDate("2015-07-26T21:46:00+01:00");
      -        } catch (ParseException e) {
      -            throw new IllegalStateException(e);
      -        }
      -    }
      -
      -    private static final FileMetadataElement metadataElement = FileMetadataElement.builder()
      -                    .setModificationDate(date)
      -                    .setWidth(1920)
      -                    .setHeight(1080)
      -                    .addDescription("Picture of 24th XSF Summit")
      -                    .addDescription("Foto vom 24. XSF Summit", "de")
      -                    .addHash(new HashElement(HashManager.ALGORITHM.SHA_256, "2XarmwTlNxDAMkvymloX3S5+VbylNrJt/l5QyPa+YoU="))
      -                    .setLength(63000)
      -                    .setMediaType("text/plain")
      -                    .setName("text.txt")
      -                    .setSize(6144)
      -                    .build();
      -
      -    private static final String expectedXml = "" +
      -            "2015-07-26T20:46:00.000+00:00" +
      -            "1920" +
      -            "1080" +
      -            "Picture of 24th XSF Summit" +
      -            "Foto vom 24. XSF Summit" +
      -            "2XarmwTlNxDAMkvymloX3S5+VbylNrJt/l5QyPa+YoU=" +
      -            "63000" +
      -            "text/plain" +
      -            "text.txt" +
      -            "6144" +
      -            "";
      -
      -    private static final String expectedLegacyXml = "" +
      -            "2015-07-26T20:46:00.000+00:00" +
      -            "1920x1080" +
      -            "Picture of 24th XSF Summit" +
      -            "Foto vom 24. XSF Summit" +
      -            "2XarmwTlNxDAMkvymloX3S5+VbylNrJt/l5QyPa+YoU=" +
      -            "63000" +
      -            "text/plain" +
      -            "text.txt" +
      -            "6144" +
      -            "";
      -
      -    @Test
      -    public void testSerialization() {
      -        assertXmlSimilar(expectedXml, metadataElement.toXML().toString());
      -    }
      -
      -    @ParameterizedTest
      -    @EnumSource(SmackTestUtil.XmlPullParserKind.class)
      -    public void testParsing(SmackTestUtil.XmlPullParserKind parserKind) throws Exception {
      -        FileMetadataElement parsed = SmackTestUtil.parse(expectedXml, FileMetadataElementProvider.class, parserKind);
      -
      -        assertEquals(metadataElement, parsed);
      -    }
      -
      -    @ParameterizedTest
      -    @EnumSource(SmackTestUtil.XmlPullParserKind.class)
      -    public void testLegacyParsing(SmackTestUtil.XmlPullParserKind parserKind) throws Exception {
      -        FileMetadataElement parsed = SmackTestUtil.parse(expectedLegacyXml, FileMetadataElementProvider.class, parserKind);
      -
      -        assertEquals(metadataElement, parsed);
      -    }
      -
      -    @ParameterizedTest
      -    @EnumSource(SmackTestUtil.XmlPullParserKind.class)
      -    public void testParseUnknownExtension(SmackTestUtil.XmlPullParserKind parserKind) throws Exception {
      -        final String xml = "" +
      -                        "2015-07-26T20:46:00.000+00:00" +
      -                        "1920" +
      -                        "1080" +
      -                        "foo" +
      -                        "Picture of 24th XSF Summit" +
      -                        "Foto vom 24. XSF Summit" +
      -                        "2XarmwTlNxDAMkvymloX3S5+VbylNrJt/l5QyPa+YoU=" +
      -                        "63000" +
      -                        "text/plain" +
      -                        "text.txt" +
      -                        "6144" +
      -                        "";
      -
      -        FileMetadataElement parsed = SmackTestUtil.parse(xml, FileMetadataElementProvider.class, parserKind);
      -
      -        assertEquals(metadataElement, parsed);
      -    }
      -
      -    @Test
      -    public void nameIsEscaped() {
      -        FileMetadataElement e = FileMetadataElement.builder().setName("/etc/passwd").build();
      -        assertEquals("%2Fetc%2Fpasswd", e.getName());
      -    }
      -
      -    @Test
      -    public void rejectNegativeSize() {
      -        assertThrows(IllegalArgumentException.class, () -> FileMetadataElement.builder().setSize(-1));
      -    }
      -
      -    @Test
      -    public void rejectNegativeLength() {
      -        assertThrows(IllegalArgumentException.class, () -> FileMetadataElement.builder().setLength(-1));
      -    }
      -
      -    @Test
      -    public void rejectNegativeWidth() {
      -        assertThrows(IllegalArgumentException.class, () -> FileMetadataElement.builder().setWidth(-1));
      -    }
      -
      -    @Test
      -    public void rejectNegativeHeight() {
      -        assertThrows(IllegalArgumentException.class, () -> FileMetadataElement.builder().setHeight(-1));
      -    }
      -
      -    @Test
      -    public void rejectEmptyDescription() {
      -        assertThrows(IllegalArgumentException.class, () -> FileMetadataElement.builder().addDescription(""));
      -        assertThrows(IllegalArgumentException.class, () -> FileMetadataElement.builder().addDescription(null));
      -    }
      -
      -    @Test
      -    public void rejectEmptyNameElement() {
      -        assertThrows(IllegalArgumentException.class, () -> FileMetadataElement.builder().setName(""));
      -        assertThrows(IllegalArgumentException.class, () -> FileMetadataElement.builder().setName(null));
      -    }
      -
      -    @Test
      -    public void rejectEmptyMediaTypeElement() {
      -        assertThrows(IllegalArgumentException.class, () -> FileMetadataElement.builder().setMediaType(""));
      -        assertThrows(IllegalArgumentException.class, () -> FileMetadataElement.builder().setMediaType(null));
      -    }
      -
      -    @Test
      -    public void getDescTest() {
      -        FileMetadataElement metadataElement = FileMetadataElement.builder()
      -                .addDescription("Foo", "br")
      -                .addDescription("Baz")
      -                .addDescription("Bag", "en")
      -                .build();
      -
      -        assertEquals("Foo", metadataElement.getDescription("br"));
      -        assertEquals("Baz", metadataElement.getDescription(null));
      -        assertEquals("Baz", metadataElement.getDescription());
      -        assertEquals("Bag", metadataElement.getDescription("en"));
      -        assertNull(metadataElement.getDescription("null"));
      -        assertEquals(3, metadataElement.getDescriptions().size());
      -    }
      -}
      diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/FiltersTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/FiltersTest.java
      index df14ea279..b5c974dce 100644
      --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/FiltersTest.java
      +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/mam/FiltersTest.java
      @@ -1,6 +1,6 @@
       /**
        *
      - * Copyright 2016 Fernando Ramirez, 2018-2024 Florian Schmaus
      + * Copyright 2016 Fernando Ramirez, 2018-2020 Florian Schmaus
        *
        * Licensed under the Apache License, Version 2.0 (the "License");
        * you may not use this file except in compliance with the License.
      @@ -46,7 +46,6 @@ public class FiltersTest extends MamTest {
               return xml;
           }
       
      -    @SuppressWarnings("JavaUtilDate")
           @Test
           public void checkStartDateFilter() throws Exception {
               Date date = new Date();
      @@ -62,7 +61,6 @@ public class FiltersTest extends MamTest {
               assertEquals(getMamXMemberWith(fields, values), dataForm.toXML().toString());
           }
       
      -    @SuppressWarnings("JavaUtilDate")
           @Test
           public void checkEndDateFilter() throws Exception {
               Date date = new Date();
      diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightAffiliationsChangeExtensionTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightAffiliationsChangeExtensionTest.java
      index ab9e53750..a07577748 100644
      --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightAffiliationsChangeExtensionTest.java
      +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightAffiliationsChangeExtensionTest.java
      @@ -18,7 +18,7 @@ package org.jivesoftware.smackx.muclight;
       
       import static org.junit.jupiter.api.Assertions.assertEquals;
       
      -import java.util.Map;
      +import java.util.HashMap;
       
       import org.jivesoftware.smack.packet.Message;
       import org.jivesoftware.smack.util.PacketParserUtils;
      @@ -55,7 +55,7 @@ public class MUCLightAffiliationsChangeExtensionTest {
               AffiliationsChangeExtension affiliationsChangeExtension = AffiliationsChangeExtension
                       .from(changeAffiliationsMessage);
       
      -        Map affiliations = affiliationsChangeExtension.getAffiliations();
      +        HashMap affiliations = affiliationsChangeExtension.getAffiliations();
               assertEquals(affiliations.size(), 3);
               assertEquals(affiliations.get(JidCreate.from("sarasa2@shakespeare.lit")), MUCLightAffiliation.owner);
               assertEquals(affiliations.get(JidCreate.from("sarasa1@shakespeare.lit")), MUCLightAffiliation.member);
      @@ -68,7 +68,7 @@ public class MUCLightAffiliationsChangeExtensionTest {
               AffiliationsChangeExtension affiliationsChangeExtension = AffiliationsChangeExtension
                       .from(changeAffiliationsMessage);
       
      -        Map affiliations = affiliationsChangeExtension.getAffiliations();
      +        HashMap affiliations = affiliationsChangeExtension.getAffiliations();
               assertEquals(affiliations.size(), 2);
               assertEquals(affiliations.get(JidCreate.from("sarasa1@shakespeare.lit")), MUCLightAffiliation.member);
               assertEquals(affiliations.get(JidCreate.from("sarasa3@shakespeare.lit")), MUCLightAffiliation.none);
      @@ -83,7 +83,7 @@ public class MUCLightAffiliationsChangeExtensionTest {
               AffiliationsChangeExtension affiliationsChangeExtension = AffiliationsChangeExtension
                       .from(changeAffiliationsMessage);
       
      -        Map affiliations = affiliationsChangeExtension.getAffiliations();
      +        HashMap affiliations = affiliationsChangeExtension.getAffiliations();
               assertEquals(affiliations.size(), 2);
               assertEquals(affiliations.get(JidCreate.from("sarasa2@shakespeare.lit")), MUCLightAffiliation.owner);
               assertEquals(affiliations.get(JidCreate.from("sarasa1@shakespeare.lit")), MUCLightAffiliation.member);
      diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightChangeAffiliationsIQTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightChangeAffiliationsIQTest.java
      index ca0e1e4cb..efbb22da7 100644
      --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightChangeAffiliationsIQTest.java
      +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightChangeAffiliationsIQTest.java
      @@ -19,7 +19,6 @@ package org.jivesoftware.smackx.muclight;
       import static org.junit.jupiter.api.Assertions.assertEquals;
       
       import java.util.HashMap;
      -import java.util.Map;
       
       import org.jivesoftware.smack.packet.IQ;
       
      @@ -33,7 +32,7 @@ public class MUCLightChangeAffiliationsIQTest {
       
           @Test
           public void checkChangeAffiliationsMUCLightStanza() throws Exception {
      -        Map affiliations = new HashMap<>();
      +        HashMap affiliations = new HashMap<>();
               affiliations.put(JidCreate.from("sarasa2@shakespeare.lit"), MUCLightAffiliation.owner);
               affiliations.put(JidCreate.from("sarasa1@shakespeare.lit"), MUCLightAffiliation.member);
               affiliations.put(JidCreate.from("sarasa3@shakespeare.lit"), MUCLightAffiliation.none);
      @@ -45,7 +44,7 @@ public class MUCLightChangeAffiliationsIQTest {
               assertEquals(mucLightChangeAffiliationsIQ.getTo(), "coven@muclight.shakespeare.lit");
               assertEquals(mucLightChangeAffiliationsIQ.getType(), IQ.Type.set);
       
      -        Map iqAffiliations = mucLightChangeAffiliationsIQ.getAffiliations();
      +        HashMap iqAffiliations = mucLightChangeAffiliationsIQ.getAffiliations();
               assertEquals(iqAffiliations.get(JidCreate.from("sarasa1@shakespeare.lit")), MUCLightAffiliation.member);
               assertEquals(iqAffiliations.get(JidCreate.from("sarasa2@shakespeare.lit")), MUCLightAffiliation.owner);
               assertEquals(iqAffiliations.get(JidCreate.from("sarasa3@shakespeare.lit")), MUCLightAffiliation.none);
      diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightCreateIQTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightCreateIQTest.java
      index 4a92da24e..216a2a494 100644
      --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightCreateIQTest.java
      +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightCreateIQTest.java
      @@ -19,8 +19,8 @@ package org.jivesoftware.smackx.muclight;
       import static org.junit.jupiter.api.Assertions.assertEquals;
       
       import java.util.ArrayList;
      +import java.util.HashMap;
       import java.util.List;
      -import java.util.Map;
       
       import org.jivesoftware.smackx.muclight.element.MUCLightCreateIQ;
       
      @@ -43,7 +43,7 @@ public class MUCLightCreateIQTest {
       
               assertEquals(mucLightCreateIQ.getConfiguration().getRoomName(), "test");
       
      -        Map iqOccupants = mucLightCreateIQ.getOccupants();
      +        HashMap iqOccupants = mucLightCreateIQ.getOccupants();
               assertEquals(iqOccupants.get(JidCreate.from("charlie@test.com")), MUCLightAffiliation.member);
               assertEquals(iqOccupants.get(JidCreate.from("pep@test.com")), MUCLightAffiliation.member);
           }
      diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightGetAffiliationsTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightGetAffiliationsTest.java
      index 5504468ef..782171ae1 100644
      --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightGetAffiliationsTest.java
      +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightGetAffiliationsTest.java
      @@ -18,7 +18,7 @@ package org.jivesoftware.smackx.muclight;
       
       import static org.junit.jupiter.api.Assertions.assertEquals;
       
      -import java.util.Map;
      +import java.util.HashMap;
       
       import org.jivesoftware.smack.packet.IQ;
       import org.jivesoftware.smack.packet.StreamOpen;
      @@ -57,7 +57,7 @@ public class MUCLightGetAffiliationsTest {
       
               assertEquals("123456", mucLightAffiliationsIQ.getVersion());
       
      -        Map affiliations = mucLightAffiliationsIQ.getAffiliations();
      +        HashMap affiliations = mucLightAffiliationsIQ.getAffiliations();
               assertEquals(3, affiliations.size());
               assertEquals(MUCLightAffiliation.owner, affiliations.get(JidCreate.from("user1@shakespeare.lit")));
               assertEquals(MUCLightAffiliation.member, affiliations.get(JidCreate.from("user2@shakespeare.lit")));
      diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightGetConfigsTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightGetConfigsTest.java
      index 02826d8d1..8c295ab0e 100644
      --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightGetConfigsTest.java
      +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/muclight/MUCLightGetConfigsTest.java
      @@ -19,7 +19,7 @@ package org.jivesoftware.smackx.muclight;
       import static org.junit.jupiter.api.Assertions.assertEquals;
       import static org.junit.jupiter.api.Assertions.assertNull;
       
      -import java.util.Map;
      +import java.util.HashMap;
       
       import org.jivesoftware.smack.packet.IQ;
       import org.jivesoftware.smack.packet.StreamOpen;
      @@ -74,7 +74,7 @@ public class MUCLightGetConfigsTest {
               assertEquals("A Dark Cave", mucLightConfigurationIQ.getConfiguration().getRoomName());
               assertNull(mucLightConfigurationIQ.getConfiguration().getSubject());
       
      -        Map customConfigs = mucLightConfigurationIQ.getConfiguration().getCustomConfigs();
      +        HashMap customConfigs = mucLightConfigurationIQ.getConfiguration().getCustomConfigs();
               assertEquals("blue", customConfigs.get("color"));
               assertEquals("20", customConfigs.get("size"));
           }
      diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/thumbnails/element/ThumbnailElementTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/thumbnails/element/ThumbnailElementTest.java
      deleted file mode 100644
      index 87d03bbb6..000000000
      --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/thumbnails/element/ThumbnailElementTest.java
      +++ /dev/null
      @@ -1,56 +0,0 @@
      -/**
      - *
      - * Copyright 2023 Paul Schaub
      - *
      - * 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.smackx.thumbnails.element;
      -
      -import static org.jivesoftware.smack.test.util.XmlAssertUtil.assertXmlSimilar;
      -import static org.junit.jupiter.api.Assertions.assertThrows;
      -
      -import org.junit.jupiter.api.Test;
      -
      -public class ThumbnailElementTest {
      -
      -    @Test
      -    public void uriIsRequired() {
      -        assertThrows(IllegalArgumentException.class, () -> new ThumbnailElement(null));
      -        assertThrows(IllegalArgumentException.class, () -> new ThumbnailElement(null, "image/png", 128, 128));
      -    }
      -
      -    @Test
      -    public void testMinimal() {
      -        ThumbnailElement minimal = new ThumbnailElement("cid:sha1+ffd7c8d28e9c5e82afea41f97108c6b4@bob.xmpp.org");
      -
      -        assertXmlSimilar("",
      -                minimal.toXML());
      -    }
      -
      -    @Test
      -    public void testFull() {
      -        ThumbnailElement full = new ThumbnailElement(
      -                "cid:sha1+ffd7c8d28e9c5e82afea41f97108c6b4@bob.xmpp.org",
      -                "image/png",
      -                128,
      -                96);
      -
      -        assertXmlSimilar("",
      -                full.toXML());
      -    }
      -}
      diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/thumbnails/provider/ThumbnailElementProviderTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/thumbnails/provider/ThumbnailElementProviderTest.java
      deleted file mode 100644
      index dbaec7c9a..000000000
      --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/thumbnails/provider/ThumbnailElementProviderTest.java
      +++ /dev/null
      @@ -1,64 +0,0 @@
      -/**
      - *
      - * Copyright 2023 Paul Schaub
      - *
      - * 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.smackx.thumbnails.provider;
      -
      -import static org.junit.jupiter.api.Assertions.assertEquals;
      -import static org.junit.jupiter.api.Assertions.assertNull;
      -
      -import java.io.IOException;
      -
      -import org.jivesoftware.smack.parsing.SmackParsingException;
      -import org.jivesoftware.smack.test.util.SmackTestUtil;
      -import org.jivesoftware.smack.xml.XmlPullParserException;
      -import org.jivesoftware.smackx.thumbnails.element.ThumbnailElement;
      -
      -import org.junit.jupiter.params.ParameterizedTest;
      -import org.junit.jupiter.params.provider.EnumSource;
      -
      -public class ThumbnailElementProviderTest {
      -
      -    @ParameterizedTest
      -    @EnumSource(SmackTestUtil.XmlPullParserKind.class)
      -    public void testParseFull(SmackTestUtil.XmlPullParserKind parserKind) throws XmlPullParserException, IOException, SmackParsingException {
      -        String xml = "";
      -
      -        ThumbnailElement element = SmackTestUtil.parse(xml, ThumbnailElementProvider.class, parserKind);
      -
      -        assertEquals("cid:sha1+ffd7c8d28e9c5e82afea41f97108c6b4@bob.xmpp.org", element.getUri());
      -        assertEquals("image/png", element.getMediaType());
      -        assertEquals(128, element.getWidth());
      -        assertEquals(96, element.getHeight());
      -    }
      -
      -    @ParameterizedTest
      -    @EnumSource(SmackTestUtil.XmlPullParserKind.class)
      -    public void testParseMinimal(SmackTestUtil.XmlPullParserKind parserKind) throws XmlPullParserException, IOException, SmackParsingException {
      -        String xml = "";
      -
      -        ThumbnailElement element = SmackTestUtil.parse(xml, ThumbnailElementProvider.class, parserKind);
      -
      -        assertEquals("cid:sha1+ffd7c8d28e9c5e82afea41f97108c6b4@bob.xmpp.org", element.getUri());
      -        assertNull(element.getMediaType());
      -        assertNull(element.getWidth());
      -        assertNull(element.getHeight());
      -    }
      -}
      diff --git a/smack-extensions/build.gradle b/smack-extensions/build.gradle
      index 0b62da32c..2489c9f87 100644
      --- a/smack-extensions/build.gradle
      +++ b/smack-extensions/build.gradle
      @@ -1,8 +1,3 @@
      -plugins {
      -	id 'org.igniterealtime.smack.java-common-conventions'
      -	id 'org.igniterealtime.smack.android-conventions'
      -}
      -
       description = """\
       Smack extensions.
       Classes and methods that implement support for the various XMPP XEPs
      diff --git a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/FileTransferTest.java b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/FileTransferTest.java
      index fc9c6d933..b3ecc362a 100644
      --- a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/FileTransferTest.java
      +++ b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/FileTransferTest.java
      @@ -109,7 +109,7 @@ public class FileTransferTest extends SmackTestCase {
                   fail();
               }
               byte [] array = queue.take();
      -        assertEquals("Received file not equal to sent file.", testTransfer, array);
      +        assertEquals("Recieved file not equal to sent file.", testTransfer, array);
           }
       
       
      diff --git a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/OfflineMessageManagerTest.java b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/OfflineMessageManagerTest.java
      index 5efb0799a..13d4bd23c 100644
      --- a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/OfflineMessageManagerTest.java
      +++ b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/OfflineMessageManagerTest.java
      @@ -50,7 +50,7 @@ public class OfflineMessageManagerTest extends SmackTestCase {
           /**
            * While user2 is connected but unavailable, user1 sends 2 messages to user1. User2 then
            * performs some "Flexible Offline Message Retrieval" checking the number of offline messages,
      -     * retrieving the headers, then the real messages of the headers and finally removing the
      +     * retriving the headers, then the real messages of the headers and finally removing the
            * loaded messages.
            */
           public void testReadAndDelete() {
      diff --git a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/ServiceDiscoveryManagerTest.java b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/ServiceDiscoveryManagerTest.java
      index 71ba8d7d2..5d56d85ba 100644
      --- a/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/ServiceDiscoveryManagerTest.java
      +++ b/smack-extensions/src/integration-test/java/org/jivesoftware/smackx/ServiceDiscoveryManagerTest.java
      @@ -90,7 +90,7 @@ public class ServiceDiscoveryManagerTest extends SmackTestCase {
            */
           public void testXHTMLFeature() {
               // Check for local XHTML service support
      -        // By default,the XHTML service support is enabled in all the connections
      +        // By default the XHTML service support is enabled in all the connections
               assertTrue(XHTMLManager.isServiceEnabled(getConnection(0)));
               assertTrue(XHTMLManager.isServiceEnabled(getConnection(1)));
               // Check for XHTML support in connection1 from connection2
      diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/address/packet/MultipleAddresses.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/address/packet/MultipleAddresses.java
      index 6f9e63e81..fba5979ce 100644
      --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/address/packet/MultipleAddresses.java
      +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/address/packet/MultipleAddresses.java
      @@ -93,7 +93,7 @@ public class MultipleAddresses implements ExtensionElement {
       
           /**
            * Returns the list of addresses that matches the specified type. Examples of address
      -     * type are: TO, CC, BCC, etc.
      +     * type are: TO, CC, BCC, etc..
            *
            * @param type Examples of address type are: TO, CC, BCC, etc.
            * @return the list of addresses that matches the specified type.
      diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/admin/ServiceAdministrationManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/admin/ServiceAdministrationManager.java
      index 9956533f7..78ce687a6 100644
      --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/admin/ServiceAdministrationManager.java
      +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/admin/ServiceAdministrationManager.java
      @@ -1,6 +1,6 @@
       /**
        *
      - * Copyright 2016-2023 Florian Schmaus
      + * Copyright 2016-2020 Florian Schmaus
        *
        * Licensed under the Apache License, Version 2.0 (the "License");
        * you may not use this file except in compliance with the License.
      @@ -27,9 +27,8 @@ import org.jivesoftware.smack.SmackException.NotConnectedException;
       import org.jivesoftware.smack.XMPPConnection;
       import org.jivesoftware.smack.XMPPException.XMPPErrorException;
       
      -import org.jivesoftware.smackx.commands.AdHocCommand;
       import org.jivesoftware.smackx.commands.AdHocCommandManager;
      -import org.jivesoftware.smackx.commands.AdHocCommandResult;
      +import org.jivesoftware.smackx.commands.RemoteCommand;
       import org.jivesoftware.smackx.xdata.form.FillableForm;
       
       import org.jxmpp.jid.EntityBareJid;
      @@ -57,38 +56,37 @@ public class ServiceAdministrationManager extends Manager {
           public ServiceAdministrationManager(XMPPConnection connection) {
               super(connection);
       
      -        adHocCommandManager = AdHocCommandManager.getInstance(connection);
      +        adHocCommandManager = AdHocCommandManager.getAddHocCommandsManager(connection);
           }
       
      -    public AdHocCommand addUser() {
      +    public RemoteCommand addUser() {
               return addUser(connection().getXMPPServiceDomain());
           }
       
      -    public AdHocCommand addUser(Jid service) {
      +    public RemoteCommand addUser(Jid service) {
               return adHocCommandManager.getRemoteCommand(service, COMMAND_NODE_HASHSIGN + "add-user");
           }
       
           public void addUser(final EntityBareJid userJid, final String password)
                           throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
      -        AdHocCommand command = addUser();
      +        RemoteCommand command = addUser();
      +        command.execute();
       
      -        AdHocCommandResult.StatusExecuting commandExecutingResult = command.execute().asExecutingOrThrow();
      -
      -        FillableForm answerForm = commandExecutingResult.getFillableForm();
      +        FillableForm answerForm = new FillableForm(command.getForm());
       
               answerForm.setAnswer("accountjid", userJid);
               answerForm.setAnswer("password", password);
               answerForm.setAnswer("password-verify", password);
       
      -        AdHocCommandResult result = command.execute(answerForm);
      -        assert result.isCompleted();
      +        command.execute(answerForm);
      +        assert command.isCompleted();
           }
       
      -    public AdHocCommand deleteUser() {
      +    public RemoteCommand deleteUser() {
               return deleteUser(connection().getXMPPServiceDomain());
           }
       
      -    public AdHocCommand deleteUser(Jid service) {
      +    public RemoteCommand deleteUser(Jid service) {
               return adHocCommandManager.getRemoteCommand(service, COMMAND_NODE_HASHSIGN + "delete-user");
           }
       
      @@ -100,14 +98,14 @@ public class ServiceAdministrationManager extends Manager {
       
           public void deleteUser(Set jidsToDelete)
                           throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
      -        AdHocCommand command = deleteUser();
      -        AdHocCommandResult.StatusExecuting commandExecutingResult = command.execute().asExecutingOrThrow();
      +        RemoteCommand command = deleteUser();
      +        command.execute();
       
      -        FillableForm answerForm = commandExecutingResult.getFillableForm();
      +        FillableForm answerForm = new FillableForm(command.getForm());
       
               answerForm.setAnswer("accountjids", jidsToDelete);
       
      -        AdHocCommandResult result = command.execute(answerForm);
      -        assert result.isCompleted();
      +        command.execute(answerForm);
      +        assert command.isCompleted();
           }
       }
      diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/blocking/BlockingCommandManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/blocking/BlockingCommandManager.java
      index 330cfbc8c..6769c9f5b 100644
      --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/blocking/BlockingCommandManager.java
      +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/blocking/BlockingCommandManager.java
      @@ -44,13 +44,13 @@ import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
       import org.jxmpp.jid.Jid;
       
       /**
      - * Block communications with contacts and other entities using XEP-0191.
      + * Block communications with contancts and other entities using XEP-0191.
        * Allows to
        * 
        *
      • Check push notifications support
      • *
      • Get blocking list
      • *
      • Block contact
      • - *
      • Unblock contact
      • + *
      • Unblock conact
      • *
      • Unblock all
      • *
      * diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/blocking/element/BlockContactsIQ.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/blocking/element/BlockContactsIQ.java index 79bd2068a..39cb9525b 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/blocking/element/BlockContactsIQ.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/blocking/element/BlockContactsIQ.java @@ -51,7 +51,6 @@ public class BlockContactsIQ extends IQ { * * @param jids TODO javadoc me please */ - @SuppressWarnings("this-escape") public BlockContactsIQ(List jids) { super(ELEMENT, NAMESPACE); this.setType(Type.set); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/blocking/element/UnblockContactsIQ.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/blocking/element/UnblockContactsIQ.java index efba53e3a..e0a28f722 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/blocking/element/UnblockContactsIQ.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/blocking/element/UnblockContactsIQ.java @@ -52,7 +52,6 @@ public class UnblockContactsIQ extends IQ { * * @param jids TODO javadoc me please */ - @SuppressWarnings("this-escape") public UnblockContactsIQ(List jids) { super(ELEMENT, NAMESPACE); this.setType(Type.set); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bob/element/BoBIQ.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bob/element/BoBIQ.java index 2790e3860..085df5fd5 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bob/element/BoBIQ.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bob/element/BoBIQ.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016 Fernando Ramirez, 2020-2024 Florian Schmaus + * Copyright 2016 Fernando Ramirez, 2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -65,6 +65,18 @@ public class BoBIQ extends IQ { this(cid, null); } + /** + * Get the BoB hash. + * + * @return the BoB hash + * @deprecated use {@link #getContentId()} instead. + */ + // TODO: Remove in Smack 4.5. + @Deprecated + public ContentId getBoBHash() { + return cid; + } + /** * Get the BoB hash. * diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bookmarks/BookmarkManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bookmarks/BookmarkManager.java index 9d00ec626..fe8323953 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bookmarks/BookmarkManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bookmarks/BookmarkManager.java @@ -103,7 +103,7 @@ public final class BookmarkManager { * * @param name the name of the conference * @param jid the jid of the conference - * @param isAutoJoin whether to join this conference automatically on login + * @param isAutoJoin whether or not to join this conference automatically on login * @param nickname the nickname to use for the user when joining the conference * @param password the password to use for the user when joining the conference * @throws XMPPErrorException thrown when there is an issue retrieving the current bookmarks from @@ -166,7 +166,7 @@ public final class BookmarkManager { * Returns an unmodifiable collection of all bookmarked urls. * * @return returns an unmodifiable collection of all bookmarked urls. - * @throws XMPPErrorException thrown when there is a problem retrieving bookmarks from the server. + * @throws XMPPErrorException thrown when there is a problem retriving bookmarks from the server. * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. @@ -181,8 +181,8 @@ public final class BookmarkManager { * * @param URL the url of the bookmark * @param name the name of the bookmark - * @param isRSS whether the url is an RSS feed - * @throws XMPPErrorException thrown when there is an error retrieving or saving bookmarks from or to + * @param isRSS whether or not the url is an rss feed + * @throws XMPPErrorException thrown when there is an error retriving or saving bookmarks from or to * the server * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException if the XMPP connection is not connected. @@ -210,7 +210,7 @@ public final class BookmarkManager { * Removes a url from the bookmarks. * * @param bookmarkURL the url of the bookmark to remove - * @throws XMPPErrorException thrown if there is an error retrieving or saving bookmarks from or to + * @throws XMPPErrorException thrown if there is an error retriving or saving bookmarks from or to * the server. * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException if the XMPP connection is not connected. diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamManager.java index e527d416a..9061a5606 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamManager.java @@ -16,8 +16,8 @@ */ package org.jivesoftware.smackx.bytestreams.ibb; -import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.WeakHashMap; @@ -135,7 +135,7 @@ public final class InBandBytestreamManager extends Manager implements Bytestream * list of listeners that respond to all In-Band Bytestream requests if there are no user * specific listeners for that request */ - private final List allRequestListeners = Collections.synchronizedList(new ArrayList()); + private final List allRequestListeners = Collections.synchronizedList(new LinkedList()); /* listener that handles all incoming In-Band Bytestream requests */ private final InitiationListener initiationListener; @@ -162,7 +162,7 @@ public final class InBandBytestreamManager extends Manager implements Bytestream * list containing session IDs of In-Band Bytestream open packets that should be ignored by the * InitiationListener */ - private final List ignoredBytestreamRequests = Collections.synchronizedList(new ArrayList()); + private final List ignoredBytestreamRequests = Collections.synchronizedList(new LinkedList()); /** * Returns the InBandBytestreamManager to handle In-Band Bytestreams for a given @@ -511,7 +511,7 @@ public final class InBandBytestreamManager extends Manager implements Bytestream } /** - * Returns the list of session IDs that should be ignored by the InitiationListener + * Returns the list of session IDs that should be ignored by the InitialtionListener * * @return list of session IDs */ diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Close.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Close.java index 9147cdd72..cdd002590 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Close.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Close.java @@ -36,7 +36,6 @@ public class Close extends IQ { * * @param sessionID unique session ID identifying this In-Band Bytestream */ - @SuppressWarnings("this-escape") public Close(String sessionID) { super(ELEMENT, NAMESPACE); if (sessionID == null || "".equals(sessionID)) { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Data.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Data.java index 77ceb9450..54bbaeb80 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Data.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Data.java @@ -34,7 +34,6 @@ public class Data extends IQ { * * @param data data stanza extension containing the encoded data */ - @SuppressWarnings("this-escape") public Data(DataPacketExtension data) { super(DataPacketExtension.ELEMENT, DataPacketExtension.NAMESPACE); if (data == null) { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Open.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Open.java index a2e54bdaf..768cf3f20 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Open.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Open.java @@ -54,7 +54,6 @@ public class Open extends IQ { * @param blockSize block size in which the data will be fragmented * @param stanza stanza type used to encapsulate the data */ - @SuppressWarnings("this-escape") public Open(String sessionID, int blockSize, StanzaType stanza) { super(ELEMENT, NAMESPACE); if (sessionID == null || "".equals(sessionID)) { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java index fac036a1d..673f7a989 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5BytestreamManager.java @@ -22,6 +22,7 @@ import java.net.Socket; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -127,7 +128,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream * list of listeners that respond to all bytestream requests if there are not user specific * listeners for that request */ - private final List allRequestListeners = Collections.synchronizedList(new ArrayList()); + private final List allRequestListeners = Collections.synchronizedList(new LinkedList()); /* listener that handles all incoming bytestream requests */ private final InitiationListener initiationListener; @@ -138,7 +139,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream /* timeout for connecting to the SOCKS5 proxy selected by the target */ private int proxyConnectionTimeout = 10000; - /* blacklist of erroneous SOCKS5 proxies */ + /* blacklist of errornous SOCKS5 proxies */ private final Set proxyBlacklist = Collections.synchronizedSet(new HashSet()); /* remember the last proxy that worked to prioritize it */ @@ -153,7 +154,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream * list containing session IDs of SOCKS5 Bytestream initialization packets that should be * ignored by the InitiationListener */ - private final List ignoredBytestreamRequests = Collections.synchronizedList(new ArrayList()); + private final List ignoredBytestreamRequests = Collections.synchronizedList(new LinkedList()); /** * Returns the Socks5BytestreamManager to handle SOCKS5 Bytestreams for a given @@ -389,7 +390,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream } /** - * Set whether the bytestream manager will announce the local stream host(s), i.e. the local SOCKS5 proxy. + * Set whether or not the bytestream manager will annouce the local stream host(s), i.e. the local SOCKS5 proxy. * * @param announceLocalStreamHost TODO javadoc me please * @see #isAnnouncingLocalStreamHostEnabled() @@ -579,7 +580,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream proxyInfo = serviceDiscoveryManager.discoverInfo(item.getEntityID()); } catch (NoResponseException | XMPPErrorException e) { - // blacklist erroneous server + // blacklist errornous server proxyBlacklist.add(item.getEntityID()); continue; } @@ -626,7 +627,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream streamHosts.addAll(response.getStreamHosts()); } catch (Exception e) { - // blacklist erroneous proxies + // blacklist errornous proxies this.proxyBlacklist.add(proxy); } } @@ -795,7 +796,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream } /** - * Returns the list of session IDs that should be ignored by the InitiationListener + * Returns the list of session IDs that should be ignored by the InitialtionListener * * @return list of session IDs */ diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Client.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Client.java index e4444c6ac..7f80e8260 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Client.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Client.java @@ -138,7 +138,7 @@ public class Socks5Client { byte[] connectionRequest; byte[] connectionResponse; /* - * use DataInputStream/DataOutputStream to assure read and write is completed in a single + * use DataInputStream/DataOutpuStream to assure read and write is completed in a single * statement */ DataInputStream in = new DataInputStream(socket.getInputStream()); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java index 117333095..88e7abfe2 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5Proxy.java @@ -26,12 +26,12 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.HashSet; import java.util.LinkedHashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -107,7 +107,7 @@ public class Socks5Proxy { private final Map connectionMap = new ConcurrentHashMap<>(); /* list of digests connections should be stored */ - private final List allowedConnections = Collections.synchronizedList(new ArrayList()); + private final List allowedConnections = Collections.synchronizedList(new LinkedList()); private final Set localAddresses = new LinkedHashSet<>(4); @@ -149,7 +149,6 @@ public class Socks5Proxy { * * @param serverSocket the server socket to use */ - @SuppressWarnings("this-escape") protected Socks5Proxy(ServerSocket serverSocket) { this.serverProcess = new Socks5ServerProcess(); this.serverSocket = serverSocket; @@ -346,7 +345,7 @@ public class Socks5Proxy { */ public List getLocalAddresses() { synchronized (localAddresses) { - return new ArrayList<>(localAddresses); + return new LinkedList<>(localAddresses); } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/packet/Bytestream.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/packet/Bytestream.java index bc049a034..f050db26e 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/packet/Bytestream.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/packet/Bytestream.java @@ -68,7 +68,6 @@ public class Bytestream extends IQ { * @param SID The session ID related to the negotiation. * @see #setSessionID(String) */ - @SuppressWarnings("this-escape") public Bytestream(final String SID) { this(); setSessionID(SID); @@ -299,7 +298,7 @@ public class Bytestream extends IQ { * @param port port of the stream host. */ public StreamHost(final Jid jid, final String address, int port) { - this(jid, InternetAddress.fromIgnoringZoneId(address), port); + this(jid, InternetAddress.from(address), port); } public StreamHost(Jid jid, InetAddress address, int port) { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java index aaa87e2b0..c549a152b 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2009 Jonas Ådahl, 2011-2024 Florian Schmaus + * Copyright © 2009 Jonas Ådahl, 2011-2022 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,12 +19,11 @@ package org.jivesoftware.smackx.caps; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; @@ -91,7 +90,7 @@ import org.jxmpp.util.cache.LruCache; * but XEP-0030 then XEP-0030 mechanisms are transparently used. *

      *

      - * The caches used by Smack for Entity Capabilities is non-persistent per default. However, it is is also possible to set + * The caches used by Smack for Entity Capabilities is non-persisent per default. However, it is is also possible to set * a persistent Entity Capabilities cache, which is recommended. *

      *

      Examples

      @@ -226,7 +225,7 @@ public final class EntityCapsManager extends Manager { /** * Get the Node version (node#ver) of a JID. Returns a String or null if - * EntityCapsManager does not have any information. + * EntiyCapsManager does not have any information. * * @param jid TODO javadoc me please * the user (Full JID) @@ -389,10 +388,7 @@ public final class EntityCapsManager extends Manager { if (autoEnableEntityCaps) enableEntityCaps(); - // Note that this is a *synchronous* stanza listener to avoid unnecessary feature lookups. If this were to be an - // asynchronous listener, then it would be possible that the entity caps information was not processed when the - // features of entity are looked up. See SMACK-937. - connection.addStanzaListener(new StanzaListener() { + connection.addAsyncStanzaListener(new StanzaListener() { // Listen for remote presence stanzas with the caps extension // If we receive such a stanza, record the JID and nodeVer @Override @@ -555,7 +551,7 @@ public final class EntityCapsManager extends Manager { if (connection != null) JID_TO_NODEVER_CACHE.put(connection.getUser(), new NodeVerHash(entityNode, currentCapsVersion)); - final List identities = new ArrayList<>(ServiceDiscoveryManager.getInstanceFor(connection).getIdentities()); + final List identities = new LinkedList<>(ServiceDiscoveryManager.getInstanceFor(connection).getIdentities()); sdm.setNodeInformationProvider(localNodeVer, new AbstractNodeInformationProvider() { List features = sdm.getFeatures(); List packetExtensions = sdm.getExtendedInfo(); @@ -702,30 +698,16 @@ public final class EntityCapsManager extends Manager { } List extendedInfos = discoverInfo.getExtensions(DataForm.class); - final Iterator iter = extendedInfos.iterator(); - while (iter.hasNext()) { - if (!iter.next().hasHiddenFormTypeField()) { + for (DataForm extendedInfo : extendedInfos) { + if (!extendedInfo.hasHiddenFormTypeField()) { // Only use the data form for calculation is it has a hidden FORM_TYPE field. // See XEP-0115 5.4 step 3.f - iter.remove(); + continue; } - } - // 6. If the service discovery information response includes - // XEP-0128 data forms, sort the forms by the FORM_TYPE (i.e., - // by the XML character data of the element). - Collections.sort(extendedInfos, new Comparator() { - @Override - public int compare(DataForm dataFormLeft, DataForm dataFormRight) { - final String formTypeLeft = dataFormLeft.getFormType(); - assert formTypeLeft != null; // ensured by the previous step. - final String formTypeRight = dataFormRight.getFormType(); - assert formTypeRight != null; // ensured by the previous step. - return formTypeLeft.compareTo(formTypeRight); - } - }); - - for (DataForm extendedInfo : extendedInfos) { + // 6. If the service discovery information response includes + // XEP-0128 data forms, sort the forms by the FORM_TYPE (i.e., + // by the XML character data of the element). SortedSet fs = new TreeSet<>(new Comparator() { @Override public int compare(FormField f1, FormField f2) { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AbstractAdHocCommand.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AbstractAdHocCommand.java deleted file mode 100755 index 8a12b29f3..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AbstractAdHocCommand.java +++ /dev/null @@ -1,277 +0,0 @@ -/** - * - * Copyright 2005-2007 Jive Software. - * - * 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.smackx.commands; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import org.jivesoftware.smack.SmackException.NoResponseException; -import org.jivesoftware.smack.SmackException.NotConnectedException; -import org.jivesoftware.smack.XMPPException.XMPPErrorException; -import org.jivesoftware.smack.packet.StanzaError; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData.Action; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData.AllowedAction; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData.Status; - -/** - * An ad-hoc command is responsible for executing the provided service and - * storing the result of the execution. Each new request will create a new - * instance of the command, allowing information related to executions to be - * stored in it. For example suppose that a command that retrieves the list of - * users on a server is implemented. When the command is executed it gets that - * list and the result is stored as a form in the command instance, i.e. the - * getForm method retrieves a form with all the users. - *

      - * Each command has a node that should be unique within a given JID. - *

      - *

      - * Commands may have zero or more stages. Each stage is usually used for - * gathering information required for the command execution. Users are able to - * move forward or backward across the different stages. Commands may not be - * cancelled while they are being executed. However, users may request the - * "cancel" action when submitting a stage response indicating that the command - * execution should be aborted. Thus, releasing any collected information. - * Commands that require user interaction (i.e. have more than one stage) will - * have to provide the data forms the user must complete in each stage and the - * allowed actions the user might perform during each stage (e.g. go to the - * previous stage or go to the next stage). - *

      - * All the actions may throw an XMPPException if there is a problem executing - * them. The XMPPError of that exception may have some specific - * information about the problem. The possible extensions are: - *
        - *
      • malformed-action. Extension of a bad-request error.
      • - *
      • bad-action. Extension of a bad-request error.
      • - *
      • bad-locale. Extension of a bad-request error.
      • - *
      • bad-payload. Extension of a bad-request error.
      • - *
      • bad-sessionid. Extension of a bad-request error.
      • - *
      • session-expired. Extension of a not-allowed error.
      • - *
      - *

      - * See the SpecificErrorCondition class for detailed description - * of each one. - *

      - * Use the getSpecificErrorConditionFrom to obtain the specific - * information from an XMPPError. - * - * @author Gabriel Guardincerri - * @author Florian Schmaus - * - */ -public abstract class AbstractAdHocCommand { - private final List requests = new ArrayList<>(); - private final List results = new ArrayList<>(); - - private final String node; - - private final String name; - - /** - * The session ID of this execution. - */ - private String sessionId; - - protected AbstractAdHocCommand(String node, String name) { - this.node = StringUtils.requireNotNullNorEmpty(node, "Ad-Hoc command node must be given"); - this.name = name; - } - - protected AbstractAdHocCommand(String node) { - this(node, null); - } - - void addRequest(AdHocCommandData request) { - requests.add(request); - } - - void addResult(AdHocCommandResult result) { - results.add(result); - } - - /** - * Returns the specific condition of the error or null if the - * error doesn't have any. - * - * @param error the error the get the specific condition from. - * @return the specific condition of this error, or null if it doesn't have - * any. - */ - public static SpecificErrorCondition getSpecificErrorCondition(StanzaError error) { - // This method is implemented to provide an easy way of getting a packet - // extension of the XMPPError. - for (SpecificErrorCondition condition : SpecificErrorCondition.values()) { - if (error.getExtension(condition.toString(), - AdHocCommandData.SpecificError.namespace) != null) { - return condition; - } - } - return null; - } - - /** - * Returns the human readable name of the command. - * - * @return the human readable name of the command - */ - public String getName() { - return name; - } - - /** - * Returns the unique identifier of the command. It is unique for the - * OwnerJID. - * - * @return the unique identifier of the command. - */ - public String getNode() { - return node; - } - - public String getSessionId() { - return sessionId; - } - - protected void setSessionId(String sessionId) { - assert this.sessionId == null || this.sessionId.equals(sessionId); - this.sessionId = StringUtils.requireNotNullNorEmpty(sessionId, "Must provide a session ID"); - } - - public AdHocCommandData getLastRequest() { - if (requests.isEmpty()) return null; - return requests.get(requests.size() - 1); - } - - public AdHocCommandResult getLastResult() { - if (results.isEmpty()) return null; - return results.get(results.size() - 1); - } - - /** - * Returns the notes that the command has at the current stage. - * - * @return a list of notes. - */ - public List getNotes() { - AdHocCommandResult result = getLastResult(); - if (result == null) return null; - - return result.getResponse().getNotes(); - } - - /** - * Cancels the execution of the command. This can be invoked on any stage of - * the execution. If there is a problem executing the command it throws an - * XMPPException. - * - * @throws NoResponseException if there was no response from the remote entity. - * @throws XMPPErrorException if there is a problem executing the command. - * @throws NotConnectedException if the XMPP connection is not connected. - * @throws InterruptedException if the calling thread was interrupted. - */ - public abstract void cancel() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException; - - /** - * Returns a collection with the allowed actions based on the current stage. - * Possible actions are: {@link AllowedAction#prev prev}, {@link AllowedAction#next next} and - * {@link AllowedAction#complete complete}. This method will be only invoked for commands that - * have one or more stages. - * - * @return a collection with the allowed actions based on the current stage - * as defined in the SessionData. - */ - public final Set getActions() { - AdHocCommandResult result = getLastResult(); - if (result == null) return null; - - return result.getResponse().getActions(); - } - - /** - * Returns the action available for the current stage which is - * considered the equivalent to "execute". When the requester sends his - * reply, if no action was defined in the command then the action will be - * assumed "execute" thus assuming the action returned by this method. This - * method will never be invoked for commands that have no stages. - * - * @return the action available for the current stage which is considered - * the equivalent to "execute". - */ - protected AllowedAction getExecuteAction() { - AdHocCommandResult result = getLastResult(); - if (result == null) return null; - - return result.getResponse().getExecuteAction(); - } - - /** - * Returns the status of the current stage. - * - * @return the current status. - */ - public Status getStatus() { - AdHocCommandResult result = getLastResult(); - if (result == null) return null; - - return result.getResponse().getStatus(); - } - - /** - * Check if this command has been completed successfully. - * - * @return true if this command is completed. - * @since 4.2 - */ - public boolean isCompleted() { - return getStatus() == AdHocCommandData.Status.completed; - } - - /** - * Returns true if the action is available in the current stage. - * The {@link Action#cancel cancel} action is always allowed. To define the - * available actions use the addActionAvailable method. - * - * @param action The action to check if it is available. - * @return True if the action is available for the current stage. - */ - public final boolean isValidAction(Action action) { - if (action == Action.cancel) { - return true; - } - - final AllowedAction executeAction; - if (action == Action.execute) { - AdHocCommandResult result = getLastResult(); - executeAction = result.getResponse().getExecuteAction(); - - // This is basically the case that was clarified with - // https://github.com/xsf/xeps/commit/fdaee2da8ffd34b5b5151e90ef1df8b396a06531 and - // https://github.com/xsf/xeps/pull/591. - if (executeAction == null) { - return false; - } - } else { - executeAction = action.allowedAction; - assert executeAction != null; - } - - Set actions = getActions(); - return actions != null && actions.contains(executeAction); - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommand.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommand.java index 0e7fabaaa..347c08f69 100755 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommand.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommand.java @@ -16,68 +16,193 @@ */ package org.jivesoftware.smackx.commands; +import java.util.List; + import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NotConnectedException; -import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException.XMPPErrorException; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.util.Objects; +import org.jivesoftware.smack.packet.StanzaError; + import org.jivesoftware.smackx.commands.packet.AdHocCommandData; import org.jivesoftware.smackx.xdata.form.FillableForm; -import org.jivesoftware.smackx.xdata.form.SubmitForm; import org.jivesoftware.smackx.xdata.packet.DataForm; import org.jxmpp.jid.Jid; /** - * Represents a ad-hoc command invoked on a remote entity. Invoking one of the - * {@link #execute()}, {@link #next(SubmitForm)}, - * {@link #prev()}, {@link #cancel()} or - * {@link #complete(SubmitForm)} actions results in executing that - * action on the remote entity. In response to that action the internal state - * of the this command instance will change. For example, if the command is a - * single stage command, then invoking the execute action will execute this - * action in the remote location. After that the local instance will have a - * state of "completed" and a form or notes that applies. + * An ad-hoc command is responsible for executing the provided service and + * storing the result of the execution. Each new request will create a new + * instance of the command, allowing information related to executions to be + * stored in it. For example suppose that a command that retrieves the list of + * users on a server is implemented. When the command is executed it gets that + * list and the result is stored as a form in the command instance, i.e. the + * getForm method retrieves a form with all the users. + *

      + * Each command has a node that should be unique within a given JID. + *

      + *

      + * Commands may have zero or more stages. Each stage is usually used for + * gathering information required for the command execution. Users are able to + * move forward or backward across the different stages. Commands may not be + * cancelled while they are being executed. However, users may request the + * "cancel" action when submitting a stage response indicating that the command + * execution should be aborted. Thus, releasing any collected information. + * Commands that require user interaction (i.e. have more than one stage) will + * have to provide the data forms the user must complete in each stage and the + * allowed actions the user might perform during each stage (e.g. go to the + * previous stage or go to the next stage). + *

      + * All the actions may throw an XMPPException if there is a problem executing + * them. The XMPPError of that exception may have some specific + * information about the problem. The possible extensions are: + *
        + *
      • malformed-action. Extension of a bad-request error.
      • + *
      • bad-action. Extension of a bad-request error.
      • + *
      • bad-locale. Extension of a bad-request error.
      • + *
      • bad-payload. Extension of a bad-request error.
      • + *
      • bad-sessionid. Extension of a bad-request error.
      • + *
      • session-expired. Extension of a not-allowed error.
      • + *
      + *

      + * See the SpecificErrorCondition class for detailed description + * of each one. + *

      + * Use the getSpecificErrorConditionFrom to obtain the specific + * information from an XMPPError. * * @author Gabriel Guardincerri - * @author Florian Schmaus * */ -public class AdHocCommand extends AbstractAdHocCommand { +public abstract class AdHocCommand { + // TODO: Analyze the redesign of command by having an ExecutionResponse as a + // TODO: result to the execution of every action. That result should have all the + // TODO: information related to the execution, e.g. the form to fill. Maybe this + // TODO: design is more intuitive and simpler than the current one that has all in + // TODO: one class. + + private AdHocCommandData data; + + public AdHocCommand() { + super(); + data = new AdHocCommandData(); + } /** - * The connection that is used to execute this command - */ - private final XMPPConnection connection; - - /** - * The full JID of the command host - */ - private final Jid jid; - - /** - * Creates a new RemoteCommand that uses an specific connection to execute a - * command identified by node in the host identified by - * jid + * Returns the specific condition of the error or null if the + * error doesn't have any. * - * @param connection the connection to use for the execution. - * @param node the identifier of the command. - * @param jid the JID of the host. + * @param error the error the get the specific condition from. + * @return the specific condition of this error, or null if it doesn't have + * any. */ - protected AdHocCommand(XMPPConnection connection, String node, Jid jid) { - super(node); - this.connection = Objects.requireNonNull(connection); - this.jid = Objects.requireNonNull(jid); + public static SpecificErrorCondition getSpecificErrorCondition(StanzaError error) { + // This method is implemented to provide an easy way of getting a packet + // extension of the XMPPError. + for (SpecificErrorCondition condition : SpecificErrorCondition.values()) { + if (error.getExtension(condition.toString(), + AdHocCommandData.SpecificError.namespace) != null) { + return condition; + } + } + return null; } - public Jid getOwnerJID() { - return jid; + /** + * Set the human readable name of the command, usually used for + * displaying in a UI. + * + * @param name the name. + */ + public void setName(String name) { + data.setName(name); } - @Override - public final void cancel() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - executeAction(AdHocCommandData.Action.cancel); + /** + * Returns the human readable name of the command. + * + * @return the human readable name of the command + */ + public String getName() { + return data.getName(); + } + + /** + * Sets the unique identifier of the command. This value must be unique for + * the OwnerJID. + * + * @param node the unique identifier of the command. + */ + public void setNode(String node) { + data.setNode(node); + } + + /** + * Returns the unique identifier of the command. It is unique for the + * OwnerJID. + * + * @return the unique identifier of the command. + */ + public String getNode() { + return data.getNode(); + } + + /** + * Returns the full JID of the owner of this command. This JID is the "to" of a + * execution request. + * + * @return the owner JID. + */ + public abstract Jid getOwnerJID(); + + /** + * Returns the notes that the command has at the current stage. + * + * @return a list of notes. + */ + public List getNotes() { + return data.getNotes(); + } + + /** + * Adds a note to the current stage. This should be used when setting a + * response to the execution of an action. All the notes added here are + * returned by the {@link #getNotes} method during the current stage. + * Once the stage changes all the notes are discarded. + * + * @param note the note. + */ + protected void addNote(AdHocCommandNote note) { + data.addNote(note); + } + + public String getRaw() { + return data.getChildElementXML().toString(); + } + + /** + * Returns the form of the current stage. Usually it is the form that must + * be answered to execute the next action. If that is the case it should be + * used by the requester to fill all the information that the executor needs + * to continue to the next stage. It can also be the result of the + * execution. + * + * @return the form of the current stage to fill out or the result of the + * execution. + */ + public DataForm getForm() { + return data.getForm(); + } + + /** + * Sets the form of the current stage. This should be used when setting a + * response. It could be a form to fill out the information needed to go to + * the next stage or the result of an execution. + * + * @param form the form of the current stage to fill out or the result of the + * execution. + */ + protected void setForm(DataForm form) { + data.setForm(form); } /** @@ -85,15 +210,12 @@ public class AdHocCommand extends AbstractAdHocCommand { * command. It is invoked on every command. If there is a problem executing * the command it throws an XMPPException. * - * @return an ad-hoc command result. * @throws NoResponseException if there was no response from the remote entity. * @throws XMPPErrorException if there is an error executing the command. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public final AdHocCommandResult execute() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - return executeAction(AdHocCommandData.Action.execute); - } + public abstract void execute() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException; /** * Executes the next action of the command with the information provided in @@ -102,16 +224,13 @@ public class AdHocCommand extends AbstractAdHocCommand { * or more stages. If there is a problem executing the command it throws an * XMPPException. * - * @param filledForm the form answer of the previous stage. - * @return an ad-hoc command result. + * @param response the form answer of the previous stage. * @throws NoResponseException if there was no response from the remote entity. * @throws XMPPErrorException if there is a problem executing the command. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public final AdHocCommandResult next(SubmitForm filledForm) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - return executeAction(AdHocCommandData.Action.next, filledForm.getDataForm()); - } + public abstract void next(FillableForm response) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException; /** * Completes the command execution with the information provided in the @@ -120,16 +239,14 @@ public class AdHocCommand extends AbstractAdHocCommand { * or more stages. If there is a problem executing the command it throws an * XMPPException. * - * @param filledForm the form answer of the previous stage. - * @return an ad-hoc command result. + * @param response the form answer of the previous stage. + * * @throws NoResponseException if there was no response from the remote entity. * @throws XMPPErrorException if there is a problem executing the command. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public AdHocCommandResult complete(SubmitForm filledForm) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - return executeAction(AdHocCommandData.Action.complete, filledForm.getDataForm()); - } + public abstract void complete(FillableForm response) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException; /** * Goes to the previous stage. The requester is asking to re-send the @@ -137,70 +254,224 @@ public class AdHocCommand extends AbstractAdHocCommand { * the previous one. If there is a problem executing the command it throws * an XMPPException. * - * @return an ad-hoc command result. * @throws NoResponseException if there was no response from the remote entity. * @throws XMPPErrorException if there is a problem executing the command. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public final AdHocCommandResult prev() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - return executeAction(AdHocCommandData.Action.prev); - } + public abstract void prev() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException; /** - * Executes the default action of the command with the information provided - * in the Form. This form must be the answer form of the previous stage. If - * there is a problem executing the command it throws an XMPPException. + * Cancels the execution of the command. This can be invoked on any stage of + * the execution. If there is a problem executing the command it throws an + * XMPPException. * - * @param form the form answer of the previous stage. - * @return an ad-hoc command result. - * @throws XMPPErrorException if an error occurs. - * @throws NoResponseException if there was no response from the server. - * @throws NotConnectedException if the XMPP connection is not connected. - * @throws InterruptedException if the calling thread was interrupted. - */ - public final AdHocCommandResult execute(FillableForm form) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - return executeAction(AdHocCommandData.Action.execute, form.getDataFormToSubmit()); - } - - private AdHocCommandResult executeAction(AdHocCommandData.Action action) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - return executeAction(action, null); - } - - /** - * Executes the action with the form. - * The action could be any of the available actions. The form must - * be the answer of the previous stage. It can be null if it is the first stage. - * - * @param action the action to execute. - * @param form the form with the information. + * @throws NoResponseException if there was no response from the remote entity. * @throws XMPPErrorException if there is a problem executing the command. - * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - private synchronized AdHocCommandResult executeAction(AdHocCommandData.Action action, DataForm form) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - AdHocCommandData request = AdHocCommandData.builder(getNode(), connection) - .ofType(IQ.Type.set) - .to(getOwnerJID()) - .setSessionId(getSessionId()) - .setAction(action) - .setForm(form) - .build(); + public abstract void cancel() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException; - addRequest(request); + /** + * Returns a collection with the allowed actions based on the current stage. + * Possible actions are: {@link Action#prev prev}, {@link Action#next next} and + * {@link Action#complete complete}. This method will be only invoked for commands that + * have one or more stages. + * + * @return a collection with the allowed actions based on the current stage + * as defined in the SessionData. + */ + protected List getActions() { + return data.getActions(); + } - AdHocCommandData response = connection.sendIqRequestAndWaitForResponse(request); + /** + * Add an action to the current stage available actions. This should be used + * when creating a response. + * + * @param action the action. + */ + protected void addActionAvailable(Action action) { + data.addAction(action); + } - // The Ad-Hoc service ("server") may have generated a session id for us. - String sessionId = response.getSessionId(); - if (sessionId != null) { - setSessionId(sessionId); + /** + * Returns the action available for the current stage which is + * considered the equivalent to "execute". When the requester sends his + * reply, if no action was defined in the command then the action will be + * assumed "execute" thus assuming the action returned by this method. This + * method will never be invoked for commands that have no stages. + * + * @return the action available for the current stage which is considered + * the equivalent to "execute". + */ + protected Action getExecuteAction() { + return data.getExecuteAction(); + } + + /** + * Sets which of the actions available for the current stage is + * considered the equivalent to "execute". This should be used when setting + * a response. When the requester sends his reply, if no action was defined + * in the command then the action will be assumed "execute" thus assuming + * the action returned by this method. + * + * @param action the action. + */ + protected void setExecuteAction(Action action) { + data.setExecuteAction(action); + } + + /** + * Returns the status of the current stage. + * + * @return the current status. + */ + public Status getStatus() { + return data.getStatus(); + } + + /** + * Check if this command has been completed successfully. + * + * @return true if this command is completed. + * @since 4.2 + */ + public boolean isCompleted() { + return getStatus() == Status.completed; + } + + /** + * Sets the data of the current stage. This should not used. + * + * @param data the data. + */ + void setData(AdHocCommandData data) { + this.data = data; + } + + /** + * Gets the data of the current stage. This should not used. + * + * @return the data. + */ + AdHocCommandData getData() { + return data; + } + + /** + * Returns true if the action is available in the current stage. + * The {@link Action#cancel cancel} action is always allowed. To define the + * available actions use the addActionAvailable method. + * + * @param action TODO javadoc me please + * The action to check if it is available. + * @return True if the action is available for the current stage. + */ + protected boolean isValidAction(Action action) { + return getActions().contains(action) || Action.cancel.equals(action); + } + + /** + * The status of the stage in the adhoc command. + */ + public enum Status { + + /** + * The command is being executed. + */ + executing, + + /** + * The command has completed. The command session has ended. + */ + completed, + + /** + * The command has been canceled. The command session has ended. + */ + canceled + } + + public enum Action { + + /** + * The command should be executed or continue to be executed. This is + * the default value. + */ + execute, + + /** + * The command should be canceled. + */ + cancel, + + /** + * The command should be digress to the previous stage of execution. + */ + prev, + + /** + * The command should progress to the next stage of execution. + */ + next, + + /** + * The command should be completed (if possible). + */ + complete, + + /** + * The action is unknown. This is used when a received message has an + * unknown action. It must not be used to send an execution request. + */ + unknown + } + + public enum SpecificErrorCondition { + + /** + * The responding JID cannot accept the specified action. + */ + badAction("bad-action"), + + /** + * The responding JID does not understand the specified action. + */ + malformedAction("malformed-action"), + + /** + * The responding JID cannot accept the specified language/locale. + */ + badLocale("bad-locale"), + + /** + * The responding JID cannot accept the specified payload (e.g. the data + * form did not provide one or more required fields). + */ + badPayload("bad-payload"), + + /** + * The responding JID cannot accept the specified sessionid. + */ + badSessionid("bad-sessionid"), + + /** + * The requesting JID specified a sessionid that is no longer active + * (either because it was completed, canceled, or timed out). + */ + sessionExpired("session-expired"); + + private final String value; + + SpecificErrorCondition(String value) { + this.value = value; } - AdHocCommandResult result = AdHocCommandResult.from(response); - addResult(result); - return result; + @Override + public String toString() { + return value; + } } - } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandHandler.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandHandler.java deleted file mode 100755 index 5eb6d6dda..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandHandler.java +++ /dev/null @@ -1,182 +0,0 @@ -/** - * - * Copyright 2005-2007 Jive Software. - * - * 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.smackx.commands; - -import org.jivesoftware.smack.SmackException.NoResponseException; -import org.jivesoftware.smack.SmackException.NotConnectedException; -import org.jivesoftware.smack.XMPPException.XMPPErrorException; -import org.jivesoftware.smack.packet.StanzaError; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData; -import org.jivesoftware.smackx.commands.packet.AdHocCommandDataBuilder; -import org.jivesoftware.smackx.xdata.form.SubmitForm; - -import org.jxmpp.jid.Jid; - -/** - * Represents a command that can be executed locally from a remote location. This - * class must be extended to implement an specific ad-hoc command. This class - * provides some useful tools:
        - *
      • Node
      • - *
      • Name
      • - *
      • Session ID
      • - *
      • Current Stage
      • - *
      • Available actions
      • - *
      • Default action
      • - *
      - * To implement a new command extend this class and implement all the abstract - * methods. When implementing the actions remember that they could be invoked - * several times, and that you must use the current stage number to know what to - * do. - * - * @author Gabriel Guardincerri - * @author Florian Schmaus - */ -public abstract class AdHocCommandHandler extends AbstractAdHocCommand { - - /** - * The time stamp of first invocation of the command. Used to implement the session timeout. - */ - private final long creationDate; - - /** - * The number of the current stage. - */ - private int currentStage; - - @SuppressWarnings("this-escape") - public AdHocCommandHandler(String node, String name, String sessionId) { - super(node, name); - setSessionId(sessionId); - this.creationDate = System.currentTimeMillis(); - } - - protected abstract AdHocCommandData execute(AdHocCommandDataBuilder response) throws NoResponseException, - XMPPErrorException, NotConnectedException, InterruptedException, IllegalStateException; - - protected abstract AdHocCommandData next(AdHocCommandDataBuilder response, SubmitForm submittedForm) - throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, - IllegalStateException; - - protected abstract AdHocCommandData complete(AdHocCommandDataBuilder response, SubmitForm submittedForm) - throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, - IllegalStateException; - - protected abstract AdHocCommandData prev(AdHocCommandDataBuilder response) throws NoResponseException, - XMPPErrorException, NotConnectedException, InterruptedException, IllegalStateException; - - /** - * Returns the date the command was created. - * - * @return the date the command was created. - */ - public long getCreationDate() { - return creationDate; - } - - /** - * Returns true if the specified requester has permission to execute all the - * stages of this action. This is checked when the first request is received, - * if the permission is grant then the requester will be able to execute - * all the stages of the command. It is not checked again during the - * execution. - * - * @param jid the JID to check permissions on. - * @return true if the user has permission to execute this action. - */ - public boolean hasPermission(Jid jid) { - return true; - }; - - /** - * Returns the currently executing stage number. The first stage number is - * 1. During the execution of the first action this method will answer 1. - * - * @return the current stage number. - */ - public final int getCurrentStage() { - return currentStage; - } - - /** - * Increase the current stage number. - */ - final void incrementStage() { - currentStage++; - } - - /** - * Decrease the current stage number. - */ - final void decrementStage() { - currentStage--; - } - - protected static XMPPErrorException newXmppErrorException(StanzaError.Condition condition) { - return newXmppErrorException(condition, null); - } - - protected static XMPPErrorException newXmppErrorException(StanzaError.Condition condition, String descriptiveText) { - StanzaError stanzaError = StanzaError.from(condition, descriptiveText).build(); - return new XMPPErrorException(null, stanzaError); - } - - protected static XMPPErrorException newBadRequestException(String descriptiveTest) { - return newXmppErrorException(StanzaError.Condition.bad_request, descriptiveTest); - } - - public abstract static class SingleStage extends AdHocCommandHandler { - - public SingleStage(String node, String name, String sessionId) { - super(node, name, sessionId); - } - - protected abstract AdHocCommandData executeSingleStage(AdHocCommandDataBuilder response) - throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException; - - @Override - protected final AdHocCommandData execute(AdHocCommandDataBuilder response) - throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - response.setStatusCompleted(); - return executeSingleStage(response); - } - - @Override - public final AdHocCommandData next(AdHocCommandDataBuilder response, SubmitForm submittedForm) - throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - throw newXmppErrorException(StanzaError.Condition.bad_request); - } - - @Override - public final AdHocCommandData complete(AdHocCommandDataBuilder response, SubmitForm submittedForm) - throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - throw newXmppErrorException(StanzaError.Condition.bad_request); - } - - @Override - public final AdHocCommandData prev(AdHocCommandDataBuilder response) - throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - throw newXmppErrorException(StanzaError.Condition.bad_request); - } - - @Override - public final void cancel() - throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - throw newXmppErrorException(StanzaError.Condition.bad_request); - } - - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandManager.java index 568b98a14..aaad5c0ee 100755 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandManager.java @@ -17,7 +17,6 @@ package org.jivesoftware.smackx.commands; -import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; @@ -45,17 +44,16 @@ import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.StanzaError; import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smackx.commands.AdHocCommand.Action; +import org.jivesoftware.smackx.commands.AdHocCommand.Status; import org.jivesoftware.smackx.commands.packet.AdHocCommandData; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData.AllowedAction; -import org.jivesoftware.smackx.commands.packet.AdHocCommandDataBuilder; import org.jivesoftware.smackx.disco.AbstractNodeInformationProvider; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; import org.jivesoftware.smackx.disco.packet.DiscoverItems; -import org.jivesoftware.smackx.xdata.form.SubmitForm; +import org.jivesoftware.smackx.xdata.form.FillableForm; import org.jivesoftware.smackx.xdata.packet.DataForm; -import org.jxmpp.jid.EntityFullJid; import org.jxmpp.jid.Jid; /** @@ -67,7 +65,6 @@ import org.jxmpp.jid.Jid; * get an instance of this class. * * @author Gabriel Guardincerri - * @author Florian Schmaus */ public final class AdHocCommandManager extends Manager { public static final String NAMESPACE = "http://jabber.org/protocol/commands"; @@ -77,7 +74,7 @@ public final class AdHocCommandManager extends Manager { /** * The session time out in seconds. */ - private static int DEFAULT_SESSION_TIMEOUT_SECS = 7 * 60; + private static final int SESSION_TIMEOUT = 2 * 60; /** * Map an XMPPConnection with it AdHocCommandManager. This map have a key-value @@ -85,7 +82,7 @@ public final class AdHocCommandManager extends Manager { */ private static final Map instances = new WeakHashMap<>(); - /* + /** * Register the listener for all the connection creations. When a new * connection is created a new AdHocCommandManager is also created and * related to that connection. @@ -94,7 +91,7 @@ public final class AdHocCommandManager extends Manager { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { @Override public void connectionCreated(XMPPConnection connection) { - getInstance(connection); + getAddHocCommandsManager(connection); } }); } @@ -105,21 +102,8 @@ public final class AdHocCommandManager extends Manager { * * @param connection the XMPP connection. * @return the AdHocCommandManager associated with the connection. - * @deprecated use {@link #getInstance(XMPPConnection)} instead. */ - @Deprecated - public static AdHocCommandManager getAddHocCommandsManager(XMPPConnection connection) { - return getInstance(connection); - } - - /** - * Returns the AdHocCommandManager related to the - * connection. - * - * @param connection the XMPP connection. - * @return the AdHocCommandManager associated with the connection. - */ - public static synchronized AdHocCommandManager getInstance(XMPPConnection connection) { + public static synchronized AdHocCommandManager getAddHocCommandsManager(XMPPConnection connection) { AdHocCommandManager ahcm = instances.get(connection); if (ahcm == null) { ahcm = new AdHocCommandManager(connection); @@ -133,8 +117,7 @@ public final class AdHocCommandManager extends Manager { * Value=command. Command node matches the node attribute sent by command * requesters. */ - // TODO: Change to Map once Smack's minimum Android API level is 24 or higher. - private final ConcurrentHashMap commands = new ConcurrentHashMap<>(); + private final Map commands = new ConcurrentHashMap<>(); /** * Map a command session ID with the instance LocalCommand. The LocalCommand @@ -142,12 +125,10 @@ public final class AdHocCommandManager extends Manager { * the command execution. Note: Key=session ID, Value=LocalCommand. Session * ID matches the sessionid attribute sent by command responders. */ - private final Map executingCommands = new ConcurrentHashMap<>(); + private final Map executingCommands = new ConcurrentHashMap<>(); private final ServiceDiscoveryManager serviceDiscoveryManager; - private int sessionTimeoutSecs = DEFAULT_SESSION_TIMEOUT_SECS; - private AdHocCommandManager(XMPPConnection connection) { super(connection); this.serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection); @@ -167,17 +148,13 @@ public final class AdHocCommandManager extends Manager { new AbstractNodeInformationProvider() { @Override public List getNodeItems() { - List answer = new ArrayList<>(); - Collection commandsList = commands.values(); - EntityFullJid ourJid = connection().getUser(); - if (ourJid == null) { - LOGGER.warning("Local connection JID not available, can not respond to " + NAMESPACE + " node information"); - return null; - } + List answer = new ArrayList<>(); + Collection commandsList = getRegisteredCommands(); for (AdHocCommandInfo info : commandsList) { - DiscoverItems.Item item = new DiscoverItems.Item(ourJid); + DiscoverItems.Item item = new DiscoverItems.Item( + info.getOwnerJID()); item.setName(info.getName()); item.setNode(info.getNode()); answer.add(item); @@ -189,17 +166,18 @@ public final class AdHocCommandManager extends Manager { // The packet listener and the filter for processing some AdHoc Commands // Packets - // TODO: This handler being async means that requests for the same command could be handled out of order. Nobody - // complained so far, and I could imagine that it does not really matter in practice. But it is certainly - // something to keep in mind. connection.registerIQRequestHandler(new AbstractIqRequestHandler(AdHocCommandData.ELEMENT, AdHocCommandData.NAMESPACE, IQ.Type.set, Mode.async) { @Override public IQ handleIQRequest(IQ iqRequest) { AdHocCommandData requestData = (AdHocCommandData) iqRequest; - AdHocCommandData response = processAdHocCommand(requestData); - assert response.getStatus() != null || response.getType() == IQ.Type.error; - return response; + try { + return processAdHocCommand(requestData); + } + catch (InterruptedException | NoResponseException | NotConnectedException e) { + LOGGER.log(Level.INFO, "processAdHocCommand threw exception", e); + return null; + } } }); } @@ -209,21 +187,18 @@ public final class AdHocCommandManager extends Manager { * connection. The node is an unique identifier of that command for * the connection related to this command manager. The name is the * human readable name of the command. The class is the class of - * the command, which must extend {@link AdHocCommandHandler} and have a default + * the command, which must extend {@link LocalCommand} and have a default * constructor. * * @param node the unique identifier of the command. * @param name the human readable name of the command. - * @param clazz the class of the command, which must extend {@link AdHocCommandHandler}. - * @throws SecurityException if there was a security violation. - * @throws NoSuchMethodException if no such method is declared. + * @param clazz the class of the command, which must extend {@link LocalCommand}. */ - public void registerCommand(String node, String name, final Class clazz) throws NoSuchMethodException, SecurityException { - Constructor constructor = clazz.getConstructor(String.class, String.class, String.class); - registerCommand(node, name, new AdHocCommandHandlerFactory() { + public void registerCommand(String node, String name, final Class clazz) { + registerCommand(node, name, new LocalCommandFactory() { @Override - public AdHocCommandHandler create(String node, String name, String sessionId) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { - return constructor.newInstance(node, name, sessionId); + public LocalCommand getInstance() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + return clazz.getConstructor().newInstance(); } }); } @@ -239,12 +214,10 @@ public final class AdHocCommandManager extends Manager { * @param name the human readable name of the command. * @param factory a factory to create new instances of the command. */ - public synchronized void registerCommand(String node, final String name, AdHocCommandHandlerFactory factory) { - AdHocCommandInfo commandInfo = new AdHocCommandInfo(node, name, factory); - - AdHocCommandInfo existing = commands.putIfAbsent(node, commandInfo); - if (existing != null) throw new IllegalArgumentException("There is already an ad-hoc command registered for " + node); + public void registerCommand(String node, final String name, LocalCommandFactory factory) { + AdHocCommandInfo commandInfo = new AdHocCommandInfo(node, name, connection().getUser(), factory); + commands.put(node, commandInfo); // Set the NodeInformationProvider that will provide information about // the added command serviceDiscoveryManager.setNodeInformationProvider(node, @@ -269,14 +242,6 @@ public final class AdHocCommandManager extends Manager { }); } - public synchronized boolean unregisterCommand(String node) { - AdHocCommandInfo commandInfo = commands.remove(node); - if (commandInfo == null) return false; - - serviceDiscoveryManager.removeNodeInformationProvider(node); - return true; - } - /** * Discover the commands of an specific JID. The jid is a * full JID. @@ -301,8 +266,8 @@ public final class AdHocCommandManager extends Manager { * @param node the identifier of the command * @return a local instance equivalent to the remote command. */ - public AdHocCommand getRemoteCommand(Jid jid, String node) { - return new AdHocCommand(connection(), node, jid); + public RemoteCommand getRemoteCommand(Jid jid, String node) { + return new RemoteCommand(connection(), node, jid); } /** @@ -326,226 +291,240 @@ public final class AdHocCommandManager extends Manager { *
    • The action to execute is one of the available actions
    • *
    * - * @param request the incoming AdHoc command request. + * @param requestData TODO javadoc me please + * the stanza to process. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws NoResponseException if there was no response from the remote entity. + * @throws InterruptedException if the calling thread was interrupted. */ - private AdHocCommandData processAdHocCommand(AdHocCommandData request) { - String sessionId = request.getSessionId(); + private IQ processAdHocCommand(AdHocCommandData requestData) throws NoResponseException, NotConnectedException, InterruptedException { + // Creates the response with the corresponding data + AdHocCommandData response = new AdHocCommandData(); + response.setTo(requestData.getFrom()); + response.setStanzaId(requestData.getStanzaId()); + response.setNode(requestData.getNode()); + response.setId(requestData.getTo()); + + String sessionId = requestData.getSessionID(); + String commandNode = requestData.getNode(); - final AdHocCommandHandler command; if (sessionId == null) { - String commandNode = request.getNode(); - // A new execution request has been received. Check that the // command exists - AdHocCommandInfo commandInfo = commands.get(commandNode); - if (commandInfo == null) { + if (!commands.containsKey(commandNode)) { // Requested command does not exist so return // item_not_found error. - return respondError(request, null, StanzaError.Condition.item_not_found); + return respondError(response, StanzaError.Condition.item_not_found); } - assert commandInfo.getNode().equals(commandNode); + // Create new session ID + sessionId = StringUtils.randomString(15); - // Create a new instance of the command with the - // corresponding session ID. try { - command = commandInfo.getCommandInstance(); + // Create a new instance of the command with the + // corresponding sessionid + LocalCommand command; + try { + command = newInstanceOfCmd(commandNode, sessionId); + } + catch (InstantiationException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException | NoSuchMethodException | SecurityException e) { + StanzaError xmppError = StanzaError.getBuilder() + .setCondition(StanzaError.Condition.internal_server_error) + .setDescriptiveEnText(e.getMessage()) + .build(); + return respondError(response, xmppError); + } + + response.setType(IQ.Type.result); + command.setData(response); + + // Check that the requester has enough permission. + // Answer forbidden error if requester permissions are not + // enough to execute the requested command + if (!command.hasPermission(requestData.getFrom())) { + return respondError(response, StanzaError.Condition.forbidden); + } + + Action action = requestData.getAction(); + + // If the action is unknown then respond an error. + if (action != null && action.equals(Action.unknown)) { + return respondError(response, StanzaError.Condition.bad_request, + AdHocCommand.SpecificErrorCondition.malformedAction); + } + + // If the action is not execute, then it is an invalid action. + if (action != null && !action.equals(Action.execute)) { + return respondError(response, StanzaError.Condition.bad_request, + AdHocCommand.SpecificErrorCondition.badAction); + } + + // Increase the state number, so the command knows in witch + // stage it is + command.incrementStage(); + // Executes the command + command.execute(); + + if (command.isLastStage()) { + // If there is only one stage then the command is completed + response.setStatus(Status.completed); + } + else { + // Else it is still executing, and is registered to be + // available for the next call + response.setStatus(Status.executing); + executingCommands.put(sessionId, command); + // See if the session sweeper thread is scheduled. If not, start it. + maybeWindUpSessionSweeper(); + } + + // Sends the response packet + return response; + } - catch (InstantiationException | IllegalAccessException | IllegalArgumentException - | InvocationTargetException e) { - LOGGER.log(Level.WARNING, "Could not instanciate ad-hoc command server", e); - StanzaError xmppError = StanzaError.getBuilder() - .setCondition(StanzaError.Condition.internal_server_error) - .setDescriptiveEnText(e.getMessage()) - .build(); - return respondError(request, null, xmppError); + catch (XMPPErrorException e) { + // If there is an exception caused by the next, complete, + // prev or cancel method, then that error is returned to the + // requester. + StanzaError error = e.getStanzaError(); + + // If the error type is cancel, then the execution is + // canceled therefore the status must show that, and the + // command be removed from the executing list. + if (StanzaError.Type.CANCEL.equals(error.getType())) { + response.setStatus(Status.canceled); + executingCommands.remove(sessionId); + } + return respondError(response, error); } - } else { - command = executingCommands.get(sessionId); + } + else { + LocalCommand command = executingCommands.get(sessionId); + // Check that a command exists for the specified sessionID // This also handles if the command was removed in the meanwhile // of getting the key and the value of the map. if (command == null) { - return respondError(request, null, StanzaError.Condition.bad_request, - SpecificErrorCondition.badSessionid); - } - } - - - final AdHocCommandDataBuilder responseBuilder = AdHocCommandDataBuilder.buildResponseFor(request) - .setSessionId(command.getSessionId()); - - final AdHocCommandData response; - /* - * Since the requester could send two requests for the same - * executing command i.e. the same session id, all the execution of - * the action must be synchronized to avoid inconsistencies. - */ - synchronized (command) { - command.addRequest(request); - - if (sessionId == null) { - response = processAdHocCommandOfNewSession(request, command, responseBuilder); - } else { - response = processAdHocCommandOfExistingSession(request, command, responseBuilder); + return respondError(response, StanzaError.Condition.bad_request, + AdHocCommand.SpecificErrorCondition.badSessionid); } + // Check if the Session data has expired (default is 10 minutes) + long creationStamp = command.getCreationDate(); + if (System.currentTimeMillis() - creationStamp > SESSION_TIMEOUT * 1000) { + // Remove the expired session + executingCommands.remove(sessionId); - AdHocCommandResult commandResult = AdHocCommandResult.from(response); - command.addResult(commandResult); - } + // Answer a not_allowed error (session-expired) + return respondError(response, StanzaError.Condition.not_allowed, + AdHocCommand.SpecificErrorCondition.sessionExpired); + } - return response; - } + /* + * Since the requester could send two requests for the same + * executing command i.e. the same session id, all the execution of + * the action must be synchronized to avoid inconsistencies. + */ + synchronized (command) { + Action action = requestData.getAction(); - private AdHocCommandData createResponseFrom(AdHocCommandData request, AdHocCommandDataBuilder response, XMPPErrorException exception, String sessionId) { - StanzaError error = exception.getStanzaError(); + // If the action is unknown the respond an error + if (action != null && action.equals(Action.unknown)) { + return respondError(response, StanzaError.Condition.bad_request, + AdHocCommand.SpecificErrorCondition.malformedAction); + } - // If the error type is cancel, then the execution is - // canceled therefore the status must show that, and the - // command be removed from the executing list. - if (error.getType() == StanzaError.Type.CANCEL) { - response.setStatus(AdHocCommandData.Status.canceled); + // If the user didn't specify an action or specify the execute + // action then follow the actual default execute action + if (action == null || Action.execute.equals(action)) { + action = command.getExecuteAction(); + } - executingCommands.remove(sessionId); + // Check that the specified action was previously + // offered + if (!command.isValidAction(action)) { + return respondError(response, StanzaError.Condition.bad_request, + AdHocCommand.SpecificErrorCondition.badAction); + } - return response.build(); - } + try { + // TODO: Check that all the required fields of the form are + // TODO: filled, if not throw an exception. This will simplify the + // TODO: construction of new commands - return respondError(request, response, error); - } + // Since all errors were passed, the response is now a + // result + response.setType(IQ.Type.result); - private static AdHocCommandData createResponseFrom(AdHocCommandData request, AdHocCommandDataBuilder response, Exception exception) { - StanzaError error = StanzaError.from(StanzaError.Condition.internal_server_error, exception.getMessage()) - .build(); - return respondError(request, response, error); - } + // Set the new data to the command. + command.setData(response); - private AdHocCommandData processAdHocCommandOfNewSession(AdHocCommandData request, AdHocCommandHandler command, AdHocCommandDataBuilder responseBuilder) { - // Check that the requester has enough permission. - // Answer forbidden error if requester permissions are not - // enough to execute the requested command - if (!command.hasPermission(request.getFrom())) { - return respondError(request, responseBuilder, StanzaError.Condition.forbidden); - } + if (Action.next.equals(action)) { + command.incrementStage(); + DataForm dataForm = requestData.getForm(); + command.next(new FillableForm(dataForm)); + if (command.isLastStage()) { + // If it is the last stage then the command is + // completed + response.setStatus(Status.completed); + } + else { + // Otherwise it is still executing + response.setStatus(Status.executing); + } + } + else if (Action.complete.equals(action)) { + command.incrementStage(); + DataForm dataForm = requestData.getForm(); + command.complete(new FillableForm(dataForm)); + response.setStatus(Status.completed); + // Remove the completed session + executingCommands.remove(sessionId); + } + else if (Action.prev.equals(action)) { + command.decrementStage(); + command.prev(); + } + else if (Action.cancel.equals(action)) { + command.cancel(); + response.setStatus(Status.canceled); + // Remove the canceled session + executingCommands.remove(sessionId); + } - AdHocCommandData.Action action = request.getAction(); + return response; + } + catch (XMPPErrorException e) { + // If there is an exception caused by the next, complete, + // prev or cancel method, then that error is returned to the + // requester. + StanzaError error = e.getStanzaError(); - // If the action is not execute, then it is an invalid action. - if (action != null && !action.equals(AdHocCommandData.Action.execute)) { - return respondError(request, responseBuilder, StanzaError.Condition.bad_request, - SpecificErrorCondition.badAction); - } - - // Increase the state number, so the command knows in witch - // stage it is - command.incrementStage(); - - final AdHocCommandData response; - try { - // Executes the command - response = command.execute(responseBuilder); - } catch (XMPPErrorException e) { - return createResponseFrom(request, responseBuilder, e, command.getSessionId()); - } catch (NoResponseException | NotConnectedException | InterruptedException | IllegalStateException e) { - return createResponseFrom(request, responseBuilder, e); - } - - if (response.isExecuting()) { - executingCommands.put(command.getSessionId(), command); - // See if the session sweeper thread is scheduled. If not, start it. - maybeWindUpSessionSweeper(); - } - - return response; - } - - private AdHocCommandData processAdHocCommandOfExistingSession(AdHocCommandData request, AdHocCommandHandler command, AdHocCommandDataBuilder responseBuilder) { - // Check if the Session data has expired (default is 10 minutes) - long creationStamp = command.getCreationDate(); - if (System.currentTimeMillis() - creationStamp > sessionTimeoutSecs * 1000L) { - // Remove the expired session - executingCommands.remove(command.getSessionId()); - - // Answer a not_allowed error (session-expired) - return respondError(request, responseBuilder, StanzaError.Condition.not_allowed, - SpecificErrorCondition.sessionExpired); - } - - AdHocCommandData.Action action = request.getAction(); - - // If the user didn't specify an action or specify the execute - // action then follow the actual default execute action - if (action == null || AdHocCommandData.Action.execute.equals(action)) { - AllowedAction executeAction = command.getExecuteAction(); - if (executeAction != null) { - action = executeAction.action; + // If the error type is cancel, then the execution is + // canceled therefore the status must show that, and the + // command be removed from the executing list. + if (StanzaError.Type.CANCEL.equals(error.getType())) { + response.setStatus(Status.canceled); + executingCommands.remove(sessionId); + } + return respondError(response, error); + } } } - - // Check that the specified action was previously - // offered - if (!command.isValidAction(action)) { - return respondError(request, responseBuilder, StanzaError.Condition.bad_request, - SpecificErrorCondition.badAction); - } - - AdHocCommandData response; - try { - DataForm dataForm; - switch (action) { - case next: - command.incrementStage(); - dataForm = request.getForm(); - response = command.next(responseBuilder, new SubmitForm(dataForm)); - break; - case complete: - command.incrementStage(); - dataForm = request.getForm(); - responseBuilder.setStatus(AdHocCommandData.Status.completed); - response = command.complete(responseBuilder, new SubmitForm(dataForm)); - // Remove the completed session - executingCommands.remove(command.getSessionId()); - break; - case prev: - command.decrementStage(); - response = command.prev(responseBuilder); - break; - case cancel: - command.cancel(); - responseBuilder.setStatus(AdHocCommandData.Status.canceled); - response = responseBuilder.build(); - // Remove the canceled session - executingCommands.remove(command.getSessionId()); - break; - default: - return respondError(request, responseBuilder, StanzaError.Condition.bad_request, - SpecificErrorCondition.badAction); - } - } catch (XMPPErrorException e) { - return createResponseFrom(request, responseBuilder, e, command.getSessionId()); - } catch (NoResponseException | NotConnectedException | InterruptedException | IllegalStateException e) { - return createResponseFrom(request, responseBuilder, e); - } - - return response; } private boolean sessionSweeperScheduled; - private int getSessionRemovalTimeoutSecs() { - return sessionTimeoutSecs * 2; - } - private void sessionSweeper() { final long currentTime = System.currentTimeMillis(); synchronized (this) { - for (Iterator> it = executingCommands.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = it.next(); - AdHocCommandHandler command = entry.getValue(); + for (Iterator> it = executingCommands.entrySet().iterator(); it.hasNext();) { + Map.Entry entry = it.next(); + LocalCommand command = entry.getValue(); long creationStamp = command.getCreationDate(); - // Check if the Session data has expired. + // Check if the Session data has expired (default is 10 minutes) // To remove it from the session list it waits for the double of // the of time out time. This is to let // the requester know why his execution request is @@ -553,7 +532,7 @@ public final class AdHocCommandManager extends Manager { // after the time out, then once the user requests to // continue the execution he will received an // invalid session error and not a time out error. - if (currentTime - creationStamp > getSessionRemovalTimeoutSecs() * 1000L) { + if (currentTime - creationStamp > SESSION_TIMEOUT * 1000 * 2) { // Remove the expired session it.remove(); } @@ -573,100 +552,104 @@ public final class AdHocCommandManager extends Manager { } sessionSweeperScheduled = true; - schedule(this::sessionSweeper, getSessionRemovalTimeoutSecs() + 1, TimeUnit.SECONDS); + schedule(this::sessionSweeper, 10, TimeUnit.SECONDS); } /** * Responds an error with an specific condition. * - * @param request the request that caused the error response. + * @param response the response to send. * @param condition the condition of the error. */ - private static AdHocCommandData respondError(AdHocCommandData request, AdHocCommandDataBuilder response, + private static IQ respondError(AdHocCommandData response, StanzaError.Condition condition) { - return respondError(request, response, StanzaError.getBuilder(condition).build()); + return respondError(response, StanzaError.getBuilder(condition).build()); } /** * Responds an error with an specific condition. * - * @param request the request that caused the error response. + * @param response the response to send. * @param condition the condition of the error. * @param specificCondition the adhoc command error condition. */ - private static AdHocCommandData respondError(AdHocCommandData request, AdHocCommandDataBuilder response, StanzaError.Condition condition, - SpecificErrorCondition specificCondition) { + private static IQ respondError(AdHocCommandData response, StanzaError.Condition condition, + AdHocCommand.SpecificErrorCondition specificCondition) { StanzaError error = StanzaError.getBuilder(condition) .addExtension(new AdHocCommandData.SpecificError(specificCondition)) .build(); - return respondError(request, response, error); + return respondError(response, error); } /** * Responds an error with an specific error. * - * @param request the request that caused the error response. + * @param response the response to send. * @param error the error to send. */ - private static AdHocCommandData respondError(AdHocCommandData request, AdHocCommandDataBuilder response, StanzaError error) { - if (response == null) { - return AdHocCommandDataBuilder.buildResponseFor(request, IQ.ResponseType.error).setError(error).build(); - } - - // Response may be not of IQ type error here, so switch that. - return response.ofType(IQ.Type.error) - .setError(error) - .build(); + private static IQ respondError(AdHocCommandData response, StanzaError error) { + response.setType(IQ.Type.error); + response.setError(error); + return response; } - public static void setDefaultSessionTimeoutSecs(int seconds) { - if (seconds < 10) { - throw new IllegalArgumentException(); - } - DEFAULT_SESSION_TIMEOUT_SECS = seconds; + /** + * Creates a new instance of a command to be used by a new execution request + * + * @param commandNode the command node that identifies it. + * @param sessionID the session id of this execution. + * @return the command instance to execute. + * @throws XMPPErrorException if there is problem creating the new instance. + * @throws SecurityException if there was a security violation. + * @throws NoSuchMethodException if no such method is declared + * @throws InvocationTargetException if a reflection-based method or constructor invocation threw. + * @throws IllegalArgumentException if an illegal argument was given. + * @throws IllegalAccessException in case of an illegal access. + * @throws InstantiationException in case of an instantiation error. + */ + private LocalCommand newInstanceOfCmd(String commandNode, String sessionID) + throws XMPPErrorException, InstantiationException, IllegalAccessException, IllegalArgumentException, + InvocationTargetException, NoSuchMethodException, SecurityException { + AdHocCommandInfo commandInfo = commands.get(commandNode); + LocalCommand command = commandInfo.getCommandInstance(); + command.setSessionID(sessionID); + command.setName(commandInfo.getName()); + command.setNode(commandInfo.getNode()); + + return command; } - public void setSessionTimeoutSecs(int seconds) { - if (seconds < 10) { - throw new IllegalArgumentException(); - } - - sessionTimeoutSecs = seconds; + /** + * Returns the registered commands of this command manager, which is related + * to a connection. + * + * @return the registered commands. + */ + private Collection getRegisteredCommands() { + return commands.values(); } /** * Stores ad-hoc command information. */ - private final class AdHocCommandInfo { + private static final class AdHocCommandInfo { - private final String node; - private final String name; - private final AdHocCommandHandlerFactory factory; + private String node; + private String name; + private final Jid ownerJID; + private LocalCommandFactory factory; - private static final int MAX_SESSION_GEN_ATTEMPTS = 3; - - private AdHocCommandInfo(String node, String name, AdHocCommandHandlerFactory factory) { + private AdHocCommandInfo(String node, String name, Jid ownerJID, + LocalCommandFactory factory) { this.node = node; this.name = name; + this.ownerJID = ownerJID; this.factory = factory; } - public AdHocCommandHandler getCommandInstance() throws InstantiationException, - IllegalAccessException, IllegalArgumentException, InvocationTargetException { - String sessionId; - // TODO: The code below contains a race condition. Use ConcurrentHashMap.computeIfAbsent() to remove the - // race condition once Smack's minimum Android API level 24 or higher. - int attempt = 0; - do { - attempt++; - if (attempt > MAX_SESSION_GEN_ATTEMPTS) { - throw new RuntimeException("Failed to compute unique session ID"); - } - // Create new session ID - sessionId = StringUtils.randomString(15); - } while (executingCommands.containsKey(sessionId)); - - return factory.create(node, name, sessionId); + public LocalCommand getCommandInstance() throws InstantiationException, + IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + return factory.getInstance(); } public String getName() { @@ -677,5 +660,8 @@ public final class AdHocCommandManager extends Manager { return node; } + public Jid getOwnerJID() { + return ownerJID; + } } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandResult.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandResult.java deleted file mode 100644 index e0927e277..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandResult.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * - * Copyright 2023 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.smackx.commands; - -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData; -import org.jivesoftware.smackx.xdata.form.FillableForm; -import org.jivesoftware.smackx.xdata.packet.DataForm; - -// TODO: Make this a sealed class once Smack is Java 17 or higher. -public abstract class AdHocCommandResult { - - private final AdHocCommandData response; - private final boolean completed; - - private AdHocCommandResult(AdHocCommandData response, boolean completed) { - this.response = response; - this.completed = completed; - } - - public final AdHocCommandData getResponse() { - return response; - } - - public final boolean isCompleted() { - return completed; - } - - public StatusExecuting asExecutingOrThrow() { - if (this instanceof StatusExecuting) - return (StatusExecuting) this; - - throw new IllegalStateException(); - } - - public StatusCompleted asCompletedOrThrow() { - if (this instanceof StatusCompleted) - return (StatusCompleted) this; - - throw new IllegalStateException(); - } - - public static final class StatusExecuting extends AdHocCommandResult { - private StatusExecuting(AdHocCommandData response) { - super(response, false); - assert response.getStatus() == AdHocCommandData.Status.executing; - } - - public FillableForm getFillableForm() { - DataForm form = getResponse().getForm(); - return new FillableForm(form); - } - } - - public static final class StatusCompleted extends AdHocCommandResult { - private StatusCompleted(AdHocCommandData response) { - super(response, true); - assert response.getStatus() == AdHocCommandData.Status.completed; - } - } - - /** - * This subclass is only used internally by Smack. - */ - @SuppressWarnings("JavaLangClash") - static final class Error extends AdHocCommandResult { - private Error(AdHocCommandData response) { - super(response, false); - } - } - - public static AdHocCommandResult from(AdHocCommandData response) { - IQ.Type iqType = response.getType(); - if (iqType == IQ.Type.error) - return new Error(response); - - assert iqType == IQ.Type.result; - - switch (response.getStatus()) { - case executing: - return new StatusExecuting(response); - case completed: - return new StatusCompleted(response); - default: - throw new IllegalArgumentException(); - } - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/LocalCommand.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/LocalCommand.java new file mode 100755 index 000000000..1dd01d3ab --- /dev/null +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/LocalCommand.java @@ -0,0 +1,168 @@ +/** + * + * Copyright 2005-2007 Jive Software. + * + * 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.smackx.commands; + +import org.jivesoftware.smackx.commands.packet.AdHocCommandData; + +import org.jxmpp.jid.Jid; + +/** + * Represents a command that can be executed locally from a remote location. This + * class must be extended to implement an specific ad-hoc command. This class + * provides some useful tools:
      + *
    • Node
    • + *
    • Name
    • + *
    • Session ID
    • + *
    • Current Stage
    • + *
    • Available actions
    • + *
    • Default action
    • + *
    + * To implement a new command extend this class and implement all the abstract + * methods. When implementing the actions remember that they could be invoked + * several times, and that you must use the current stage number to know what to + * do. + * + * @author Gabriel Guardincerri + */ +public abstract class LocalCommand extends AdHocCommand { + + /** + * The time stamp of first invocation of the command. Used to implement the session timeout. + */ + private final long creationDate; + + /** + * The unique ID of the execution of the command. + */ + private String sessionID; + + /** + * The full JID of the host of the command. + */ + private Jid ownerJID; + + /** + * The number of the current stage. + */ + private int currentStage; + + public LocalCommand() { + super(); + this.creationDate = System.currentTimeMillis(); + currentStage = -1; + } + + /** + * The sessionID is an unique identifier of an execution request. This is + * automatically handled and should not be called. + * + * @param sessionID the unique session id of this execution + */ + public void setSessionID(String sessionID) { + this.sessionID = sessionID; + getData().setSessionID(sessionID); + } + + /** + * Returns the session ID of this execution. + * + * @return the unique session id of this execution + */ + public String getSessionID() { + return sessionID; + } + + /** + * Sets the JID of the command host. This is automatically handled and should + * not be called. + * + * @param ownerJID the JID of the owner. + */ + public void setOwnerJID(Jid ownerJID) { + this.ownerJID = ownerJID; + } + + @Override + public Jid getOwnerJID() { + return ownerJID; + } + + /** + * Returns the date the command was created. + * + * @return the date the command was created. + */ + public long getCreationDate() { + return creationDate; + } + + /** + * Returns true if the current stage is the last one. If it is then the + * execution of some action will complete the execution of the command. + * Commands that don't have multiple stages can always return true. + * + * @return true if the command is in the last stage. + */ + public abstract boolean isLastStage(); + + /** + * Returns true if the specified requester has permission to execute all the + * stages of this action. This is checked when the first request is received, + * if the permission is grant then the requester will be able to execute + * all the stages of the command. It is not checked again during the + * execution. + * + * @param jid the JID to check permissions on. + * @return true if the user has permission to execute this action. + */ + public abstract boolean hasPermission(Jid jid); + + /** + * Returns the currently executing stage number. The first stage number is + * 0. During the execution of the first action this method will answer 0. + * + * @return the current stage number. + */ + public int getCurrentStage() { + return currentStage; + } + + @Override + void setData(AdHocCommandData data) { + data.setSessionID(sessionID); + super.setData(data); + } + + /** + * Increase the current stage number. This is automatically handled and should + * not be called. + * + */ + void incrementStage() { + currentStage++; + } + + /** + * Decrease the current stage number. This is automatically handled and should + * not be called. + * + */ + void decrementStage() { + currentStage--; + } +} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandHandlerFactory.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/LocalCommandFactory.java similarity index 64% rename from smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandHandlerFactory.java rename to smack-extensions/src/main/java/org/jivesoftware/smackx/commands/LocalCommandFactory.java index 1ea08477b..bc635d72a 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandHandlerFactory.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/LocalCommandFactory.java @@ -19,31 +19,28 @@ package org.jivesoftware.smackx.commands; import java.lang.reflect.InvocationTargetException; /** - * A factory for creating ad-hoc command handlers. It's useful in cases where instantiation + * A factory for creating local commands. It's useful in cases where instantiation * of a command is more complicated than just using the default constructor. For example, * when arguments must be passed into the constructor or when using a dependency injection - * framework. When a factory isn't used, you can provide the AdHocCommandManager + * framework. When a LocalCommandFactory isn't used, you can provide the AdHocCommandManager * a Class object instead. For more details, see - * {@link AdHocCommandManager#registerCommand(String, String, AdHocCommandHandlerFactory)}. + * {@link AdHocCommandManager#registerCommand(String, String, LocalCommandFactory)}. * * @author Matt Tucker */ -public interface AdHocCommandHandlerFactory { +public interface LocalCommandFactory { /** - * Returns a new instance of an ad-hoc command handler. + * Returns an instance of a LocalCommand. * - * @param node the node of the ad-hoc command. - * @param name the name of the ad-hoc command. - * @param sessionId the session ID of the ad-hoc command. * @return a LocalCommand instance. * @throws InstantiationException if creating an instance failed. * @throws IllegalAccessException if creating an instance is not allowed. + * @throws SecurityException if there was a security violation. + * @throws NoSuchMethodException if no such method is declared * @throws InvocationTargetException if a reflection-based method or constructor invocation threw. * @throws IllegalArgumentException if an illegal argument was given. */ - AdHocCommandHandler create(String node, String name, String sessionId) - throws InstantiationException, IllegalAccessException, IllegalArgumentException, - InvocationTargetException; + LocalCommand getInstance() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/RemoteCommand.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/RemoteCommand.java new file mode 100755 index 000000000..e79919eb6 --- /dev/null +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/RemoteCommand.java @@ -0,0 +1,164 @@ +/** + * + * Copyright 2005-2007 Jive Software. + * + * 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.smackx.commands; + +import org.jivesoftware.smack.SmackException.NoResponseException; +import org.jivesoftware.smack.SmackException.NotConnectedException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.XMPPException.XMPPErrorException; +import org.jivesoftware.smack.packet.IQ; + +import org.jivesoftware.smackx.commands.packet.AdHocCommandData; +import org.jivesoftware.smackx.xdata.form.FillableForm; +import org.jivesoftware.smackx.xdata.packet.DataForm; + +import org.jxmpp.jid.Jid; + +/** + * Represents a command that is in a remote location. Invoking one of the + * {@link AdHocCommand.Action#execute execute}, {@link AdHocCommand.Action#next next}, + * {@link AdHocCommand.Action#prev prev}, {@link AdHocCommand.Action#cancel cancel} or + * {@link AdHocCommand.Action#complete complete} actions results in executing that + * action in the remote location. In response to that action the internal state + * of the this command instance will change. For example, if the command is a + * single stage command, then invoking the execute action will execute this + * action in the remote location. After that the local instance will have a + * state of "completed" and a form or notes that applies. + * + * @author Gabriel Guardincerri + * + */ +public class RemoteCommand extends AdHocCommand { + + /** + * The connection that is used to execute this command + */ + private final XMPPConnection connection; + + /** + * The full JID of the command host + */ + private final Jid jid; + + /** + * The session ID of this execution. + */ + private String sessionID; + + /** + * Creates a new RemoteCommand that uses an specific connection to execute a + * command identified by node in the host identified by + * jid + * + * @param connection the connection to use for the execution. + * @param node the identifier of the command. + * @param jid the JID of the host. + */ + protected RemoteCommand(XMPPConnection connection, String node, Jid jid) { + super(); + this.connection = connection; + this.jid = jid; + this.setNode(node); + } + + @Override + public void cancel() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + executeAction(Action.cancel); + } + + @Override + public void complete(FillableForm form) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + executeAction(Action.complete, form.getDataFormToSubmit()); + } + + @Override + public void execute() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + executeAction(Action.execute); + } + + /** + * Executes the default action of the command with the information provided + * in the Form. This form must be the answer form of the previous stage. If + * there is a problem executing the command it throws an XMPPException. + * + * @param form the form answer of the previous stage. + * @throws XMPPErrorException if an error occurs. + * @throws NoResponseException if there was no response from the server. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + */ + public void execute(FillableForm form) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + executeAction(Action.execute, form.getDataFormToSubmit()); + } + + @Override + public void next(FillableForm form) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + executeAction(Action.next, form.getDataFormToSubmit()); + } + + @Override + public void prev() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + executeAction(Action.prev); + } + + private void executeAction(Action action) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + executeAction(action, null); + } + + /** + * Executes the action with the form. + * The action could be any of the available actions. The form must + * be the answer of the previous stage. It can be null if it is the first stage. + * + * @param action the action to execute. + * @param form the form with the information. + * @throws XMPPErrorException if there is a problem executing the command. + * @throws NoResponseException if there was no response from the server. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + */ + private void executeAction(Action action, DataForm form) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + // TODO: Check that all the required fields of the form were filled, if + // TODO: not throw the corresponding exception. This will make a faster response, + // TODO: since the request is stopped before it's sent. + AdHocCommandData data = new AdHocCommandData(); + data.setType(IQ.Type.set); + data.setTo(getOwnerJID()); + data.setNode(getNode()); + data.setSessionID(sessionID); + data.setAction(action); + data.setForm(form); + + AdHocCommandData responseData = null; + try { + responseData = connection.sendIqRequestAndWaitForResponse(data); + } + finally { + // We set the response data in a 'finally' block, so that it also gets set even if an error IQ was returned. + if (responseData != null) { + this.sessionID = responseData.getSessionID(); + super.setData(responseData); + } + } + + } + + @Override + public Jid getOwnerJID() { + return jid; + } +} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/SpecificErrorCondition.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/SpecificErrorCondition.java deleted file mode 100644 index fcf94a989..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/SpecificErrorCondition.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * - * Copyright 2005-2007 Jive Software. - * - * 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.smackx.commands; - -public enum SpecificErrorCondition { - - /** - * The responding JID cannot accept the specified action. - */ - badAction("bad-action"), - - /** - * The responding JID does not understand the specified action. - */ - malformedAction("malformed-action"), - - /** - * The responding JID cannot accept the specified language/locale. - */ - badLocale("bad-locale"), - - /** - * The responding JID cannot accept the specified payload (e.g. the data - * form did not provide one or more required fields). - */ - badPayload("bad-payload"), - - /** - * The responding JID cannot accept the specified sessionid. - */ - badSessionid("bad-sessionid"), - - /** - * The requesting JID specified a sessionid that is no longer active - * (either because it was completed, canceled, or timed out). - */ - sessionExpired("session-expired"); - - private final String value; - - SpecificErrorCondition(String value) { - this.value = value; - } - - @Override - public String toString() { - return value; - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandData.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandData.java index 19f29ac9b..f5681b0fc 100755 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandData.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandData.java @@ -18,114 +18,63 @@ package org.jivesoftware.smackx.commands.packet; import java.util.ArrayList; -import java.util.EnumSet; import java.util.List; -import java.util.Set; -import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.IqData; import org.jivesoftware.smack.packet.XmlElement; +import org.jivesoftware.smackx.commands.AdHocCommand; +import org.jivesoftware.smackx.commands.AdHocCommand.Action; +import org.jivesoftware.smackx.commands.AdHocCommand.SpecificErrorCondition; import org.jivesoftware.smackx.commands.AdHocCommandNote; -import org.jivesoftware.smackx.commands.SpecificErrorCondition; import org.jivesoftware.smackx.xdata.packet.DataForm; +import org.jxmpp.jid.Jid; + /** * Represents the state and the request of the execution of an adhoc command. * * @author Gabriel Guardincerri - * @author Florian Schmaus */ -public class AdHocCommandData extends IQ implements AdHocCommandDataView { +public class AdHocCommandData extends IQ { public static final String ELEMENT = "command"; public static final String NAMESPACE = "http://jabber.org/protocol/commands"; - private final String node; + /* JID of the command host */ + private Jid id; - private final String name; + /* Command name */ + private String name; - private final String sessionId; + /* Command identifier */ + private String node; + + /* Unique ID of the execution */ + private String sessionID; private final List notes = new ArrayList<>(); - private final DataForm form; + private DataForm form; - private final Action action; + /* Action request to be executed */ + private AdHocCommand.Action action; - private final Status status; + /* Current execution status */ + private AdHocCommand.Status status; - private final Set actions = EnumSet.noneOf(AllowedAction.class); + private final ArrayList actions = new ArrayList<>(); - private final AllowedAction executeAction; + private AdHocCommand.Action executeAction; - public AdHocCommandData(AdHocCommandDataBuilder builder) { - super(builder, ELEMENT, NAMESPACE); - node = builder.getNode(); - name = builder.getName(); - sessionId = builder.getSessionId(); - notes.addAll(builder.getNotes()); - form = builder.getForm(); - action = builder.getAction(); - status = builder.getStatus(); - actions.addAll(builder.getActions()); - executeAction = builder.getExecuteAction(); - - if (executeAction != null && !actions.contains(executeAction)) { - throw new IllegalArgumentException("Execute action " + executeAction + " is not part of allowed actions: " + actions); - } - } - - @Override - public String getNode() { - return node; - } - - @Override - public String getName() { - return name; - } - - @Override - public String getSessionId() { - return sessionId; - } - - @Override - public List getNotes() { - return notes; - } - - @Override - public DataForm getForm() { - return form; - } - - @Override - public Action getAction() { - return action; - } - - @Override - public Status getStatus() { - return status; - } - - @Override - public Set getActions() { - return actions; - } - - @Override - public AllowedAction getExecuteAction() { - return executeAction; + public AdHocCommandData() { + super(ELEMENT, NAMESPACE); } @Override protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { xml.attribute("node", node); - xml.optAttribute("sessionid", sessionId); + xml.optAttribute("sessionid", sessionID); xml.optAttribute("status", status); xml.optAttribute("action", action); xml.rightAngleBracket(); @@ -138,19 +87,19 @@ public class AdHocCommandData extends IQ implements AdHocCommandDataView { } else { xml.rightAngleBracket(); - for (AdHocCommandData.AllowedAction action : actions) { + for (AdHocCommand.Action action : actions) { xml.emptyElement(action); } xml.closeElement("actions"); } } - xml.optAppend(form); + if (form != null) { + xml.append(form.toXML()); + } for (AdHocCommandNote note : notes) { - xml.halfOpenElement("note") - .attribute("type", note.getType().toString()) - .rightAngleBracket(); + xml.halfOpenElement("note").attribute("type", note.getType().toString()).rightAngleBracket(); xml.append(note.getValue()); xml.closeElement("note"); } @@ -163,16 +112,132 @@ public class AdHocCommandData extends IQ implements AdHocCommandDataView { return xml; } - public static AdHocCommandDataBuilder builder(String node, IqData iqCommon) { - return new AdHocCommandDataBuilder(node, iqCommon); + /** + * Returns the JID of the command host. + * + * @return the JID of the command host. + */ + public Jid getId() { + return id; } - public static AdHocCommandDataBuilder builder(String node, String stanzaId) { - return new AdHocCommandDataBuilder(node, stanzaId); + public void setId(Jid id) { + this.id = id; } - public static AdHocCommandDataBuilder builder(String node, XMPPConnection connection) { - return new AdHocCommandDataBuilder(node, connection); + /** + * Returns the human name of the command. + * + * @return the name of the command. + */ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + /** + * Returns the identifier of the command. + * + * @return the node. + */ + public String getNode() { + return node; + } + + public void setNode(String node) { + this.node = node; + } + + /** + * Returns the list of notes that the command has. + * + * @return the notes. + */ + public List getNotes() { + return notes; + } + + public void addNote(AdHocCommandNote note) { + this.notes.add(note); + } + + public void removeNote(AdHocCommandNote note) { + this.notes.remove(note); + } + + /** + * Returns the form of the command. + * + * @return the data form associated with the command. + */ + public DataForm getForm() { + return form; + } + + public void setForm(DataForm form) { + this.form = form; + } + + /** + * Returns the action to execute. The action is set only on a request. + * + * @return the action to execute. + */ + public AdHocCommand.Action getAction() { + return action; + } + + public void setAction(AdHocCommand.Action action) { + this.action = action; + } + + /** + * Returns the status of the execution. + * + * @return the status. + */ + public AdHocCommand.Status getStatus() { + return status; + } + + public void setStatus(AdHocCommand.Status status) { + this.status = status; + } + + public List getActions() { + return actions; + } + + public void addAction(Action action) { + actions.add(action); + } + + public void setExecuteAction(Action executeAction) { + this.executeAction = executeAction; + } + + public Action getExecuteAction() { + return executeAction; + } + + /** + * Set the 'sessionid' attribute of the command. + *

    + * This value can be null or empty for the first command, but MUST be set for subsequent commands. See also XEP-0050 § 3.3 Session Lifetime. + *

    + * + * @param sessionID TODO javadoc me please + */ + public void setSessionID(String sessionID) { + this.sessionID = sessionID; + } + + public String getSessionID() { + return sessionID; } public static class SpecificError implements XmlElement { @@ -206,86 +271,4 @@ public class AdHocCommandData extends IQ implements AdHocCommandDataView { return buf.toString(); } } - - /** - * The status of the stage in the adhoc command. - */ - public enum Status { - - /** - * The command is being executed. - */ - executing, - - /** - * The command has completed. The command session has ended. - */ - completed, - - /** - * The command has been canceled. The command session has ended. - */ - canceled - } - - public enum AllowedAction { - - /** - * The command should be digress to the previous stage of execution. - */ - prev(Action.prev), - - /** - * The command should progress to the next stage of execution. - */ - next(Action.next), - - /** - * The command should be completed (if possible). - */ - complete(Action.complete), - ; - - public final Action action; - - AllowedAction(Action action) { - this.action = action; - } - } - - public enum Action { - /** - * The command should be executed or continue to be executed. This is - * the default value. - */ - execute(null), - - /** - * The command should be canceled. - */ - cancel(null), - - /** - * The command should be digress to the previous stage of execution. - */ - prev(AllowedAction.prev), - - /** - * The command should progress to the next stage of execution. - */ - next(AllowedAction.next), - - /** - * The command should be completed (if possible). - */ - complete(AllowedAction.complete), - ; - - public final AllowedAction allowedAction; - - Action(AllowedAction allowedAction) { - this.allowedAction = allowedAction; - } - - } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandDataBuilder.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandDataBuilder.java deleted file mode 100644 index fea5e6259..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandDataBuilder.java +++ /dev/null @@ -1,220 +0,0 @@ -/** - * - * Copyright 2023 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.smackx.commands.packet; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; -import java.util.Set; - -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.packet.AbstractIqBuilder; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.IqBuilder; -import org.jivesoftware.smack.packet.IqData; -import org.jivesoftware.smack.util.StringUtils; - -import org.jivesoftware.smackx.commands.AdHocCommandNote; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData.Action; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData.AllowedAction; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData.Status; -import org.jivesoftware.smackx.xdata.packet.DataForm; - -public class AdHocCommandDataBuilder extends IqBuilder implements AdHocCommandDataView { - - private final String node; - - private String name; - - private String sessionId; - - private final List notes = new ArrayList<>(); - - private DataForm form; - - /* Action request to be executed */ - private Action action; - - /* Current execution status */ - private Status status; - - private final Set actions = EnumSet.noneOf(AllowedAction.class); - - private AllowedAction executeAction; - - AdHocCommandDataBuilder(String node, IqData iqCommon) { - super(iqCommon); - this.node = StringUtils.requireNotNullNorEmpty(node, "Ad-Hoc Command node must be set"); - } - - AdHocCommandDataBuilder(String node, String stanzaId) { - super(stanzaId); - this.node = StringUtils.requireNotNullNorEmpty(node, "Ad-Hoc Command node must be set"); - } - - AdHocCommandDataBuilder(String node, XMPPConnection connection) { - super(connection); - this.node = StringUtils.requireNotNullNorEmpty(node, "Ad-Hoc Command node must be set"); - } - - @Override - public String getNode() { - return node; - } - - @Override - public String getName() { - return name; - } - - public AdHocCommandDataBuilder setName(String name) { - this.name = name; - return getThis(); - } - - @Override - public String getSessionId() { - return sessionId; - } - - public AdHocCommandDataBuilder setSessionId(String sessionId) { - this.sessionId = sessionId; - return getThis(); - } - - @Override - public List getNotes() { - return notes; - } - - public AdHocCommandDataBuilder addNote(AdHocCommandNote note) { - notes.add(note); - return getThis(); - } - - @Override - public DataForm getForm() { - return form; - } - - public AdHocCommandDataBuilder setForm(DataForm form) { - this.form = form; - return getThis(); - } - - @Override - public Action getAction() { - return action; - } - - public AdHocCommandDataBuilder setAction(AdHocCommandData.Action action) { - this.action = action; - return getThis(); - } - @Override - - public AdHocCommandData.Status getStatus() { - return status; - } - - public AdHocCommandDataBuilder setStatus(AdHocCommandData.Status status) { - this.status = status; - return getThis(); - } - - public AdHocCommandDataBuilder setStatusCompleted() { - return setStatus(AdHocCommandData.Status.completed); - } - - public enum PreviousStage { - exists, - none, - } - - public enum NextStage { - isFinal, - nonFinal, - } - - @SuppressWarnings("fallthrough") - public AdHocCommandDataBuilder setStatusExecuting(PreviousStage previousStage, NextStage nextStage) { - setStatus(AdHocCommandData.Status.executing); - - switch (previousStage) { - case exists: - addAction(AllowedAction.prev); - break; - case none: - break; - } - - setExecuteAction(AllowedAction.next); - - switch (nextStage) { - case isFinal: - addAction(AllowedAction.complete); - // Override execute action of 'next'. - setExecuteAction(AllowedAction.complete); - // Deliberate fallthrough, we want 'next' to be added. - case nonFinal: - addAction(AllowedAction.next); - break; - } - - return getThis(); - } - - @Override - public Set getActions() { - return actions; - } - - public AdHocCommandDataBuilder addAction(AllowedAction action) { - actions.add(action); - return getThis(); - } - - @Override - public AllowedAction getExecuteAction() { - return executeAction; - } - - public AdHocCommandDataBuilder setExecuteAction(AllowedAction action) { - this.executeAction = action; - return getThis(); - } - - @Override - public AdHocCommandData build() { - return new AdHocCommandData(this); - } - - @Override - public AdHocCommandDataBuilder getThis() { - return this; - } - - public static AdHocCommandDataBuilder buildResponseFor(AdHocCommandData request) { - return buildResponseFor(request, IQ.ResponseType.result); - } - - public static AdHocCommandDataBuilder buildResponseFor(AdHocCommandData request, IQ.ResponseType responseType) { - AdHocCommandDataBuilder builder = new AdHocCommandDataBuilder(request.getNode(), AbstractIqBuilder.createResponse(request, responseType)); - return builder; - } - -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandDataView.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandDataView.java deleted file mode 100644 index f1cc4b0ca..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandDataView.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * - * Copyright 2023 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.smackx.commands.packet; - -import java.util.List; -import java.util.Set; - -import org.jivesoftware.smack.packet.IqView; - -import org.jivesoftware.smackx.commands.AdHocCommandNote; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData.Action; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData.AllowedAction; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData.Status; -import org.jivesoftware.smackx.xdata.packet.DataForm; - -public interface AdHocCommandDataView extends IqView { - - /** - * Returns the identifier of the command. - * - * @return the node. - */ - String getNode(); - - /** - * Returns the human name of the command. - * - * @return the name of the command. - */ - String getName(); - - String getSessionId(); - - /** - * Returns the list of notes that the command has. - * - * @return the notes. - */ - List getNotes(); - - /** - * Returns the form of the command. - * - * @return the data form associated with the command. - */ - DataForm getForm(); - - /** - * Returns the action to execute. The action is set only on a request. - * - * @return the action to execute. - */ - Action getAction(); - - /** - * Returns the status of the execution. - * - * @return the status. - */ - Status getStatus(); - - Set getActions(); - - AllowedAction getExecuteAction(); - - default boolean isCompleted() { - return getStatus() == Status.completed; - } - - default boolean isExecuting() { - return getStatus() == Status.executing; - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/provider/AdHocCommandDataProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/provider/AdHocCommandDataProvider.java index 6f9b75477..26dfa56a3 100755 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/provider/AdHocCommandDataProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/provider/AdHocCommandDataProvider.java @@ -29,13 +29,10 @@ import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.xml.XmlPullParser; import org.jivesoftware.smack.xml.XmlPullParserException; +import org.jivesoftware.smackx.commands.AdHocCommand; +import org.jivesoftware.smackx.commands.AdHocCommand.Action; import org.jivesoftware.smackx.commands.AdHocCommandNote; -import org.jivesoftware.smackx.commands.SpecificErrorCondition; import org.jivesoftware.smackx.commands.packet.AdHocCommandData; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData.Action; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData.AllowedAction; -import org.jivesoftware.smackx.commands.packet.AdHocCommandDataBuilder; -import org.jivesoftware.smackx.xdata.packet.DataForm; import org.jivesoftware.smackx.xdata.provider.DataFormProvider; /** @@ -47,69 +44,64 @@ public class AdHocCommandDataProvider extends IqProvider { @Override public AdHocCommandData parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { - String commandNode = parser.getAttributeValue("node"); - AdHocCommandDataBuilder builder = AdHocCommandData.builder(commandNode, iqData); + boolean done = false; + AdHocCommandData adHocCommandData = new AdHocCommandData(); DataFormProvider dataFormProvider = new DataFormProvider(); - String sessionId = parser.getAttributeValue("sessionid"); - builder.setSessionId(sessionId); + XmlPullParser.Event eventType; + String elementName; + String namespace; + adHocCommandData.setSessionID(parser.getAttributeValue("", "sessionid")); + adHocCommandData.setNode(parser.getAttributeValue("", "node")); // Status String status = parser.getAttributeValue("", "status"); - if (AdHocCommandData.Status.executing.toString().equalsIgnoreCase(status)) { - builder.setStatus(AdHocCommandData.Status.executing); + if (AdHocCommand.Status.executing.toString().equalsIgnoreCase(status)) { + adHocCommandData.setStatus(AdHocCommand.Status.executing); } - else if (AdHocCommandData.Status.completed.toString().equalsIgnoreCase(status)) { - builder.setStatus(AdHocCommandData.Status.completed); + else if (AdHocCommand.Status.completed.toString().equalsIgnoreCase(status)) { + adHocCommandData.setStatus(AdHocCommand.Status.completed); } - else if (AdHocCommandData.Status.canceled.toString().equalsIgnoreCase(status)) { - builder.setStatus(AdHocCommandData.Status.canceled); + else if (AdHocCommand.Status.canceled.toString().equalsIgnoreCase(status)) { + adHocCommandData.setStatus(AdHocCommand.Status.canceled); } // Action String action = parser.getAttributeValue("", "action"); if (action != null) { - Action realAction = Action.valueOf(action); - if (realAction == null) { - throw new SmackParsingException("Invalid value for action attribute: " + action); + Action realAction = AdHocCommand.Action.valueOf(action); + if (realAction == null || realAction.equals(Action.unknown)) { + adHocCommandData.setAction(Action.unknown); + } + else { + adHocCommandData.setAction(realAction); } - - builder.setAction(realAction); } - - // TODO: Improve parsing below. Currently, the next actions like are not checked for the correct position. - outerloop: - while (true) { - String elementName; - XmlPullParser.Event event = parser.next(); - String namespace = parser.getNamespace(); - switch (event) { - case START_ELEMENT: + while (!done) { + eventType = parser.next(); + namespace = parser.getNamespace(); + if (eventType == XmlPullParser.Event.START_ELEMENT) { elementName = parser.getName(); - switch (elementName) { - case "actions": - String execute = parser.getAttributeValue("execute"); + if (parser.getName().equals("actions")) { + String execute = parser.getAttributeValue("", "execute"); if (execute != null) { - builder.setExecuteAction(AllowedAction.valueOf(execute)); + adHocCommandData.setExecuteAction(AdHocCommand.Action.valueOf(execute)); } - break; - case "next": - builder.addAction(AllowedAction.next); - break; - case "complete": - builder.addAction(AllowedAction.complete); - break; - case "prev": - builder.addAction(AllowedAction.prev); - break; - case "x": - if (namespace.equals("jabber:x:data")) { - DataForm form = dataFormProvider.parse(parser); - builder.setForm(form); - } - break; - case "note": - String typeString = parser.getAttributeValue("type"); + } + else if (parser.getName().equals("next")) { + adHocCommandData.addAction(AdHocCommand.Action.next); + } + else if (parser.getName().equals("complete")) { + adHocCommandData.addAction(AdHocCommand.Action.complete); + } + else if (parser.getName().equals("prev")) { + adHocCommandData.addAction(AdHocCommand.Action.prev); + } + else if (elementName.equals("x") && namespace.equals("jabber:x:data")) { + adHocCommandData.setForm(dataFormProvider.parse(parser)); + } + else if (parser.getName().equals("note")) { + String typeString = parser.getAttributeValue("", "type"); AdHocCommandNote.Type type; if (typeString != null) { type = AdHocCommandNote.Type.valueOf(typeString); @@ -118,67 +110,61 @@ public class AdHocCommandDataProvider extends IqProvider { type = AdHocCommandNote.Type.info; } String value = parser.nextText(); - builder.addNote(new AdHocCommandNote(type, value)); - break; - case "error": + adHocCommandData.addNote(new AdHocCommandNote(type, value)); + } + else if (parser.getName().equals("error")) { StanzaError error = PacketParserUtils.parseError(parser); - builder.setError(error); - break; + adHocCommandData.setError(error); } - break; - case END_ELEMENT: + } + else if (eventType == XmlPullParser.Event.END_ELEMENT) { if (parser.getName().equals("command")) { - break outerloop; + done = true; } - break; - default: - // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement. - break; } } - - return builder.build(); + return adHocCommandData; } public static class BadActionError extends ExtensionElementProvider { @Override public AdHocCommandData.SpecificError parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) { - return new AdHocCommandData.SpecificError(SpecificErrorCondition.badAction); + return new AdHocCommandData.SpecificError(AdHocCommand.SpecificErrorCondition.badAction); } } public static class MalformedActionError extends ExtensionElementProvider { @Override public AdHocCommandData.SpecificError parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) { - return new AdHocCommandData.SpecificError(SpecificErrorCondition.malformedAction); + return new AdHocCommandData.SpecificError(AdHocCommand.SpecificErrorCondition.malformedAction); } } public static class BadLocaleError extends ExtensionElementProvider { @Override public AdHocCommandData.SpecificError parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) { - return new AdHocCommandData.SpecificError(SpecificErrorCondition.badLocale); + return new AdHocCommandData.SpecificError(AdHocCommand.SpecificErrorCondition.badLocale); } } public static class BadPayloadError extends ExtensionElementProvider { @Override public AdHocCommandData.SpecificError parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) { - return new AdHocCommandData.SpecificError(SpecificErrorCondition.badPayload); + return new AdHocCommandData.SpecificError(AdHocCommand.SpecificErrorCondition.badPayload); } } public static class BadSessionIDError extends ExtensionElementProvider { @Override public AdHocCommandData.SpecificError parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) { - return new AdHocCommandData.SpecificError(SpecificErrorCondition.badSessionid); + return new AdHocCommandData.SpecificError(AdHocCommand.SpecificErrorCondition.badSessionid); } } public static class SessionExpiredError extends ExtensionElementProvider { @Override public AdHocCommandData.SpecificError parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) { - return new AdHocCommandData.SpecificError(SpecificErrorCondition.sessionExpired); + return new AdHocCommandData.SpecificError(AdHocCommand.SpecificErrorCondition.sessionExpired); } } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/delay/filter/DelayedStanzaFilter.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/delay/filter/DelayedStanzaFilter.java index 90c30f563..054ed42cf 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/delay/filter/DelayedStanzaFilter.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/delay/filter/DelayedStanzaFilter.java @@ -23,14 +23,14 @@ import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smackx.delay.DelayInformationManager; /** - * Filters stanza with delay information, i.e. stanzas that got delayed for some reason + * Filters stanza with delay information, ie. stanzas that got delayed for some reason */ public final class DelayedStanzaFilter implements StanzaFilter { public static final StanzaFilter INSTANCE = new DelayedStanzaFilter(); /** - * Filters stanzas that got not delayed, i.e. have no delayed information + * Filters stanzas that got not delayed, ie. have no delayed information */ public static final StanzaFilter NOT_DELAYED_STANZA = new NotFilter(INSTANCE); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/ServiceDiscoveryManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/ServiceDiscoveryManager.java index e50f6d956..6e43fbc9a 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/ServiceDiscoveryManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/ServiceDiscoveryManager.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2018-2024 Florian Schmaus. + * Copyright 2003-2007 Jive Software, 2018-2022 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -293,7 +294,7 @@ public final class ServiceDiscoveryManager extends Manager { /** * Returns all identities of this client as unmodifiable Collection. * - * @return all identities as a set + * @return all identies as set */ public Set getIdentities() { Set res = new HashSet<>(identities); @@ -441,6 +442,27 @@ public final class ServiceDiscoveryManager extends Manager { return features.contains(feature); } + /** + * Registers extended discovery information of this XMPP entity. When this + * client is queried for its information this data form will be returned as + * specified by XEP-0128. + *

    + * + * Since no stanza is actually sent to the server it is safe to perform this + * operation before logging to the server. In fact, you may want to + * configure the extended info before logging to the server so that the + * information is already available if it is required upon login. + * + * @param info the data form that contains the extend service discovery + * information. + * @deprecated use {@link #addExtendedInfo(DataForm)} instead. + */ + // TODO: Remove in Smack 4.5 + @Deprecated + public synchronized void setExtendedInfo(DataForm info) { + addExtendedInfo(info); + } + /** * Registers extended discovery information of this XMPP entity. When this * client is queried for its information this data form will be returned as @@ -496,6 +518,19 @@ public final class ServiceDiscoveryManager extends Manager { return CollectionUtil.newListWith(extendedInfos); } + /** + * Returns the data form as List of PacketExtensions, or null if no data form is set. + * This representation is needed by some classes (e.g. EntityCapsManager, NodeInformationProvider) + * + * @return the data form as List of PacketExtensions + * @deprecated use {@link #getExtendedInfo()} instead. + */ + // TODO: Remove in Smack 4.5 + @Deprecated + public List getExtendedInfoAsList() { + return getExtendedInfo(); + } + /** * Removes the data form containing extended service discovery information * from the information returned by this XMPP entity.

    @@ -771,7 +806,7 @@ public final class ServiceDiscoveryManager extends Manager { return serviceDiscoInfo; } } - serviceDiscoInfo = new ArrayList<>(); + serviceDiscoInfo = new LinkedList<>(); // Send the disco packet to the server itself DiscoverInfo info; try { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java index 9df5c64ac..abe18f630 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java @@ -17,8 +17,10 @@ package org.jivesoftware.smackx.disco.packet; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -81,6 +83,17 @@ public class DiscoverInfo extends IQ implements DiscoverInfoView { } } + /** + * Deprecated. + * + * @deprecated use {@link DiscoverInfoBuilder} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public DiscoverInfo() { + super(ELEMENT, NAMESPACE); + } + /** * Copy constructor. * @@ -101,11 +114,85 @@ public class DiscoverInfo extends IQ implements DiscoverInfoView { identitiesSet.addAll(d.identitiesSet); } + /** + * Adds a new feature to the discovered information. + * + * @param feature the discovered feature + * @return true if the feature did not already exist. + * @deprecated use {@link DiscoverInfoBuilder#addFeature(String)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public boolean addFeature(String feature) { + return addFeature(new Feature(feature)); + } + + /** + * Adds a collection of features to the packet. Does noting if featuresToAdd is null. + * + * @param featuresToAdd TODO javadoc me please + * @deprecated use {@link DiscoverInfoBuilder#addFeatures(Collection)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void addFeatures(Collection featuresToAdd) { + if (featuresToAdd == null) return; + for (String feature : featuresToAdd) { + addFeature(feature); + } + } + + /** + * Deprecated. + * + * @param feature the future. + * @return true if the feature is new. + * @deprecated use {@link DiscoverInfoBuilder#addFeature(DiscoverInfo.Feature)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public boolean addFeature(Feature feature) { + features.add(feature); + boolean featureIsNew = featuresSet.add(feature); + if (!featureIsNew) { + containsDuplicateFeatures = true; + } + return featureIsNew; + } + @Override public List getFeatures() { return Collections.unmodifiableList(features); } + /** + * Adds a new identity of the requested entity to the discovered information. + * + * @param identity the discovered entity's identity + * @deprecated use {@link DiscoverInfoBuilder#addIdentity(DiscoverInfo.Identity)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void addIdentity(Identity identity) { + identities.add(identity); + identitiesSet.add(identity.getKey()); + } + + /** + * Adds identities to the DiscoverInfo stanza. + * + * @param identitiesToAdd TODO javadoc me please + * @deprecated use {@link DiscoverInfoBuilder#addIdentities(Collection)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void addIdentities(Collection identitiesToAdd) { + if (identitiesToAdd == null) return; + for (Identity identity : identitiesToAdd) { + addIdentity(identity); + } + } + @Override public List getIdentities() { return Collections.unmodifiableList(identities); @@ -128,7 +215,7 @@ public class DiscoverInfo extends IQ implements DiscoverInfoView { * * @param category category the category to look for. * @param type type the type to look for. - * @return a list of Identities with the given category and type. + * @return a list of Identites with the given category and type. */ public List getIdentities(String category, String type) { List res = new ArrayList<>(identities.size()); @@ -145,6 +232,22 @@ public class DiscoverInfo extends IQ implements DiscoverInfoView { return node; } + /** + * Sets the node attribute that supplements the 'jid' attribute. A node is merely + * something that is associated with a JID and for which the JID can provide information.

    + * + * Node attributes SHOULD be used only when trying to provide or query information which + * is not directly addressable. + * + * @param node the node attribute that supplements the 'jid' attribute + * @deprecated use {@link DiscoverInfoBuilder#setNode(String)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void setNode(String node) { + this.node = StringUtils.requireNullOrNotEmpty(node, "The node can not be the empty string"); + } + /** * Returns true if the specified feature is part of the discovered information. * @@ -183,7 +286,7 @@ public class DiscoverInfo extends IQ implements DiscoverInfoView { * @return true if duplicate identities where found, otherwise false */ public boolean containsDuplicateIdentities() { - List checkedIdentities = new ArrayList<>(identities.size()); + List checkedIdentities = new LinkedList<>(); for (Identity i : identities) { for (Identity i2 : checkedIdentities) { if (i.equals(i2)) @@ -207,6 +310,18 @@ public class DiscoverInfo extends IQ implements DiscoverInfoView { return new DiscoverInfoBuilder(this, stanzaId); } + /** + * Deprecated, do not use. + * + * @deprecated use {@link #asBuilder(String)} instead. + */ + // TODO: Remove in Smack 4.5. + @Deprecated + @Override + public DiscoverInfo clone() { + return new DiscoverInfo(this); + } + public static DiscoverInfoBuilder builder(XMPPConnection connection) { return new DiscoverInfoBuilder(connection); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverItems.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverItems.java index a6394716c..34c62a8a1 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverItems.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverItems.java @@ -16,9 +16,9 @@ */ package org.jivesoftware.smackx.disco.packet; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.LinkedList; import java.util.List; import org.jivesoftware.smack.packet.IQ; @@ -40,7 +40,7 @@ public class DiscoverItems extends IQ { public static final String ELEMENT = QUERY_ELEMENT; public static final String NAMESPACE = "http://jabber.org/protocol/disco#items"; - private final List items = new ArrayList<>(); + private final List items = new LinkedList<>(); private String node; public DiscoverItems() { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/IncomingFileTransfer.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/IncomingFileTransfer.java index 9a17438d0..c09e9fcb2 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/IncomingFileTransfer.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/IncomingFileTransfer.java @@ -51,7 +51,7 @@ import org.jivesoftware.smack.util.CloseableUtil; * The second way that a file can be received through this class is by invoking * the {@link #receiveFile(File)} method. This method returns immediately and * takes as its parameter a file on the local file system where the file - * received from the transfer will be put. + * recieved from the transfer will be put. * * @author Alexander Wenckus */ diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/StreamNegotiator.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/StreamNegotiator.java index 0fc025827..adf7297e5 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/StreamNegotiator.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/StreamNegotiator.java @@ -52,7 +52,7 @@ public abstract class StreamNegotiator extends Manager { } /** - * An event manager for stream initiation requests send to us. + * A event manager for stream initiation requests send to us. *

    * Those are typical XEP-45 Open or XEP-65 Bytestream IQ requests. The even key is in the format * "initiationFrom + '\t' + streamId" diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/package-info.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/package-info.java index a05f6d56c..505394d1e 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/package-info.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/filetransfer/package-info.java @@ -144,7 +144,7 @@ *

  • **isDone()** - Similar to getProgress() except it returns a _boolean_. If the state is rejected, canceled, error, * or complete then true will be returned and false otherwise.
  • *
  • **getError()** - If there is an error during the file transfer this method will return the type of error that - * occurred.
  • + * occured. * *

    Examples

    *

    diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/formtypes/FormFieldRegistry.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/formtypes/FormFieldRegistry.java index 9dae0e1d5..5dda27842 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/formtypes/FormFieldRegistry.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/formtypes/FormFieldRegistry.java @@ -94,13 +94,7 @@ public class FormFieldRegistry { } else { previousType = fieldNameToType.get(fieldName); if (previousType != null && previousType != fieldType) { - String message = "The field '" + fieldName + "' from form type '" + formType - + "' was already registered with field type '" + previousType - + "' while it is now seen with type '" + fieldType - + "'. Form field types have to be unambigiously." - + " XMPP uses a registry for form field tpes, scoped by the form type." - + " You may find the correct value at https://xmpp.org/registrar/formtypes.html"; - throw new IllegalArgumentException(message); + throw new IllegalArgumentException(); } } previousType = fieldNameToType.put(fieldName, fieldType); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationManager.java index eb91bec55..f29306251 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/geoloc/GeoLocationManager.java @@ -43,7 +43,7 @@ import org.jxmpp.jid.Jid; *
    * To publish a UserLocation, please use {@link #publishGeoLocation(GeoLocation)} method. This will publish the node. *
    - * To stop publishing a UserLocation, please use {@link #stopPublishingGeolocation()} method. This will send a disable publishing signal. + * To stop publishing a UserLocation, please use {@link #stopPublishingGeolocation()} method. This will send a disble publishing signal. *
    * To add a {@link PepEventListener} in order to remain updated with other users GeoLocation, use {@link #addGeoLocationListener(PepEventListener)} method. *
    diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqlast/packet/LastActivity.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqlast/packet/LastActivity.java index 9a94d0198..08d3ac686 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqlast/packet/LastActivity.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqlast/packet/LastActivity.java @@ -45,13 +45,11 @@ public class LastActivity extends IQ { public long lastActivity = -1; public String message; - @SuppressWarnings("this-escape") public LastActivity() { super(ELEMENT, NAMESPACE); setType(IQ.Type.get); } - @SuppressWarnings("this-escape") public LastActivity(Jid to) { this(); setTo(to); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/packet/PrivateData.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/packet/PrivateData.java index c6670c900..058b0c2d5 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/packet/PrivateData.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/packet/PrivateData.java @@ -41,7 +41,7 @@ public interface PrivateData { String getNamespace(); /** - * Returns the XML representation of the PrivateData. + * Returns the XML reppresentation of the PrivateData. * * @return the private data as XML. */ diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/packet/PrivateDataIQ.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/packet/PrivateDataIQ.java index 5df357e09..6063e040e 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/packet/PrivateDataIQ.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/packet/PrivateDataIQ.java @@ -1,6 +1,6 @@ /** * - * Copyright 2014-2024 Florian Schmaus + * Copyright © 2014 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,13 +27,11 @@ public class PrivateDataIQ extends IQ { private final String getElement; private final String getNamespace; - @SuppressWarnings("this-escape") public PrivateDataIQ(PrivateData privateData) { this(privateData, null, null); setType(Type.set); } - @SuppressWarnings("this-escape") public PrivateDataIQ(String element, String namespace) { this(null, element, namespace); setType(Type.get); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/AccountManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/AccountManager.java index c6f32970c..7a991978c 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/AccountManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/AccountManager.java @@ -354,17 +354,15 @@ public final class AccountManager extends Manager { /** * Gets the account registration info from the server. * - * @return Registration information * @throws XMPPErrorException if there was an XMPP error returned. * @throws NoResponseException if there was no response from the remote entity. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public synchronized Registration getRegistrationInfo() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + private synchronized void getRegistrationInfo() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { Registration reg = new Registration(); reg.setTo(connection().getXMPPServiceDomain()); info = createStanzaCollectorAndSend(reg).nextResultOrThrow(); - return info; } private StanzaCollector createStanzaCollectorAndSend(IQ req) throws NotConnectedException, InterruptedException { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/provider/RegistrationProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/provider/RegistrationProvider.java index d087a5bf4..67da11bbe 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/provider/RegistrationProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/provider/RegistrationProvider.java @@ -17,8 +17,8 @@ package org.jivesoftware.smackx.iqregister.provider; import java.io.IOException; -import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -40,7 +40,7 @@ public class RegistrationProvider extends IqProvider { public Registration parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { String instruction = null; Map fields = new HashMap<>(); - List packetExtensions = new ArrayList<>(); + List packetExtensions = new LinkedList<>(); outerloop: while (true) { XmlPullParser.Event eventType = parser.next(); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqversion/packet/Version.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqversion/packet/Version.java index fb0ca01fa..b0dd5c1d0 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqversion/packet/Version.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqversion/packet/Version.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2021-2024 Florian Schmaus. + * Copyright 2003-2007 Jive Software, 2021 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import org.jivesoftware.smack.util.StringUtils; /** * A Version IQ packet, which is used by XMPP clients to discover version information - * about the software running at another entity's JID. + * about the software running at another entity's JID.

    * * @author Gaston Dombiak */ diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/element/Jingle.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/element/Jingle.java index 4fb09922c..ea36bcc31 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/element/Jingle.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/element/Jingle.java @@ -52,7 +52,7 @@ import org.jxmpp.jid.FullJid; * | transport-info * | transport-reject * | transport-replace - * │ initiator (RECOMMENDED for session initiate, NOT RECOMMENDED otherwise, full JID, XEP-0166 § 7.1) + * │ initator (RECOMMENDED for session initiate, NOT RECOMMENDED otherwise, full JID, XEP-0166 § 7.1) * │ responder (RECOMMENDED for session accept, NOT RECOMMENDED otherwise, full JID. XEP-0166 § 7.1) * │ sid (REQUIRED, SHOULD match XML Nmtoken production) * │ diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/element/JingleContent.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/element/JingleContent.java index 702183dd2..ab5680c1d 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/element/JingleContent.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/element/JingleContent.java @@ -71,7 +71,7 @@ public final class JingleContent implements XmlElement { private final JingleContentTransport transport; /** - * Creates a content description. + * Creates a content description.. */ private JingleContent(Creator creator, String disposition, String name, Senders senders, JingleContentDescription description, JingleContentTransport transport) { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/JingleTransportManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/JingleTransportManager.java index ba344ee7c..8c91c8976 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/JingleTransportManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/JingleTransportManager.java @@ -30,7 +30,6 @@ public abstract class JingleTransportManager i private final XMPPConnection connection; - @SuppressWarnings("this-escape") public JingleTransportManager(XMPPConnection connection) { this.connection = connection; connection.addConnectionListener(this); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/jingle_s5b/elements/JingleS5BTransportCandidate.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/jingle_s5b/elements/JingleS5BTransportCandidate.java index d3be5a4b3..4ad96fcca 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/jingle_s5b/elements/JingleS5BTransportCandidate.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/jingle_s5b/elements/JingleS5BTransportCandidate.java @@ -51,7 +51,7 @@ public final class JingleS5BTransportCandidate extends JingleContentTransportCan private final Type type; public JingleS5BTransportCandidate(String candidateId, String hostString, Jid jid, int port, int priority, Type type) { - this(candidateId, InternetAddress.fromIgnoringZoneId(hostString), jid, port, priority, type); + this(candidateId, InternetAddress.from(hostString), jid, port, priority, type); } public JingleS5BTransportCandidate(String candidateId, InternetAddress host, Jid jid, int port, int priority, Type type) { @@ -176,7 +176,7 @@ public final class JingleS5BTransportCandidate extends JingleContentTransportCan } public Builder setHost(String host) { - InternetAddress inetAddress = InternetAddress.fromIgnoringZoneId(host); + InternetAddress inetAddress = InternetAddress.from(host); return setHost(inetAddress); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/JivePropertiesManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/JivePropertiesManager.java index 09bf70c5b..f02f56c8e 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/JivePropertiesManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/JivePropertiesManager.java @@ -1,6 +1,6 @@ /** * - * Copyright 2014-2024 Florian Schmaus. + * Copyright 2014 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,6 +50,25 @@ public class JivePropertiesManager { return javaObjectEnabled; } + /** + * Convenience method to add a property to a packet. + * + * @param packet the stanza to add the property to. + * @param name the name of the property to add. + * @param value the value of the property to add. + * @deprecated use {@link #addProperty(StanzaBuilder, String, Object)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public static void addProperty(Stanza packet, String name, Object value) { + JivePropertiesExtension jpe = (JivePropertiesExtension) packet.getExtension(JivePropertiesExtension.NAMESPACE); + if (jpe == null) { + jpe = new JivePropertiesExtension(); + packet.addExtension(jpe); + } + jpe.setProperty(name, value); + } + /** * Convenience method to add a property to a stanza. * diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/package-info.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/package-info.java index a5ea271a5..45a9fe3e9 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/package-info.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/package-info.java @@ -70,7 +70,7 @@ chat.sendMessage(message); *

      *
    • When you send a Java object as a property, only clients running Java will be able to interpret the data. So, * consider using a series of primitive values to transfer data instead.
    • - *
    • Objects sent as property values must implement Serializable. Additionally, both the sender and receiver must have + *
    • Objects sent as property values must implement Serialiable. Additionally, both the sender and receiver must have * identical versions of the class, or a serialization exception will occur when de-serializing the object.
    • *
    • Serialized objects can potentially be quite large, which will use more bandwidth and server resources.
    • *
    diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/provider/JivePropertiesExtensionProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/provider/JivePropertiesExtensionProvider.java index 8326e93e5..6d99c1637 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/provider/JivePropertiesExtensionProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jiveproperties/provider/JivePropertiesExtensionProvider.java @@ -46,7 +46,7 @@ public class JivePropertiesExtensionProvider extends ExtensionElementProvider - * Note that you have to explicitly enabled Java object deserialization with + * Note that you have to explicitly enabled Java object deserialization with @{link * {@link JivePropertiesManager#setJavaObjectEnabled(boolean)} * * @param parser the XML parser, positioned at the start of a properties sub-packet. diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/last_interaction/element/IdleElement.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/last_interaction/element/IdleElement.java index 6603fe21b..2799c1224 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/last_interaction/element/IdleElement.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/last_interaction/element/IdleElement.java @@ -37,7 +37,6 @@ public class IdleElement implements ExtensionElement { /** * Create a new IdleElement with the current date as date of last user interaction. */ - @SuppressWarnings("JavaUtilDate") public IdleElement() { this(new Date()); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/Affiliate.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/Affiliate.java index d3e034c6c..3e3648f26 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/Affiliate.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/Affiliate.java @@ -55,10 +55,10 @@ public class Affiliate { } /** - * Returns the affiliation of the affiliated user. Possible affiliations are: "owner", "admin", + * Returns the affiliation of the afffiliated user. Possible affiliations are: "owner", "admin", * "member", "outcast". This information will always be available. * - * @return the affiliation of the affiliated user. + * @return the affiliation of the afffiliated user. */ public MUCAffiliation getAffiliation() { return affiliation; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/DefaultParticipantStatusListener.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/DefaultParticipantStatusListener.java new file mode 100644 index 000000000..c9d809cd2 --- /dev/null +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/DefaultParticipantStatusListener.java @@ -0,0 +1,98 @@ +/** + * + * Copyright 2003-2007 Jive Software. + * + * 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.smackx.muc; + +import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.parts.Resourcepart; + +/** + * Default implementation of the ParticipantStatusListener interface.

    + * + * This class does not provide any behavior by default. It just avoids having + * to implement all the inteface methods if the user is only interested in implementing + * some of the methods. + * + * @author Gaston Dombiak + * @deprecated use {@link ParticipantStatusListener} instead. + */ +// TODO: Remove in Smack 4.5 +@Deprecated +public class DefaultParticipantStatusListener implements ParticipantStatusListener { + + @Override + public void joined(EntityFullJid participant) { + } + + @Override + public void left(EntityFullJid participant) { + } + + @Override + public void kicked(EntityFullJid participant, Jid actor, String reason) { + } + + @Override + public void voiceGranted(EntityFullJid participant) { + } + + @Override + public void voiceRevoked(EntityFullJid participant) { + } + + @Override + public void banned(EntityFullJid participant, Jid actor, String reason) { + } + + @Override + public void membershipGranted(EntityFullJid participant) { + } + + @Override + public void membershipRevoked(EntityFullJid participant) { + } + + @Override + public void moderatorGranted(EntityFullJid participant) { + } + + @Override + public void moderatorRevoked(EntityFullJid participant) { + } + + @Override + public void ownershipGranted(EntityFullJid participant) { + } + + @Override + public void ownershipRevoked(EntityFullJid participant) { + } + + @Override + public void adminGranted(EntityFullJid participant) { + } + + @Override + public void adminRevoked(EntityFullJid participant) { + } + + @Override + public void nicknameChanged(EntityFullJid participant, Resourcepart newNickname) { + } + +} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/DefaultUserStatusListener.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/DefaultUserStatusListener.java new file mode 100644 index 000000000..0ac93ccbd --- /dev/null +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/DefaultUserStatusListener.java @@ -0,0 +1,88 @@ +/** + * + * Copyright 2003-2007 Jive Software. + * + * 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.smackx.muc; + +import org.jxmpp.jid.Jid; + +/** + * Default implementation of the UserStatusListener interface.

    + * + * This class does not provide any behavior by default. It just avoids having + * to implement all the inteface methods if the user is only interested in implementing + * some of the methods. + * + * @author Gaston Dombiak + * @deprecated use {@link UserStatusListener} instead. + */ +// TODO: Remove in Smack 4.5. +@Deprecated +public class DefaultUserStatusListener implements UserStatusListener { + + @Override + public void kicked(Jid actor, String reason) { + } + + @Override + public void voiceGranted() { + } + + @Override + public void voiceRevoked() { + } + + @Override + public void banned(Jid actor, String reason) { + } + + @Override + public void membershipGranted() { + } + + @Override + public void membershipRevoked() { + } + + @Override + public void moderatorGranted() { + } + + @Override + public void moderatorRevoked() { + } + + @Override + public void ownershipGranted() { + } + + @Override + public void ownershipRevoked() { + } + + @Override + public void adminGranted() { + } + + @Override + public void adminRevoked() { + } + + @Override + public void roomDestroyed(MultiUserChat alternateMUC, String reason) { + } + +} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/DirectMucInvitationListener.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/DirectMucInvitationListener.java deleted file mode 100644 index e8ef1af5e..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/DirectMucInvitationListener.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub. - * - * 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.smackx.muc; - -import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smackx.muc.packet.GroupChatInvitation; - -public interface DirectMucInvitationListener { - - void invitationReceived(GroupChatInvitation invitation, Stanza stanza); -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/DirectMucInvitationManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/DirectMucInvitationManager.java deleted file mode 100644 index b05f10df0..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/DirectMucInvitationManager.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub. - * - * 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.smackx.muc; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; - -import org.jivesoftware.smack.Manager; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPConnectionRegistry; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.filter.StanzaExtensionFilter; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.MessageBuilder; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; -import org.jivesoftware.smackx.muc.packet.GroupChatInvitation; - -import org.jxmpp.jid.EntityBareJid; - -/** - * Smacks API for XEP-0249: Direct MUC Invitations. - * Use this instead of {@link org.jivesoftware.smackx.muc.packet.MUCUser.Invite}. - * - * To invite a user to a group chat, use {@link #inviteToMuc(MultiUserChat, EntityBareJid)}. - * - * In order to listen for incoming invitations, register a {@link DirectMucInvitationListener} using - * {@link #addInvitationListener(DirectMucInvitationListener)}. - * - * @see Direct MUC Invitations - */ -public final class DirectMucInvitationManager extends Manager { - - private static final Map INSTANCES = new WeakHashMap<>(); - private final List directMucInvitationListeners = new ArrayList<>(); - private final ServiceDiscoveryManager serviceDiscoveryManager; - - static { - XMPPConnectionRegistry.addConnectionCreationListener(DirectMucInvitationManager::getInstanceFor); - } - - public static synchronized DirectMucInvitationManager getInstanceFor(XMPPConnection connection) { - DirectMucInvitationManager manager = INSTANCES.get(connection); - if (manager == null) { - manager = new DirectMucInvitationManager(connection); - INSTANCES.put(connection, manager); - } - return manager; - } - - private DirectMucInvitationManager(XMPPConnection connection) { - super(connection); - serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection); - - connection().addAsyncStanzaListener(stanza -> { - GroupChatInvitation invitation = stanza.getExtension(GroupChatInvitation.class); - for (DirectMucInvitationListener listener : directMucInvitationListeners) { - listener.invitationReceived(invitation, stanza); - } - }, new StanzaExtensionFilter(GroupChatInvitation.ELEMENT, GroupChatInvitation.NAMESPACE)); - serviceDiscoveryManager.addFeature(GroupChatInvitation.NAMESPACE); - } - - public void inviteToMuc(MultiUserChat muc, EntityBareJid user) - throws SmackException.NotConnectedException, InterruptedException { - inviteToMuc(muc, user, null, null, false, null); - } - - public void inviteToMuc(MultiUserChat muc, EntityBareJid user, String password, String reason, boolean continueAsOneToOneChat, String thread) - throws SmackException.NotConnectedException, InterruptedException { - inviteToMuc(user, new GroupChatInvitation(muc.getRoom(), reason, password, continueAsOneToOneChat, thread)); - } - - public void inviteToMuc(EntityBareJid jid, GroupChatInvitation invitation) throws SmackException.NotConnectedException, InterruptedException { - Message invitationMessage = MessageBuilder.buildMessage() - .to(jid) - .addExtension(invitation) - .build(); - connection().sendStanza(invitationMessage); - } - - public boolean userSupportsInvitations(EntityBareJid jid) - throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, - SmackException.NoResponseException { - return serviceDiscoveryManager.supportsFeature(jid, GroupChatInvitation.NAMESPACE); - } - - public synchronized void addInvitationListener(DirectMucInvitationListener listener) { - directMucInvitationListeners.add(listener); - } - - public synchronized void removeInvitationListener(DirectMucInvitationListener listener) { - directMucInvitationListeners.remove(listener); - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MucConfigFormManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MucConfigFormManager.java index b847cd025..1735d0b4f 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MucConfigFormManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MucConfigFormManager.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015-2024 Florian Schmaus + * Copyright 2015-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,6 @@ import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smackx.muc.MultiUserChatException.MucConfigurationNotSupportedException; -import org.jivesoftware.smackx.xdata.BooleanFormField; import org.jivesoftware.smackx.xdata.FormField; import org.jivesoftware.smackx.xdata.form.FillableForm; import org.jivesoftware.smackx.xdata.form.FilledForm; @@ -62,13 +61,6 @@ public class MucConfigFormManager { */ public static final String MUC_ROOMCONFIG_ROOMOWNERS = "muc#roomconfig_roomowners"; - /** - * The constant String {@value}. - * - * @see XEP-0045 § 10. Owner Use Cases - */ - public static final String MUC_ROOMCONFIG_ROOMADMINS = "muc#roomconfig_roomadmins"; - /** * The constant String {@value}. */ @@ -96,25 +88,10 @@ public class MucConfigFormManager { */ public static final String MUC_ROOMCONFIG_PUBLICLYSEARCHABLEROOM = "muc#roomconfig_publicroom"; - /** - * The constant String {@value}. - */ - public static final String MUC_ROOMCONFIG_ROOMNAME = "muc#roomconfig_roomname"; - - /** - * The constant String {@value}. - */ - public static final String MUC_ROOMCONFIG_ENABLE_PUBLIC_LOGGING = "muc#roomconfig_enablelogging"; - - /** - * The constant String {@value}. - */ - public static final String MUC_ROOMCONFIG_CHANGE_SUBJECT = "muc#roomconfig_changesubject"; private final MultiUserChat multiUserChat; private final FillableForm answerForm; private final List owners; - private final List admins; /** * Create a new MUC config form manager. @@ -148,18 +125,6 @@ public class MucConfigFormManager { // roomowners not supported, this should barely be the case owners = null; } - - FormField roomAdminsFormField = answerForm.getDataForm().getField(MUC_ROOMCONFIG_ROOMADMINS); - if (roomAdminsFormField != null) { - // Set 'admins' to the currently configured admins - List adminStrings = roomAdminsFormField.getValues(); - admins = new ArrayList<>(adminStrings.size()); - JidUtil.jidsFrom(adminStrings, admins, null); - } - else { - // roomadmins not supported, this should barely be the case - admins = null; - } } /** @@ -171,15 +136,6 @@ public class MucConfigFormManager { return owners != null; } - /** - * Check if the room supports room admins. - * @return true if supported, false if not. - * @see #MUC_ROOMCONFIG_ROOMADMINS - */ - public boolean supportsRoomAdmins() { - return admins != null; - } - /** * Set the owners of the room. * @@ -197,23 +153,6 @@ public class MucConfigFormManager { return this; } - /** - * Set the admins of the room. - * - * @param newAdmins a collection of JIDs to become the new admins of the room. - * @return a reference to this object. - * @throws MucConfigurationNotSupportedException if the MUC service does not support this option. - * @see #MUC_ROOMCONFIG_ROOMADMINS - */ - public MucConfigFormManager setRoomAdmins(Collection newAdmins) throws MucConfigurationNotSupportedException { - if (!supportsRoomAdmins()) { - throw new MucConfigurationNotSupportedException(MUC_ROOMCONFIG_ROOMADMINS); - } - admins.clear(); - admins.addAll(newAdmins); - return this; - } - /** * Check if the room supports a members only configuration. * @@ -284,15 +223,6 @@ public class MucConfigFormManager { } - /** - * Check if the room supports its visibility being controlled via configuration. - * - * @return true if supported, false if not. - */ - public boolean supportsPublicRoom() { - return answerForm.hasField(MUC_ROOMCONFIG_PUBLICLYSEARCHABLEROOM); - } - /** * Make the room publicly searchable. * @@ -321,25 +251,13 @@ public class MucConfigFormManager { * @throws MucConfigurationNotSupportedException if the requested MUC configuration is not supported by the MUC service. */ public MucConfigFormManager setPublic(boolean isPublic) throws MucConfigurationNotSupportedException { - if (!supportsPublicRoom()) { + if (!supportsModeration()) { throw new MucConfigurationNotSupportedException(MUC_ROOMCONFIG_PUBLICLYSEARCHABLEROOM); } answerForm.setAnswer(MUC_ROOMCONFIG_PUBLICLYSEARCHABLEROOM, isPublic); return this; } - public boolean supportsRoomname() { - return answerForm.hasField(MUC_ROOMCONFIG_ROOMNAME); - } - - public MucConfigFormManager setRoomName(String roomName) throws MucConfigurationNotSupportedException { - if (!supportsRoomname()) { - throw new MucConfigurationNotSupportedException(MUC_ROOMCONFIG_ROOMNAME); - } - answerForm.setAnswer(MUC_ROOMCONFIG_ROOMNAME, roomName); - return this; - } - /** * Check if the room supports password protection. * @@ -381,33 +299,13 @@ public class MucConfigFormManager { */ public MucConfigFormManager setIsPasswordProtected(boolean isPasswordProtected) throws MucConfigurationNotSupportedException { - if (!supportsPasswordProtected()) { + if (!supportsMembersOnly()) { throw new MucConfigurationNotSupportedException(MUC_ROOMCONFIG_PASSWORDPROTECTEDROOM); } answerForm.setAnswer(MUC_ROOMCONFIG_PASSWORDPROTECTEDROOM, isPasswordProtected); return this; } - public boolean supportsPublicLogging() { - return answerForm.hasField(MUC_ROOMCONFIG_ENABLE_PUBLIC_LOGGING); - } - - public MucConfigFormManager setPublicLogging(boolean enabled) throws MucConfigurationNotSupportedException { - if (!supportsPublicLogging()) { - throw new MucConfigurationNotSupportedException(MUC_ROOMCONFIG_ENABLE_PUBLIC_LOGGING); - } - answerForm.setAnswer(MUC_ROOMCONFIG_ENABLE_PUBLIC_LOGGING, enabled); - return this; - } - - public MucConfigFormManager enablePublicLogging() throws MucConfigurationNotSupportedException { - return setPublicLogging(true); - } - - public MucConfigFormManager disablPublicLogging() throws MucConfigurationNotSupportedException { - return setPublicLogging(false); - } - /** * Set the room secret, aka the room password. If set and enabled, the password is required to * join the room. Note that this does only set it by does not enable password protection. Use @@ -426,33 +324,6 @@ public class MucConfigFormManager { return this; } - public boolean supportsChangeSubjectByOccupant() { - return answerForm.hasField(MUC_ROOMCONFIG_CHANGE_SUBJECT); - } - - public boolean occupantsAreAllowedToChangeSubject() throws MucConfigurationNotSupportedException { - if (!supportsChangeSubjectByOccupant()) { - throw new MucConfigurationNotSupportedException(MUC_ROOMCONFIG_CHANGE_SUBJECT); - } - return answerForm.getField(MUC_ROOMCONFIG_CHANGE_SUBJECT).ifPossibleAsOrThrow(BooleanFormField.class).getValueAsBoolean(); - } - - public MucConfigFormManager setChangeSubjectByOccupant(boolean enabled) throws MucConfigurationNotSupportedException { - if (!supportsChangeSubjectByOccupant()) { - throw new MucConfigurationNotSupportedException(MUC_ROOMCONFIG_CHANGE_SUBJECT); - } - answerForm.setAnswer(MUC_ROOMCONFIG_CHANGE_SUBJECT, enabled); - return this; - } - - public MucConfigFormManager allowOccupantsToChangeSubject() throws MucConfigurationNotSupportedException { - return setChangeSubjectByOccupant(true); - } - - public MucConfigFormManager disallowOccupantsToChangeSubject() throws MucConfigurationNotSupportedException { - return setChangeSubjectByOccupant(false); - } - /** * Submit the configuration as {@link FilledForm} to the room. * @@ -466,9 +337,6 @@ public class MucConfigFormManager { if (owners != null) { answerForm.setAnswer(MUC_ROOMCONFIG_ROOMOWNERS, JidUtil.toStringList(owners)); } - if (admins != null) { - answerForm.setAnswer(MUC_ROOMCONFIG_ROOMADMINS, JidUtil.toStringList(admins)); - } multiUserChat.sendConfigurationForm(answerForm); } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MucEnterConfiguration.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MucEnterConfiguration.java index 58c0c4e26..ef3e17ba7 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MucEnterConfiguration.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MucEnterConfiguration.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015-2024 Florian Schmaus + * Copyright 2015-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,8 +60,13 @@ public final class MucEnterConfiguration { since = builder.since; timeout = builder.timeout; - final PresenceBuilder joinPresenceBuilder = builder.joinPresenceBuilder.ofType(Presence.Type.available); - + final PresenceBuilder joinPresenceBuilder; + if (builder.joinPresence == null) { + joinPresenceBuilder = builder.joinPresenceBuilder.ofType(Presence.Type.available); + } + else { + joinPresenceBuilder = builder.joinPresence.asBuilder(); + } // Indicate the client supports MUC joinPresenceBuilder.addExtension(new MUCInitialPresence(password, maxChars, maxStanzas, seconds, since)); @@ -90,6 +95,9 @@ public final class MucEnterConfiguration { private final PresenceBuilder joinPresenceBuilder; + // TODO: Remove in Smack 4.5. + private Presence joinPresence; + Builder(Resourcepart nickname, XMPPConnection connection) { this.nickname = Objects.requireNonNull(nickname, "Nickname must not be null"); @@ -101,7 +109,31 @@ public final class MucEnterConfiguration { /** * Set the presence used to join the MUC room. + *

    + * The 'to' value of the given presence will be overridden and the given presence must be of type + * 'available', otherwise an {@link IllegalArgumentException} will be thrown. + *

    + * + * @param presence TODO javadoc me please + * @return a reference to this builder. + * @deprecated use {@link #withPresence(Consumer)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public Builder withPresence(Presence presence) { + if (presence.getType() != Presence.Type.available) { + throw new IllegalArgumentException("Presence must be of type 'available'"); + } + + joinPresence = presence; + return this; + } + + /** + * Set the presence used to join the MUC room. + *

    * The consumer must not modify the presence type, otherwise an {@link IllegalArgumentException} will be thrown. + *

    * * @param presenceBuilderConsumer a consumer which will be passed the presence build. * @return a reference to this builder. diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java index e71f6b523..b7fd3ad97 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software. 2020-2024 Florian Schmaus + * Copyright 2003-2007 Jive Software. 2020-2022 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -87,10 +87,10 @@ import org.jivesoftware.smackx.xdata.form.FillableForm; import org.jivesoftware.smackx.xdata.form.Form; import org.jivesoftware.smackx.xdata.packet.DataForm; -import org.jxmpp.jid.BareJid; import org.jxmpp.jid.DomainBareJid; import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityFullJid; +import org.jxmpp.jid.EntityJid; import org.jxmpp.jid.Jid; import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.jid.parts.Resourcepart; @@ -258,14 +258,13 @@ public class MultiUserChat { break; case unavailable: occupantsMap.remove(from); - Set status = mucUser.getStatus(); - if (mucUser != null && !status.isEmpty()) { - if (isUserStatusModification && !status.contains(MUCUser.Status.NEW_NICKNAME_303)) { + if (mucUser != null && mucUser.hasStatus()) { + if (isUserStatusModification) { userHasLeft(); } // Fire events according to the received presence code checkPresenceCode( - status, + mucUser.getStatus(), isUserStatusModification, mucUser, from); @@ -290,9 +289,8 @@ public class MultiUserChat { } for (UserStatusListener listener : userStatusListeners) { - listener.roomDestroyed(alternateMuc, destroy.getPassword(), destroy.getReason()); + listener.roomDestroyed(alternateMuc, destroy.getReason()); } - userHasLeft(); } if (isUserStatusModification) { @@ -352,7 +350,7 @@ public class MultiUserChat { * @throws NoResponseException if there was no response from the remote entity. * @throws XMPPErrorException if there was an XMPP error returned. * @throws InterruptedException if the calling thread was interrupted. - * @throws NotAMucServiceException if the entity is not a MUC service. + * @throws NotAMucServiceException if the entity is not a MUC serivce. * @see XEP-45 7.2 Entering a Room */ private Presence enter(MucEnterConfiguration conf) throws NotConnectedException, NoResponseException, @@ -366,7 +364,7 @@ public class MultiUserChat { // field is in the form "roomName@service/nickname" Presence joinPresence = conf.getJoinPresence(this); - // Set up the messageListeners and presenceListeners *before* the join presence is sent. + // Setup the messageListeners and presenceListeners *before* the join presence is send. connection.addStanzaListener(messageListener, fromRoomGroupchatFilter); StanzaFilter presenceFromRoomFilter = new AndFilter(fromRoomFilter, StanzaTypeFilter.PRESENCE, @@ -402,12 +400,12 @@ public class MultiUserChat { StanzaCollector presenceStanzaCollector = null; final Presence reflectedSelfPresence; try { - // This stanza collector will collect the final self presence from the MUC, which also signals that we have successfully entered the MUC. + // This stanza collector will collect the final self presence from the MUC, which also signals that we have successful entered the MUC. StanzaCollector selfPresenceCollector = connection.createStanzaCollectorAndSend(responseFilter, joinPresence); - StanzaCollector.Configuration presenceStanzaCollectorConfiguration = StanzaCollector.newConfiguration().setCollectorToReset( + StanzaCollector.Configuration presenceStanzaCollectorConfguration = StanzaCollector.newConfiguration().setCollectorToReset( selfPresenceCollector).setStanzaFilter(presenceFromRoomFilter); // This stanza collector is used to reset the timeout of the selfPresenceCollector. - presenceStanzaCollector = connection.createStanzaCollector(presenceStanzaCollectorConfiguration); + presenceStanzaCollector = connection.createStanzaCollector(presenceStanzaCollectorConfguration); reflectedSelfPresence = selfPresenceCollector.nextResultOrThrow(conf.getTimeout()); } catch (NotConnectedException | InterruptedException | NoResponseException | XMPPErrorException e) { @@ -424,15 +422,15 @@ public class MultiUserChat { synchronized (presenceListener) { // Only continue after we have received *and* processed the reflected self-presence. Since presences are // handled in an extra listener, we may return from enter() without having processed all presences of the - // participants, resulting in a e.g. to low participant counter after enter(). Hence, we wait here until the + // participants, resulting in a e.g. to low participant counter after enter(). Hence we wait here until the // processing is done. while (!processedReflectedSelfPresence) { presenceListener.wait(); } } - // This presence must be sent from a full JID. We use the resourcepart of this JID as nick, since the room may - // have performed roomnick rewriting + // This presence must be send from a full JID. We use the resourcepart of this JID as nick, since the room may + // performed roomnick rewriting Resourcepart receivedNickname = reflectedSelfPresence.getFrom().getResourceOrThrow(); setNickname(receivedNickname); @@ -482,7 +480,7 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws MucAlreadyJoinedException if already joined the Multi-User Chat.7y * @throws MissingMucCreationAcknowledgeException if there MUC creation was not acknowledged by the service. - * @throws NotAMucServiceException if the entity is not a MUC service. + * @throws NotAMucServiceException if the entity is not a MUC serivce. */ public synchronized MucCreateConfigFormHandle create(Resourcepart nickname) throws NoResponseException, XMPPErrorException, InterruptedException, MucAlreadyJoinedException, @@ -516,7 +514,7 @@ public class MultiUserChat { * @throws InterruptedException if the calling thread was interrupted. * @throws NotConnectedException if the XMPP connection is not connected. * @throws MucAlreadyJoinedException if already joined the Multi-User Chat.7y - * @throws NotAMucServiceException if the entity is not a MUC service. + * @throws NotAMucServiceException if the entity is not a MUC serivce. */ public synchronized MucCreateConfigFormHandle createOrJoin(Resourcepart nickname) throws NoResponseException, XMPPErrorException, InterruptedException, MucAlreadyJoinedException, NotConnectedException, NotAMucServiceException { @@ -538,7 +536,7 @@ public class MultiUserChat { * @throws InterruptedException if the calling thread was interrupted. * @throws MucAlreadyJoinedException if the MUC is already joined * @throws NotConnectedException if the XMPP connection is not connected. - * @throws NotAMucServiceException if the entity is not a MUC service. + * @throws NotAMucServiceException if the entity is not a MUC serivce. */ public synchronized MucCreateConfigFormHandle createOrJoin(MucEnterConfiguration mucEnterConfiguration) throws NoResponseException, XMPPErrorException, InterruptedException, MucAlreadyJoinedException, NotConnectedException, NotAMucServiceException { @@ -611,7 +609,7 @@ public class MultiUserChat { * @throws XMPPErrorException if there was an XMPP error returned. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. - * @throws NotAMucServiceException if the entity is not a MUC service. + * @throws NotAMucServiceException if the entity is not a MUC serivce. */ public MucCreateConfigFormHandle createOrJoinIfNecessary(Resourcepart nickname, String password) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, NotAMucServiceException { @@ -647,7 +645,7 @@ public class MultiUserChat { * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. - * @throws NotAMucServiceException if the entity is not a MUC service. + * @throws NotAMucServiceException if the entity is not a MUC serivce. */ public Presence join(Resourcepart nickname) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, NotAMucServiceException { @@ -677,7 +675,7 @@ public class MultiUserChat { * @throws InterruptedException if the calling thread was interrupted. * @throws NotConnectedException if the XMPP connection is not connected. * @throws NoResponseException if there was no response from the server. - * @throws NotAMucServiceException if the entity is not a MUC service. + * @throws NotAMucServiceException if the entity is not a MUC serivce. */ public void join(Resourcepart nickname, String password) throws XMPPErrorException, InterruptedException, NoResponseException, NotConnectedException, NotAMucServiceException { MucEnterConfiguration.Builder builder = getEnterConfigurationBuilder(nickname).withPassword( @@ -710,7 +708,7 @@ public class MultiUserChat { * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. - * @throws NotAMucServiceException if the entity is not a MUC service. + * @throws NotAMucServiceException if the entity is not a MUC serivce. */ public synchronized Presence join(MucEnterConfiguration mucEnterConfiguration) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException, NotAMucServiceException { @@ -718,7 +716,7 @@ public class MultiUserChat { // nickname. if (isJoined()) { try { - leave(); + leaveSync(); } catch (XMPPErrorException | NoResponseException | MucNotJoinedException e) { LOGGER.log(Level.WARNING, "Could not leave MUC prior joining, assuming we are not joined", e); @@ -738,6 +736,23 @@ public class MultiUserChat { return getMyRoomJid() != null; } + /** + * Leave the chat room. + * + * @return the leave presence as reflected by the MUC. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + * @throws XMPPErrorException if there was an XMPP error returned. + * @throws NoResponseException if there was no response from the remote entity. + * @throws MucNotJoinedException if not joined to the Multi-User Chat. + * @deprecated use {@link #leave()} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public synchronized Presence leaveSync() throws NotConnectedException, InterruptedException, MucNotJoinedException, NoResponseException, XMPPErrorException { + return leave(); + } + /** * Leave the chat room. * @@ -817,9 +832,9 @@ public class MultiUserChat { /** * Returns the room's configuration form that the room's owner can use. * The configuration form allows to set the room's language, - * enable logging, specify room's type, etc. + * enable logging, specify room's type, etc.. * - * @return the Form that contains the fields to complete together with the instructions or + * @return the Form that contains the fields to complete together with the instrucions or * null if no configuration is possible. * @throws XMPPErrorException if an error occurs asking the configuration form for the room. * @throws NoResponseException if there was no response from the server. @@ -873,7 +888,7 @@ public class MultiUserChat { * error to the user (error code 405). * * @return the registration Form that contains the fields to complete together with the - * instructions or null if no registration is possible. + * instrucions or null if no registration is possible. * @throws XMPPErrorException if an error occurs asking the registration form for the room or a * 405 error if the user is not allowed to register with the room. * @throws NoResponseException if there was no response from the server. @@ -949,32 +964,12 @@ public class MultiUserChat { * @throws InterruptedException if the calling thread was interrupted. */ public void destroy(String reason, EntityBareJid alternateJID) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - destroy(reason, alternateJID, null); - } - - /** - * Sends a request to the server to destroy the room. The sender of the request - * should be the room's owner. If the sender of the destroy request is not the room's owner - * then the server will answer a "Forbidden" error (403). - * - * @param reason an optional reason for the room destruction. - * @param alternateJID an optional JID of an alternate location. - * @param password an optional password for the alternate location - * @throws XMPPErrorException if an error occurs while trying to destroy the room. - * An error can occur which will be wrapped by an XMPPException -- - * XMPP error code 403. The error code can be used to present more - * appropriate error messages to end-users. - * @throws NoResponseException if there was no response from the server. - * @throws NotConnectedException if the XMPP connection is not connected. - * @throws InterruptedException if the calling thread was interrupted. - */ - public void destroy(String reason, EntityBareJid alternateJID, String password) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { MUCOwner iq = new MUCOwner(); iq.setTo(room); iq.setType(IQ.Type.set); // Create the reason for the room destruction - Destroy destroy = new Destroy(alternateJID, password, reason); + Destroy destroy = new Destroy(alternateJID, reason); iq.setDestroy(destroy); try { @@ -1011,6 +1006,36 @@ public class MultiUserChat { invite(connection.getStanzaFactory().buildMessageStanza(), user, reason); } + /** + * Invites another user to the room in which one is an occupant using a given Message. The invitation + * will be sent to the room which in turn will forward the invitation to the invitee.

    + * + * If the room is password-protected, the invitee will receive a password to use to join + * the room. If the room is members-only, the invitee may be added to the member list. + * + * @param message the message to use for sending the invitation. + * @param user the user to invite to the room.(e.g. hecate@shakespeare.lit) + * @param reason the reason why the user is being invited. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + * @deprecated use {@link #invite(MessageBuilder, EntityBareJid, String)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void invite(Message message, EntityBareJid user, String reason) throws NotConnectedException, InterruptedException { + // TODO listen for 404 error code when inviter supplies a non-existent JID + message.setTo(room); + + // Create the MUCUser packet that will include the invitation + MUCUser mucUser = new MUCUser(); + MUCUser.Invite invite = new MUCUser.Invite(reason, user); + mucUser.setInvite(invite); + // Add the MUCUser packet that includes the invitation to the message + message.addExtension(mucUser); + + connection.sendStanza(message); + } + /** * Invites another user to the room in which one is an occupant using a given Message. The invitation * will be sent to the room which in turn will forward the invitation to the invitee.

    @@ -1248,8 +1273,6 @@ public class MultiUserChat { return myRoomJid; } - private static final Object changeNicknameLock = new Object(); - /** * Changes the occupant's nickname to a new nickname within the room. Each room occupant * will receive two presence packets. One of type "unavailable" for the old nickname and one @@ -1264,7 +1287,7 @@ public class MultiUserChat { * @throws InterruptedException if the calling thread was interrupted. * @throws MucNotJoinedException if not joined to the Multi-User Chat. */ - public void changeNickname(Resourcepart nickname) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, MucNotJoinedException { + public synchronized void changeNickname(Resourcepart nickname) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, MucNotJoinedException { Objects.requireNonNull(nickname, "Nickname must not be null or blank."); // Check that we already have joined the room before attempting to change the // nickname. @@ -1280,20 +1303,18 @@ public class MultiUserChat { .ofType(Presence.Type.available) .build(); - synchronized (changeNicknameLock) { - // Wait for a presence packet back from the server. - StanzaFilter responseFilter = - new AndFilter( - FromMatchesFilter.createFull(jid), - new StanzaTypeFilter(Presence.class)); - StanzaCollector response = connection.createStanzaCollectorAndSend(responseFilter, joinPresence); - // Wait up to a certain number of seconds for a reply. If there is a negative reply, an - // exception will be thrown - response.nextResultOrThrow(); + // Wait for a presence packet back from the server. + StanzaFilter responseFilter = + new AndFilter( + FromMatchesFilter.createFull(jid), + new StanzaTypeFilter(Presence.class)); + StanzaCollector response = connection.createStanzaCollectorAndSend(responseFilter, joinPresence); + // Wait up to a certain number of seconds for a reply. If there is a negative reply, an + // exception will be thrown + response.nextResultOrThrow(); - // TODO: Shouldn't this handle nickname rewriting by the MUC service? - setNickname(nickname); - } + // TODO: Shouldn't this handle nickname rewriting by the MUC service? + setNickname(nickname); } /** @@ -1463,7 +1484,7 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void banUsers(Collection jids) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { + public void banUsers(Collection jids) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { changeAffiliationByAdmin(jids, MUCAffiliation.outcast); } @@ -1483,7 +1504,7 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void banUser(BareJid jid, String reason) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { + public void banUser(Jid jid, String reason) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { changeAffiliationByAdmin(jid, MUCAffiliation.outcast, reason); } @@ -1513,7 +1534,7 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void grantMembership(BareJid jid) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { + public void grantMembership(Jid jid) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { changeAffiliationByAdmin(jid, MUCAffiliation.member, null); } @@ -1529,7 +1550,7 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void revokeMembership(Collection jids) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { + public void revokeMembership(Collection jids) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { changeAffiliationByAdmin(jids, MUCAffiliation.none); } @@ -1545,14 +1566,14 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void revokeMembership(BareJid jid) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { + public void revokeMembership(Jid jid) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { changeAffiliationByAdmin(jid, MUCAffiliation.none, null); } /** * Grants moderator privileges to participants or visitors. Room administrators may grant * moderator privileges. A moderator is allowed to kick users, grant and revoke voice, invite - * other users, modify room's subject plus all the participant privileges. + * other users, modify room's subject plus all the partcipants privileges. * * @param nicknames the nicknames of the occupants to grant moderator privileges. * @throws XMPPErrorException if an error occurs granting moderator privileges to a user. @@ -1567,7 +1588,7 @@ public class MultiUserChat { /** * Grants moderator privileges to a participant or visitor. Room administrators may grant * moderator privileges. A moderator is allowed to kick users, grant and revoke voice, invite - * other users, modify room's subject plus all the participant privileges. + * other users, modify room's subject plus all the partcipants privileges. * * @param nickname the nickname of the occupant to grant moderator privileges. * @throws XMPPErrorException if an error occurs granting moderator privileges to a user. @@ -1623,7 +1644,7 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void grantOwnership(Collection jids) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { + public void grantOwnership(Collection jids) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { changeAffiliationByAdmin(jids, MUCAffiliation.owner); } @@ -1639,7 +1660,7 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void grantOwnership(BareJid jid) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { + public void grantOwnership(Jid jid) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { changeAffiliationByAdmin(jid, MUCAffiliation.owner, null); } @@ -1654,7 +1675,7 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void revokeOwnership(Collection jids) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { + public void revokeOwnership(Collection jids) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { changeAffiliationByAdmin(jids, MUCAffiliation.admin); } @@ -1669,7 +1690,7 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void revokeOwnership(BareJid jid) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { + public void revokeOwnership(Jid jid) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { changeAffiliationByAdmin(jid, MUCAffiliation.admin, null); } @@ -1684,7 +1705,7 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void grantAdmin(Collection jids) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { + public void grantAdmin(Collection jids) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { changeAffiliationByAdmin(jids, MUCAffiliation.admin); } @@ -1700,7 +1721,7 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void grantAdmin(BareJid jid) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { + public void grantAdmin(Jid jid) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { changeAffiliationByAdmin(jid, MUCAffiliation.admin); } @@ -1715,7 +1736,7 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void revokeAdmin(Collection jids) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { + public void revokeAdmin(Collection jids) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { changeAffiliationByAdmin(jids, MUCAffiliation.admin); } @@ -1731,7 +1752,7 @@ public class MultiUserChat { * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. */ - public void revokeAdmin(BareJid jid) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { + public void revokeAdmin(EntityJid jid) throws XMPPErrorException, NoResponseException, NotConnectedException, InterruptedException { changeAffiliationByAdmin(jid, MUCAffiliation.member); } @@ -1842,7 +1863,7 @@ public class MultiUserChat { /** * Returns the presence info for a particular user, or null if the user - * is not in the room. + * is not in the room.

    * * @param user the room occupant to search for his presence. The format of user must * be: roomName@service/nickname (e.g. darkcave@macbeth.shakespeare.lit/thirdwitch). @@ -1856,7 +1877,7 @@ public class MultiUserChat { /** * Returns the Occupant information for a particular occupant, or null if the * user is not in the room. The Occupant object may include information such as full - * JID of the user as well as the role and affiliation of the user in the room. + * JID of the user as well as the role and affiliation of the user in the room.

    * * @param user the room occupant to search for his presence. The format of user must * be: roomName@service/nickname (e.g. darkcave@macbeth.shakespeare.lit/thirdwitch). @@ -2090,6 +2111,20 @@ public class MultiUserChat { ; } + /** + * Sends a Message to the chat room. + * + * @param message the message. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + * @deprecated use {@link #sendMessage(MessageBuilder)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public void sendMessage(Message message) throws NotConnectedException, InterruptedException { + sendMessage(message.asBuilder()); + } + /** * Sends a Message to the chat room. * @@ -2111,7 +2146,7 @@ public class MultiUserChat { /** * Polls for and returns the next message, or null if there isn't * a message immediately available. This method provides significantly different - * functionality than the {@link #nextMessage()} method since it's non-blocking. + * functionalty than the {@link #nextMessage()} method since it's non-blocking. * In other words, the method call will always return immediately, whereas the * nextMessage method will return only when a message is available (or after * a specific timeout). @@ -2144,7 +2179,7 @@ public class MultiUserChat { /** * Returns the next available message in the chat. The method call will block - * (not return) until a stanza is available or the timeout has elapsed. + * (not return) until a stanza is available or the timeout has elapased. * If the timeout elapses without a result, null will be returned. * * @param timeout the maximum amount of time to wait for the next message. @@ -2208,20 +2243,17 @@ public class MultiUserChat { * @throws InterruptedException if the calling thread was interrupted. */ public void changeSubject(final String subject) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - Message message = buildMessage() - .setSubject(subject) - .build(); + MessageBuilder message = buildMessage(); + message.setSubject(subject); // Wait for an error or confirmation message back from the server. - StanzaFilter successFilter = new AndFilter(fromRoomGroupchatFilter, new StanzaFilter() { + StanzaFilter responseFilter = new AndFilter(fromRoomGroupchatFilter, new StanzaFilter() { @Override public boolean accept(Stanza packet) { Message msg = (Message) packet; return subject.equals(msg.getSubject()); } }); - StanzaFilter errorFilter = new AndFilter(fromRoomFilter, new StanzaIdFilter(message), MessageTypeFilter.ERROR); - StanzaFilter responseFilter = new OrFilter(successFilter, errorFilter); - StanzaCollector response = connection.createStanzaCollectorAndSend(responseFilter, message); + StanzaCollector response = connection.createStanzaCollectorAndSend(responseFilter, message.build()); // Wait up to a certain number of seconds for a reply. response.nextResultOrThrow(); } @@ -2596,10 +2628,6 @@ public class MultiUserChat { for (UserStatusListener listener : userStatusListeners) { listener.membershipRevoked(); } - } else { - for (ParticipantStatusListener listener : participantStatusListeners) { - listener.membershipRevoked(from); - } } } // A occupant has changed his nickname in the room diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatException.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatException.java index 11de8dff4..1f7f930a2 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatException.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatException.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014-2024 Florian Schmaus + * Copyright © 2014-2015 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -88,7 +88,7 @@ public abstract class MultiUserChatException extends SmackException { /** * Thrown when trying to enter a MUC room that is not hosted a domain providing a MUC service. - * Try {@link MultiUserChatManager#getMucServiceDomains()} for a list of client-local domains + * Try {@link MultiUserChatManager#getXMPPServiceDomains()} for a list of client-local domains * providing a MUC service. */ public static class NotAMucServiceException extends MultiUserChatException { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatManager.java index 4d8c5c637..00b088095 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatManager.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014-2024 Florian Schmaus + * Copyright © 2014-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -83,10 +83,6 @@ import org.jxmpp.util.cache.ExpirationCache; * further attempts will be made for the other rooms. *

    * - * Note: - * For inviting other users to a group chat or listening for such invitations, take a look at the - * {@link DirectMucInvitationManager} which provides an implementation of XEP-0249: Direct MUC Invitations. - * * @see XEP-0045: Multi-User Chat */ public final class MultiUserChatManager extends Manager { @@ -108,7 +104,6 @@ public final class MultiUserChatManager extends Manager { final WeakReference weakRefConnection = new WeakReference(connection); ServiceDiscoveryManager.getInstanceFor(connection).setNodeInformationProvider(DISCO_NODE, new AbstractNodeInformationProvider() { - @SuppressWarnings({"JavaUtilDate", "MixedMutabilityReturnType"}) @Override public List getNodeItems() { XMPPConnection connection = weakRefConnection.get(); @@ -149,7 +144,6 @@ public final class MultiUserChatManager extends Manager { private static final StanzaFilter DIRECT_INVITATION_FILTER = new AndFilter(StanzaTypeFilter.MESSAGE, new ExtensionElementFilter(GroupChatInvitation.class), - NotFilter.of(MUCUser.class), new NotFilter(MessageTypeFilter.ERROR)); private static final ExpirationCache KNOWN_MUC_SERVICES = new ExpirationCache<>( @@ -299,7 +293,7 @@ public final class MultiUserChatManager extends Manager { * {@link MultiUserChat#join(org.jxmpp.jid.parts.Resourcepart) join} the chat room. On some server implementations, the room will not be * created until the first person joins it. *

    - * Most XMPP servers use a sub-domain for the chat service (e.g.chat.example.com for the XMPP server example.com). + * Most XMPP servers use a sub-domain for the chat service (eg chat.example.com for the XMPP server example.com). * You must ensure that the room address you're trying to connect to includes the proper chat sub-domain. *

    * @@ -422,6 +416,22 @@ public final class MultiUserChatManager extends Manager { return serviceDiscoveryManager.findServices(MUCInitialPresence.NAMESPACE, false, false); } + /** + * Returns a collection with the XMPP addresses of the Multi-User Chat services. + * + * @return a collection with the XMPP addresses of the Multi-User Chat services. + * @throws XMPPErrorException if there was an XMPP error returned. + * @throws NoResponseException if there was no response from the remote entity. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + * @deprecated use {@link #getMucServiceDomains()} instead. + */ + // TODO: Remove in Smack 4.5 + @Deprecated + public List getXMPPServiceDomains() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + return getMucServiceDomains(); + } + /** * Check if the provided domain bare JID provides a MUC service. * @@ -466,7 +476,7 @@ public final class MultiUserChatManager extends Manager { * @throws NoResponseException if there was no response from the remote entity. * @throws NotConnectedException if the XMPP connection is not connected. * @throws InterruptedException if the calling thread was interrupted. - * @throws NotAMucServiceException if the entity is not a MUC service. + * @throws NotAMucServiceException if the entity is not a MUC serivce. * @since 4.3.1 */ public Map getRoomsHostedBy(DomainBareJid serviceName) throws NoResponseException, XMPPErrorException, diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/ParticipantStatusListener.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/ParticipantStatusListener.java index 58454d6e9..8a376ca36 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/ParticipantStatusListener.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/ParticipantStatusListener.java @@ -129,7 +129,7 @@ public interface ParticipantStatusListener { /** * Called when an administrator grants moderator privileges to a user. This means that the user * will be able to kick users, grant and revoke voice, invite other users, modify room's - * subject plus all the participant privileges. + * subject plus all the partcipants privileges. * * @param participant the participant that was granted moderator privileges in the room * (e.g. room@conference.jabber.org/nick). @@ -140,7 +140,7 @@ public interface ParticipantStatusListener { /** * Called when an administrator revokes moderator privileges from a user. This means that the * user will no longer be able to kick users, grant and revoke voice, invite other users, - * modify room's subject plus all the participant privileges. + * modify room's subject plus all the partcipants privileges. * * @param participant the participant that was revoked moderator privileges in the room * (e.g. room@conference.jabber.org/nick). diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/RoomInfo.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/RoomInfo.java index b43e33ae9..d321903dd 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/RoomInfo.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/RoomInfo.java @@ -77,7 +77,7 @@ public class RoomInfo { */ private final boolean moderated; /** - * Every presence stanza can include the JID of every occupant unless the owner deactivates this + * Every presence stanza can include the JID of every occupant unless the owner deactives this * configuration. */ private final boolean nonanonymous; @@ -250,7 +250,7 @@ public class RoomInfo { /** * Returns the room name. *

    - * The name returned here was provided as value of the name attribute + * The name returnd here was provided as value of the name attribute * of the returned identity within the disco#info result. *

    * @@ -324,9 +324,9 @@ public class RoomInfo { } /** - * Returns true if users must provide a valid password in order to join the room. + * Returns true if users musy provide a valid password in order to join the room. * - * @return true if users must provide a valid password in order to join the room. + * @return true if users musy provide a valid password in order to join the room. */ public boolean isPasswordProtected() { return passwordProtected; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/UserStatusListener.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/UserStatusListener.java index 93cf585fe..0e87cb5bd 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/UserStatusListener.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/UserStatusListener.java @@ -28,7 +28,7 @@ import org.jxmpp.jid.Jid; * banned, or granted admin permissions or the room is destroyed. *

    * Note that the methods {@link #kicked(Jid, String)}, {@link #banned(Jid, String)} and - * {@link #roomDestroyed(MultiUserChat, String, String)} will be called before the generic {@link #removed(MUCUser, Presence)} + * {@link #roomDestroyed(MultiUserChat, String)} will be called before the generic {@link #removed(MUCUser, Presence)} * callback will be invoked. The generic {@link #removed(MUCUser, Presence)} callback will be invoked every time the user * was removed from the MUC involuntarily. It is hence the recommended callback to listen for and act upon. *

    @@ -39,7 +39,7 @@ public interface UserStatusListener { /** * Called when a moderator kicked your user from the room. This means that you are no longer - * participating in the room. + * participanting in the room. * * @param actor the moderator that kicked your user from the room (e.g. user@host.org). * @param reason the reason provided by the actor to kick you from the room. @@ -106,7 +106,7 @@ public interface UserStatusListener { /** * Called when an administrator grants moderator privileges to your user. This means that you * will be able to kick users, grant and revoke voice, invite other users, modify room's - * subject plus all the participant privileges. + * subject plus all the partcipants privileges. * */ default void moderatorGranted() { @@ -115,7 +115,7 @@ public interface UserStatusListener { /** * Called when an administrator revokes moderator privileges from your user. This means that * you will no longer be able to kick users, grant and revoke voice, invite other users, - * modify room's subject plus all the participant privileges. + * modify room's subject plus all the partcipants privileges. * */ default void moderatorRevoked() { @@ -161,11 +161,10 @@ public interface UserStatusListener { * Called when the room is destroyed. * * @param alternateMUC an alternate MultiUserChat, may be null. - * @param password a password for the alternative MultiUserChat, may be null. * @param reason the reason why the room was closed, may be null. * @see #removed(MUCUser, Presence) */ - default void roomDestroyed(MultiUserChat alternateMUC, String password, String reason) { + default void roomDestroyed(MultiUserChat alternateMUC, String reason) { } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/package-info.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/package-info.java index 78866dd6a..5adaa5a6f 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/package-info.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/package-info.java @@ -534,7 +534,7 @@ *

    *

    Usage

    *

    - * In order to grant membership to a room, administrator privileges or owner privileges just send + * In order to grant membership to a room, administrator privileges or owner priveliges just send * **grantMembership(String jid)**, **grantAdmin(String jid)** or **grantOwnership(String jid)** to _**MultiUserChat**_ * respectively. Use **revokeMembership(String jid)**, **revokeAdmin(String jid)** or revokeOwnership(String jid)** to * revoke the membership to a room, administrator privileges or owner priveliges respectively. diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/Destroy.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/Destroy.java index 9da151c4c..1361f79fe 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/Destroy.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/Destroy.java @@ -40,22 +40,14 @@ public class Destroy implements NamedElement, Serializable { private final String reason; private final EntityBareJid jid; - private final String password; public Destroy(Destroy other) { - this(other.jid, other.password, other.reason); + this(other.jid, other.reason); } public Destroy(EntityBareJid alternativeJid, String reason) { this.jid = alternativeJid; this.reason = reason; - this.password = null; - } - - public Destroy(EntityBareJid alternativeJid, String password, String reason) { - this.jid = alternativeJid; - this.password = password; - this.reason = reason; } /** @@ -67,15 +59,6 @@ public class Destroy implements NamedElement, Serializable { return jid; } - /** - * Returns the password of the alternate location. - * - * @return the password of the alternate location. - */ - public String getPassword() { - return password; - } - /** * Returns the reason for the room destruction. * @@ -90,7 +73,6 @@ public class Destroy implements NamedElement, Serializable { XmlStringBuilder xml = new XmlStringBuilder(this); xml.optAttribute("jid", getJid()); xml.rightAngleBracket(); - xml.optElement("password", getPassword()); xml.optElement("reason", getReason()); xml.closeElement(this); return xml; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/GroupChatInvitation.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/GroupChatInvitation.java index e243d46ed..dc6660ae9 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/GroupChatInvitation.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/GroupChatInvitation.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2020 Paul Schaub. + * Copyright 2003-2007 Jive Software. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +20,6 @@ import javax.xml.namespace.QName; import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smack.util.EqualsUtil; -import org.jivesoftware.smack.util.HashCode; import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.XmlStringBuilder; @@ -29,13 +27,32 @@ import org.jxmpp.jid.EntityBareJid; /** * A group chat invitation stanza extension, which is used to invite other - * users to a group chat room. + * users to a group chat room. To invite a user to a group chat room, address + * a new message to the user and set the room name appropriately, as in the + * following code example: * - * This implementation now conforms to XEP-0249: Direct MUC Invitations, - * while staying backwards compatible to legacy MUC invitations. + *

    + * Message message = new Message("user@chat.example.com");
    + * message.setBody("Join me for a group chat!");
    + * message.addExtension(new GroupChatInvitation("room@chat.example.com"););
    + * con.sendStanza(message);
    + * 
    + * + * To listen for group chat invitations, use a StanzaExtensionFilter for the + * x element name and jabber:x:conference namespace, as in the + * following code example: + * + *
    + * PacketFilter filter = new StanzaExtensionFilter("x", "jabber:x:conference");
    + * // Create a stanza collector or stanza listeners using the filter...
    + * 
    + * + * Note: this protocol is outdated now that the Multi-User Chat (MUC) XEP is available + * (XEP-45). However, most + * existing clients still use this older protocol. Once MUC support becomes more + * widespread, this API may be deprecated. * * @author Matt Tucker - * @author Paul Schaub */ public class GroupChatInvitation implements ExtensionElement { @@ -51,12 +68,6 @@ public class GroupChatInvitation implements ExtensionElement { public static final QName QNAME = new QName(NAMESPACE, ELEMENT); - public static final String ATTR_CONTINUE = "continue"; - public static final String ATTR_JID = "jid"; - public static final String ATTR_PASSWORD = "password"; - public static final String ATTR_REASON = "reason"; - public static final String ATTR_THREAD = "thread"; - private final EntityBareJid roomAddress; private final String reason; private final String password; @@ -159,37 +170,18 @@ public class GroupChatInvitation implements ExtensionElement { @Override public XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) { XmlStringBuilder xml = new XmlStringBuilder(this); - xml.jidAttribute(getRoomAddress()); - xml.optAttribute(ATTR_REASON, getReason()); - xml.optAttribute(ATTR_PASSWORD, getPassword()); - xml.optAttribute(ATTR_THREAD, getThread()); - xml.optBooleanAttribute(ATTR_CONTINUE, continueAsOneToOneChat()); + xml.attribute("jid", getRoomAddress()); + xml.optAttribute("reason", getReason()); + xml.optAttribute("password", getPassword()); + xml.optAttribute("thread", getThread()); + + if (continueAsOneToOneChat()) + xml.optBooleanAttribute("continue", true); xml.closeEmptyElement(); return xml; } - @Override - public boolean equals(Object obj) { - return EqualsUtil.equals(this, obj, (equalsBuilder, other) -> equalsBuilder - .append(getRoomAddress(), other.getRoomAddress()) - .append(getPassword(), other.getPassword()) - .append(getReason(), other.getReason()) - .append(continueAsOneToOneChat(), other.continueAsOneToOneChat()) - .append(getThread(), other.getThread())); - } - - @Override - public int hashCode() { - return HashCode.builder() - .append(getRoomAddress()) - .append(getPassword()) - .append(getReason()) - .append(continueAsOneToOneChat()) - .append(getThread()) - .build(); - } - /** * Get the group chat invitation from the given stanza. * @param packet TODO javadoc me please diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/MUCItem.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/MUCItem.java index 8da0efb78..c1ee5ae28 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/MUCItem.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/MUCItem.java @@ -169,11 +169,8 @@ public class MUCItem implements NamedElement { xml.optAttribute("role", getRole()); xml.rightAngleBracket(); xml.optElement("reason", getReason()); - if (getActor() != null || getActorNick() != null) { - xml.halfOpenElement("actor"); - xml.optAttribute("jid", getActor()); - xml.optAttribute("nick", getActorNick()); - xml.closeEmptyElement(); + if (getActor() != null) { + xml.halfOpenElement("actor").attribute("jid", getActor()).closeEmptyElement(); } xml.closeElement(Stanza.ITEM); return xml; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/provider/GroupChatInvitationProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/provider/GroupChatInvitationProvider.java index 00ddabaf9..31f6472c8 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/provider/GroupChatInvitationProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/provider/GroupChatInvitationProvider.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2020 Paul Schaub, 2022-2023 Florian Schmaus. + * Copyright 2003-2007 Jive Software, 2022 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,8 @@ */ package org.jivesoftware.smackx.muc.provider; -import static org.jivesoftware.smackx.muc.packet.GroupChatInvitation.ATTR_CONTINUE; -import static org.jivesoftware.smackx.muc.packet.GroupChatInvitation.ATTR_PASSWORD; -import static org.jivesoftware.smackx.muc.packet.GroupChatInvitation.ATTR_REASON; -import static org.jivesoftware.smackx.muc.packet.GroupChatInvitation.ATTR_THREAD; - import java.io.IOException; +import java.text.ParseException; import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.parsing.SmackParsingException; @@ -37,14 +33,11 @@ public class GroupChatInvitationProvider extends ExtensionElementProvider * In order to handle privacy changes, clients SHOULD listen manager’s updates. When a list is changed the manager * notifies every added listener. Listeners MUST implement the PrivacyListListener interface. Clients may - * need to react when a privacy list is modified. The PrivacyListManager lets you add listeners that will + * need to react when a privacy list is modified. The PrivacyListManager lets you add listerners that will * be notified when a list has been changed. Listeners should implement the PrivacyListListener interface. *

    *

    diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/privacy/packet/PrivacyItem.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/privacy/packet/PrivacyItem.java index a80276e5b..c977fdaf3 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/privacy/packet/PrivacyItem.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/privacy/packet/PrivacyItem.java @@ -171,7 +171,7 @@ public class PrivacyItem { } /** - * Sets whether the receiver allows or denies incoming messages or not. + * Sets wheather the receiver allows or denies incoming messages or not. * * @param filterMessage indicates if the receiver allows or denies incoming messages or not. */ diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ItemDeleteEvent.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ItemDeleteEvent.java index 3ac132246..424c3da0b 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ItemDeleteEvent.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ItemDeleteEvent.java @@ -31,7 +31,7 @@ public class ItemDeleteEvent extends SubscriptionEvent { * Constructs an ItemDeleteEvent that indicates the supplied * items (by id) have been deleted, and that the event matches the listed * subscriptions. The subscriptions would have been created by calling - * {@link LeafNode#subscribe(org.jxmpp.Jid)}. + * {@link LeafNode#subscribe(String)}. * * @param nodeId The id of the node the event came from * @param deletedItemIds The item ids of the items that were deleted. diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ItemPublishEvent.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ItemPublishEvent.java index 7018b5934..577dad4f7 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ItemPublishEvent.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/ItemPublishEvent.java @@ -109,7 +109,6 @@ public class ItemPublishEvent extends SubscriptionEvent { return originalDate; } - @SuppressWarnings("JavaUtilDate") @Override public String toString() { return getClass().getName() + " [subscriptions: " + getSubscriptions() + "], [Delayed: " + diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Node.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Node.java index 9741ce51f..4db909dfa 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Node.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/Node.java @@ -52,6 +52,8 @@ import org.jivesoftware.smackx.shim.packet.HeadersExtension; import org.jivesoftware.smackx.xdata.packet.DataForm; import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; public abstract class Node { protected final PubSubManager pubSubManager; @@ -401,6 +403,39 @@ public abstract class Node { return reply.getExtension(PubSubElementType.SUBSCRIPTION); } + /** + * The user subscribes to the node using the supplied jid. The + * bare jid portion of this one must match the jid for the connection. + * + * Please note that the {@link Subscription.State} should be checked + * on return since more actions may be required by the caller. + * {@link Subscription.State#pending} - The owner must approve the subscription + * request before messages will be received. + * {@link Subscription.State#unconfigured} - If the {@link Subscription#isConfigRequired()} is true, + * the caller must configure the subscription before messages will be received. If it is false + * the caller can configure it but is not required to do so. + * + * @param jidString The jid to subscribe as. + * @return The subscription + * @throws XMPPErrorException if there was an XMPP error returned. + * @throws NoResponseException if there was no response from the remote entity. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + * @throws IllegalArgumentException if the provided string is not a valid JID. + * @deprecated use {@link #subscribe(Jid)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public Subscription subscribe(String jidString) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + Jid jid; + try { + jid = JidCreate.from(jidString); + } catch (XmppStringprepException e) { + throw new IllegalArgumentException(e); + } + return subscribe(jid); + } + /** * The user subscribes to the node using the supplied jid and subscription * options. The bare jid portion of this one must match the jid for the @@ -431,6 +466,42 @@ public abstract class Node { return reply.getExtension(PubSubElementType.SUBSCRIPTION); } + /** + * The user subscribes to the node using the supplied jid and subscription + * options. The bare jid portion of this one must match the jid for the + * connection. + * + * Please note that the {@link Subscription.State} should be checked + * on return since more actions may be required by the caller. + * {@link Subscription.State#pending} - The owner must approve the subscription + * request before messages will be received. + * {@link Subscription.State#unconfigured} - If the {@link Subscription#isConfigRequired()} is true, + * the caller must configure the subscription before messages will be received. If it is false + * the caller can configure it but is not required to do so. + * + * @param jidString The jid to subscribe as. + * @param subForm TODO javadoc me please + * + * @return The subscription + * @throws XMPPErrorException if there was an XMPP error returned. + * @throws NoResponseException if there was no response from the remote entity. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + * @throws IllegalArgumentException if the provided string is not a valid JID. + * @deprecated use {@link #subscribe(Jid, FillableSubscribeForm)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public Subscription subscribe(String jidString, FillableSubscribeForm subForm) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + Jid jid; + try { + jid = JidCreate.from(jidString); + } catch (XmppStringprepException e) { + throw new IllegalArgumentException(e); + } + return subscribe(jid, subForm); + } + /** * Remove the subscription related to the specified JID. This will only * work if there is only 1 subscription. If there are multiple subscriptions, diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java index 3c7c756de..cbe9c10cb 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/PubSubManager.java @@ -156,6 +156,33 @@ public final class PubSubManager extends Manager { return pubSubManager; } + /** + * Deprecated. + * + * @param connection the connection. + * @return the PubSub manager for the given connection. + * @deprecated use {@link #getInstanceFor(XMPPConnection)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public static PubSubManager getInstance(XMPPConnection connection) { + return getInstanceFor(connection); + } + + /** + * Deprecated. + * + * @param connection the connection. + * @param pubSubService the XMPP address of the PubSub service. + * @return the PubSub manager for the given connection. + * @deprecated use {@link #getInstanceFor(XMPPConnection, BareJid)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5. + public static PubSubManager getInstance(XMPPConnection connection, BareJid pubSubService) { + return getInstanceFor(connection, pubSubService); + } + /** * Create a pubsub manager associated to the specified connection where * the pubsub requests require a specific to address for packets. @@ -236,7 +263,7 @@ public final class PubSubManager extends Manager { DataForm submitForm = config.getDataFormToSubmit(); request.addExtension(new FormNode(FormNodeType.CONFIGURE, submitForm)); NodeType nodeType = config.getNodeType(); - // Note that some implementations do to have the pubsub#node_type field in their default configuration, + // Note that some implementations do to have the pubsub#node_type field in their defauilt configuration, // which I believe to be a bug. However, since PubSub specifies the default node type to be 'leaf' we assume // leaf if the field does not exist. isLeafNode = nodeType == null || nodeType == NodeType.leaf; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/SimplePayload.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/SimplePayload.java index 95667a6e5..200be7f4b 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/SimplePayload.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/SimplePayload.java @@ -59,6 +59,27 @@ public class SimplePayload implements XmlElement { ns = StringUtils.requireNotNullNorEmpty(qname.getNamespaceURI(), "Could not determine namespace from XML payload"); } + /** + * Construct a SimplePayload object with the specified element name, + * namespace and content. The content must be well formed XML. + * + * @param elementName The root element name (of the payload) + * @param namespace The namespace of the payload, null if there is none + * @param xmlPayload The payload data + * @deprecated use {@link #SimplePayload(String)} insteas. + */ + // TODO: Remove in Smack 4.5 + @Deprecated + public SimplePayload(String elementName, String namespace, CharSequence xmlPayload) { + this(xmlPayload.toString()); + if (!elementName.equals(this.elemName)) { + throw new IllegalArgumentException(); + } + if (!namespace.equals(this.ns)) { + throw new IllegalArgumentException(); + } + } + @Override public String getElementName() { return elemName; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/packet/PubSub.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/packet/PubSub.java index 138558207..a2756d5ff 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/packet/PubSub.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pubsub/packet/PubSub.java @@ -43,14 +43,13 @@ public class PubSub extends IQ { super(ELEMENT, ns.getXmlns()); } - @SuppressWarnings("this-escape") public PubSub(Jid to, Type type, PubSubNamespace ns) { super(ELEMENT, (ns == null ? PubSubNamespace.basic : ns).getXmlns()); setTo(to); setType(type); } - @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) + @SuppressWarnings("unchecked") public PE getExtension(PubSubElementType elem) { return (PE) getExtensionElement(elem.getElementName(), elem.getNamespace().getXmlns()); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/rsm/RSMManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/rsm/RSMManager.java index 9f03c257a..ea6924fae 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/rsm/RSMManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/rsm/RSMManager.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014-2024 Florian Schmaus + * Copyright © 2014-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,8 @@ */ package org.jivesoftware.smackx.rsm; -import java.util.ArrayList; import java.util.Collection; +import java.util.LinkedList; import java.util.List; import org.jivesoftware.smack.packet.XmlElement; @@ -29,7 +29,7 @@ import org.jivesoftware.smackx.rsm.packet.RSMSet.PageDirection; public class RSMManager { Collection page(int max) { - List packetExtensions = new ArrayList<>(); + List packetExtensions = new LinkedList<>(); packetExtensions.add(new RSMSet(max)); return packetExtensions; } @@ -45,7 +45,7 @@ public class RSMManager { throw new IllegalArgumentException("returnedExtensions must no be null"); } if (additionalExtensions == null) { - additionalExtensions = new ArrayList<>(); + additionalExtensions = new LinkedList<>(); } RSMSet resultRsmSet = PacketUtil.extensionElementFrom(returnedExtensions, RSMSet.ELEMENT, RSMSet.NAMESPACE); if (resultRsmSet == null) { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/search/ReportedData.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/search/ReportedData.java index ac2cec39d..36853164b 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/search/ReportedData.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/search/ReportedData.java @@ -150,7 +150,7 @@ public class ReportedData { /** * Creates a new column with the specified definition. * - * @param label the column's label. + * @param label the columns's label. * @param variable the variable name of the column. * @param type the format for the returned data. */ diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/si/provider/StreamInitiationProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/si/provider/StreamInitiationProvider.java index d6333ed80..a4be338b5 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/si/provider/StreamInitiationProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/si/provider/StreamInitiationProvider.java @@ -45,7 +45,6 @@ import org.jxmpp.util.XmppDateTime; public class StreamInitiationProvider extends IqProvider { private static final Logger LOGGER = Logger.getLogger(StreamInitiationProvider.class.getName()); - @SuppressWarnings("JavaUtilDate") @Override public StreamInitiation parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { // si diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/time/packet/Time.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/time/packet/Time.java index 387a7d390..bb7632210 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/time/packet/Time.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/time/packet/Time.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2014-2024 Florian Schmaus + * Copyright 2003-2007 Jive Software, 2014-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,7 +46,6 @@ public class Time extends IQ implements TimeView { private final String utc; private final String tzo; - @SuppressWarnings("this-escape") public Time(TimeBuilder timeBuilder) { super(timeBuilder, ELEMENT, NAMESPACE); utc = timeBuilder.getUtc(); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/element/DescElement.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/element/DescElement.java deleted file mode 100644 index 7cb6b4b6b..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/element/DescElement.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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.smackx.urldata.element; - -import org.jivesoftware.smack.packet.NamedElement; -import org.jivesoftware.smack.packet.XmlEnvironment; -import org.jivesoftware.smack.util.EqualsUtil; -import org.jivesoftware.smack.util.HashCode; -import org.jivesoftware.smack.util.XmlStringBuilder; - -public class DescElement implements NamedElement { - - public static final String ELEMENT = "desc"; - - private final String desc; - - public DescElement(String desc) { - this.desc = desc; - } - - public String getDesc() { - return desc; - } - - @Override - public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) { - return new XmlStringBuilder(this) - .rightAngleBracket() - .append(getDesc()) - .closeElement(this); - } - - @Override - public String getElementName() { - return ELEMENT; - } - - @Override - public int hashCode() { - return HashCode.builder() - .append(getElementName()) - .append(getDesc()) - .build(); - } - - @Override - public boolean equals(Object obj) { - return EqualsUtil.equals(this, obj, (equalsBuilder, other) -> - equalsBuilder - .append(getElementName(), other.getElementName()) - .append(getDesc(), other.getDesc())); - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/element/MetaInformationElement.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/element/MetaInformationElement.java deleted file mode 100644 index 95628092b..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/element/MetaInformationElement.java +++ /dev/null @@ -1,22 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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.smackx.urldata.element; - -import org.jivesoftware.smack.packet.NamedElement; - -public interface MetaInformationElement extends NamedElement { -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/element/UrlDataElement.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/element/UrlDataElement.java deleted file mode 100644 index b10478e44..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/element/UrlDataElement.java +++ /dev/null @@ -1,160 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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.smackx.urldata.element; - -import java.util.ArrayList; -import java.util.List; - -import org.jivesoftware.smack.packet.ExtensionElement; -import org.jivesoftware.smack.packet.NamedElement; -import org.jivesoftware.smack.packet.XmlEnvironment; -import org.jivesoftware.smack.util.EqualsUtil; -import org.jivesoftware.smack.util.HashCode; -import org.jivesoftware.smack.util.XmlStringBuilder; - -import org.jivesoftware.smackx.urldata.http.element.CookieElement; -import org.jivesoftware.smackx.urldata.http.element.HeaderElement; -import org.jivesoftware.smackx.urldata.http.element.HttpAuthElement; - -/** - * The url-data element. - */ -public class UrlDataElement implements ExtensionElement { - - public static final String ELEMENT = "url-data"; - public static final String NAMESPACE = "http://jabber.org/protocol/url-data"; - public static final String ATTR_TARGET = "target"; - public static final String ATTR_SID = "sid"; - public static final String XMLNS_HTTP = "xmlns:http"; - - public static final String SCHEME_HTTP = "http://jabber.org/protocol/url-data/scheme/http"; - - private final String target; - private final String sid; - private final List authParamElements = new ArrayList<>(); - private final List cookieElements = new ArrayList<>(); - private final List headerElements = new ArrayList<>(); - - public UrlDataElement(String target, - String sid) { - this(target, sid, null, null, null); - } - - public UrlDataElement(String target, - String sid, - List authParamElements, - List cookieElements, - List headerElements) { - this.target = target; - this.sid = sid; - if (authParamElements != null) { - this.authParamElements.addAll(authParamElements); - } - if (cookieElements != null) { - this.cookieElements.addAll(cookieElements); - } - if (headerElements != null) { - this.headerElements.addAll(headerElements); - } - } - - public String getTarget() { - return target; - } - - /** - * Return the optional stream identifier used for XEP-0095: Stream Initiation. - * - * @return stream identifier or null - */ - public String getSid() { - return sid; - } - - public List getAuthParameters() { - return authParamElements; - } - - public List getCookies() { - return cookieElements; - } - - public List getHeaders() { - return headerElements; - } - - private List getMetaInformationElements() { - List elements = new ArrayList<>(); - elements.addAll(getAuthParameters()); - elements.addAll(getCookies()); - elements.addAll(getHeaders()); - return elements; - } - - @Override - public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) { - List metaInformation = getMetaInformationElements(); - - XmlStringBuilder sb = new XmlStringBuilder(this); - if (!metaInformation.isEmpty()) { - sb.attribute(XMLNS_HTTP, SCHEME_HTTP); - } - sb.attribute(ATTR_TARGET, getTarget()) - .optAttribute(ATTR_SID, getSid()); - if (metaInformation.isEmpty()) { - return sb.closeEmptyElement(); - } else { - return sb.rightAngleBracket() - .append(metaInformation) - .closeElement(this); - } - } - - @Override - public String getNamespace() { - return NAMESPACE; - } - - @Override - public String getElementName() { - return ELEMENT; - } - - @Override - public int hashCode() { - return HashCode.builder() - .append(getElementName()) - .append(getNamespace()) - .append(getTarget()) - .append(getAuthParameters()) - .append(getCookies()) - .append(getHeaders()) - .build(); - } - - @Override - public boolean equals(Object obj) { - return EqualsUtil.equals(this, obj, (equalsBuilder, other) -> - equalsBuilder - .append(getElementName(), other.getElementName()) - .append(getNamespace(), other.getNamespace()) - .append(getTarget(), other.getTarget()) - .append(getAuthParameters(), other.getAuthParameters()) - .append(getCookies(), other.getCookies()) - .append(getHeaders(), other.getHeaders())); - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/element/package-info.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/element/package-info.java deleted file mode 100644 index 0682aff01..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/element/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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. - */ - -/** - * Element classes for XEP-0103: URL Address Information. - * - * @see XEP-0103 - URL Address Information. - */ -package org.jivesoftware.smackx.urldata.element; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/AuthParamElement.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/AuthParamElement.java deleted file mode 100644 index 42ca5218a..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/AuthParamElement.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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.smackx.urldata.http.element; - -import org.jivesoftware.smack.packet.XmlEnvironment; -import org.jivesoftware.smack.util.EqualsUtil; -import org.jivesoftware.smack.util.HashCode; -import org.jivesoftware.smack.util.XmlStringBuilder; - -public class AuthParamElement extends NameValuePairElement { - - public static final String ELEMENT = "auth-param"; - public static final String PREFIX = "http"; - - public static final String NAME_REALM = "realm"; - public static final String NAME_USERNAME = "username"; - public static final String NAME_PASSWORD = "password"; - - public AuthParamElement(String name, String value) { - super(name, value); - } - - public static AuthParamElement realm(String realm) { - return new AuthParamElement(NAME_REALM, realm); - } - - public static AuthParamElement username(String username) { - return new AuthParamElement(NAME_USERNAME, username); - } - - public static AuthParamElement password(String password) { - return new AuthParamElement(NAME_PASSWORD, password); - } - - @Override - public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) { - return addCommonXml(new XmlStringBuilder(this)) - .closeEmptyElement(); - } - - @Override - public String getElementName() { - return PREFIX + ':' + ELEMENT; - } - - @Override - public int hashCode() { - return HashCode.builder() - .append(getElementName()) - .append(getName()) - .append(getValue()) - .build(); - } - - @Override - public boolean equals(Object obj) { - return EqualsUtil.equals(this, obj, (equalsBuilder, other) -> - equalsBuilder - .append(getElementName(), other.getElementName()) - .append(getName(), other.getName()) - .append(getValue(), other.getValue())); - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/CookieElement.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/CookieElement.java deleted file mode 100644 index 3bd95347b..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/CookieElement.java +++ /dev/null @@ -1,128 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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.smackx.urldata.http.element; - -import org.jivesoftware.smack.packet.XmlEnvironment; -import org.jivesoftware.smack.util.EqualsUtil; -import org.jivesoftware.smack.util.HashCode; -import org.jivesoftware.smack.util.XmlStringBuilder; - -public class CookieElement extends NameValuePairElement { - - public static final String ELEMENT = "cookie"; - public static final String PREFIX = "http"; - public static final String ATTR_DOMAIN = "domain"; - public static final String ATTR_MAX_AGE = "max-age"; - public static final String ATTR_PATH = "path"; - public static final String ATTR_COMMENT = "comment"; - public static final String ATTR_VERSION = "version"; - public static final String ATTR_SECURE = "secure"; - - private final String domain; - private final Integer maxAge; - private final String path; - private final String comment; - private final String version; - private final Boolean secure; - - public CookieElement(String name, String value) { - this(name, value, null, null, null, null, null, null); - } - - public CookieElement(String name, String value, String domain, Integer maxAge, String path, String comment, String version, Boolean secure) { - super(name, value); - this.domain = domain; - this.maxAge = maxAge; - this.path = path; - this.comment = comment; - this.version = version; - this.secure = secure; - } - - public String getPath() { - return path; - } - - public int getMaxAge() { - return maxAge == null ? 0 : maxAge; - } - - public String getDomain() { - return domain; - } - - public String getComment() { - return comment; - } - - public String getVersion() { - return version == null ? "1.0" : version; - } - - public boolean isSecure() { - return secure != null && secure; - } - - @Override - public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) { - XmlStringBuilder sb = addCommonXml(new XmlStringBuilder(this)) - .optAttribute(ATTR_DOMAIN, domain) - .optAttribute(ATTR_MAX_AGE, maxAge) - .optAttribute(ATTR_PATH, path) - .optAttribute(ATTR_COMMENT, comment) - .optAttribute(ATTR_VERSION, version); - if (secure != null) { - sb.attribute(ATTR_SECURE, secure); - } - return sb.closeEmptyElement(); - } - - @Override - public String getElementName() { - return PREFIX + ':' + ELEMENT; - } - - @Override - public int hashCode() { - return HashCode.builder() - .append(getElementName()) - .append(getName()) - .append(getValue()) - .append(getDomain()) - .append(getMaxAge()) - .append(getPath()) - .append(getComment()) - .append(getVersion()) - .append(isSecure()) - .build(); - } - - @Override - public boolean equals(Object obj) { - return EqualsUtil.equals(this, obj, (equalsBuilder, other) -> - equalsBuilder - .append(getElementName(), other.getElementName()) - .append(getName(), other.getName()) - .append(getValue(), other.getValue()) - .append(getDomain(), other.getDomain()) - .append(getMaxAge(), other.getMaxAge()) - .append(getPath(), other.getPath()) - .append(getComment(), other.getComment()) - .append(getVersion(), other.getVersion()) - .append(isSecure(), other.isSecure())); - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/HeaderElement.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/HeaderElement.java deleted file mode 100644 index 0feb816e3..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/HeaderElement.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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.smackx.urldata.http.element; - -import org.jivesoftware.smack.packet.XmlEnvironment; -import org.jivesoftware.smack.util.EqualsUtil; -import org.jivesoftware.smack.util.HashCode; -import org.jivesoftware.smack.util.XmlStringBuilder; - -public class HeaderElement extends NameValuePairElement { - - public static final String ELEMENT = "header"; - public static final String PREFIX = "http"; - - public HeaderElement(String name, String value) { - super(name, value); - } - - @Override - public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) { - return addCommonXml(new XmlStringBuilder(this)) - .closeEmptyElement(); - } - - @Override - public String getElementName() { - return PREFIX + ':' + ELEMENT; - } - - @Override - public int hashCode() { - return HashCode.builder() - .append(getElementName()) - .append(getName()) - .append(getValue()) - .build(); - } - - @Override - public boolean equals(Object obj) { - return EqualsUtil.equals(this, obj, (equalsBuilder, other) -> - equalsBuilder - .append(getElementName(), other.getElementName()) - .append(getName(), other.getName()) - .append(getValue(), other.getValue())); - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/HttpAuthElement.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/HttpAuthElement.java deleted file mode 100644 index ff11163f2..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/HttpAuthElement.java +++ /dev/null @@ -1,123 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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.smackx.urldata.http.element; - -import java.util.ArrayList; -import java.util.List; - -import org.jivesoftware.smack.packet.XmlEnvironment; -import org.jivesoftware.smack.util.EqualsUtil; -import org.jivesoftware.smack.util.HashCode; -import org.jivesoftware.smack.util.XmlStringBuilder; - -import org.jivesoftware.smackx.urldata.element.MetaInformationElement; - -public final class HttpAuthElement implements MetaInformationElement { - - public static final String ELEMENT = "auth"; - public static final String PREFIX = "http"; - public static final String ATTR_SCHEME = "scheme"; - - public static final String SCHEME_BASIC = "basic"; - - private final String scheme; - private final List params = new ArrayList<>(); - - public HttpAuthElement(String scheme, List params) { - this.scheme = scheme; - if (params != null) { - this.params.addAll(params); - } - } - - public static HttpAuthElement basicAuth() { - return basicAuth(null, null); - } - - public static HttpAuthElement basicAuth(String username, String password) { - return basicAuth(null, username, password); - } - - public static HttpAuthElement basicAuth(String realm, String username, String password) { - List params = new ArrayList<>(); - if (realm != null) { - params.add(AuthParamElement.realm(realm)); - } - if (username != null) { - params.add(AuthParamElement.username(username)); - } - if (password != null) { - params.add(AuthParamElement.password(password)); - } - - return new HttpAuthElement(SCHEME_BASIC, params); - } - - public String getScheme() { - return scheme; - } - - public List getParams() { - return params; - } - - @Override - public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) { - XmlStringBuilder sb = new XmlStringBuilder(this) - .attribute(ATTR_SCHEME, getScheme()); - if (getParams().isEmpty()) { - return sb.closeEmptyElement(); - } else { - return sb.rightAngleBracket() - .append(getParams()) - .closeElement(this); - } - } - - @Override - public String getElementName() { - return PREFIX + ':' + ELEMENT; - } - - public AuthParamElement getParam(String name) { - for (AuthParamElement param : getParams()) { - if (param.getName().equals(name)) { - return param; - } - } - return null; - } - - @Override - public int hashCode() { - return HashCode.builder() - .append(getElementName()) - .append(getScheme()) - .append(getParams()) - .build(); - } - - @Override - public boolean equals(Object obj) { - return EqualsUtil.equals(this, obj, (equalsBuilder, other) -> - equalsBuilder - .append(getElementName(), other.getElementName()) - .append(getScheme(), other.getScheme()) - .append(getParams(), other.getParams())); - } - -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/NameValuePairElement.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/NameValuePairElement.java deleted file mode 100644 index 911bdb339..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/NameValuePairElement.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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.smackx.urldata.http.element; - -import org.jivesoftware.smack.util.XmlStringBuilder; - -import org.jivesoftware.smackx.urldata.element.MetaInformationElement; - -public abstract class NameValuePairElement implements MetaInformationElement { - - public static final String ATTR_NAME = "name"; - public static final String ATTR_VALUE = "value"; - - private final String name; - private final String value; - - public NameValuePairElement(String name, String value) { - this.name = name; - this.value = value; - } - - public String getName() { - return name; - } - - public String getValue() { - return value; - } - - public XmlStringBuilder addCommonXml(XmlStringBuilder sb) { - return sb.attribute(ATTR_NAME, getName()) - .attribute(ATTR_VALUE, getValue()); - } - -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/package-info.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/package-info.java deleted file mode 100644 index 7bc42714a..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/element/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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. - */ - -/** - * Element classes for XEP-0104. - */ -package org.jivesoftware.smackx.urldata.http.element; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/package-info.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/package-info.java deleted file mode 100644 index 4a7f1b8db..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/http/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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. - */ - -/** - * Smack's API for XEP-0104: HTTP Scheme for URL Address Information. - * - * @see XEP-0104 - HTTP Scheme for URL Address Information - */ -package org.jivesoftware.smackx.urldata.http; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/package-info.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/package-info.java deleted file mode 100644 index 06fec0af9..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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. - */ - -/** - * Smack's API for XEP-0103 - URL Address Information. - */ -package org.jivesoftware.smackx.urldata; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/provider/UrlDataElementProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/provider/UrlDataElementProvider.java deleted file mode 100644 index f1a8a2b25..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/provider/UrlDataElementProvider.java +++ /dev/null @@ -1,101 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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.smackx.urldata.provider; - -import static org.jivesoftware.smackx.urldata.element.UrlDataElement.ATTR_SID; -import static org.jivesoftware.smackx.urldata.element.UrlDataElement.ATTR_TARGET; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.jivesoftware.smack.packet.XmlEnvironment; -import org.jivesoftware.smack.parsing.SmackParsingException; -import org.jivesoftware.smack.provider.ExtensionElementProvider; -import org.jivesoftware.smack.util.ParserUtils; -import org.jivesoftware.smack.xml.XmlPullParser; -import org.jivesoftware.smack.xml.XmlPullParserException; - -import org.jivesoftware.smackx.urldata.element.UrlDataElement; -import org.jivesoftware.smackx.urldata.http.element.AuthParamElement; -import org.jivesoftware.smackx.urldata.http.element.CookieElement; -import org.jivesoftware.smackx.urldata.http.element.HeaderElement; -import org.jivesoftware.smackx.urldata.http.element.HttpAuthElement; - -public class UrlDataElementProvider extends ExtensionElementProvider { - - @Override - public UrlDataElement parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, IOException, SmackParsingException { - String target = parser.getAttributeValue(ATTR_TARGET); - String sid = parser.getAttributeValue(ATTR_SID); - List authElements = new ArrayList<>(); - List cookieElements = new ArrayList<>(); - List headerElements = new ArrayList<>(); - do { - XmlPullParser.TagEvent event = parser.nextTag(); - String name = parser.getName(); - - if (event == XmlPullParser.TagEvent.START_ELEMENT) { - switch (name) { - case UrlDataElement.ELEMENT: - continue; - - case HttpAuthElement.ELEMENT: - String scheme = parser.getAttributeValue(HttpAuthElement.ATTR_SCHEME); - List authParamElements = new ArrayList<>(); - int innerDepth = parser.getDepth(); - do { - XmlPullParser.TagEvent innerTag = parser.nextTag(); - String innerName = parser.getName(); - if (innerTag.equals(XmlPullParser.TagEvent.START_ELEMENT)) { - if (innerName.equals(AuthParamElement.ELEMENT)) { - String attrName = ParserUtils.getRequiredAttribute(parser, AuthParamElement.ATTR_NAME); - String attrVal = ParserUtils.getRequiredAttribute(parser, AuthParamElement.ATTR_VALUE); - authParamElements.add(new AuthParamElement(attrName, attrVal)); - } - } - } while (parser.getDepth() != innerDepth); - - authElements.add(new HttpAuthElement(scheme, authParamElements)); - break; - - case CookieElement.ELEMENT: - String cookieName = ParserUtils.getRequiredAttribute(parser, CookieElement.ATTR_NAME); - String cookieValue = ParserUtils.getRequiredAttribute(parser, CookieElement.ATTR_VALUE); - String cookieDomain = parser.getAttributeValue(CookieElement.ATTR_DOMAIN); - Integer cookieMaxAge = ParserUtils.getIntegerAttribute(parser, CookieElement.ATTR_MAX_AGE); - String cookiePath = parser.getAttributeValue(CookieElement.ATTR_PATH); - String cookieComment = parser.getAttributeValue(CookieElement.ATTR_COMMENT); - Boolean cookieSecure = ParserUtils.getBooleanAttribute(parser, CookieElement.ATTR_SECURE); - String cookieVersion = parser.getAttributeValue(CookieElement.ATTR_VERSION); - - cookieElements.add(new CookieElement(cookieName, cookieValue, cookieDomain, cookieMaxAge, cookiePath, cookieComment, cookieVersion, cookieSecure)); - break; - - case HeaderElement.ELEMENT: - String headerName = ParserUtils.getRequiredAttribute(parser, HeaderElement.ATTR_NAME); - String headerValue = ParserUtils.getRequiredAttribute(parser, HeaderElement.ATTR_VALUE); - - headerElements.add(new HeaderElement(headerName, headerValue)); - break; - } - } - } while (parser.getDepth() != initialDepth); - - return new UrlDataElement(target, sid, authElements, cookieElements, headerElements); - } -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/provider/package-info.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/provider/package-info.java deleted file mode 100644 index c31c44db0..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/urldata/provider/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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. - */ - -/** - * Provider classes for XEP-0103: URL Address Information. - * - * @see XEP-0103 - URL Address Information. - */ -package org.jivesoftware.smackx.urldata.provider; diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/VCardManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/VCardManager.java index 5aefdeeff..0bfbba9b2 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/VCardManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/VCardManager.java @@ -106,7 +106,7 @@ public final class VCardManager extends Manager { vcard.setType(IQ.Type.set); // Also make sure to generate a new stanza id (the given vcard could be a vcard result), in which case we don't // want to use the same stanza id again (although it wouldn't break if we did) - // vcard.setStanzaId(); TODO FIXME + vcard.setStanzaId(); connection().sendIqRequestAndWaitForResponse(vcard); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/packet/VCard.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/packet/VCard.java index 4d6f18ecf..4f4d74a19 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/packet/VCard.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/packet/VCard.java @@ -122,7 +122,7 @@ public final class VCard extends IQ { private String photoBinval; /** - * Such as DESC ROLE GEO etc. see XEP-0054 + * Such as DESC ROLE GEO etc.. see XEP-0054 */ private final Map otherSimpleFields = new HashMap<>(); @@ -575,7 +575,7 @@ public final class VCard extends IQ { * Load VCard information for a given user. XMPPConnection should be authenticated and not anonymous. * * @param connection connection. - * @param user user whose information we want to load. + * @param user user whos information we want to load. * * @throws XMPPErrorException if there was an XMPP error returned. * @throws NoResponseException if there was no response from the server. diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/BooleanFormField.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/BooleanFormField.java index 756c14b52..6681e6408 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/BooleanFormField.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/BooleanFormField.java @@ -36,7 +36,7 @@ public class BooleanFormField extends SingleValueFormField { } /** - * Get the value of the boolean field. Note that, if no explicit boolean value is provided, in the form of "true", + * Get the value of the booelan field. Note that, if no explicit boolean value is provided, in the form of "true", * "false", "0", or "1", then the default value of a boolean field is false, according to * XEP-0004 § 3.3. * diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java index bd172be54..a2ad8cb76 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2019-2024 Florian Schmaus. + * Copyright 2003-2007 Jive Software, 2019-2021 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -342,6 +342,23 @@ public abstract class FormField implements XmlElement { return XmppDateTime.parseXEP0082Date(valueString); } + /** + * Returns the field's name, also known as the variable name in case this is an filled out answer form. + *

    + * According to XEP-4 § 3.2 the variable name (the 'var' attribute) + * "uniquely identifies the field in the context of the form" (if the field is not of type 'fixed', in which case + * the field "MAY possess a 'var' attribute") + *

    + * + * @return the field's name. + * @deprecated use {@link #getFieldName()} instead. + */ + // TODO: Remove in Smack 4.5 + @Deprecated + public String getVariable() { + return getFieldName(); + } + /** * Returns the field's name, also known as the variable name in case this is an filled out answer form. *

    @@ -386,7 +403,7 @@ public abstract class FormField implements XmlElement { protected transient List extraXmlChildElements; /** - * Populate {@link #extraXmlChildElements}. Note that this method may be overridden by subclasses. + * Populate @{link {@link #extraXmlChildElements}}. Note that this method may be overridden by subclasses. */ protected void populateExtraXmlChildElements() { List values = getRawValues(); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/form/FillableForm.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/form/FillableForm.java index 302156c2c..159c20544 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/form/FillableForm.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/form/FillableForm.java @@ -1,6 +1,6 @@ /** * - * Copyright 2020-2024 Florian Schmaus + * Copyright 2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,8 +30,6 @@ import org.jivesoftware.smackx.xdata.AbstractMultiFormField; import org.jivesoftware.smackx.xdata.AbstractSingleStringValueFormField; import org.jivesoftware.smackx.xdata.FormField; import org.jivesoftware.smackx.xdata.FormFieldChildElement; -import org.jivesoftware.smackx.xdata.ListMultiFormField; -import org.jivesoftware.smackx.xdata.ListSingleFormField; import org.jivesoftware.smackx.xdata.packet.DataForm; import org.jxmpp.jid.Jid; @@ -49,7 +47,6 @@ public class FillableForm extends FilledForm { private final Map filledFields = new HashMap<>(); - @SuppressWarnings("this-escape") public FillableForm(DataForm dataForm) { super(dataForm); if (dataForm.getType() != DataForm.Type.form) { @@ -57,7 +54,6 @@ public class FillableForm extends FilledForm { } Set requiredFields = new HashSet<>(); - List requiredFieldsWithDefaultValue = new ArrayList<>(); for (FormField formField : dataForm.getFields()) { if (formField.isRequired()) { String fieldName = formField.getFieldName(); @@ -65,17 +61,13 @@ public class FillableForm extends FilledForm { if (formField.hasValueSet()) { // This is a form field with a default value. - requiredFieldsWithDefaultValue.add(formField); + write(formField); } else { missingRequiredFields.add(fieldName); } } } this.requiredFields = Collections.unmodifiableSet(requiredFields); - - for (FormField field : requiredFieldsWithDefaultValue) { - write(field); - } } protected void writeListMulti(String fieldName, List values) { @@ -229,20 +221,11 @@ public class FillableForm extends FilledForm { if (filledFormField.getType() == FormField.Type.fixed) { throw new IllegalArgumentException(); } - - String fieldName = filledFormField.getFieldName(); - - boolean isListField = filledFormField instanceof ListMultiFormField - || filledFormField instanceof ListSingleFormField; - // Only list-* fields require a value to be set. Other fields types can be empty. For example MUC's - // muc#roomconfig_roomadmins, which is of type jid-multi, is submitted without values to reset the room's admin - // list. - if (isListField && !filledFormField.hasValueSet()) { - throw new IllegalArgumentException("Tried to write form field " + fieldName + " of type " - + filledFormField.getType() - + " without any values set. However, according to XEP-0045 § 3.3 fields of type list-multi or list-single must have one item set."); + if (!filledFormField.hasValueSet()) { + throw new IllegalArgumentException(); } + String fieldName = filledFormField.getFieldName(); if (!getDataForm().hasField(fieldName)) { throw new IllegalArgumentException(); } @@ -287,8 +270,4 @@ public class FillableForm extends FilledForm { return builder.build(); } - public SubmitForm getSubmitForm() { - DataForm form = getDataFormToSubmit(); - return new SubmitForm(form); - } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/form/SubmitForm.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/form/SubmitForm.java deleted file mode 100644 index f317dda27..000000000 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/form/SubmitForm.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * - * Copyright 2023 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.smackx.xdata.form; - -import org.jivesoftware.smackx.xdata.packet.DataForm; - -public class SubmitForm extends FilledForm { - - public SubmitForm(DataForm dataForm) { - super(dataForm); - - if (dataForm.getType() != DataForm.Type.submit) { - throw new IllegalArgumentException(); - } - } - -} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/packet/DataForm.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/packet/DataForm.java index e9f2da625..9ab354d57 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/packet/DataForm.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xdata/packet/DataForm.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2020-2024 Florian Schmaus. + * Copyright 2003-2007 Jive Software, 2020-2021 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,6 +33,7 @@ import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.StanzaView; import org.jivesoftware.smack.packet.XmlEnvironment; import org.jivesoftware.smack.util.CollectionUtil; +import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.XmlStringBuilder; @@ -355,7 +356,8 @@ public final class DataForm implements ExtensionElement { } public static final class Builder { - private final Type type; + // TODO: Make this field final once setType() is gone. + private Type type; private String title; private List instructions; private ReportedData reportedData; @@ -407,6 +409,20 @@ public final class DataForm implements ExtensionElement { } } + /** + * Deprecated do not use. + * + * @param type the type. + * @return a reference to this builder. + * @deprecated use {@link DataForm#builder(Type)} instead. + */ + @Deprecated + // TODO: Remove in Smack 4.5 and then make this.type final. + public Builder setType(Type type) { + this.type = Objects.requireNonNull(type); + return this; + } + /** * Sets the description of the data. It is similar to the title on a web page or an X window. * You can put a <title/> on either a form to fill out, or a set of data results. diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/package-info.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/package-info.java index 7ebb8cee9..7054e0f22 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/package-info.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/package-info.java @@ -152,7 +152,7 @@ * Before you start to send XHTML messages to a user you should discover if the user supports XHTML messages. There are * two ways to achieve the discovery, explicitly and implicitly. Explicit is when you first try to discover if the user * supports XHTML before sending any XHTML message. Implicit is when you send XHTML messages without first discovering - * if the conversation partner's client supports XHTML and depending on the answer (normal message or XHTML message) you + * if the conversation partner's client supports XHTML and depenging on the answer (normal message or XHTML message) you * find out if the user supports XHTML messages or not. This section explains how to explicitly discover for XHTML * support. *

    diff --git a/smack-extensions/src/main/resources/org.jivesoftware.smack.extensions/extensions.providers b/smack-extensions/src/main/resources/org.jivesoftware.smack.extensions/extensions.providers index 8dd5b32d3..c2ac6921e 100644 --- a/smack-extensions/src/main/resources/org.jivesoftware.smack.extensions/extensions.providers +++ b/smack-extensions/src/main/resources/org.jivesoftware.smack.extensions/extensions.providers @@ -365,13 +365,6 @@ org.jivesoftware.smackx.si.provider.StreamInitiationProvider - - - url-data - http://jabber.org/protocol/url-data - org.jivesoftware.smackx.urldata.provider.UrlDataElementProvider - - mood diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamManagerTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamManagerTest.java index 0c59cf73c..00e721e5b 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamManagerTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ByteStreamManagerTest.java @@ -179,7 +179,7 @@ public class Socks5ByteStreamManagerTest { Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection); byteStreamManager.setAnnounceLocalStreamHost(false); - /* + /** * create responses in the order they should be queried specified by the XEP-0065 * specification */ @@ -231,7 +231,7 @@ public class Socks5ByteStreamManagerTest { Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection); byteStreamManager.setAnnounceLocalStreamHost(false); - /* + /** * create responses in the order they should be queried specified by the XEP-0065 * specification */ @@ -292,7 +292,7 @@ public class Socks5ByteStreamManagerTest { Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection); byteStreamManager.setAnnounceLocalStreamHost(false); - /* + /** * create responses in the order they should be queried specified by the XEP-0065 * specification */ @@ -375,7 +375,7 @@ public class Socks5ByteStreamManagerTest { Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection); byteStreamManager.setAnnounceLocalStreamHost(false); - /* + /** * create responses in the order they should be queried specified by the XEP-0065 * specification */ @@ -454,7 +454,7 @@ public class Socks5ByteStreamManagerTest { // TODO: It appears that it is not required to disable the local stream host for this unit test. byteStreamManager.setAnnounceLocalStreamHost(false); - /* + /** * create responses in the order they should be queried specified by the XEP-0065 * specification */ @@ -541,7 +541,7 @@ public class Socks5ByteStreamManagerTest { byteStreamManager.setAnnounceLocalStreamHost(false); byteStreamManager.setProxyConnectionTimeout(3000); - /* + /** * create responses in the order they should be queried specified by the XEP-0065 * specification */ @@ -634,7 +634,7 @@ public class Socks5ByteStreamManagerTest { Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection); byteStreamManager.setAnnounceLocalStreamHost(false); - /* + /** * create responses in the order they should be queried specified by the XEP-0065 * specification */ @@ -760,7 +760,7 @@ public class Socks5ByteStreamManagerTest { // get Socks5ByteStreamManager for connection Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection); - /* + /** * create responses in the order they should be queried specified by the XEP-0065 * specification */ diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/caps/EntityCapsManagerTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/caps/EntityCapsManagerTest.java index d9a0666c3..87700708e 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/caps/EntityCapsManagerTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/caps/EntityCapsManagerTest.java @@ -22,8 +22,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; +import java.util.LinkedList; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.test.util.SmackTestSuite; @@ -47,41 +47,6 @@ import org.jxmpp.stringprep.XmppStringprepException; public class EntityCapsManagerTest extends SmackTestSuite { - /** - * XEP- - * 0115 Simple Generation Example. - * @throws XmppStringprepException if the provided string is invalid. - */ - @Test - public void testSimpleGenerationExample() throws XmppStringprepException { - DiscoverInfo di = createSimpleSamplePacket(); - - CapsVersionAndHash versionAndHash = EntityCapsManager.generateVerificationString(di, StringUtils.SHA1); - assertEquals("QgayPKawpkPSDYmwT/WM94uAlu0=", versionAndHash.version); - } - - /** - * Asserts that the order in which data forms are present in the disco/info does not affect the calculated - * verification string, as the XEP mandates that these are ordered by FORM_TYPE (i.e., by the XML character data of - * the element). - * @throws XmppStringprepException if the provided string is invalid. - */ - @Test - public void testReversedDataFormOrder() throws XmppStringprepException { - final DiscoverInfoBuilder builderA = createSimpleSampleBuilder(); - builderA.addExtension(createSampleServerInfoDataForm()); // This works, as the underlying MultiMap maintains insertion-order. - builderA.addExtension(createSampleSoftwareInfoDataForm()); - - final DiscoverInfoBuilder builderB = createSimpleSampleBuilder(); - builderB.addExtension(createSampleSoftwareInfoDataForm()); - builderB.addExtension(createSampleServerInfoDataForm()); - - CapsVersionAndHash versionAndHashA = EntityCapsManager.generateVerificationString(builderA.build(), StringUtils.SHA1); - CapsVersionAndHash versionAndHashB = EntityCapsManager.generateVerificationString(builderB.build(), StringUtils.SHA1); - - assertEquals(versionAndHashA.version, versionAndHashB.version); - } - /** * XEP- * 0115 Complex Generation Example. @@ -177,48 +142,13 @@ public class EntityCapsManagerTest extends SmackTestSuite { return df.build(); } - private static DataForm createSampleServerInfoDataForm() { - DataForm.Builder df = DataForm.builder(DataForm.Type.result); - - { - TextMultiFormField.Builder ff = FormField.textMultiBuilder("admin-addresses"); - ff.addValue("xmpp:admin@example.org"); - ff.addValue("mailto:admin@example.com"); - df.addField(ff.build()); - } - - { - TextSingleFormField.Builder ff = FormField.hiddenBuilder("FORM_TYPE"); - ff.setValue("http://jabber.org/network/serverinfo"); - df.addField(ff.build()); - } - - return df.build(); - } - - private static DiscoverInfoBuilder createSimpleSampleBuilder() throws XmppStringprepException { - DiscoverInfoBuilder di = DiscoverInfo.builder("disco1"); - di.ofType(IQ.Type.result); - - di.addIdentity(new DiscoverInfo.Identity("client", "Exodus 0.9.1", "pc")); - di.addFeature("http://jabber.org/protocol/disco#info"); - di.addFeature("http://jabber.org/protocol/disco#items"); - di.addFeature("http://jabber.org/protocol/muc"); - di.addFeature("http://jabber.org/protocol/caps"); - - return di; - } - private static DiscoverInfo createSimpleSamplePacket() throws XmppStringprepException { - return createSimpleSampleBuilder().build(); - } - private static DiscoverInfo createComplexSamplePacket() throws XmppStringprepException { DiscoverInfoBuilder di = DiscoverInfo.builder("disco1"); di.from(JidCreate.from("benvolio@capulet.lit/230193")); di.to(JidCreate.from("juliet@capulet.lit/chamber")); di.ofType(IQ.Type.result); - Collection identities = new ArrayList(); + Collection identities = new LinkedList(); DiscoverInfo.Identity i = new DiscoverInfo.Identity("client", "pc", "Psi 0.11", "en"); identities.add(i); i = new DiscoverInfo.Identity("client", "pc", "Ψ 0.11", "el"); @@ -241,7 +171,7 @@ public class EntityCapsManagerTest extends SmackTestSuite { di.to(")juliet@capulet.lit/chamber"); di.ofType(IQ.Type.result); - Collection identities = new ArrayList(); + Collection identities = new LinkedList(); DiscoverInfo.Identity i = new DiscoverInfo.Identity("client", "pc", "Psi 0.11", "en"); identities.add(i); i = new DiscoverInfo.Identity("client", "pc", "Ψ 0.11", "el"); diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/commands/provider/CommandsProviderTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/commands/provider/CommandsProviderTest.java index d8b0e734f..68d2098b7 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/commands/provider/CommandsProviderTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/commands/provider/CommandsProviderTest.java @@ -23,6 +23,7 @@ import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.StanzaError; import org.jivesoftware.smack.util.PacketParserUtils; +import org.jivesoftware.smackx.commands.AdHocCommand; import org.jivesoftware.smackx.commands.packet.AdHocCommandData; import org.junit.jupiter.api.Test; @@ -40,7 +41,7 @@ public class CommandsProviderTest { final AdHocCommandData adHocIq = (AdHocCommandData) requestStanza; assertEquals(IQ.Type.error, adHocIq.getType()); - assertEquals(AdHocCommandData.Action.execute, adHocIq.getAction()); + assertEquals(AdHocCommand.Action.execute, adHocIq.getAction()); StanzaError error = adHocIq.getError(); assertEquals(StanzaError.Type.CANCEL, error.getType()); diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/muc/packet/GroupChatInvitationElementTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/muc/packet/GroupChatInvitationElementTest.java deleted file mode 100644 index 1f28be5ce..000000000 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/muc/packet/GroupChatInvitationElementTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub. - * - * 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.smackx.muc.packet; - -import static org.jivesoftware.smack.test.util.XmlAssertUtil.assertXmlSimilar; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.IOException; - -import org.jivesoftware.smack.parsing.SmackParsingException; -import org.jivesoftware.smack.test.util.TestUtils; -import org.jivesoftware.smack.xml.XmlPullParserException; -import org.jivesoftware.smackx.muc.provider.GroupChatInvitationProvider; - -import org.junit.jupiter.api.Test; -import org.jxmpp.jid.EntityBareJid; -import org.jxmpp.jid.impl.JidCreate; - -public class GroupChatInvitationElementTest { - private static final GroupChatInvitationProvider TEST_PROVIDER = new GroupChatInvitationProvider(); - - private static final EntityBareJid mucJid = JidCreate.entityBareFromOrThrowUnchecked("darkcave@macbeth.shakespeare.lit"); - - @Test - public void serializeFullElement() throws XmlPullParserException, IOException, SmackParsingException { - final String expectedXml = "" + - ""; - - GroupChatInvitation invitation = new GroupChatInvitation(mucJid, - "Hey Hecate, this is the place for all good witches!", - "cauldronburn", - true, - "e0ffe42b28561960c6b12b944a092794b9683a38"); - assertXmlSimilar(expectedXml, invitation.toXML()); - - GroupChatInvitation parsed = TEST_PROVIDER.parse(TestUtils.getParser(expectedXml)); - assertEquals(invitation, parsed); - } - - @Test - public void serializeMinimalElementTest() throws XmlPullParserException, IOException, SmackParsingException { - final String expectedXml = ""; - - GroupChatInvitation invitation = new GroupChatInvitation(mucJid); - assertXmlSimilar(expectedXml, invitation.toXML()); - - GroupChatInvitation parsed = TEST_PROVIDER.parse(TestUtils.getParser(expectedXml)); - assertEquals(invitation, parsed); - } -} diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/urldata/UrlDataElementTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/urldata/UrlDataElementTest.java deleted file mode 100644 index 72bc4f32a..000000000 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/urldata/UrlDataElementTest.java +++ /dev/null @@ -1,219 +0,0 @@ -/** - * - * Copyright 2020 Paul Schaub - * - * 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.smackx.urldata; - -import static org.jivesoftware.smack.test.util.XmlAssertUtil.assertXmlSimilar; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; - -import org.jivesoftware.smack.parsing.SmackParsingException; -import org.jivesoftware.smack.test.util.SmackTestSuite; -import org.jivesoftware.smack.test.util.TestUtils; -import org.jivesoftware.smack.xml.XmlPullParserException; - -import org.jivesoftware.smackx.urldata.element.UrlDataElement; -import org.jivesoftware.smackx.urldata.http.element.CookieElement; -import org.jivesoftware.smackx.urldata.http.element.HeaderElement; -import org.jivesoftware.smackx.urldata.http.element.HttpAuthElement; -import org.jivesoftware.smackx.urldata.provider.UrlDataElementProvider; - -import org.junit.jupiter.api.Test; - -public class UrlDataElementTest extends SmackTestSuite { - - public static final UrlDataElementProvider URL_DATA_ELEMENT_PROVIDER = new UrlDataElementProvider(); - - @Test - public void simpleSerializationTest() throws XmlPullParserException, IOException, SmackParsingException { - UrlDataElement urlDataElement = new UrlDataElement("http://www.jabber.org/members/index.php", - null, - Collections.singletonList(HttpAuthElement.basicAuth()), - null, null); - - final String expectedXml = "" + - "" + - "" + - ""; - assertXmlSimilar(expectedXml, urlDataElement.toXML().toString()); - - UrlDataElement parsed = URL_DATA_ELEMENT_PROVIDER.parse(TestUtils.getParser(expectedXml)); - assertEquals(urlDataElement, parsed); - } - - @Test - public void additionalAuthParamTest() throws XmlPullParserException, IOException, SmackParsingException { - - UrlDataElement urlDataElement = new UrlDataElement("http://www.jabber.org/members/index.php", - null, - Collections.singletonList(HttpAuthElement.basicAuth( - "www.jabber.org", - "defaultuser", - "defaultpwd" - )), - null, - null); - - final String expectedXml = "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " "; - assertXmlSimilar(expectedXml, urlDataElement.toXML().toString()); - - UrlDataElement parsed = URL_DATA_ELEMENT_PROVIDER.parse(TestUtils.getParser(expectedXml)); - assertEquals(urlDataElement, parsed); - } - - @Test - public void simpleUrlWithSidTest() throws XmlPullParserException, IOException, SmackParsingException { - UrlDataElement urlDataElement = new UrlDataElement("http://pass.jabber.org:8519/test.txt", "a0"); - - final String expectedXml = ""; - assertXmlSimilar(expectedXml, urlDataElement.toXML().toString()); - - UrlDataElement parsed = URL_DATA_ELEMENT_PROVIDER.parse(TestUtils.getParser(expectedXml)); - assertEquals(urlDataElement, parsed); - } - - @Test - public void simpleUrlNoChildrenTest() throws XmlPullParserException, IOException, SmackParsingException { - UrlDataElement urlDataElement = new UrlDataElement("http://festhall.outer-planes.net/d20M/announce/latest/", null); - - final String expectedXml = ""; - assertXmlSimilar(expectedXml, urlDataElement.toXML().toString()); - - UrlDataElement parsed = URL_DATA_ELEMENT_PROVIDER.parse(TestUtils.getParser(expectedXml)); - assertEquals(urlDataElement, parsed); - } - - @Test - public void simpleCookieTest() throws XmlPullParserException, IOException, SmackParsingException { - UrlDataElement urlDataElement = new UrlDataElement("http://www.jabber.org/members/index.php", - null, - null, - Collections.singletonList(new CookieElement("jsessionid", "1243asd234190sa32ds")), - null); - - final String expectedXml = "" + - "\n" + - " \n" + - ""; - assertXmlSimilar(expectedXml, urlDataElement.toXML().toString()); - - UrlDataElement parsed = URL_DATA_ELEMENT_PROVIDER.parse(TestUtils.getParser(expectedXml)); - assertEquals(urlDataElement, parsed); - } - - @Test - public void additionalParametersCookieTest() throws XmlPullParserException, IOException, SmackParsingException { - UrlDataElement urlDataElement = new UrlDataElement("http://www.jabber.org/members/index.php", - null, - null, - Collections.singletonList(new CookieElement( - "jsessionid", - "1243asd234190sa32ds", - "jabber.org", - 1234000, - "/members", - "Web Session Identifier", - "1.0", - false - )), - null); - - final String expectedXml = "\n" + - " \n" + - ""; - assertXmlSimilar(expectedXml, urlDataElement.toXML().toString()); - - UrlDataElement parsed = URL_DATA_ELEMENT_PROVIDER.parse(TestUtils.getParser(expectedXml)); - assertEquals(urlDataElement, parsed); - } - - @Test - public void simpleHeaderTest() throws XmlPullParserException, IOException, SmackParsingException { - UrlDataElement urlDataElement = new UrlDataElement( - "http://www.jabber.org/members/index.php", - null, - null, - null, - Collections.singletonList(new HeaderElement("Custom-Data", "some custom data"))); - - final String expectedXml = "\n" + - " \n" + - " "; - assertXmlSimilar(expectedXml, urlDataElement.toXML().toString()); - - UrlDataElement parsed = URL_DATA_ELEMENT_PROVIDER.parse(TestUtils.getParser(expectedXml)); - assertEquals(urlDataElement, parsed); - } - - @Test - public void multiChildTest() throws XmlPullParserException, IOException, SmackParsingException { - UrlDataElement urlDataElement = new UrlDataElement( - "https://blog.jabberhead.tk", - null, - Collections.singletonList(HttpAuthElement.basicAuth()), - Arrays.asList( - new CookieElement("jsessionid", "somecookievalue"), - new CookieElement("come2darkSide", "weHaveCookies")), - Arrays.asList( - new HeaderElement("Accept", "text/plain"), - new HeaderElement("Access-Control-Allow-Origin", "*"))); - - final String expectedXml = - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " "; - assertXmlSimilar(expectedXml, urlDataElement.toXML().toString()); - - UrlDataElement parsed = URL_DATA_ELEMENT_PROVIDER.parse(TestUtils.getParser(expectedXml)); - assertEquals(urlDataElement, parsed); - } -} diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/xdata/form/FillableFormTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/xdata/form/FillableFormTest.java deleted file mode 100644 index 1e495fe60..000000000 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/xdata/form/FillableFormTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * - * Copyright 2024 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.smackx.xdata.form; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.jivesoftware.smackx.xdata.FormField; -import org.jivesoftware.smackx.xdata.packet.DataForm; - -import org.junit.jupiter.api.Test; - -public class FillableFormTest { - - @Test - public void testThrowOnIncompleteyFilled() { - FormField fieldA = FormField.textSingleBuilder("a").setRequired().build(); - FormField fieldB = FormField.textSingleBuilder("b").setRequired().build(); - DataForm form = DataForm.builder(DataForm.Type.form) - .addField(fieldA) - .addField(fieldB) - .build(); - - FillableForm fillableForm = new FillableForm(form); - fillableForm.setAnswer("a", 42); - - IllegalStateException ise = assertThrows(IllegalStateException.class, () -> fillableForm.getSubmitForm()); - assertTrue(ise.getMessage().startsWith("Not all required fields filled. ")); - } -} diff --git a/smack-extensions/src/testFixtures/java/org/jivesoftware/util/Protocol.java b/smack-extensions/src/testFixtures/java/org/jivesoftware/util/Protocol.java index 9e1bdc652..f256a9728 100644 --- a/smack-extensions/src/testFixtures/java/org/jivesoftware/util/Protocol.java +++ b/smack-extensions/src/testFixtures/java/org/jivesoftware/util/Protocol.java @@ -89,7 +89,6 @@ public class Protocol { public boolean printProtocol = false; // responses to requests are taken form this queue - @SuppressWarnings("JdkObsolete") private final Queue responses = new LinkedList<>(); // list of verifications diff --git a/smack-im/build.gradle b/smack-im/build.gradle index beb30a966..f3cb2d475 100644 --- a/smack-im/build.gradle +++ b/smack-im/build.gradle @@ -1,8 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} - description = """\ Smack IM. Classes and methods for XMPP-IM (RFC 6121): @@ -13,7 +8,4 @@ Roster, Chat and other functionality.""" dependencies { api project(':smack-core') testImplementation(testFixtures(project(":smack-core"))) - - // TODO: Migrate Junit4 tests to Junit5. - testImplementation "org.junit.vintage:junit-vintage-engine:$junitVersion" } diff --git a/smack-im/src/main/java/org/jivesoftware/smack/chat/Chat.java b/smack-im/src/main/java/org/jivesoftware/smack/chat/Chat.java index a9cbe98b1..c57bc5e34 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/chat/Chat.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/chat/Chat.java @@ -79,7 +79,7 @@ public class Chat { /** * Returns the name of the user the chat is with. * - * @return the name of the user the chat is occurring with. + * @return the name of the user the chat is occuring with. */ public EntityJid getParticipant() { return participant; @@ -133,12 +133,10 @@ public class Chat { public void sendMessage(Message message) throws NotConnectedException, InterruptedException { // Force the recipient, message type, and thread ID since the user elected // to send the message through this chat object. - Message chatMessage = message.asBuilder() - .to(participant) - .ofType(Message.Type.chat) - .setThread(threadID) - .build(); - chatManager.sendMessage(this, chatMessage); + message.setTo(participant); + message.setType(Message.Type.chat); + message.setThread(threadID); + chatManager.sendMessage(this, message); } /** @@ -201,10 +199,10 @@ public class Chat { // Because the collector and listeners are expecting a thread ID with // a specific value, set the thread ID on the message even though it // probably never had one. - Message chatMessage = message.asBuilder().setThread(threadID).build(); + message.setThread(threadID); for (ChatMessageListener listener : listeners) { - listener.processMessage(this, chatMessage); + listener.processMessage(this, message); } } diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java index b51542015..8df18a77b 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/Roster.java @@ -1,6 +1,6 @@ /** * - * Copyright 2003-2007 Jive Software, 2016-2024 Florian Schmaus. + * Copyright 2003-2007 Jive Software, 2016-2022 Florian Schmaus. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -118,8 +118,8 @@ import org.jxmpp.util.cache.LruCache; * Every entry in the roster has presence associated with it. The * {@link #getPresence(BareJid)} method will return a Presence object with the * user's presence or `null` if the user is not online or you are not subscribed - * to the user's presence. _Note:_ Presence subscription is not tied to the - * user being on the roster, and vice versa: You could be subscribed to a remote + * to the user's presence. _Note:_ Presence subscription is nnot tied to the + * user being on the roster, and vice versa: You could be subscriped to a remote * users presence without the user in your roster, and a remote user can be in * your roster without any presence subscription relation. *

    @@ -218,7 +218,7 @@ public final class Roster extends Manager { *

    * This method will never return null, instead if the user has not yet logged into * the server all modifying methods of the returned roster object - * like {@link Roster#createItemAndRequestSubscription(BareJid, String, String[])}, + * like {@link Roster#createEntry(BareJid, String, String[])}, * {@link Roster#removeEntry(RosterEntry)} , etc. except adding or removing * {@link RosterListener}s will throw an IllegalStateException. *

    @@ -242,13 +242,13 @@ public final class Roster extends Manager { private static boolean rosterLoadedAtLoginDefault = true; /** - * The default subscription processing mode to use when a Roster is created. By default, + * The default subscription processing mode to use when a Roster is created. By default * all subscription requests are automatically rejected. */ private static SubscriptionMode defaultSubscriptionMode = SubscriptionMode.reject_all; /** - * The initial maximum size of the map holding presence information of entities without a Roster entry. Currently + * The initial maximum size of the map holding presence information of entities without an Roster entry. Currently * {@value #INITIAL_DEFAULT_NON_ROSTER_PRESENCE_MAP_SIZE}. */ public static final int INITIAL_DEFAULT_NON_ROSTER_PRESENCE_MAP_SIZE = 1024; @@ -285,7 +285,7 @@ public final class Roster extends Manager { private final Map> presenceMap = new ConcurrentHashMap<>(); /** - * Like {@link #presenceMap} but for presences of entities not in our Roster. + * Like {@link presenceMap} but for presences of entities not in our Roster. */ // TODO Ideally we want here to use a LRU cache like Map which will evict all superfluous items // if their maximum size is lowered below the current item count. LruCache does not provide @@ -299,7 +299,7 @@ public final class Roster extends Manager { private final Set rosterLoadedListeners = new LinkedHashSet<>(); /** - * Mutually exclude roster listener invocation and changing the {@link #entries} map. Also used + * Mutually exclude roster listener invocation and changing the {@link entries} map. Also used * to synchronize access to either the roster listeners or the entries map. */ private final Object rosterListenersAndEntriesLock = new Object(); @@ -439,7 +439,7 @@ public final class Roster extends Manager { return; } - // Ensure that all available presences received so far in an eventually existing previous session are + // Ensure that all available presences received so far in a eventually existing previous session are // marked 'offline'. setOfflinePresencesAndResetLoaded(); @@ -754,6 +754,27 @@ public final class Roster extends Manager { return group; } + /** + * Creates a new roster entry and presence subscription. The server will asynchronously + * update the roster with the subscription status. + * + * @param user the user. (e.g. johndoe@jabber.org) + * @param name the nickname of the user. + * @param groups the list of group names the entry will belong to, or null if the + * the roster entry won't belong to a group. + * @throws NoResponseException if there was no response from the server. + * @throws XMPPErrorException if an XMPP exception occurs. + * @throws NotLoggedInException If not logged in. + * @throws NotConnectedException if the XMPP connection is not connected. + * @throws InterruptedException if the calling thread was interrupted. + * @deprecated use {@link #createItemAndRequestSubscription(BareJid, String, String[])} instead. + */ + // TODO: Remove in Smack 4.5. + @Deprecated + public void createEntry(BareJid user, String name, String[] groups) throws NotLoggedInException, NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { + createItemAndRequestSubscription(user, name, groups); + } + /** * Creates a new roster item. The server will asynchronously update the roster with the subscription status. *

    @@ -797,7 +818,7 @@ public final class Roster extends Manager { * * @param jid the XMPP address of the contact (e.g. johndoe@jabber.org) * @param name the nickname of the user. - * @param groups the list of group names the entry will belong to, or null if + * @param groups the list of group names the entry will belong to, or null if the * the roster entry won't belong to a group. * @throws NoResponseException if there was no response from the server. * @throws XMPPErrorException if an XMPP exception occurs. @@ -818,7 +839,7 @@ public final class Roster extends Manager { * * @param user the user. (e.g. johndoe@jabber.org) * @param name the nickname of the user. - * @param groups the list of group names the entry will belong to, or null if + * @param groups the list of group names the entry will belong to, or null if the * the roster entry won't belong to a group. * @throws NoResponseException if there was no response from the server. * @throws XMPPErrorException if an XMPP exception occurs. @@ -1021,7 +1042,7 @@ public final class Roster extends Manager { * Returns the roster entry associated with the given XMPP address or * null if the user is not an entry in the roster. * - * @param jid the XMPP address of the user (e.g."jsmith@example.com"). The address could be + * @param jid the XMPP address of the user (eg "jsmith@example.com"). The address could be * in any valid format (e.g. "domain/resource", "user@domain" or "user@domain/resource"). * @return the roster entry or null if it does not exist. */ @@ -1035,7 +1056,7 @@ public final class Roster extends Manager { /** * Returns true if the specified XMPP address is an entry in the roster. * - * @param jid the XMPP address of the user (e.g."jsmith@example.com"). The + * @param jid the XMPP address of the user (eg "jsmith@example.com"). The * address must be a bare JID e.g. "domain/resource" or * "user@domain". * @return true if the XMPP address is an entry in the roster. @@ -1097,11 +1118,11 @@ public final class Roster extends Manager { * {@link RosterListener}. *

    * - * @param jid the XMPP address of the user (e.g."jsmith@example.com"). The + * @param jid the XMPP address of the user (eg "jsmith@example.com"). The * address must be a bare JID e.g. "domain/resource" or * "user@domain". * @return the user's current presence, or unavailable presence if the user is offline - * or if no presence information is available. + * or if no presence information is available.. */ public Presence getPresence(BareJid jid) { Map userPresences = getPresencesInternal(jid); @@ -1631,20 +1652,11 @@ public final class Roster extends Manager { } } - - final Jid from = packet.getFrom(); - if (!isLoaded() && rosterLoadedAtLogin) { - XMPPConnection connection = connection(); - - // Only log the warning, if this is not the reflected self-presence. Otherwise, - // the reflected self-presence may cause a spurious warning in case the - // connection got quickly shut down. See SMACK-941. - if (connection != null && from != null && !from.equals(connection.getUser())) { - LOGGER.warning("Roster not loaded while processing " + packet); - } + LOGGER.warning("Roster not loaded while processing " + packet); } final Presence presence = (Presence) packet; + final Jid from = presence.getFrom(); final BareJid key; if (from != null) { diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterEntry.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterEntry.java index 0360f892b..8a13fda90 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterEntry.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterEntry.java @@ -108,7 +108,7 @@ public final class RosterEntry extends Manager { packet.setType(IQ.Type.set); // Create a new roster item with the current RosterEntry and the *new* name. Note that we can't set the name of - // RosterEntry right away, as otherwise the updated event won't get fired, because equalsDeep would return true. + // RosterEntry right away, as otherwise the updated event wont get fired, because equalsDeep would return true. packet.addRosterItem(toRosterItem(this, name)); connection().sendIqRequestAndWaitForResponse(packet); @@ -136,7 +136,7 @@ public final class RosterEntry extends Manager { } /** - * Returns a copied list of the roster groups that this entry belongs to. + * Returns an copied list of the roster groups that this entry belongs to. * * @return an iterator for the groups this entry belongs to. */ @@ -306,7 +306,7 @@ public final class RosterEntry extends Manager { * * @param entry the roster entry. * @param name the name of the roster item. - * @param includeAskAttribute whether to include the 'ask' attribute. + * @param includeAskAttribute whether or not to include the 'ask' attribute. * @return the roster item. */ private static RosterPacket.Item toRosterItem(RosterEntry entry, String name, boolean includeAskAttribute) { diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterGroup.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterGroup.java index d6467dd83..f8718fcbb 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterGroup.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterGroup.java @@ -116,7 +116,7 @@ public class RosterGroup extends Manager { * Returns the roster entry associated with the given XMPP address or * null if the user is not an entry in the group. * - * @param user the XMPP address of the user (e.g."jsmith@example.com"). + * @param user the XMPP address of the user (eg "jsmith@example.com"). * @return the roster entry or null if it does not exist in the group. */ public RosterEntry getEntry(Jid user) { diff --git a/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterUtil.java b/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterUtil.java index 5f2093404..843b24bad 100644 --- a/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterUtil.java +++ b/smack-im/src/main/java/org/jivesoftware/smack/roster/RosterUtil.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016-2024 Florian Schmaus + * Copyright 2016 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,7 +34,6 @@ import org.jxmpp.jid.Jid; public class RosterUtil { - @SuppressWarnings("JavaUtilDate") public static void waitUntilOtherEntityIsSubscribed(Roster roster, BareJid otherEntity, long timeoutMillis) throws InterruptedException, TimeoutException { Date deadline = new Date(System.currentTimeMillis() + timeoutMillis); @@ -148,7 +147,6 @@ public class RosterUtil { ensureSubscribedTo(connectionTwo, connectionOne, timeout); } - @SuppressWarnings("JavaUtilDate") public static void ensureSubscribedTo(XMPPConnection connectionOne, XMPPConnection connectionTwo, long timeout) throws NotLoggedInException, NotConnectedException, InterruptedException, TimeoutException { Date deadline = new Date(System.currentTimeMillis() + timeout); diff --git a/smack-integration-test/build.gradle b/smack-integration-test/build.gradle index ede353266..ea08655af 100644 --- a/smack-integration-test/build.gradle +++ b/smack-integration-test/build.gradle @@ -1,18 +1,13 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.application-conventions' -} +apply plugin: 'application' description = """\ Smack integration tests.""" - -application { - mainClass = 'org.igniterealtime.smack.inttest.SmackIntegrationTestFramework' -} +mainClassName = 'org.igniterealtime.smack.inttest.SmackIntegrationTestFramework' +applicationDefaultJvmArgs = ["-enableassertions"] dependencies { - api project(':smack-java11-full') + api project(':smack-java8-full') api project(':smack-resolver-dnsjava') implementation project(':smack-websocket-java11') implementation "com.google.guava:guava:${guavaVersion}" @@ -25,3 +20,8 @@ dependencies { testFixturesApi(testFixtures(project(":smack-core"))) testImplementation "org.jxmpp:jxmpp-jid:$jxmppVersion:tests" } + +run { + // Pass all system properties down to the "application" run + systemProperties System.getProperties() +} diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/XmppConnectionStressTest.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/XmppConnectionStressTest.java index a0f658977..f9d988308 100644 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/XmppConnectionStressTest.java +++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/XmppConnectionStressTest.java @@ -100,8 +100,8 @@ public class XmppConnectionStressTest { for (int c = 0; c < payloadChunkCount; c++) { int payloadChunkSize = random.nextInt(configuration.maxPayloadChunkSize) + 1; - String payloadChunk = StringUtils.randomString(payloadChunkSize, random); - JivePropertiesManager.addProperty(messageBuilder, "payload-chunk-" + c, payloadChunk); + String payloadCunk = StringUtils.randomString(payloadChunkSize, random); + JivePropertiesManager.addProperty(messageBuilder, "payload-chunk-" + c, payloadCunk); } JivePropertiesManager.addProperty(messageBuilder, MESSAGE_NUMBER_PROPERTY, i); @@ -184,7 +184,7 @@ public class XmppConnectionStressTest { Exception exception = new Exception(exceptionMessage.toString()); receiveExceptions.put(connection, exception); // TODO: Current Smack design does not guarantee that the listener won't be invoked again. - // This is because the decision to invoke a sync listeners is done at a different place + // This is because the decission to invoke a sync listeners is done at a different place // then invoking the listener. connection.removeSyncStanzaListener(this); receivedSemaphore.release(); @@ -300,7 +300,6 @@ public class XmppConnectionStressTest { Integer markerFromConnectionId = connectionIds.get(markerFromAddress); sb.append(markerToConnectionId) .append(" is missing ").append(numberOfFalseMarkers) - .append(" ( of ").append(marker.length).append(" messages)") .append(" messages from ").append(markerFromConnectionId) .append(": "); for (int i = 0; i < marker.length; i++) { @@ -338,7 +337,7 @@ public class XmppConnectionStressTest { sb.append("Exceptions while sending and/or receiving."); if (!sendExceptions.isEmpty()) { - sb.append(" Send exceptions: "); + sb.append(" Send exxceptions: "); for (Map.Entry entry : sendExceptions.entrySet()) { sb.append(entry.getKey()).append(": ").append(entry.getValue()).append(';'); } diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackIntTest.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackIntTest.java index 9f94fe26b..2b94b2190 100644 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackIntTest.java +++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackIntTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015-2024 Florian Schmaus + * Copyright 2015-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,6 @@ import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; -import java.util.List; import java.util.Random; import java.util.concurrent.TimeoutException; import java.util.logging.Logger; @@ -34,11 +33,6 @@ import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.filter.StanzaFilter; -import org.igniterealtime.smack.inttest.util.MultiResultSyncPoint; -import org.igniterealtime.smack.inttest.util.ResultSyncPoint; - -import org.opentest4j.AssertionFailedError; - public abstract class AbstractSmackIntTest { protected static final Logger LOGGER = Logger.getLogger(AbstractSmackIntTest.class.getName()); @@ -96,32 +90,4 @@ public abstract class AbstractSmackIntTest { } return urlConnection; } - - public R assertResult(ResultSyncPoint syncPoint, String message) throws InterruptedException, TimeoutException, AssertionFailedError { - return assertResult(syncPoint, timeout, message); - } - - public static R assertResult(ResultSyncPoint syncPoint, long timeout, String message) throws InterruptedException, TimeoutException, AssertionFailedError { - try { - return syncPoint.waitForResult(timeout, message); - } catch (InterruptedException | TimeoutException e) { - throw e; - } catch (Exception e) { - throw new AssertionFailedError(message, e); - } - } - - public List assertResult(MultiResultSyncPoint syncPoint, String message) throws InterruptedException, TimeoutException, AssertionFailedError { - return assertResult(syncPoint, timeout, message); - } - - public static List assertResult(MultiResultSyncPoint syncPoint, long timeout, String message) throws InterruptedException, TimeoutException, AssertionFailedError { - try { - return syncPoint.waitForResults(timeout, message); - } catch (InterruptedException | TimeoutException e) { - throw e; - } catch (Exception e) { - throw new AssertionFailedError(message, e); - } - } } diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackLowLevelIntegrationTest.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackLowLevelIntegrationTest.java index 480129575..d517494db 100644 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackLowLevelIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/AbstractSmackLowLevelIntegrationTest.java @@ -50,7 +50,7 @@ public abstract class AbstractSmackLowLevelIntegrationTest extends AbstractSmack * Get a connected connection. Note that this method will return a connection constructed via the default connection * descriptor. It is primarily meant for integration tests to discover if the XMPP service supports a certain * feature, that the integration test requires to run. This feature discovery is typically done in the constructor of the - * integration tests. And if the discovery fails a {@link TestNotPossibleException} should be thrown by the constructor. + * integration tests. And if the discovery fails a {@link TestNotPossibleException} should be thrown by he constructor. * *

    Please ensure that you invoke {@link #recycle(AbstractXMPPConnection connection)} once you are done with this connection. * diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/Configuration.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/Configuration.java index fab1e00c9..700c12eff 100644 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/Configuration.java +++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/Configuration.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015-2024 Florian Schmaus + * Copyright 2015-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,24 +22,20 @@ import java.io.IOException; import java.lang.reflect.Method; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.logging.Logger; -import java.util.stream.Collectors; import javax.net.ssl.SSLContext; import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode; import org.jivesoftware.smack.debugger.ConsoleDebugger; -import org.jivesoftware.smack.debugger.SmackDebuggerFactory; import org.jivesoftware.smack.util.CollectionUtil; import org.jivesoftware.smack.util.Function; import org.jivesoftware.smack.util.Objects; @@ -65,6 +61,12 @@ public final class Configuration { serviceAdministration, } + public enum Debugger { + none, + console, + enhanced, + } + public enum DnsResolver { minidns, javax, @@ -73,8 +75,6 @@ public final class Configuration { public final DomainBareJid service; - public final String host; - public final String serviceTlsPin; public final SslContextFactory sslContextFactory; @@ -101,7 +101,7 @@ public final class Configuration { public final String accountThreePassword; - public final SmackDebuggerFactory debuggerFactory; + public final Debugger debugger; public final Set enabledTests; @@ -111,10 +111,6 @@ public final class Configuration { private final Map> disabledTestsMap; - public final Set enabledSpecifications; - - public final Set disabledSpecifications; - public final String defaultConnectionNickname; public final Set enabledConnections; @@ -136,12 +132,9 @@ public final class Configuration { public final CompatibilityMode compatibilityMode; - public final List testRunResultProcessors; - private Configuration(Configuration.Builder builder) throws KeyManagementException, NoSuchAlgorithmException { service = Objects.requireNonNull(builder.service, "'service' must be set. Either via 'properties' files or via system property 'sinttest.service'."); - host = builder.host; serviceTlsPin = builder.serviceTlsPin; if (serviceTlsPin != null) { SSLContext sslContext = Java7Pinning.forPin(serviceTlsPin); @@ -153,9 +146,9 @@ public final class Configuration { if (builder.replyTimeout > 0) { replyTimeout = builder.replyTimeout; } else { - replyTimeout = 47000; + replyTimeout = 60000; } - debuggerFactory = builder.debuggerFactory; + debugger = builder.debugger; if (StringUtils.isNotEmpty(builder.adminAccountUsername, builder.adminAccountPassword)) { accountRegistration = AccountRegistration.serviceAdministration; } @@ -188,8 +181,6 @@ public final class Configuration { this.enabledTestsMap = convertTestsToMap(enabledTests); this.disabledTests = CollectionUtil.nullSafeUnmodifiableSet(builder.disabledTests); this.disabledTestsMap = convertTestsToMap(disabledTests); - this.enabledSpecifications = CollectionUtil.nullSafeUnmodifiableSet(builder.enabledSpecifications); - this.disabledSpecifications = CollectionUtil.nullSafeUnmodifiableSet(builder.disabledSpecifications); this.defaultConnectionNickname = builder.defaultConnectionNickname; this.enabledConnections = builder.enabledConnections; this.disabledConnections = builder.disabledConnections; @@ -201,12 +192,17 @@ public final class Configuration { } b.setSecurityMode(securityMode); b.setXmppDomain(service); - if (host != null) { - b.setHost(host); - } - if (debuggerFactory != null) { - b.setDebuggerFactory(debuggerFactory); + switch (debugger) { + case enhanced: + b.setDebuggerFactory(EnhancedDebugger.Factory.INSTANCE); + break; + case console: + b.setDebuggerFactory(ConsoleDebugger.Factory.INSTANCE); + break; + case none: + // Nothing to do :). + break; } }; @@ -214,7 +210,6 @@ public final class Configuration { this.dnsResolver = builder.dnsResolver; this.compatibilityMode = builder.compatibilityMode; - this.testRunResultProcessors = builder.testRunResultProcessors; } public boolean isAccountRegistrationPossible() { @@ -229,8 +224,6 @@ public final class Configuration { private DomainBareJid service; - private String host; - private String serviceTlsPin; private SecurityMode securityMode; @@ -253,16 +246,12 @@ public final class Configuration { public String accountThreePassword; - private SmackDebuggerFactory debuggerFactory; + private Debugger debugger = Debugger.none; private Set enabledTests; private Set disabledTests; - private Set enabledSpecifications; - - private Set disabledSpecifications; - private String defaultConnectionNickname; private Set enabledConnections; @@ -277,8 +266,6 @@ public final class Configuration { private CompatibilityMode compatibilityMode = CompatibilityMode.standardsCompliant; - private List testRunResultProcessors; - private Builder() { } @@ -296,11 +283,6 @@ public final class Configuration { return this; } - private Builder setHost(String host) { - this.host = host; - return this; - } - public Builder addEnabledTest(Class enabledTest) { if (enabledTests == null) { enabledTests = new HashSet<>(); @@ -333,7 +315,7 @@ public final class Configuration { this.accountOneUsername = StringUtils.requireNotNullNorEmpty(accountOneUsername, "accountOneUsername must not be null nor empty"); this.accountOnePassword = StringUtils.requireNotNullNorEmpty(accountOnePassword, "accountOnePassword must not be null nor empty"); this.accountTwoUsername = StringUtils.requireNotNullNorEmpty(accountTwoUsername, "accountTwoUsername must not be null nor empty"); - this.accountTwoPassword = StringUtils.requireNotNullNorEmpty(accountTwoPassword, "accountTwoPassword must not be null nor empty"); + this.accountTwoPassword = StringUtils.requireNotNullNorEmpty(accountTwoPassword, "accountTwoPasswordmust not be null nor empty"); this.accountThreeUsername = StringUtils.requireNotNullNorEmpty(accountThreeUsername, "accountThreeUsername must not be null nor empty"); this.accountThreePassword = StringUtils.requireNotNullNorEmpty(accountThreePassword, "accountThreePassword must not be null nor empty"); return this; @@ -370,23 +352,18 @@ public final class Configuration { case "false": // For backwards compatibility settings with previous boolean setting. LOGGER.warning("Debug string \"" + debuggerString + "\" is deprecated, please use \"none\" instead"); case "none": - debuggerFactory = null; + debugger = Debugger.none; break; case "true": // For backwards compatibility settings with previous boolean setting. LOGGER.warning("Debug string \"" + debuggerString + "\" is deprecated, please use \"console\" instead"); case "console": - debuggerFactory = ConsoleDebugger.Factory.INSTANCE; + debugger = Debugger.console; break; case "enhanced": - debuggerFactory = EnhancedDebugger.Factory.INSTANCE; + debugger = Debugger.enhanced; break; default: - try { - final Class aClass = Class.forName(debuggerString).asSubclass(SmackDebuggerFactory.class); - debuggerFactory = aClass.getConstructor().newInstance(); - } catch (Exception e) { - throw new IllegalArgumentException("Unable to construct debugger from value: " + debuggerString, e); - } + throw new IllegalArgumentException("Unrecognized debugger string: " + debuggerString); } return this; } @@ -401,16 +378,6 @@ public final class Configuration { return this; } - public Builder setEnabledSpecifications(String enabledSpecificationsString) { - enabledSpecifications = getSpecificationSetFrom(enabledSpecificationsString); - return this; - } - - public Builder setDisabledSpecifications(String disabledSpecificationsString) { - disabledSpecifications = getSpecificationSetFrom(disabledSpecificationsString); - return this; - } - public Builder setDefaultConnection(String defaultConnectionNickname) { this.defaultConnectionNickname = defaultConnectionNickname; return this; @@ -494,15 +461,6 @@ public final class Configuration { return setCompatibilityMode(compatibilityMode); } - public Builder setTestRunResultProcessors(String testRunResultProcessorsString) { - if (testRunResultProcessorsString == null) { - return this; - } - - testRunResultProcessors = getTestRunProcessorListFrom(testRunResultProcessorsString); - return this; - } - public Configuration build() throws KeyManagementException, NoSuchAlgorithmException { return new Configuration(this); } @@ -530,15 +488,14 @@ public final class Configuration { } key = key.substring(SINTTEST.length()); String value = (String) entry.getValue(); - properties.put(key.trim(), value.trim()); + properties.put(key, value); } Builder builder = builder(); builder.setService(properties.getProperty("service")); - builder.setHost(properties.getProperty("host")); builder.setServiceTlsPin(properties.getProperty("serviceTlsPin")); builder.setSecurityMode(properties.getProperty("securityMode")); - builder.setReplyTimeout(properties.getProperty("replyTimeout", "47000")); + builder.setReplyTimeout(properties.getProperty("replyTimeout", "60000")); String adminAccountUsername = properties.getProperty("adminAccountUsername"); String adminAccountPassword = properties.getProperty("adminAccountPassword"); @@ -560,14 +517,12 @@ public final class Configuration { String debugString = properties.getProperty("debug"); if (debugString != null) { - LOGGER.warning("Usage of deprecated 'debug' option detected, please use 'debugger' instead"); + LOGGER.warning("Usage of depreacted 'debug' option detected, please use 'debugger' instead"); builder.setDebugger(debugString); } builder.setDebugger(properties.getProperty("debugger")); builder.setEnabledTests(properties.getProperty("enabledTests")); builder.setDisabledTests(properties.getProperty("disabledTests")); - builder.setEnabledSpecifications(properties.getProperty("enabledSpecifications")); - builder.setDisabledSpecifications(properties.getProperty("disabledSpecifications")); builder.setDefaultConnection(properties.getProperty("defaultConnection")); builder.setEnabledConnections(properties.getProperty("enabledConnections")); builder.setDisabledConnections(properties.getProperty("disabledConnections")); @@ -581,14 +536,11 @@ public final class Configuration { builder.setCompatibilityMode(properties.getProperty("compatibilityMode")); - builder.setTestRunResultProcessors(properties.getProperty("testRunResultProcessors", - SmackIntegrationTestFramework.JulTestRunResultProcessor.class.getName())); - return builder.build(); } private static File findPropertiesFile() { - List possibleLocations = new ArrayList<>(); + List possibleLocations = new LinkedList<>(); possibleLocations.add("properties"); String userHome = System.getProperty("user.home"); if (userHome != null) { @@ -635,23 +587,6 @@ public final class Configuration { }); } - private static Set getSpecificationSetFrom(String input) { - return split(input, Configuration::normalizeSpecification); - } - - private static List getTestRunProcessorListFrom(String input) { - return Arrays.stream(input.split(",")) - .map(element -> { - try { - final Class aClass = Class.forName(element).asSubclass(SmackIntegrationTestFramework.TestRunResultProcessor.class); - return aClass.getConstructor().newInstance(); - } catch (Exception e) { - throw new IllegalArgumentException("Unable to construct TestRunResultProcessor from value: " + element, e); - } - }) - .collect(Collectors.toList()); - } - private static Map> convertTestsToMap(Set tests) { Map> res = new HashMap<>(); for (String test : tests) { @@ -760,34 +695,4 @@ public final class Configuration { return contains(method, disabledTestsMap); } - public boolean isSpecificationEnabled(String specification) { - if (enabledSpecifications.isEmpty()) { - return true; - } - - if (specification == null) { - return false; - } - - return enabledSpecifications.contains(normalizeSpecification(specification)); - } - - public boolean isSpecificationDisabled(String specification) { - if (disabledSpecifications.isEmpty()) { - return false; - } - - if (specification == null) { - return false; - } - - return disabledSpecifications.contains(normalizeSpecification(specification)); - } - - public static String normalizeSpecification(String specification) { - if (specification == null || specification.isBlank()) { - return null; - } - return specification.replaceAll("[\\s-]", "").toUpperCase(Locale.ROOT); - } } diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/SmackIntegrationTestFramework.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/SmackIntegrationTestFramework.java index 3fb4edaae..21d5994b1 100644 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/SmackIntegrationTestFramework.java +++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/SmackIntegrationTestFramework.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015-2024 Florian Schmaus + * Copyright 2015-2023 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,12 +39,11 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; @@ -65,7 +64,6 @@ import org.jivesoftware.smack.util.dns.dnsjava.DNSJavaResolver; import org.jivesoftware.smack.util.dns.javax.JavaxResolver; import org.jivesoftware.smack.util.dns.minidns.MiniDnsResolver; -import org.jivesoftware.smackx.debugger.EnhancedDebugger; import org.jivesoftware.smackx.debugger.EnhancedDebuggerWindow; import org.jivesoftware.smackx.iqregister.AccountManager; @@ -73,7 +71,6 @@ import org.igniterealtime.smack.inttest.Configuration.AccountRegistration; import org.igniterealtime.smack.inttest.annotations.AfterClass; import org.igniterealtime.smack.inttest.annotations.BeforeClass; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.reflections.Reflections; import org.reflections.scanners.MethodAnnotationsScanner; import org.reflections.scanners.MethodParameterScanner; @@ -90,8 +87,6 @@ public class SmackIntegrationTestFramework { public static boolean SINTTEST_UNIT_TEST = false; - private static ConcreteTest TEST_UNDER_EXECUTION; - protected final Configuration config; protected TestRunResult testRunResult; @@ -113,86 +108,47 @@ public class SmackIntegrationTestFramework { SmackIntegrationTestFramework sinttest = new SmackIntegrationTestFramework(config); TestRunResult testRunResult = sinttest.run(); - for (final TestRunResultProcessor testRunResultProcessor : config.testRunResultProcessors) { - try { - testRunResultProcessor.process(testRunResult); - } catch (Throwable t) { - LOGGER.log(Level.WARNING, "Invocation of TestRunResultProcessor " + testRunResultProcessor + " failed.", t); + for (Map.Entry, Throwable> entry : testRunResult.impossibleTestClasses.entrySet()) { + LOGGER.info("Could not run " + entry.getKey().getName() + " because: " + + entry.getValue().getLocalizedMessage()); + } + for (TestNotPossible testNotPossible : testRunResult.impossibleIntegrationTests) { + LOGGER.info("Could not run " + testNotPossible.concreteTest + " because: " + + testNotPossible.testNotPossibleException.getMessage()); + } + for (SuccessfulTest successfulTest : testRunResult.successfulIntegrationTests) { + LOGGER.info(successfulTest.concreteTest + " ✔"); + } + final int successfulTests = testRunResult.successfulIntegrationTests.size(); + final int failedTests = testRunResult.failedIntegrationTests.size(); + final int availableTests = testRunResult.getNumberOfAvailableTests(); + LOGGER.info("SmackIntegrationTestFramework[" + testRunResult.testRunId + ']' + " finished: " + + successfulTests + '/' + availableTests + " [" + failedTests + " failed]"); + + final int exitStatus; + if (failedTests > 0) { + LOGGER.warning("💀 The following " + failedTests + " tests failed! 💀"); + for (FailedTest failedTest : testRunResult.failedIntegrationTests) { + final Throwable cause = failedTest.failureReason; + LOGGER.log(Level.SEVERE, failedTest.concreteTest + " failed: " + cause, cause); } + exitStatus = 2; + } else { + LOGGER.info("All possible Smack Integration Tests completed successfully. \\o/"); + exitStatus = 0; } - if (config.debuggerFactory instanceof EnhancedDebugger) { + switch (config.debugger) { + case enhanced: EnhancedDebuggerWindow.getInstance().waitUntilClosed(); + break; + default: + break; } - final int exitStatus = testRunResult.failedIntegrationTests.isEmpty() ? 0 : 2; System.exit(exitStatus); } - public static class JulTestRunResultProcessor implements TestRunResultProcessor { - - @Override - public void process(final TestRunResult testRunResult) { - for (Map.Entry, Throwable> entry : testRunResult.impossibleTestClasses.entrySet()) { - LOGGER.info("Could not run " + entry.getKey().getName() + " because: " - + entry.getValue().getLocalizedMessage()); - } - for (TestNotPossible testNotPossible : testRunResult.impossibleIntegrationTests) { - LOGGER.info("Could not run " + testNotPossible.concreteTest + " because: " - + testNotPossible.testNotPossibleException.getMessage()); - } - for (SuccessfulTest successfulTest : testRunResult.successfulIntegrationTests) { - LOGGER.info(successfulTest.concreteTest + " ✔"); - } - final int successfulTests = testRunResult.successfulIntegrationTests.size(); - final int failedTests = testRunResult.failedIntegrationTests.size(); - final int availableTests = testRunResult.getNumberOfAvailableTests(); - LOGGER.info("SmackIntegrationTestFramework[" + testRunResult.testRunId + ']' + " finished: " - + successfulTests + '/' + availableTests + " [" + failedTests + " failed]"); - - if (failedTests > 0) { - LOGGER.warning("💀 The following " + failedTests + " tests failed! 💀"); - final SortedSet bySpecification = new TreeSet<>(); - for (FailedTest failedTest : testRunResult.failedIntegrationTests) { - final Throwable cause = failedTest.failureReason; - LOGGER.log(Level.SEVERE, failedTest.concreteTest + " failed: " + cause, cause); - if (failedTest.concreteTest.method.getDeclaringClass().isAnnotationPresent(SpecificationReference.class)) { - final String specificationReference = getSpecificationReference(failedTest.concreteTest.method); - if (specificationReference != null) { - bySpecification.add("- " + specificationReference + " (as tested by '" + failedTest.concreteTest + "')"); - } - } - } - if (!bySpecification.isEmpty()) { - LOGGER.log(Level.SEVERE, "The failed tests correspond to the following specifications:" + System.lineSeparator() + String.join(System.lineSeparator(), bySpecification)); - } - } else { - LOGGER.info("All possible Smack Integration Tests completed successfully. \\o/"); - } - } - } - - private static String getSpecificationReference(Method method) { - final SpecificationReference spec = method.getDeclaringClass().getAnnotation(SpecificationReference.class); - if (spec == null || spec.document().isBlank()) { - return null; - } - String line = spec.document().trim(); - if (!spec.version().isBlank()) { - line += " (version " + spec.version() + ")"; - } - - final SmackIntegrationTest test = method.getAnnotation(SmackIntegrationTest.class); - if (!test.section().isBlank()) { - line += " section " + test.section().trim(); - } - if (!test.quote().isBlank()) { - line += ":\t\"" + test.quote().trim() + "\""; - } - assert !line.isBlank(); - return line; - } - public SmackIntegrationTestFramework(Configuration configuration) { this.config = configuration; } @@ -219,7 +175,7 @@ public class SmackIntegrationTestFramework { this.connectionManager = new XmppConnectionManager(this); LOGGER.info("SmackIntegrationTestFramework [" + testRunResult.testRunId + ']' + ": Starting\nSmack version: " + Smack.getVersion()); - if (config.debuggerFactory != null) { + if (config.debugger != Configuration.Debugger.none) { // JUL Debugger will not print any information until configured to print log messages of // level FINE // TODO configure JUL for log? @@ -236,7 +192,7 @@ public class SmackIntegrationTestFramework { String[] testPackages; if (config.testPackages == null || config.testPackages.isEmpty()) { - testPackages = new String[] { "org.jivesoftware.smackx", "org.jivesoftware.smack", "org.igniterealtime.smackx", "org.igniterealtime.smack" }; + testPackages = new String[] { "org.jivesoftware.smackx", "org.jivesoftware.smack" }; } else { testPackages = config.testPackages.toArray(new String[config.testPackages.size()]); @@ -268,8 +224,7 @@ public class SmackIntegrationTestFramework { } LOGGER.info("SmackIntegrationTestFramework [" + testRunResult.testRunId - + "]: Finished scanning for tests, preparing environment\n" - + "\tJava SE Platform version: " + Runtime.version()); + + "]: Finished scanning for tests, preparing environment"); environment = prepareEnvironment(); try { @@ -288,10 +243,6 @@ public class SmackIntegrationTestFramework { return testRunResult; } - public static ConcreteTest getTestUnderExecution() { - return TEST_UNDER_EXECUTION; - } - @SuppressWarnings({"Finally"}) private void runTests(Set> classes) throws InterruptedException, InstantiationException, IllegalAccessException, @@ -340,27 +291,7 @@ public class SmackIntegrationTestFramework { } if (config.isClassDisabled(testClass)) { - DisabledTestClass disabledTestClass = new DisabledTestClass(testClass, "Skipping test class " + testClassName + " because it is disabled"); - testRunResult.disabledTestClasses.add(disabledTestClass); - continue; - } - - final String specification; - if (testClass.isAnnotationPresent(SpecificationReference.class)) { - final SpecificationReference specificationReferenceAnnotation = testClass.getAnnotation(SpecificationReference.class); - specification = Configuration.normalizeSpecification(specificationReferenceAnnotation.document()); - } else { - specification = null; - } - - if (!config.isSpecificationEnabled(specification)) { - DisabledTestClass disabledTestClass = new DisabledTestClass(testClass, "Skipping test method " + testClass + " because it tests a specification ('" + specification + "') that is not enabled"); - testRunResult.disabledTestClasses.add(disabledTestClass); - continue; - } - - if (config.isSpecificationDisabled(specification)) { - DisabledTestClass disabledTestClass = new DisabledTestClass(testClass, "Skipping test method " + testClass + " because it tests a specification ('" + specification + "') that is disabled"); + DisabledTestClass disabledTestClass = new DisabledTestClass(testClass, "Skipping test class " + testClassName + " because it is disalbed"); testRunResult.disabledTestClasses.add(disabledTestClass); continue; } @@ -431,7 +362,7 @@ public class SmackIntegrationTestFramework { final Class[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length > 0) { throw new IllegalStateException( - "SmackIntegrationTest annotation on " + method + " that takes arguments "); + "SmackIntegrationTest annotaton on " + method + " that takes arguments "); } break; case LowLevel: @@ -526,11 +457,6 @@ public class SmackIntegrationTestFramework { } sb.append('\n'); } - - if (numberOfAvailableTests == 0) { - throw new IllegalArgumentException("No integration tests selected."); - } - sb.append("Available tests: ").append(numberOfAvailableTests); if (!testRunResult.disabledTestClasses.isEmpty() || !testRunResult.disabledTests.isEmpty()) { sb.append(" (Disabled ").append(testRunResult.disabledTestClasses.size()).append(" classes") @@ -567,7 +493,7 @@ public class SmackIntegrationTestFramework { return; } Throwable nonFatalFailureReason; - // junit asserts throw an AssertionError if they fail, those should not be + // junit assert's throw an AssertionError if they fail, those should not be // thrown up, as it would be done by throwFatalException() if (cause instanceof AssertionError) { nonFatalFailureReason = cause; @@ -667,8 +593,8 @@ public class SmackIntegrationTestFramework { throw (InterruptedException) e; } - // We handle NullPointerException as a non-fatal exception, as they are mostly caused by an invalid reply where - // an extension element is missing. Consider for example + // We handle NullPointerException as a non fatal exception, as they are mostly caused by an invalid reply where + // a extension element is missing. Consider for example // assertEquals(StanzaError.Condition.foo, response.getError().getCondition()) // Otherwise NPEs could be caused by an internal bug in Smack, e.g. missing null handling. if (e instanceof NullPointerException) { @@ -683,23 +609,18 @@ public class SmackIntegrationTestFramework { return (Exception) e; } - @FunctionalInterface - public interface TestRunResultProcessor { - void process(SmackIntegrationTestFramework.TestRunResult testRunResult); - } - public static final class TestRunResult { /** - * A short String of lowercase characters and numbers used to identify an integration test + * A short String of lowercase characters and numbers used to identify a integration test * run. We use lowercase characters because this string will eventually be part of the - * localpart of the used JIDs (and the localpart is case-insensitive). + * localpart of the used JIDs (and the localpart is case insensitive). */ public final String testRunId = StringUtils.insecureRandomString(5).toLowerCase(Locale.US); - private final List successfulIntegrationTests = Collections.synchronizedList(new ArrayList()); - private final List failedIntegrationTests = Collections.synchronizedList(new ArrayList()); - private final List impossibleIntegrationTests = Collections.synchronizedList(new ArrayList()); + private final List successfulIntegrationTests = Collections.synchronizedList(new LinkedList()); + private final List failedIntegrationTests = Collections.synchronizedList(new LinkedList()); + private final List impossibleIntegrationTests = Collections.synchronizedList(new LinkedList()); // TODO: Ideally three would only be a list of disabledTests, but since we do not process a disabled test class // any further, we can not determine the concrete disabled tests. @@ -758,12 +679,7 @@ public class SmackIntegrationTestFramework { executeSinttestSpecialMethod(beforeClassMethod); for (ConcreteTest concreteTest : concreteTests) { - TEST_UNDER_EXECUTION = concreteTest; - try { - runConcreteTest(concreteTest); - } finally { - TEST_UNDER_EXECUTION = null; - } + runConcreteTest(concreteTest); } } finally { @@ -812,33 +728,21 @@ public class SmackIntegrationTestFramework { return null; } - public static final class ConcreteTest { + static final class ConcreteTest { private final TestType testType; private final Method method; private final Executor executor; - private final List subdescriptons; + private final String[] subdescriptons; private ConcreteTest(TestType testType, Method method, Executor executor, String... subdescriptions) { this.testType = testType; this.method = method; this.executor = executor; - this.subdescriptons = List.of(subdescriptions); + this.subdescriptons = subdescriptions; } private transient String stringCache; - public TestType getTestType() { - return testType; - } - - public Method getMethod() { - return method; - } - - public List getSubdescriptons() { - return subdescriptons; - } - @Override public String toString() { if (stringCache != null) { @@ -851,9 +755,9 @@ public class SmackIntegrationTestFramework { .append(method.getName()) .append(" (") .append(testType.name()); - if (!subdescriptons.isEmpty()) { + if (subdescriptons != null && subdescriptons.length > 0) { sb.append(", "); - StringUtils.appendTo(subdescriptons, sb); + StringUtils.appendTo(Arrays.asList(subdescriptons), sb); } sb.append(')'); diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/TestNotPossibleException.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/TestNotPossibleException.java index cf7030efd..843726ca8 100644 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/TestNotPossibleException.java +++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/TestNotPossibleException.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015-2024 Florian Schmaus + * Copyright 2015 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,12 +26,4 @@ public class TestNotPossibleException extends Exception { public TestNotPossibleException(String reason) { super(reason); } - - public TestNotPossibleException(Throwable reason) { - super(reason); - } - - public TestNotPossibleException(String message, Throwable reason) { - super(message, reason); - } } diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/XmppConnectionDescriptor.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/XmppConnectionDescriptor.java index adcdcaa40..173407429 100644 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/XmppConnectionDescriptor.java +++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/XmppConnectionDescriptor.java @@ -155,7 +155,7 @@ public final class XmppConnectionDescriptor< return XmppConnectionDescriptor.buildWith(ModularXmppClientToServerConnection.class, ModularXmppClientToServerConnectionConfiguration.class, ModularXmppClientToServerConnectionConfiguration.Builder.class) .withNickname(nickname) - .applyExtraConfiguration(cb -> { + .applyExtraConfguration(cb -> { cb.removeAllModules(); ModularXmppClientToServerConnectionModuleDescriptor webSocketModuleDescriptor = XmppWebSocketTransportModuleDescriptor.getBuilder(cb) @@ -184,13 +184,7 @@ public final class XmppConnectionDescriptor< nickname = connectionClass.getSimpleName(); } - // TODO Remove in Smack 4.6 - @Deprecated // Replaced by applyExtraConfiguration(Consumer extraBuilder) public Builder applyExtraConfguration(Consumer extraBuilder) { - return applyExtraConfiguration(extraBuilder); - } - - public Builder applyExtraConfiguration(Consumer extraBuilder) { this.extraBuilder = extraBuilder; return this; } diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/XmppConnectionManager.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/XmppConnectionManager.java index 3b2f21b60..e74bced82 100644 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/XmppConnectionManager.java +++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/XmppConnectionManager.java @@ -85,7 +85,7 @@ public class XmppConnectionManager { addConnectionDescriptor( XmppConnectionDescriptor.buildWith(ModularXmppClientToServerConnection.class, ModularXmppClientToServerConnectionConfiguration.class, ModularXmppClientToServerConnectionConfiguration.Builder.class) .withNickname("modular-nocompress") - .applyExtraConfiguration(cb -> cb.removeModule(CompressionModuleDescriptor.class)) + .applyExtraConfguration(cb -> cb.removeModule(CompressionModuleDescriptor.class)) .build() ); addConnectionDescriptor( @@ -187,13 +187,14 @@ public class XmppConnectionManager { case inBandRegistration: accountRegistrationConnection = defaultConnectionDescriptor.construct(sinttestConfiguration); accountRegistrationConnection.connect(); + accountRegistrationConnection.login(sinttestConfiguration.adminAccountUsername, + sinttestConfiguration.adminAccountPassword); if (sinttestConfiguration.accountRegistration == AccountRegistration.inBandRegistration) { + adminManager = null; accountManager = AccountManager.getInstance(accountRegistrationConnection); } else { - accountRegistrationConnection.login(sinttestConfiguration.adminAccountUsername, - sinttestConfiguration.adminAccountPassword); adminManager = ServiceAdministrationManager.getInstanceFor(accountRegistrationConnection); accountManager = null; } @@ -286,7 +287,7 @@ public class XmppConnectionManager { if (unsuccessfullyDeletedAccountsCount == 0) { LOGGER.info("Successfully deleted all created accounts ✔"); } else { - LOGGER.warning("Could not delete all created accounts, " + unsuccessfullyDeletedAccountsCount + " remaining"); + LOGGER.warning("Could not delete all created accounts, " + unsuccessfullyDeletedAccountsCount + " remainaing"); } } @@ -365,11 +366,11 @@ public class XmppConnectionManager { break; case inBandRegistration: if (!accountManager.supportsAccountCreation()) { - throw new UnsupportedOperationException("Account creation/registration is not supported"); + throw new UnsupportedOperationException("Account creation/registation is not supported"); } Set requiredAttributes = accountManager.getAccountAttributes(); if (requiredAttributes.size() > 4) { - throw new IllegalStateException("Unknown required attributes"); + throw new IllegalStateException("Unkown required attributes"); } Map additionalAttributes = new HashMap<>(); additionalAttributes.put("name", "Smack Integration Test"); diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/annotations/SmackIntegrationTest.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/annotations/SmackIntegrationTest.java index 55b1ef684..173b4d2e9 100644 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/annotations/SmackIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/annotations/SmackIntegrationTest.java @@ -31,18 +31,4 @@ public @interface SmackIntegrationTest { int connectionCount() default -1; - /** - * Unique identifier for a section (or paragraph) of the document referenced by {@link SpecificationReference}, - * such as '6.2.1'. - * - * @return a document section identifier - */ - String section() default ""; - - /** - * A quotation of relevant text from the section referenced by {@link #section()}. - * - * @return human-readable text from the references document and section. - */ - String quote() default ""; } diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/annotations/SpecificationReference.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/annotations/SpecificationReference.java deleted file mode 100644 index beadb7782..000000000 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/annotations/SpecificationReference.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * - * Copyright 2024 Guus der Kinderen - * - * 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.igniterealtime.smack.inttest.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Reference to a specification document. - * - * @author Guus der Kinderen, guus@goodbytes.nl - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface SpecificationReference { - - /** - * Unique identifier for a specification document, such as 'RFC 6120' or 'XEP-0485'. - * - * @return a document identifier - */ - String document(); - - /** - * An optional version number, such as '1.2.0'. - * - * @return a version number - */ - String version() default ""; -} diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/package-info.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/package-info.java index 84301a2f5..2caf8d792 100644 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/package-info.java +++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/package-info.java @@ -80,10 +80,6 @@ * XMPP service to run the tests on * * - * host - * IP address or DNS name of the XMPP service to run the tests on - * - * * serviceTlsPin * TLS Pin (used by java-pinning) * @@ -129,7 +125,7 @@ * * * debugger - * ‘console’ for console debugger, ‘enhanced’ for the enhanced debugger, or the name of a class that implements SmackDebuggerFactory for a custom debugger + * ‘console’ for console debugger, ‘enhanced’ for the enhanced debugger * * * enabledTests @@ -140,14 +136,6 @@ * List of disabled tests * * - * enabledSpecifications - * List of specifications for which to enable tests - * - * - * disabledSpecifications - * List of specifications for which to disable tests - * - * * defaultConnection * Nickname of the default connection * @@ -171,10 +159,6 @@ * dnsResolver * One of ‘minidns’, ‘javax’ or ‘dnsjava’. Defaults to ‘minidns’. * - * - * testRunResultProcessors - * List of class names for generating test run output. Defaults to 'org.igniterealtime.smack.inttest.SmackIntegrationTestFramework$ConsoleTestRunResultProcessor' - * * *

    Where to place the properties file

    *

    @@ -203,20 +187,6 @@ *

    * would run all tests defined in the SoftwareInfoIntegrationTest class. *

    - *

    - * Use enabledSpecifications to run all tests that assert implementation of functionality that is described - * in standards identified by the provided specification-reference. - *

    - *

    - * For example: - *

    - * - *
    - * $ gradle integrationTest -Dsinttest.enabledSpecifications=XEP-0045
    - * 
    - *

    - * would run all tests that are annotated to verify functionality specified in XEP-0045: "Multi-User Chat". - *

    *

    Overview of the components

    *

    * Package org.igniterealtime.smack.inttest @@ -279,7 +249,7 @@ * the required XMPP feature. If it does not, simply throw a TestNotPossibleException. *

    *

    - * Test methods must be public, take zero arguments i.e. declare no parameters and be annotated with + * Test methods must be public, take zero arguments i.e. declare no parameters and be annoated with * @SmackIntegrationTest. If the test method is not able to perform a test then it should throw a * TestNotPossibleException. *

    @@ -296,7 +266,7 @@ *

    *

    Low-Level Integration Tests

    *

    - * Classes that implement low-level integration tests need to subclass + * Classes that implement low-level integration tests need to sublcass * {@link org.igniterealtime.smack.inttest.AbstractSmackLowLevelIntegrationTest}. The test methods can declare as many * parameters as they need to, but every parameter must be of type XMPPTCPConnection. The framework will * automatically create, register and login the connections. After the test is finished, the connections will be @@ -314,18 +284,6 @@ * Debug Window launching when your tests launch, and you'll get a stanza-by-stanza account of what happened on each * connection, hopefully enough to diagnose what went wrong. *

    - *

    - * Lastly, you can provide a custom debugger, by providing the fully qualified name of a class that implements - * {@link org.jivesoftware.smack.debugger.SmackDebuggerFactory}. The provided factory must declare a public constructor - * that takes no arguments. - *

    - *

    - * Example: - *

    - * - *
    {@code
    - * $ gradle integrationTest -Dsinttest.service=my.xmppservice.org -Dsinttest.debugger="org.example.MyDebugger$Factory"
    - * }
    *

    Debugging in the IDE

    *

    * If the output isn't enough, you may need to debug and inspect running code within the IDE. Depending on the IDE, in @@ -344,20 +302,7 @@ *

    * *
    {@code
    - * $ gradle integrationTest -Dsinttest.service=my.xmppservice.org -Dsinttest.testPackages=org.mypackage,org.otherpackage
    - * }
    - *

    Generating test run reports

    - *

    - * By default, the results of the test run is printed to standard-error. You can, however, provide your own processing - * for the test run results. To do so, create an implementation of - * {@link org.igniterealtime.smack.inttest.SmackIntegrationTestFramework.TestRunResultProcessor} and provide its class - * name to the testRunResultProcessor property. This property takes a comma separated list of class names. - *

    - *

    - * Example: - *

    - *
    {@code
    - * $ gradle integrationTest -Dsinttest.service=my.xmppservice.org -Dsinttest.testRunResultProcessor=org.igniterealtime.smack.inttest.SmackIntegrationTestFramework$ConsoleTestRunResultProcessor
    + * $ gradle integrationTest -Dsinttest.service=my.xmppserivce.org -Dsinttest.testPackages=org.mypackage,org.otherpackage
      * }
    */ package org.igniterealtime.smack.inttest; diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/util/IntegrationTestRosterUtil.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/util/IntegrationTestRosterUtil.java index befa9eb23..4a6569dcf 100644 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/util/IntegrationTestRosterUtil.java +++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/util/IntegrationTestRosterUtil.java @@ -79,7 +79,7 @@ public class IntegrationTestRosterUtil { try { presenceRequestingRoster.sendSubscriptionRequest(presenceRequestReceiverAddress.asBareJid()); - syncPoint.waitForResult(timeout, "Timeout while waiting for subscription request of '" + presenceRequestingAddress + "' to '" + presenceRequestReceiverAddress + "' to be answered."); + syncPoint.waitForResult(timeout); } finally { presenceRequestReceiverRoster.removeSubscribeListener(subscribeListener); presenceRequestingRoster.removePresenceEventListener(presenceEventListener); diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/util/MultiResultSyncPoint.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/util/MultiResultSyncPoint.java deleted file mode 100644 index aaf0bd4f1..000000000 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/util/MultiResultSyncPoint.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * - * Copyright 2021-2024 Guus der Kinderen - * - * 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.igniterealtime.smack.inttest.util; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeoutException; - -import org.jivesoftware.smack.util.Objects; - -public class MultiResultSyncPoint { - - private final List results; - private E exception; - private final int expectedResultCount; - - public MultiResultSyncPoint(int expectedResultCount) { - this.expectedResultCount = expectedResultCount; - this.results = new ArrayList<>(expectedResultCount); - } - - public synchronized List waitForResults(long timeout) throws E, InterruptedException, TimeoutException { - return waitForResults(timeout, null); - } - - public synchronized List waitForResults(long timeout, String timeoutMessage) throws E, InterruptedException, TimeoutException { - long now = System.currentTimeMillis(); - final long deadline = now + timeout; - while (results.size() < expectedResultCount && exception == null && now < deadline) { - wait(deadline - now); - now = System.currentTimeMillis(); - } - if (now >= deadline) { - StringBuilder sb = new StringBuilder(); - if (timeoutMessage != null) { - sb.append(timeoutMessage).append(". "); - } - sb.append("MultiResultSyncPoint timeout waiting " + timeout + " ms. Got " + results.size() + " results of " + expectedResultCount + " results"); - - throw new TimeoutException(sb.toString()); - } - if (exception != null) throw exception; - return new ArrayList<>(results); - } - - public synchronized void signal(R result) { - this.results.add(Objects.requireNonNull(result)); - if (expectedResultCount <= results.size()) { - notifyAll(); - } - } - - public synchronized void signal(E exception) { - this.exception = Objects.requireNonNull(exception); - notifyAll(); - } -} diff --git a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/util/ResultSyncPoint.java b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/util/ResultSyncPoint.java index ee691bf90..37b143934 100644 --- a/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/util/ResultSyncPoint.java +++ b/smack-integration-test/src/main/java/org/igniterealtime/smack/inttest/util/ResultSyncPoint.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015-2024 Florian Schmaus + * Copyright 2015 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,10 +26,6 @@ public class ResultSyncPoint { private E exception; public R waitForResult(long timeout) throws E, InterruptedException, TimeoutException { - return waitForResult(timeout, null); - } - - public R waitForResult(long timeout, String timeoutMessage) throws E, InterruptedException, TimeoutException { synchronized (this) { if (result != null) { return result; @@ -50,12 +46,7 @@ public class ResultSyncPoint { if (exception != null) { throw exception; } - - String message = "Timeout after " + timeout + "ms"; - if (timeoutMessage != null) { - message += ": " + timeoutMessage; - } - throw new TimeoutException(message); + throw new TimeoutException("Timeout expired"); } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smack/ChatTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smack/ChatTest.java index 56a5ec10e..d956c92ee 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smack/ChatTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smack/ChatTest.java @@ -66,8 +66,8 @@ public class ChatTest extends AbstractSmackIntegrationTest { JivePropertiesManager.setJavaObjectEnabled(false); } + @SuppressWarnings("deprecation") @SmackIntegrationTest - @SuppressWarnings({"deprecation", "JavaUtilDate"}) public void testProperties() throws Exception { org.jivesoftware.smack.chat.Chat newChat = chatManagerOne.createChat(conTwo.getUser()); StanzaCollector collector = conTwo.createStanzaCollector(new ThreadFilter(newChat.getThreadID())); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smack/LoginIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smack/LoginIntegrationTest.java index 1e75154a9..2c9dbb9ec 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smack/LoginIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smack/LoginIntegrationTest.java @@ -48,7 +48,7 @@ public class LoginIntegrationTest extends AbstractSmackLowLevelIntegrationTest { * @throws IOException if an I/O error occurred. * @throws SmackException if Smack detected an exceptional situation. * @throws NoSuchAlgorithmException if no such algorithm is available. - * @throws KeyManagementException if there was a key management error. + * @throws KeyManagementException if there was a key mangement error. */ @SmackIntegrationTest public void testInvalidLogin(UnconnectedConnectionSource unconnectedConnectionSource) throws SmackException, IOException, XMPPException, @@ -64,8 +64,7 @@ public class LoginIntegrationTest extends AbstractSmackLowLevelIntegrationTest { () -> connection.login(nonExistentUserString, invalidPassword)); SaslNonza.SASLFailure saslFailure = saslErrorException.getSASLFailure(); - assertEquals(SASLError.not_authorized, saslFailure.getSASLError(), - "Expected the server to return the appropriate SASL failure condition (but it did not)"); + assertEquals(SASLError.not_authorized, saslFailure.getSASLError()); } finally { connection.disconnect(); } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smack/StreamManagementTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smack/StreamManagementTest.java index fdbb755c7..c9ca9095b 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smack/StreamManagementTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smack/StreamManagementTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015-2024 Florian Schmaus + * Copyright 2015-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,11 +32,9 @@ import org.igniterealtime.smack.inttest.AbstractSmackSpecificLowLevelIntegration import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.jxmpp.jid.EntityFullJid; public class StreamManagementTest extends AbstractSmackSpecificLowLevelIntegrationTest { - @SuppressWarnings("this-escape") public StreamManagementTest(SmackIntegrationTestEnvironment environment) throws Exception { super(environment, XMPPTCPConnection.class); XMPPTCPConnection connection = getSpecificUnconnectedConnection(); @@ -59,7 +57,7 @@ public class StreamManagementTest extends AbstractSmackSpecificLowLevelIntegrati try { send(body1, conOne, conTwo); - assertMessageWithBodyReceived(body1, collector, conTwo.getUser()); + assertMessageWithBodyReceived(body1, collector); conOne.instantShutdown(); @@ -67,10 +65,10 @@ public class StreamManagementTest extends AbstractSmackSpecificLowLevelIntegrati // Reconnect with xep198 conOne.connect().login(); - assertMessageWithBodyReceived(body2, collector, conTwo.getUser()); + assertMessageWithBodyReceived(body2, collector); send(body3, conOne, conTwo); - assertMessageWithBodyReceived(body3, collector, conTwo.getUser()); + assertMessageWithBodyReceived(body3, collector); } finally { collector.cancel(); @@ -86,9 +84,9 @@ public class StreamManagementTest extends AbstractSmackSpecificLowLevelIntegrati from.sendStanza(message); } - private static void assertMessageWithBodyReceived(String body, StanzaCollector collector, EntityFullJid recipient) throws InterruptedException { + private static void assertMessageWithBodyReceived(String body, StanzaCollector collector) throws InterruptedException { Message message = collector.nextResult(); - assertNotNull(message, "Expected '" + recipient + "' to receive a message stanza with body '" + body + "', but it didn't receive the message stanza at all."); - assertEquals(body, message.getBody(), "Expected '" + recipient + "'to receive a message stanza with a specific body, but it received a message stanza with a different body."); + assertNotNull(message); + assertEquals(body, message.getBody()); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smack/WaitForClosingStreamElementTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smack/WaitForClosingStreamElementTest.java index dc9153aab..2326866c7 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smack/WaitForClosingStreamElementTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smack/WaitForClosingStreamElementTest.java @@ -39,6 +39,6 @@ public class WaitForClosingStreamElementTest extends AbstractSmackLowLevelIntegr Field closingStreamReceivedField = AbstractXMPPConnection.class.getDeclaredField("closingStreamReceived"); closingStreamReceivedField.setAccessible(true); boolean closingStreamReceived = (boolean) closingStreamReceivedField.get(connection); - assertTrue(closingStreamReceived, "Expected to, but did not, receive a closing stream element on connection " + connection); + assertTrue(closingStreamReceived); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smack/roster/LowLevelRosterIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smack/roster/LowLevelRosterIntegrationTest.java index 9f150bd7a..305e9ae47 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smack/roster/LowLevelRosterIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smack/roster/LowLevelRosterIntegrationTest.java @@ -49,7 +49,7 @@ public class LowLevelRosterIntegrationTest extends AbstractSmackLowLevelIntegrat final SimpleResultSyncPoint offlineTriggered = new SimpleResultSyncPoint(); - final AbstractPresenceEventListener presenceEventListener = new AbstractPresenceEventListener() { + rosterOne.addPresenceEventListener(new AbstractPresenceEventListener() { @Override public void presenceUnavailable(FullJid jid, Presence presence) { if (!jid.equals(conTwo.getUser())) { @@ -57,24 +57,15 @@ public class LowLevelRosterIntegrationTest extends AbstractSmackLowLevelIntegrat } offlineTriggered.signal(); } - }; - rosterOne.addPresenceEventListener(presenceEventListener); + }); - try { - // Disconnect conTwo, this should cause an 'unavailable' presence to be sent from conTwo to - // conOne. - conTwo.disconnect(); + // Disconnect conTwo, this should cause an 'unavailable' presence to be send from conTwo to + // conOne. + conTwo.disconnect(); - Boolean result = offlineTriggered.waitForResult(timeout); - if (!result) { - throw new Exception("presenceUnavailable() was not called"); - } - } finally { - // Clean up test fixture. - rosterOne.removePresenceEventListener(presenceEventListener); - conTwo.connect(); - conTwo.login(); - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); + Boolean result = offlineTriggered.waitForResult(timeout); + if (!result) { + throw new Exception("presenceUnavailable() was not called"); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smack/roster/RosterIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smack/roster/RosterIntegrationTest.java index 98db355c6..55aad5c12 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smack/roster/RosterIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smack/roster/RosterIntegrationTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015-2024 Florian Schmaus, 2022-2024 Guus der Kinderen + * Copyright 2015-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,34 +16,23 @@ */ package org.jivesoftware.smack.roster; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Collection; import java.util.concurrent.TimeoutException; -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.filter.AndFilter; -import org.jivesoftware.smack.filter.FromMatchesFilter; -import org.jivesoftware.smack.filter.PresenceTypeFilter; -import org.jivesoftware.smack.filter.StanzaTypeFilter; import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.packet.PresenceBuilder; import org.jivesoftware.smack.roster.packet.RosterPacket.ItemType; -import org.jivesoftware.smack.util.Consumer; import org.jivesoftware.smack.util.StringUtils; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.igniterealtime.smack.inttest.util.IntegrationTestRosterUtil; -import org.igniterealtime.smack.inttest.util.ResultSyncPoint; import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; import org.jxmpp.jid.BareJid; import org.jxmpp.jid.Jid; -@SpecificationReference(document = "RFC6121") public class RosterIntegrationTest extends AbstractSmackIntegrationTest { private final Roster rosterOne; @@ -72,7 +61,7 @@ public class RosterIntegrationTest extends AbstractSmackIntegrationTest { final String conTwosRosterName = "ConTwo " + testRunId; final SimpleResultSyncPoint addedAndSubscribed = new SimpleResultSyncPoint(); - final RosterListener rosterListener = new AbstractRosterListener() { + rosterOne.addRosterListener(new AbstractRosterListener() { @Override public void entriesAdded(Collection addresses) { checkIfAddedAndSubscribed(addresses); @@ -89,16 +78,16 @@ public class RosterIntegrationTest extends AbstractSmackIntegrationTest { BareJid bareJid = conTwo.getUser().asBareJid(); RosterEntry rosterEntry = rosterOne.getEntry(bareJid); if (rosterEntry == null) { - addedAndSubscribed.signalFailure("Added/Updated entry was not for " + bareJid); + addedAndSubscribed.signalFailure("No roster entry for " + bareJid); return; } String name = rosterEntry.getName(); if (StringUtils.isNullOrEmpty(name)) { - addedAndSubscribed.signalFailure("Added/Updated entry without name"); + addedAndSubscribed.signalFailure("Roster entry without name"); return; } if (!rosterEntry.getName().equals(conTwosRosterName)) { - addedAndSubscribed.signalFailure("Added/Updated entry name does not match. Expected: " + conTwosRosterName + " but was: " + rosterEntry.getName()); + addedAndSubscribed.signalFailure("Roster name does not match"); return; } if (!rosterEntry.getType().equals(ItemType.to)) { @@ -107,327 +96,15 @@ public class RosterIntegrationTest extends AbstractSmackIntegrationTest { addedAndSubscribed.signal(); } } - }; - - rosterOne.addRosterListener(rosterListener); + }); try { rosterOne.createItemAndRequestSubscription(conTwo.getUser().asBareJid(), conTwosRosterName, null); - assertResult(addedAndSubscribed, - "A roster entry for " + conTwo.getUser().asBareJid() + " using the name '" + conTwosRosterName + - "' of type 'to' was expected to be added to the roster of " + conOne.getUser() + " (but it was not)."); + + assertTrue(addedAndSubscribed.waitForResult(2 * connection.getReplyTimeout())); } finally { rosterTwo.removeSubscribeListener(subscribeListener); - rosterOne.removeRosterListener(rosterListener); - } - } - - /** - * Asserts that when a user sends out a presence subscription request, the server sends a roster push back to the - * user. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "3.1.2", quote = - "After locally delivering or remotely routing the presence subscription request, the user's server MUST then " + - "send a roster push to all of the user's interested resources, containing the potential contact with a " + - "subscription state of \"none\" and with notation that the subscription is pending (via an 'ask' attribute " + - "whose value is \"subscribe\").") - public void testRosterPushAfterSubscriptionRequest() throws Exception { - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); - rosterTwo.setSubscriptionMode(Roster.SubscriptionMode.manual); // prevents a race condition when asserting the captured roster entry. - final ResultSyncPoint added = new ResultSyncPoint<>(); - - final RosterListener rosterListener = new AbstractRosterListener() { - @Override - public void entriesAdded(Collection addresses) { - for (Jid jid : addresses) { - if (!jid.equals(conTwo.getUser().asBareJid())) { - continue; - } - final BareJid bareJid = conTwo.getUser().asBareJid(); - RosterEntry rosterEntry = rosterOne.getEntry(bareJid); - added.signal(rosterEntry); - return; - } - } - }; - rosterOne.addRosterListener(rosterListener); - - final Presence subscribe = conOne.getStanzaFactory().buildPresenceStanza() - .ofType(Presence.Type.subscribe) - .to(conTwo.getUser().asBareJid()) - .build(); - - try { - conOne.sendStanza(subscribe); - - final RosterEntry rosterEntry = assertResult(added, "Expected the server to send a roster push back to '" + conOne.getUser() + "' after they sent a presence subscription request to '" + conTwo.getUser().asBareJid() + "' (but the server did not)."); - assertEquals(ItemType.none, rosterEntry.getType(), "Unexpected subscription type on roster push after '" + conOne.getUser() + "' sent a presence subscription request to '" + conTwo.getUser().asBareJid() + "'."); - assertTrue(rosterEntry.isSubscriptionPending(), "Missing 'ask=subscribe' attribute on roster push after '" + conOne.getUser() + "' sent a presence subscription request to '" + conTwo.getUser().asBareJid() + "'."); - } finally { - rosterTwo.setSubscriptionMode(Roster.getDefaultSubscriptionMode()); - rosterOne.removeRosterListener(rosterListener); - } - } - - /** - * Asserts that when a user sends out a presence subscription request to an entity for which the user does not have - * a pre-existing subscription, the server will deliver the subscription request to that entity. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "3.1.3", quote = - "if there is at least one available resource associated with the contact when the subscription request is " + - "received by the contact's server, then the contact's server MUST send that subscription request to all " + - "available resources in accordance with Section 8.") - public void testPresenceDeliveredToRecipient() throws Exception { - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); - - final ResultSyncPoint added = new ResultSyncPoint<>(); - final StanzaListener stanzaListener = stanza -> added.signal((Presence) stanza); - conTwo.addAsyncStanzaListener(stanzaListener, new AndFilter(StanzaTypeFilter.PRESENCE, FromMatchesFilter.createBare(conOne.getUser()))); - - final Presence subscribe = conOne.getStanzaFactory().buildPresenceStanza() - .ofType(Presence.Type.subscribe) - .to(conTwo.getUser().asBareJid()) - .build(); - - try { - conOne.sendStanza(subscribe); - final Presence received = assertResult(added, "Expected subscription request from '" + conOne.getUser() + "' to '" + conTwo.getUser().asBareJid() + "' to be delivered to " + conTwo.getUser() + " (but it did not)."); - assertEquals(Presence.Type.subscribe, received.getType(), "Unexpected presence type in presence stanza received by '" + conTwo.getUser() + "' after '" + conOne.getUser() + "' sent a presence subscription request."); - } finally { - conTwo.removeAsyncStanzaListener(stanzaListener); - } - } - - /** - * Asserts that when a user sends a presence subscription approval, the server stamps the bare JID of the sender, - * and delivers it to the requester. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "3.1.5", quote = - "When the contact's client sends the subscription approval, the contact's server MUST stamp the outbound " + - "stanza with the bare JID of the contact and locally deliver or remotely route the " + - "stanza to the user.") - public void testPresenceApprovalStampedAndDelivered() throws Exception { - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); - - rosterTwo.setSubscriptionMode(Roster.SubscriptionMode.accept_all); - - // Modify the outbound 'subscribed' stanza, to be 'wrong' (addressed to a full rather than a bare JID), to test if the server overrides this. - final Consumer interceptor = (PresenceBuilder presenceBuilder) -> presenceBuilder.to(conOne.getUser()).build(); - conTwo.addPresenceInterceptor(interceptor, p -> p.getType() == Presence.Type.subscribed); - - final ResultSyncPoint added = new ResultSyncPoint<>(); - final StanzaListener stanzaListener = stanza -> added.signal((Presence) stanza); - - conOne.addAsyncStanzaListener(stanzaListener, PresenceTypeFilter.SUBSCRIBED); - - final Presence subscribe = conOne.getStanzaFactory().buildPresenceStanza() - .ofType(Presence.Type.subscribe) - .to(conTwo.getUser().asBareJid()) - .build(); - - try { - conOne.sendStanza(subscribe); - - final Presence received = assertResult(added, "Expected presence 'subscribed' stanza to be delivered to '" + conOne.getUser() + "' after '" + conTwo.getUser() + "' approved their subscription request (but it was not)."); - assertEquals(conTwo.getUser().asBareJid(), received.getFrom().asEntityBareJidOrThrow(), "Expected presence 'subscribed' stanza that was delivered to '" + conOne.getUser() + "' after '" + conTwo.getUser() + "' approved their subscription request to have a 'from' attribute value that is associated to '" + conTwo.getUser().getLocalpart() + "' (but it did not)."); - assertTrue(received.getFrom().isEntityBareJid(), "Expected presence 'subscribed' stanza that was delivered to '" + conOne.getUser() + "' after '" + conTwo.getUser() + "' approved their subscription request to have a 'from' attribute value that is a bare JID (but it was not)."); - } finally { - rosterTwo.setSubscriptionMode(Roster.getDefaultSubscriptionMode()); - conTwo.removePresenceInterceptor(interceptor); - conOne.removeAsyncStanzaListener(stanzaListener); - } - } - - /** - * Asserts that when a user sends a presence subscription approval, the server sends a roster push to the user with - * a subscription 'from'. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "3.1.5", quote = - "The contact's server then MUST send an updated roster push to all of the contact's interested resources, " + - "with the 'subscription' attribute set to a value of \"from\".") - public void testPresenceApprovalYieldsRosterPush() throws Exception { - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); - - rosterTwo.setSubscriptionMode(Roster.SubscriptionMode.accept_all); - - final ResultSyncPoint updated = new ResultSyncPoint<>(); - - final RosterListener rosterListener = new AbstractRosterListener() { - @Override - public void entriesAdded(Collection addresses) { - for (Jid jid : addresses) { - if (!jid.equals(conOne.getUser().asBareJid())) { - continue; - } - BareJid bareJid = conOne.getUser().asBareJid(); - RosterEntry rosterEntry = rosterTwo.getEntry(bareJid); - updated.signal(rosterEntry); - } - } - }; - rosterTwo.addRosterListener(rosterListener); - - final Presence subscribe = conOne.getStanzaFactory().buildPresenceStanza() - .ofType(Presence.Type.subscribe) - .to(conTwo.getUser().asBareJid()) - .build(); - - try { - conOne.sendStanza(subscribe); - // The 'subscribe' gets automatically approved by conTwo. - - final RosterEntry entry = assertResult(updated, "Expected '" + conTwo.getUser() + "' to receive a roster push with an update for the entry of '" + conOne.getUser().asBareJid() + "' after '" + conTwo.getUser() + "' approved their subscription request."); - assertEquals(ItemType.from, entry.getType(), "Unexpected type for '" + conOne.getUser().asBareJid() + "''s entry in '" + conTwo.getUser().asBareJid() + "''s roster."); - } finally { - rosterTwo.setSubscriptionMode(Roster.getDefaultSubscriptionMode()); - rosterTwo.removeRosterListener(rosterListener); - } - } - - /** - * Asserts that when a user sends a presence subscription approval, the server sends a roster push to the user with - * a subscription 'both' when the contact already has a subscription to the other entity. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "3.1.5", quote = - "The contact's server then MUST send an updated roster push to all of the contact's interested resources, " + - "with the 'subscription' attribute set to a value of \"from\". (Here we assume that the contact does not " + - "already have a subscription to the user; if that were the case, the 'subscription' attribute would be set " + - "to a value of \"both\", as explained under Appendix A.)") - public void testPresenceApprovalYieldsRosterPush2() throws Exception { - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); - - // Setup fixture: establish one-way subscription. - rosterOne.setSubscriptionMode(Roster.SubscriptionMode.accept_all); - - final SimpleResultSyncPoint fixtureComplete = new SimpleResultSyncPoint(); - RosterListener rosterListenerTwo = new AbstractRosterListener() { - @Override - public void entriesAdded(Collection addresses) { - checkIfAdded(addresses); - } - @Override - public void entriesUpdated(Collection addresses) { - checkIfAdded(addresses); - } - private void checkIfAdded(Collection addresses) { - for (Jid jid : addresses) { - final BareJid bareJid = conOne.getUser().asBareJid(); - if (!jid.equals(bareJid)) { - continue; - } - if (rosterTwo.getEntry(bareJid) == null) { - continue; - } - if (rosterTwo.getEntry(bareJid).getType() == ItemType.none) { - continue; - } - fixtureComplete.signal(); - rosterTwo.removeRosterListener(this); - } - } - }; - rosterTwo.addRosterListener(rosterListenerTwo); - - final Presence subscribeOne = conTwo.getStanzaFactory().buildPresenceStanza() - .ofType(Presence.Type.subscribe) - .to(conOne.getUser().asBareJid()) - .build(); - try { - conTwo.sendStanza(subscribeOne); - - fixtureComplete.waitForResult(connection.getReplyTimeout()); - } finally { - rosterOne.setSubscriptionMode(Roster.getDefaultSubscriptionMode()); - rosterTwo.removeRosterListener(rosterListenerTwo); - } - - // Setup fixture is now complete. Execute the test. - rosterTwo.setSubscriptionMode(Roster.SubscriptionMode.accept_all); - - final ResultSyncPoint updated = new ResultSyncPoint<>(); - - rosterListenerTwo = new AbstractRosterListener() { - @Override - public void entriesUpdated(Collection addresses) { - for (Jid jid : addresses) { - if (!jid.equals(conOne.getUser().asBareJid())) { - continue; - } - BareJid bareJid = conOne.getUser().asBareJid(); - updated.signal(rosterTwo.getEntry(bareJid)); - } - } - }; - rosterTwo.addRosterListener(rosterListenerTwo); - - final Presence subscribeTwo = conOne.getStanzaFactory().buildPresenceStanza() - .ofType(Presence.Type.subscribe) - .to(conTwo.getUser().asBareJid()) - .build(); - - try { - conOne.sendStanza(subscribeTwo); - - final RosterEntry entry = assertResult(updated, "Expected '" + conTwo.getUser() + "' to receive a roster push with an update for the entry of '" + conOne.getUser().asBareJid() + "' after '" + conOne.getUser() + "' approved their subscription request."); - assertEquals(ItemType.both, entry.getType(), "Unexpected type for '" + conOne.getUser().asBareJid() + "''s entry in '" + conTwo.getUser().asBareJid() + "''s roster."); - } finally { - rosterTwo.setSubscriptionMode(Roster.getDefaultSubscriptionMode()); - rosterTwo.removeRosterListener(rosterListenerTwo); - } - } - - /** - * Asserts that when a presence subscription request is approved, the server sends the latest presence of the now - * subscribed entity to the subscriber. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "3.1.5", quote = - "The contact's server MUST then also send current presence to the user from each of the contact's available resources.") - public void testCurrentPresenceSentAfterSubscriptionApproval() throws Exception { - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); - - final String needle = "Look for me!"; - conTwo.sendStanza(conTwo.getStanzaFactory().buildPresenceStanza().setStatus(needle).build()); - - rosterTwo.setSubscriptionMode(Roster.SubscriptionMode.accept_all); - - final SimpleResultSyncPoint received = new SimpleResultSyncPoint(); - final StanzaListener stanzaListener = stanza -> { - final Presence presence = (Presence) stanza; - - String status = presence.getStatus(); - if (status == null) return; - - if (status.equals(needle)) { - received.signal(); - } - }; - conOne.addAsyncStanzaListener(stanzaListener, new AndFilter(StanzaTypeFilter.PRESENCE, FromMatchesFilter.createBare(conTwo.getUser()))); - - final Presence subscribe = conOne.getStanzaFactory().buildPresenceStanza() - .ofType(Presence.Type.subscribe) - .to(conTwo.getUser().asBareJid()) - .build(); - - try { - conOne.sendStanza(subscribe); - - assertResult(received, "Expected '" + conTwo.getUser() + "' to receive '" + conOne.getUser() + "''s current presence update (including the status '" + needle + "'), but it did not."); - } finally { - rosterTwo.setSubscriptionMode(Roster.getDefaultSubscriptionMode()); - conOne.removeAsyncStanzaListener(stanzaListener); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/caps/EntityCapsTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/caps/EntityCapsTest.java index 74d9aa6a8..4c373a9ce 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/caps/EntityCapsTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/caps/EntityCapsTest.java @@ -18,7 +18,6 @@ package org.jivesoftware.smackx.caps; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -52,9 +51,7 @@ import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.annotations.AfterClass; import org.igniterealtime.smack.inttest.annotations.BeforeClass; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; -@SpecificationReference(document = "XEP-0115", version = "1.6.0") public class EntityCapsTest extends AbstractSmackIntegrationTest { private final EntityCapsManager ecmTwo; @@ -97,9 +94,7 @@ public class EntityCapsTest extends AbstractSmackIntegrationTest { public void testLocalEntityCaps() throws InterruptedException, NoResponseException, XMPPErrorException, NotConnectedException { final String dummyFeature = getNewDummyFeature(); DiscoverInfo info = EntityCapsManager.getDiscoveryInfoByNodeVer(ecmTwo.getLocalNodeVer()); - assertFalse(info.containsFeature(dummyFeature), - "Expected the service discovery info for node '" + ecmTwo.getLocalNodeVer() + - "' to contain the feature '" + dummyFeature + "' (but it did not)."); // TODO Shouldn't this assertion be in a unit test instead of an integration test? + assertFalse(info.containsFeature(dummyFeature)); dropWholeEntityCapsCache(); @@ -123,12 +118,8 @@ public class EntityCapsTest extends AbstractSmackIntegrationTest { // The other connection has to receive this stanza and record the // information in order for this test to succeed. info = EntityCapsManager.getDiscoveryInfoByNodeVer(ecmTwo.getLocalNodeVer()); - assertNotNull(info, - "Expected '" + conOne.getUser() + "' to have received an 'available' presence from '" + conTwo.getUser() + - "' with a new CAPS 'ver' attribute (but it did not)."); - assertTrue(info.containsFeature(dummyFeature), - "Expected the service discovery info for node '" + ecmTwo.getLocalNodeVer() + - "' to contain the feature '" + dummyFeature + "' (but it did not)."); // TODO As above: shouldn't this assertion be in a unit test instead of an integration test? + assertNotNull(info); + assertTrue(info.containsFeature(dummyFeature)); } /** @@ -155,7 +146,7 @@ public class EntityCapsTest extends AbstractSmackIntegrationTest { // discover that DiscoverInfo info = sdmOne.discoverInfo(conTwo.getUser()); // that discovery should cause a disco#info - assertTrue(discoInfoSend.get(), "Expected '" + conOne.getUser() + "' to have made a disco/info request to '" + conTwo.getUser() + "', but it did not."); + assertTrue(discoInfoSend.get()); assertTrue(info.containsFeature(dummyFeature), "The info response '" + info + "' does not contain the expected feature '" + dummyFeature + '\''); discoInfoSend.set(false); @@ -163,9 +154,8 @@ public class EntityCapsTest extends AbstractSmackIntegrationTest { // discover that info = sdmOne.discoverInfo(conTwo.getUser()); // that discovery shouldn't cause a disco#info - assertFalse(discoInfoSend.get(), "Expected '" + conOne.getUser() + "' to not have made a disco/info request to '" + conTwo.getUser() + "' (as CAPS should have been cached), but it did not."); - assertTrue(info.containsFeature(dummyFeature), - "The info response '" + info + "' does not contain the expected feature '" + dummyFeature + '\''); + assertFalse(discoInfoSend.get()); + assertTrue(info.containsFeature(dummyFeature)); } @SmackIntegrationTest @@ -175,8 +165,7 @@ public class EntityCapsTest extends AbstractSmackIntegrationTest { addFeatureAndWaitForPresence(conOne, conTwo, dummyFeature); String nodeVerAfter = EntityCapsManager.getNodeVersionByJid(conTwo.getUser()); - assertNotEquals(nodeVerBefore, nodeVerAfter, - "Expected the reported node 'ver' value to differ after a feature was added (but it did not)."); + assertFalse(nodeVerBefore.equals(nodeVerAfter)); } @SmackIntegrationTest @@ -202,12 +191,12 @@ public class EntityCapsTest extends AbstractSmackIntegrationTest { DiscoverInfo info = sdmOne.discoverInfo(conTwo.getUser()); String u1ver = EntityCapsManager.getNodeVersionByJid(conTwo.getUser()); - assertNotNull(u1ver, "Expected " + conOne.getUser() + " to have received a CAPS 'ver' value for " + conTwo.getUser() + " (but did not)."); + assertNotNull(u1ver); DiscoverInfo entityInfo = EntityCapsManager.CAPS_CACHE.lookup(u1ver); - assertNotNull(entityInfo, "Expected the local static cache to have a value cached for 'ver' value '" + u1ver + "' (but it did not)."); + assertNotNull(entityInfo); - assertEquals(info.toXML().toString(), entityInfo.toXML().toString(), "Expected the cached service/discovery info to be equal to the original (but it was not)."); + assertEquals(info.toXML().toString(), entityInfo.toXML().toString()); } private static void dropWholeEntityCapsCache() { diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/chatstate/ChatStateIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/chatstate/ChatStateIntegrationTest.java index 2c1b56e1a..11e1340f4 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/chatstate/ChatStateIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/chatstate/ChatStateIntegrationTest.java @@ -27,10 +27,8 @@ import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.annotations.AfterClass; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; -@SpecificationReference(document = "XEP-0085", version = "2.1") public class ChatStateIntegrationTest extends AbstractSmackIntegrationTest { // Listener for composing chat state @@ -75,7 +73,7 @@ public class ChatStateIntegrationTest extends AbstractSmackIntegrationTest { Chat chat = ChatManager.getInstanceFor(conOne) .chatWith(conTwo.getUser().asEntityBareJid()); chat.send("Hi!"); - assertResult(activeSyncPoint, "Expected " + conTwo.getUser() + " to receive an 'active' chat state from " + conOne + " (but they did not)."); + activeSyncPoint.waitForResult(timeout); } @AfterClass diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandIntegrationTest.java deleted file mode 100644 index 1ece51611..000000000 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/commands/AdHocCommandIntegrationTest.java +++ /dev/null @@ -1,364 +0,0 @@ -/** - * - * Copyright 2023-2024 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.smackx.commands; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import org.jivesoftware.smack.SmackException.NoResponseException; -import org.jivesoftware.smack.SmackException.NotConnectedException; -import org.jivesoftware.smack.XMPPException.XMPPErrorException; -import org.jivesoftware.smack.packet.StanzaError; -import org.jivesoftware.smackx.commands.packet.AdHocCommandData; -import org.jivesoftware.smackx.commands.packet.AdHocCommandDataBuilder; -import org.jivesoftware.smackx.commands.packet.AdHocCommandDataBuilder.NextStage; -import org.jivesoftware.smackx.commands.packet.AdHocCommandDataBuilder.PreviousStage; -import org.jivesoftware.smackx.xdata.FormField; -import org.jivesoftware.smackx.xdata.form.FillableForm; -import org.jivesoftware.smackx.xdata.form.SubmitForm; -import org.jivesoftware.smackx.xdata.packet.DataForm; - -import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; -import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; -import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; - -@SpecificationReference(document = "XEP-0050", version = "1.3.0") -public class AdHocCommandIntegrationTest extends AbstractSmackIntegrationTest { - - public AdHocCommandIntegrationTest(SmackIntegrationTestEnvironment environment) { - super(environment); - } - - @SmackIntegrationTest - public void singleStageAdHocCommandTest() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - AdHocCommandManager manOne = AdHocCommandManager.getInstance(conOne); - AdHocCommandManager manTwo = AdHocCommandManager.getInstance(conTwo); - - String commandNode = "test-list"; - String commandName = "Return a list for testing purposes"; - AdHocCommandHandlerFactory factory = (String node, String name, String sessionId) -> { - return new AdHocCommandHandler.SingleStage(node, name, sessionId) { - @Override - public AdHocCommandData executeSingleStage(AdHocCommandDataBuilder response) { - FormField field = FormField.textPrivateBuilder("my-field").build(); - DataForm form = DataForm.builder(DataForm.Type.result).addField(field).build(); - - response.setForm(form); - - return response.build(); - } - }; - }; - manOne.registerCommand(commandNode, commandName, factory); - try { - AdHocCommand command = manTwo.getRemoteCommand(conOne.getUser(), commandNode); - - AdHocCommandResult result = command.execute(); - AdHocCommandData response = result.getResponse(); - DataForm form = response.getForm(); - FormField field = form.getField("my-field"); - assertNotNull(field, "Expected a field named 'my-field' to exist in the form that " + - conTwo.getUser() + " obtained from " + conOne.getUser() + "'s command node '" + commandNode + - "' (but it did not)."); - } finally { - manOne.unregisterCommand(commandNode); - } - } - - private static class MyMultiStageAdHocCommandServer extends AdHocCommandHandler { - - private Integer a; - private Integer b; - - private static DataForm createDataForm(String variableName) { - FormField field = FormField.textSingleBuilder(variableName).setRequired().build(); - return DataForm.builder(DataForm.Type.form) - .setTitle("Variable " + variableName) - .setInstructions("Please provide an integer variable " + variableName) - .addField(field) - .build(); - } - - private static DataForm createDataFormOp() { - FormField field = FormField.listSingleBuilder("op") - .setLabel("Arithmetic Operation") - .setRequired() - .addOption("+") - .addOption("-") - .build(); - return DataForm.builder(DataForm.Type.form) - .setTitle("Operation") - .setInstructions("Please select the arithmetic operation to be performed with a and b") - .addField(field) - .build(); - } - private static final DataForm dataFormAskingForA = createDataForm("a"); - private static final DataForm dataFormAskingForB = createDataForm("b"); - private static final DataForm dataFormAskingForOp = createDataFormOp(); - - MyMultiStageAdHocCommandServer(String node, String name, String sessionId) { - super(node, name, sessionId); - } - - @Override - protected AdHocCommandData execute(AdHocCommandDataBuilder response) throws XMPPErrorException { - return response.setForm(dataFormAskingForA).setStatusExecuting(PreviousStage.none, - NextStage.nonFinal).build(); - } - - private static Integer extractIntegerField(SubmitForm form, String fieldName) throws XMPPErrorException { - FormField field = form.getField(fieldName); - if (field == null) - throw newBadRequestException("Submitted form does not contain a field of name " + fieldName); - - String fieldValue = field.getFirstValue(); - if (fieldValue == null) - throw newBadRequestException("Submitted form contains field of name " + fieldName + " without value"); - - try { - return Integer.parseInt(fieldValue); - } catch (NumberFormatException e) { - throw newBadRequestException("Submitted form contains field of name " + fieldName + " with value " + fieldValue + " that is not an integer"); - } - } - - @Override - protected AdHocCommandData next(AdHocCommandDataBuilder response, SubmitForm submittedForm) - throws XMPPErrorException { - DataForm form; - switch (getCurrentStage()) { - case 2: - a = extractIntegerField(submittedForm, "a"); - form = dataFormAskingForB; - response.setStatusExecuting(PreviousStage.exists, NextStage.nonFinal); - break; - case 3: - b = extractIntegerField(submittedForm, "b"); - form = dataFormAskingForOp; - response.setStatusExecuting(PreviousStage.exists, NextStage.isFinal); - break; - case 4: - // Ad-Hoc Commands particularity: Can get to 'complete' via 'next'. - return complete(response, submittedForm); - default: - throw new IllegalStateException(); - } - - return response.setForm(form).build(); - } - - @Override - protected AdHocCommandData complete(AdHocCommandDataBuilder response, SubmitForm submittedForm) - throws XMPPErrorException { - if (getCurrentStage() != 4) { - throw new IllegalStateException(); - } - - if (a == null || b == null) { - throw new IllegalStateException(); - } - - String op = submittedForm.getField("op").getFirstValue(); - - int result; - switch (op) { - case "+": - result = a + b; - break; - case "-": - result = a - b; - break; - default: - throw newBadRequestException("Submitted operation " + op + " is neither + nor -"); - } - - response.setStatusCompleted(); - - FormField field = FormField.textSingleBuilder("result").setValue(result).build(); - DataForm form = DataForm.builder(DataForm.Type.result).setTitle("Result").addField(field).build(); - - return response.setForm(form).build(); - } - - @Override - protected AdHocCommandData prev(AdHocCommandDataBuilder response) throws XMPPErrorException { - switch (getCurrentStage()) { - case 1: - return execute(response); - case 2: - return response.setForm(dataFormAskingForA) - .setStatusExecuting(PreviousStage.exists, NextStage.nonFinal) - .build(); - case 3: - return response.setForm(dataFormAskingForB) - .setStatusExecuting(PreviousStage.exists, NextStage.isFinal) - .build(); - default: - throw new IllegalStateException(); - } - } - - @Override - public void cancel() { - } - - } - - @SmackIntegrationTest - public void multiStageAdHocCommandTest() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - AdHocCommandManager manOne = AdHocCommandManager.getInstance(conOne); - AdHocCommandManager manTwo = AdHocCommandManager.getInstance(conTwo); - - String commandNode = "my-multi-stage-command"; - String commandName = "An example multi-sage ad-hoc command"; - AdHocCommandHandlerFactory factory = (String node, String name, String sessionId) -> { - return new MyMultiStageAdHocCommandServer(node, name, sessionId); - }; - manOne.registerCommand(commandNode, commandName, factory); - - try { - AdHocCommand command = manTwo.getRemoteCommand(conOne.getUser(), commandNode); - - AdHocCommandResult.StatusExecuting result = command.execute().asExecutingOrThrow(); - - FillableForm form = result.getFillableForm(); - form.setAnswer("a", 42); - - SubmitForm submitForm = form.getSubmitForm(); - - - result = command.next(submitForm).asExecutingOrThrow(); - - form = result.getFillableForm(); - form.setAnswer("b", 23); - - submitForm = form.getSubmitForm(); - - - result = command.next(submitForm).asExecutingOrThrow(); - - form = result.getFillableForm(); - form.setAnswer("op", "+"); - - submitForm = form.getSubmitForm(); - - AdHocCommandResult.StatusCompleted completed = command.complete(submitForm).asCompletedOrThrow(); - - String operationResult = completed.getResponse().getForm().getField("result").getFirstValue(); - assertEquals("65", operationResult, - "Unexpected value in the field 'result' from the command result that " + conTwo.getUser() + - " received from " + conOne.getUser() + " after completing a multi-staged ad-hoc command on node '" + - commandNode + "'."); - } finally { - manTwo.unregisterCommand(commandNode); - } - } - - @SmackIntegrationTest - public void multiStageWithPrevAdHocCommandTest() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - AdHocCommandManager manOne = AdHocCommandManager.getInstance(conOne); - AdHocCommandManager manTwo = AdHocCommandManager.getInstance(conTwo); - - String commandNode = "my-multi-stage-with-prev-command"; - String commandName = "An example multi-sage ad-hoc command"; - AdHocCommandHandlerFactory factory = (String node, String name, String sessionId) -> { - return new MyMultiStageAdHocCommandServer(node, name, sessionId); - }; - manOne.registerCommand(commandNode, commandName, factory); - - try { - AdHocCommand command = manTwo.getRemoteCommand(conOne.getUser(), commandNode); - - AdHocCommandResult.StatusExecuting result = command.execute().asExecutingOrThrow(); - - FillableForm form = result.getFillableForm(); - form.setAnswer("a", 42); - - SubmitForm submitForm = form.getSubmitForm(); - - command.next(submitForm).asExecutingOrThrow(); - - - // Ups, I wanted a different value for 'a', lets execute 'prev' to get back to the previous stage. - result = command.prev().asExecutingOrThrow(); - - form = result.getFillableForm(); - form.setAnswer("a", 77); - - submitForm = form.getSubmitForm(); - - - result = command.next(submitForm).asExecutingOrThrow(); - - form = result.getFillableForm(); - form.setAnswer("b", 23); - - submitForm = form.getSubmitForm(); - - - result = command.next(submitForm).asExecutingOrThrow(); - - form = result.getFillableForm(); - form.setAnswer("op", "+"); - - submitForm = form.getSubmitForm(); - - AdHocCommandResult.StatusCompleted completed = command.complete(submitForm).asCompletedOrThrow(); - - String operationResult = completed.getResponse().getForm().getField("result").getFirstValue(); - assertEquals("100", operationResult, - "Unexpected value in the field 'result' from the command result that " + conTwo.getUser() + - " received from " + conOne.getUser() + " after completing a multi-staged ad-hoc command on node '" + - commandNode + "'."); - } finally { - manTwo.unregisterCommand(commandNode); - } - } - - @SmackIntegrationTest - public void multiStageInvalidArgAdHocCommandTest() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { - AdHocCommandManager manOne = AdHocCommandManager.getInstance(conOne); - AdHocCommandManager manTwo = AdHocCommandManager.getInstance(conTwo); - - String commandNode = "my-multi-stage-invalid-arg-command"; - String commandName = "An example multi-sage ad-hoc command"; - AdHocCommandHandlerFactory factory = (String node, String name, String sessionId) -> { - return new MyMultiStageAdHocCommandServer(node, name, sessionId); - }; - manOne.registerCommand(commandNode, commandName, factory); - - try { - AdHocCommand command = manTwo.getRemoteCommand(conOne.getUser(), commandNode); - - AdHocCommandResult.StatusExecuting result = command.execute().asExecutingOrThrow(); - - FillableForm form = result.getFillableForm(); - form.setAnswer("a", "forty-two"); - - SubmitForm submitForm = form.getSubmitForm(); - - XMPPErrorException exception = assertThrows(XMPPErrorException.class, () -> command.next(submitForm)); - assertEquals(StanzaError.Condition.bad_request, exception.getStanzaError().getCondition(), - "Unexpected error condition received after " + conTwo.getUser() + " supplied an invalid argument " + - "to the command node '" + commandNode + "' of " + conOne.getUser()); - } finally { - manTwo.unregisterCommand(commandNode); - } - } -} diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/commands/package-info.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/commands/package-info.java deleted file mode 100644 index 22bfe9d75..000000000 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/commands/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/** - * - * Copyright 2023 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. - */ - - -/** - * Smacks implementation of XEP-0050: Ad-Hoc Commands. - */ -package org.jivesoftware.smackx.commands; diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferIntegrationTest.java index 25ebb9b2a..ac79e46ec 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferIntegrationTest.java @@ -31,10 +31,8 @@ import org.jivesoftware.smackx.filetransfer.FileTransfer.Status; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; -import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; +import org.igniterealtime.smack.inttest.util.ResultSyncPoint; -@SpecificationReference(document = "XEP-0096", version = "1.3.1") public class FileTransferIntegrationTest extends AbstractSmackIntegrationTest { private static final int MAX_FT_DURATION = 360; @@ -67,7 +65,7 @@ public class FileTransferIntegrationTest extends AbstractSmackIntegrationTest { } private void genericfileTransferTest() throws Exception { - final SimpleResultSyncPoint resultSyncPoint = new SimpleResultSyncPoint(); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); final FileTransferListener receiveListener = new FileTransferListener() { @Override public void fileTransferRequest(FileTransferRequest request) { @@ -84,7 +82,7 @@ public class FileTransferIntegrationTest extends AbstractSmackIntegrationTest { os.flush(); dataReceived = os.toByteArray(); if (Arrays.equals(dataToSend, dataReceived)) { - resultSyncPoint.signal(); + resultSyncPoint.signal("Received data matches send data. \\o/"); } else { resultSyncPoint.signal(new Exception("Received data does not match")); @@ -117,9 +115,7 @@ public class FileTransferIntegrationTest extends AbstractSmackIntegrationTest { } } - assertResult(resultSyncPoint, MAX_FT_DURATION * 1000, - "Expected data to be transferred successfully from " + conOne.getUser() + " to " + conTwo.getUser() + - " (but it did not)."); + resultSyncPoint.waitForResult(MAX_FT_DURATION * 1000); ftManagerTwo.removeFileTransferListener(receiveListener); } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/geolocation/GeolocationIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/geolocation/GeolocationIntegrationTest.java index 1cd1d3b8d..7e149ff3b 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/geolocation/GeolocationIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/geolocation/GeolocationIntegrationTest.java @@ -17,6 +17,7 @@ package org.jivesoftware.smackx.geolocation; import java.net.URI; +import java.util.concurrent.TimeoutException; import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NotConnectedException; @@ -33,12 +34,11 @@ import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.annotations.AfterClass; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.igniterealtime.smack.inttest.util.IntegrationTestRosterUtil; import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; +import org.junit.jupiter.api.Assertions; import org.jxmpp.util.XmppDateTime; -@SpecificationReference(document = "XEP-0080", version = "1.9") public class GeolocationIntegrationTest extends AbstractSmackIntegrationTest { private final GeoLocationManager glm1; @@ -106,12 +106,16 @@ public class GeolocationIntegrationTest extends AbstractSmackIntegrationTest { glm1.publishGeoLocation(data); // for the purpose of this test, this needs not be blocking/use publishAndWait(); // Wait for the data to be received. - assertResult(geoLocationReceived, - "Expected " + conTwo.getUser() + " to receive a PEP notification from " + conOne.getUser() + - " that contained '" + data.toXML() + "', but did not."); + try { + Object result = geoLocationReceived.waitForResult(timeout); + + // Explicitly assert the success case. + Assertions.assertNotNull(result, "Expected to receive a PEP notification, but did not."); + } catch (TimeoutException e) { + Assertions.fail("Expected to receive a PEP notification, but did not."); + } } finally { unregisterListener(glm2, geoLocationListener); - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); } } @@ -167,12 +171,16 @@ public class GeolocationIntegrationTest extends AbstractSmackIntegrationTest { registerListenerAndWait(glm2, ServiceDiscoveryManager.getInstanceFor(conTwo), geoLocationListener); // Wait for the data to be received. - assertResult(geoLocationReceived, - "Expected " + conTwo.getUser() + " to receive a PEP notification from " + conOne.getUser() + - " that contained '" + data.toXML() + "', but did not."); + try { + Object result = geoLocationReceived.waitForResult(timeout); + + // Explicitly assert the success case. + Assertions.assertNotNull(result, "Expected to receive a PEP notification, but did not."); + } catch (TimeoutException e) { + Assertions.fail("Expected to receive a PEP notification, but did not."); + } } finally { unregisterListener(glm2, geoLocationListener); - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadIntegrationTest.java index 862a06af2..243bfec36 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadIntegrationTest.java @@ -36,9 +36,7 @@ import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; -@SpecificationReference(document = "XEP-0363", version = "0.4.0") public class HttpFileUploadIntegrationTest extends AbstractSmackIntegrationTest { private static final int FILE_SIZE = 1024 * 128; @@ -82,7 +80,7 @@ public class HttpFileUploadIntegrationTest extends AbstractSmackIntegrationTest URL getUrl = hfumOne.uploadFile(file, new UploadProgressListener() { @Override public void onUploadProgress(long uploadedBytes, long totalBytes) { - double progress = uploadedBytes / ((double) totalBytes); + double progress = uploadedBytes / totalBytes; LOGGER.fine("HTTP File Upload progress " + progress + "% (" + uploadedBytes + '/' + totalBytes + ')'); } }); @@ -104,6 +102,6 @@ public class HttpFileUploadIntegrationTest extends AbstractSmackIntegrationTest byte[] downBytes = baos.toByteArray(); - assertArrayEquals(upBytes, downBytes, "Expected the downloaded bytes to be equal to the uploaded bytes (but they were not)."); + assertArrayEquals(upBytes, downBytes); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/iot/IoTControlIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/iot/IoTControlIntegrationTest.java index 4d4844adf..498493b5b 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/iot/IoTControlIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/iot/IoTControlIntegrationTest.java @@ -33,12 +33,10 @@ import org.jivesoftware.smackx.iot.control.element.SetData; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.igniterealtime.smack.inttest.util.IntegrationTestRosterUtil; import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; import org.jxmpp.jid.Jid; -@SpecificationReference(document = "XEP-0347", version = "0.5.1") public class IoTControlIntegrationTest extends AbstractSmackIntegrationTest { private final IoTControlManager IoTControlManagerOne; @@ -89,7 +87,7 @@ public class IoTControlIntegrationTest extends AbstractSmackIntegrationTest { SetData data = new SetBoolData(testRunId, true); IoTSetResponse response = IoTControlManagerTwo.setUsingIq(conOne.getUser(), data); - assertNotNull(response, "Expected " + conOne.getUser() + " to receive an IQ response with an 'setResponse' child element, but no such response was received."); + assertNotNull(response); } finally { IoTControlManagerOne.uninstallThing(controlThing); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/iot/IoTDataIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/iot/IoTDataIntegrationTest.java index 731260475..858eae9a7 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/iot/IoTDataIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/iot/IoTDataIntegrationTest.java @@ -37,10 +37,8 @@ import org.jivesoftware.smackx.iot.data.element.TimestampElement; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.igniterealtime.smack.inttest.util.IntegrationTestRosterUtil; -@SpecificationReference(document = "XEP-0347", version = "0.5.1") public class IoTDataIntegrationTest extends AbstractSmackIntegrationTest { private final IoTDataManager iotDataManagerOne; @@ -86,23 +84,23 @@ public class IoTDataIntegrationTest extends AbstractSmackIntegrationTest { IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); } - assertEquals(1, values.size(), "An unexpected amount of momentary values was received by " + conOne.getUser()); + assertEquals(1, values.size()); IoTFieldsExtension iotFieldsExtension = values.get(0); List nodes = iotFieldsExtension.getNodes(); - assertEquals(1, nodes.size(), "The momentary value received by " + conOne.getUser() + " contains an unexpected amount of nodes."); + assertEquals(1, nodes.size()); NodeElement node = nodes.get(0); List timestamps = node.getTimestampElements(); - assertEquals(1, timestamps.size(), "The node received by " + conOne.getUser() + " contains an unexpected amount of timestamps."); + assertEquals(1, timestamps.size()); TimestampElement timestamp = timestamps.get(0); List fields = timestamp.getDataFields(); - assertEquals(1, fields.size(), "The timestamp received by " + conOne.getUser() + " contains an unexpected amount of data fields."); + assertEquals(1, fields.size()); IoTDataField dataField = fields.get(0); - assertTrue(dataField instanceof IoTDataField.IntField, "The data field received by " + conOne.getUser() + " was expected to be an instance of " + IoTDataField.IntField.class.getSimpleName() + ", but instead, it was " + dataField.getClass().getSimpleName()); + assertTrue(dataField instanceof IoTDataField.IntField); IoTDataField.IntField intDataField = (IoTDataField.IntField) dataField; - assertEquals(testRunId, intDataField.getName(), "Unexpected name in the data field received by " + conOne.getUser()); - assertEquals(value, intDataField.getValue(), "Unexpected value in the data field received by " + conOne.getUser()); + assertEquals(testRunId, intDataField.getName()); + assertEquals(value, intDataField.getValue()); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/iot/IoTDiscoveryIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/iot/IoTDiscoveryIntegrationTest.java index 7c3f3dcac..df6bf345e 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/iot/IoTDiscoveryIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/iot/IoTDiscoveryIntegrationTest.java @@ -34,10 +34,8 @@ import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.jxmpp.jid.Jid; -@SpecificationReference(document = "XEP-0347", version = "0.5.1") public class IoTDiscoveryIntegrationTest extends AbstractSmackIntegrationTest { private final IoTDiscoveryManager discoveryManagerOne; @@ -62,7 +60,7 @@ public class IoTDiscoveryIntegrationTest extends AbstractSmackIntegrationTest { registerThing(discoveryManagerOne, thing); IoTClaimed iotClaimed = discoveryManagerTwo.claimThing(thing.getMetaTags()); - assertEquals(conOne.getUser().asBareJid(), iotClaimed.getJid(), "Thing claimed by an unexpected JID"); + assertEquals(conOne.getUser().asBareJid(), iotClaimed.getJid()); discoveryManagerTwo.disownThing(iotClaimed.getJid()); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/iqversion/VersionIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/iqversion/VersionIntegrationTest.java index 05c8fa18d..9e903bbb8 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/iqversion/VersionIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/iqversion/VersionIntegrationTest.java @@ -28,9 +28,7 @@ import org.jivesoftware.smackx.iqversion.packet.Version; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; -@SpecificationReference(document = "XEP-0092", version = "1.1") public class VersionIntegrationTest extends AbstractSmackIntegrationTest { public VersionIntegrationTest(SmackIntegrationTestEnvironment environment) { @@ -47,8 +45,8 @@ public class VersionIntegrationTest extends AbstractSmackIntegrationTest { final String versionName = "Smack Integration Test " + testRunId; versionManagerTwo.setVersion(versionName, "1.0"); - assertTrue(versionManagerOne.isSupported(conTwo.getUser()), "Expected " + conTwo.getUser() + " to support " + Version.NAMESPACE + " (but it does not)."); + assertTrue (versionManagerOne.isSupported(conTwo.getUser())); Version version = versionManagerOne.getVersion(conTwo.getUser()); - assertEquals(versionName, version.getName(), "Unexpected version name reported by " + conTwo.getUser()); + assertEquals(versionName, version.getName()); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/mam/MamIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/mam/MamIntegrationTest.java index 9b9cba7a3..046a33ac6 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/mam/MamIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/mam/MamIntegrationTest.java @@ -42,11 +42,9 @@ import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; import org.jxmpp.jid.EntityBareJid; -@SpecificationReference(document = "XEP-0313", version = "0.6.3") public class MamIntegrationTest extends AbstractSmackIntegrationTest { private final MamManager mamManagerConTwo; @@ -115,14 +113,14 @@ public class MamIntegrationTest extends AbstractSmackIntegrationTest { .build(); MamQuery mamQuery = mamManagerConTwo.queryArchive(mamQueryArgs); - assertEquals(1, mamQuery.getMessages().size(), conTwo.getUser() + " received an unexpected amount of messages in response to a MAM query."); + assertEquals(1, mamQuery.getMessages().size()); Message mamMessage = mamQuery.getMessages().get(0); - assertEquals(messageId, mamMessage.getStanzaId(), "The message received by " + conTwo.getUser() + " via a MAM query has an unexpected stanza ID."); - assertEquals(messageBody, mamMessage.getBody(), "The message received by " + conTwo.getUser() + " via a MAM query has an unexpected body."); - assertEquals(conOne.getUser(), mamMessage.getFrom(), "The message received by " + conTwo.getUser() + " via a MAM query has an unexpected from-attribute value."); - assertEquals(userTwo, mamMessage.getTo(), "The message received by " + conTwo.getUser() + " via a MAM query has an unexpected to-attribute value."); + assertEquals(messageId, mamMessage.getStanzaId()); + assertEquals(messageBody, mamMessage.getBody()); + assertEquals(conOne.getUser(), mamMessage.getFrom()); + assertEquals(userTwo, mamMessage.getTo()); } @SmackIntegrationTest @@ -176,8 +174,8 @@ public class MamIntegrationTest extends AbstractSmackIntegrationTest { MamQuery mamQuery = mamManagerConTwo.queryArchive(mamQueryArgs); - assertFalse(mamQuery.isComplete(), "Expected the first MAM response received by " + conTwo.getUser() + " to NOT be complete (but it was)."); - assertEquals(messagesPerPage, mamQuery.getMessageCount(), "Unexpected message count in MAM response received by " + conTwo.getUser()); + assertFalse(mamQuery.isComplete()); + assertEquals(messagesPerPage, mamQuery.getMessageCount()); List> pages = new ArrayList<>(numPages); pages.add(mamQuery.getMessages()); @@ -187,12 +185,12 @@ public class MamIntegrationTest extends AbstractSmackIntegrationTest { boolean isLastQuery = additionalPageRequestNum == numPages - 2; if (isLastQuery) { - assertTrue(mamQuery.isComplete(), "Expected the last MAM response received by " + conTwo.getUser() + " to be complete (but it was not)."); + assertTrue(mamQuery.isComplete()); } else { - assertFalse(mamQuery.isComplete(), "Expected an intermediate MAM response received by " + conTwo.getUser() + " to NOT be complete (but it was)."); + assertFalse(mamQuery.isComplete()); } - assertEquals(messagesPerPage, page.size(), "Unexpected amount of messages in the MAM response page received by " + conTwo.getUser()); + assertEquals(messagesPerPage, page.size()); pages.add(page); } @@ -202,13 +200,13 @@ public class MamIntegrationTest extends AbstractSmackIntegrationTest { queriedMessages.addAll(messages); } - assertEquals(outgoingMessages.size(), queriedMessages.size(), "An unexpected total number of messages was received through MAM by " + conTwo.getUser()); + assertEquals(outgoingMessages.size(), queriedMessages.size()); for (int i = 0; i < outgoingMessages.size(); i++) { Message outgoingMessage = outgoingMessages.get(i); Message queriedMessage = queriedMessages.get(i); - assertEquals(outgoingMessage.getBody(), queriedMessage.getBody(), "Unexpected message body for message number " + (i + 1) + " as received by " + conTwo.getUser() + " (are messages received out of order?)"); + assertEquals(outgoingMessage.getBody(), queriedMessage.getBody()); } } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/mood/MoodIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/mood/MoodIntegrationTest.java index c430938db..1a83085dc 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/mood/MoodIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/mood/MoodIntegrationTest.java @@ -16,6 +16,8 @@ */ package org.jivesoftware.smackx.mood; +import java.util.concurrent.TimeoutException; + import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; @@ -28,11 +30,10 @@ import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.annotations.AfterClass; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.igniterealtime.smack.inttest.util.IntegrationTestRosterUtil; import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; +import org.junit.jupiter.api.Assertions; -@SpecificationReference(document = "XEP-0107", version = "1.2.1") public class MoodIntegrationTest extends AbstractSmackIntegrationTest { private final MoodManager mm1; @@ -79,10 +80,13 @@ public class MoodIntegrationTest extends AbstractSmackIntegrationTest { mm1.setMood(data); // for the purpose of this test, this needs not be blocking/use publishAndWait(); // Wait for the data to be received. - assertResult(moodReceived, "Expected " + conTwo.getUser() + " to receive a PEP notification, but did not."); + try { + moodReceived.waitForResult(timeout); + } catch (TimeoutException e) { + Assertions.fail("Expected to receive a PEP notification, but did not."); + } } finally { unregisterListener(mm2, moodListener); - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); } } @@ -115,10 +119,16 @@ public class MoodIntegrationTest extends AbstractSmackIntegrationTest { registerListenerAndWait(mm2, ServiceDiscoveryManager.getInstanceFor(conTwo), moodListener); // Wait for the data to be received. - assertResult(moodReceived, "Expected " + conTwo.getUser() + " to receive a PEP notification, but did not."); + try { + Object result = moodReceived.waitForResult(timeout); + + // Explicitly assert the success case. + Assertions.assertNotNull(result, "Expected to receive a PEP notification, but did not."); + } catch (TimeoutException e) { + Assertions.fail("Expected to receive a PEP notification, but did not."); + } } finally { unregisterListener(mm2, moodListener); - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/AbstractMultiUserChatIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/AbstractMultiUserChatIntegrationTest.java index 9465ef14a..5b2879c63 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/AbstractMultiUserChatIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/AbstractMultiUserChatIntegrationTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2021-2024 Florian Schmaus + * Copyright 2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,18 +18,10 @@ package org.jivesoftware.smackx.muc; import java.util.List; -import java.util.logging.Level; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.XMPPException.XMPPErrorException; -import org.jivesoftware.smack.packet.StanzaError; import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.muc.MultiUserChatException.MissingMucCreationAcknowledgeException; -import org.jivesoftware.smackx.muc.MultiUserChatException.MucAlreadyJoinedException; -import org.jivesoftware.smackx.muc.MultiUserChatException.NotAMucServiceException; -import org.jivesoftware.smackx.xdata.form.FillableForm; -import org.jivesoftware.smackx.xdata.form.Form; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; @@ -42,7 +34,7 @@ import org.jxmpp.jid.parts.Resourcepart; import org.jxmpp.stringprep.XmppStringprepException; -public abstract class AbstractMultiUserChatIntegrationTest extends AbstractSmackIntegrationTest { +public class AbstractMultiUserChatIntegrationTest extends AbstractSmackIntegrationTest { final String randomString = StringUtils.insecureRandomString(6); @@ -53,7 +45,7 @@ public abstract class AbstractMultiUserChatIntegrationTest extends AbstractSmack public AbstractMultiUserChatIntegrationTest(SmackIntegrationTestEnvironment environment) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, - InterruptedException, TestNotPossibleException, MucAlreadyJoinedException, MissingMucCreationAcknowledgeException, NotAMucServiceException, XmppStringprepException { + InterruptedException, TestNotPossibleException { super(environment); mucManagerOne = MultiUserChatManager.getInstanceFor(conOne); mucManagerTwo = MultiUserChatManager.getInstanceFor(conTwo); @@ -61,40 +53,10 @@ public abstract class AbstractMultiUserChatIntegrationTest extends AbstractSmack List services = mucManagerOne.getMucServiceDomains(); if (services.isEmpty()) { - throw new TestNotPossibleException("No MUC (XEP-0045) service found"); + throw new TestNotPossibleException("No MUC (XEP-45) service found"); } - DomainBareJid needle = null; - for (final DomainBareJid service : services) { - MultiUserChat multiUserChat = null; - try { - String roomNameLocal = String.join("-", "smack-inttest-abstract", testRunId, StringUtils.insecureRandomString(6)); - EntityBareJid mucAddress = JidCreate.entityBareFrom(Localpart.from(roomNameLocal), service.getDomain()); - multiUserChat = mucManagerOne.getMultiUserChat(mucAddress); - - createMuc(multiUserChat, "test"); - - needle = service; - break; - } catch (XMPPException.XMPPErrorException e) { - mucCreationDisallowedOrThrow(e); - LOGGER.log(Level.FINER, "MUC service " + service + " does not allow MUC creation", e); - } finally { - tryDestroy(multiUserChat); - } - } - - if (needle == null) { - throw new TestNotPossibleException("No MUC (XEP-0045) service found that allows test users to createa new room. Considered MUC services: " + services); - } - mucService = needle; - } - - static void mucCreationDisallowedOrThrow(XMPPException.XMPPErrorException e) throws XMPPErrorException { - StanzaError.Condition condition = e.getStanzaError().getCondition(); - if (condition == StanzaError.Condition.not_allowed) - return; - throw e; + mucService = services.get(0); } /** @@ -178,58 +140,4 @@ public abstract class AbstractMultiUserChatIntegrationTest extends AbstractSmack .makeHidden() .submitConfigurationForm(); } - - /** - * Creates a non-anonymous room. - * - *

    From XEP-0045 § 10.1.3:

    - *
    - * Note: The _whois configuration option specifies whether the room is non-anonymous (a value of "anyone"), - * semi-anonymous (a value of "moderators"), or fully anonymous (a value of "none", not shown here). - *
    - */ - static void createNonAnonymousMuc(MultiUserChat muc, Resourcepart resourceName) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, InterruptedException, MultiUserChatException.MucAlreadyJoinedException, SmackException.NotConnectedException, MultiUserChatException.MissingMucCreationAcknowledgeException, MultiUserChatException.NotAMucServiceException { - muc.create(resourceName); - Form configForm = muc.getConfigurationForm(); - FillableForm answerForm = configForm.getFillableForm(); - answerForm.setAnswer("muc#roomconfig_whois", "anyone"); - muc.sendConfigurationForm(answerForm); - } - - /** - * Creates a semi-anonymous room. - * - *

    From XEP-0045 § 10.1.3:

    - *
    - * Note: The _whois configuration option specifies whether the room is non-anonymous (a value of "anyone"), - * semi-anonymous (a value of "moderators"), or fully anonymous (a value of "none", not shown here). - *
    - */ - static void createSemiAnonymousMuc(MultiUserChat muc, Resourcepart resourceName) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, InterruptedException, MultiUserChatException.MucAlreadyJoinedException, SmackException.NotConnectedException, MultiUserChatException.MissingMucCreationAcknowledgeException, MultiUserChatException.NotAMucServiceException { - muc.create(resourceName); - Form configForm = muc.getConfigurationForm(); - FillableForm answerForm = configForm.getFillableForm(); - answerForm.setAnswer("muc#roomconfig_whois", "moderators"); - muc.sendConfigurationForm(answerForm); - } - - /** - * Creates a password-protected room. - */ - static void createPasswordProtectedMuc(MultiUserChat muc, Resourcepart resourceName, String password) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, InterruptedException, MultiUserChatException.MucAlreadyJoinedException, SmackException.NotConnectedException, MultiUserChatException.MissingMucCreationAcknowledgeException, MultiUserChatException.NotAMucServiceException { - muc.create(resourceName); - Form configForm = muc.getConfigurationForm(); - FillableForm answerForm = configForm.getFillableForm(); - answerForm.setAnswer("muc#roomconfig_passwordprotectedroom", true); - answerForm.setAnswer("muc#roomconfig_roomsecret", password); - muc.sendConfigurationForm(answerForm); - } - - static void setMaxUsers(MultiUserChat muc, int maxUsers) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, InterruptedException, SmackException.NotConnectedException { - Form configForm = muc.getConfigurationForm(); - FillableForm answerForm = configForm.getFillableForm(); - answerForm.setAnswer("muc#roomconfig_maxusers", maxUsers); - muc.sendConfigurationForm(answerForm); - } - } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatEntityIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatEntityIntegrationTest.java index aa30d5b78..279160c0f 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatEntityIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatEntityIntegrationTest.java @@ -22,7 +22,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.util.List; import java.util.Map; import org.jivesoftware.smack.SmackException; @@ -31,71 +30,55 @@ import org.jivesoftware.smack.packet.StanzaError; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; import org.jivesoftware.smackx.disco.packet.DiscoverItems; -import org.jivesoftware.smackx.muc.MultiUserChatException.MissingMucCreationAcknowledgeException; -import org.jivesoftware.smackx.muc.MultiUserChatException.MucAlreadyJoinedException; -import org.jivesoftware.smackx.muc.MultiUserChatException.NotAMucServiceException; -import org.jivesoftware.smackx.muc.packet.MUCInitialPresence; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; - -import org.jxmpp.jid.DomainBareJid; import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityFullJid; import org.jxmpp.jid.parts.Resourcepart; -import org.jxmpp.stringprep.XmppStringprepException; -@SpecificationReference(document = "XEP-0045", version = "1.34.6") public class MultiUserChatEntityIntegrationTest extends AbstractMultiUserChatIntegrationTest { public MultiUserChatEntityIntegrationTest(SmackIntegrationTestEnvironment environment) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, - SmackException.NotConnectedException, InterruptedException, TestNotPossibleException, MucAlreadyJoinedException, MissingMucCreationAcknowledgeException, NotAMucServiceException, XmppStringprepException { + SmackException.NotConnectedException, InterruptedException, TestNotPossibleException { super(environment); } /** - * Asserts that a MUC service can be discovered. + * Asserts that a MUC service can have its features discovered + * + *

    From XEP-0045 § 6.2:

    + *
    + * An entity may wish to discover if a service implements the Multi-User Chat protocol; in order to do so, it + * sends a service discovery information ("disco#info") query to the MUC service's JID. The service MUST return + * its identity and the features it supports. + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "6.1", quote = - "An entity often discovers a MUC service by sending a Service Discovery items (\"disco#items\") request to " + - "its own server. The server then returns the services that are associated with it.") - public void mucTestForDiscoveringMuc() throws Exception { - // This repeats some logic from the `AbstractMultiUserChatIntegrationTest` constructor, but is preserved here - // as an explicit test, because that might not always be true. - List services = ServiceDiscoveryManager.getInstanceFor(conOne).findServices(MUCInitialPresence.NAMESPACE, true, false); - assertFalse(services.isEmpty(), "Expected to be able to find MUC services on the domain that '" + conOne.getUser() + "' is connecting to (but could not)."); - } - - /** - * Asserts that a MUC service can have its features discovered. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "6.2", quote = - "An entity may wish to discover if a service implements the Multi-User Chat protocol; in order to do so, it " + - "sends a service discovery information (\"disco#info\") query to the MUC service's JID. The service MUST " + - "return its identity and the features it supports.") + @SmackIntegrationTest public void mucTestForDiscoveringFeatures() throws Exception { - DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(conOne).discoverInfo(mucService); - assertFalse(info.getIdentities().isEmpty(), "Expected the service discovery information for service " + mucService + " to include identities (but it did not)."); - assertFalse(info.getFeatures().isEmpty(), "Expected the service discovery information for service " + mucService + " to include features (but it did not)."); + DiscoverInfo info = mucManagerOne.getMucServiceDiscoInfo(mucManagerOne.getMucServiceDomains().get(0)); + assertTrue(info.getIdentities().size() > 0); + assertTrue(info.getFeatures().size() > 0); } /** * Asserts that a MUC Service lists its public rooms. * + *

    From XEP-0045 § 6.3:

    + *
    + * The service discovery items ("disco#items") protocol enables an entity to query a service for a list of + * associated items, which in the case of a chat service would consist of the specific chat rooms hosted by the + * service. The service SHOULD return a full list of the public rooms it hosts (i.e., not return any rooms that + * are hidden). + *
    + * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "6.3", quote = - "The service discovery items (\"disco#items\") protocol enables an entity to query a service for a list of " + - "associated items, which in the case of a chat service would consist of the specific chat rooms hosted by the" + - "service. The service SHOULD return a full list of the public rooms it hosts (i.e., not return any rooms that" + - "are hidden).") + @SmackIntegrationTest public void mucTestForDiscoveringRooms() throws Exception { EntityBareJid mucAddressPublic = getRandomRoom("smack-inttest-publicroom"); MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddressPublic); @@ -114,18 +97,22 @@ public class MultiUserChatEntityIntegrationTest extends AbstractMultiUserChatInt tryDestroy(mucAsSeenByTwo); } - assertTrue(rooms.containsKey(mucAddressPublic), "Expected the disco response from " + mucService + " to include the public room " + mucAddressPublic + " (but it did not)."); - assertFalse(rooms.containsKey(mucAddressHidden), "Expected the disco response from " + mucService + " to not include the hidden room " + mucAddressHidden + " (but it did)."); + assertTrue(rooms.containsKey(mucAddressPublic)); + assertFalse(rooms.containsKey(mucAddressHidden)); } /** * Asserts that a MUC Service returns disco info for a room. * + *

    From XEP-0045 § 6.4:

    + *
    + * Using the disco#info protocol, an entity may also query a specific chat room for more detailed information + * about the room....The room MUST return its identity and SHOULD return the features it supports + *
    + * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "6.4", quote = - "Using the disco#info protocol, an entity may also query a specific chat room for more detailed information " + - "about the room....The room MUST return its identity and SHOULD return the features it supports") + @SmackIntegrationTest public void mucTestForDiscoveringRoomInfo() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest-discoinfo"); MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); @@ -139,20 +126,23 @@ public class MultiUserChatEntityIntegrationTest extends AbstractMultiUserChatInt tryDestroy(mucAsSeenByOne); } - assertFalse(discoInfo.getIdentities().isEmpty(), "Expected the service discovery information for room " + mucAddress + " to include identities (but it did not)."); - assertFalse(discoInfo.getFeatures().isEmpty(), "Expected the service discovery information for room " + mucAddress + " to include features (but it did not)."); - assertTrue(discoInfo.getFeatures().stream().anyMatch(feature -> MultiUserChatConstants.NAMESPACE.equals(feature.getVar())), "Expected the service discovery information for room " + mucAddress + " to include the '" + MultiUserChatConstants.NAMESPACE + "' feature (but it did not)."); + assertTrue(discoInfo.getIdentities().size() > 0); + assertTrue(discoInfo.getFeatures().size() > 0); } /** * Asserts that a MUC Service returns disco info for a room's items. * + *

    From XEP-0045 § 6.5:

    + *
    + * An entity MAY also query a specific chat room for its associated items. An implementation MAY return a list + * of existing occupants if that information is publicly available, or return no list at all if this information is + * kept private. + *
    + * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "6.5", quote = - "An entity MAY also query a specific chat room for its associated items. An implementation MAY return a list " + - "of existing occupants if that information is publicly available, or return no list at all if this " + - "information is kept private.") + @SmackIntegrationTest public void mucTestForDiscoveringRoomItems() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest-discoitems"); MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); @@ -165,18 +155,22 @@ public class MultiUserChatEntityIntegrationTest extends AbstractMultiUserChatInt tryDestroy(mucAsSeenByOne); } - assertEquals(1, roomItems.getItems().size(), "Unexpected amount of disco items for " + mucAddress); + assertEquals(1, roomItems.getItems().size()); } /** * Asserts that a non-occupant receives a Bad Request error when attempting to query an occupant by their * occupant JID. * + *

    From XEP-0045 § 6.6:

    + *
    + * If a non-occupant attempts to send a disco request to an address of the form <room@service/nick>, a MUC service + * MUST return a <bad-request/> error + *
    + * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "6.6", quote = - "If a non-occupant attempts to send a disco request to an address of the form , a MUC " + - "service MUST return a error") + @SmackIntegrationTest public void mucTestForRejectingDiscoOnRoomOccupantByNonOccupant() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest-discoitems"); MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); @@ -192,8 +186,7 @@ public class MultiUserChatEntityIntegrationTest extends AbstractMultiUserChatInt XMPPException.XMPPErrorException xe; try { xe = assertThrows(XMPPException.XMPPErrorException.class, - () -> ServiceDiscoveryManager.getInstanceFor(conTwo).discoverItems(mucAsSeenByOneUserJid), - "Expected an XMPP error when " + conTwo.getUser() + " was trying to discover items of " + mucAsSeenByOneUserJid); + () -> ServiceDiscoveryManager.getInstanceFor(conTwo).discoverItems(mucAsSeenByOneUserJid)); } finally { tryDestroy(mucAsSeenByOne); } @@ -207,7 +200,6 @@ public class MultiUserChatEntityIntegrationTest extends AbstractMultiUserChatInt expectedCondition = StanzaError.Condition.not_acceptable; break; } - assertEquals(expectedCondition, xe.getStanzaError().getCondition(), - "Unexpected error condition in error returned when " + conTwo.getUser() + " was trying to discover items of " + mucAsSeenByOneUserJid); + assertEquals(xe.getStanzaError().getCondition(), expectedCondition); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatIntegrationTest.java index be59229c9..36fa47815 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatIntegrationTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015-2024 Florian Schmaus + * Copyright 2015-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,44 +17,100 @@ package org.jivesoftware.smackx.muc; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; -import java.util.Set; import java.util.concurrent.TimeoutException; import org.jivesoftware.smack.MessageListener; import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.SmackException.NoResponseException; -import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.StanzaError; -import org.jivesoftware.smackx.muc.MultiUserChatException.MissingMucCreationAcknowledgeException; -import org.jivesoftware.smackx.muc.MultiUserChatException.MucAlreadyJoinedException; -import org.jivesoftware.smackx.muc.MultiUserChatException.MucConfigurationNotSupportedException; -import org.jivesoftware.smackx.muc.MultiUserChatException.NotAMucServiceException; +import org.jivesoftware.smack.packet.Presence; + +import org.jivesoftware.smackx.muc.packet.MUCUser; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; +import org.igniterealtime.smack.inttest.util.ResultSyncPoint; import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.parts.Resourcepart; -import org.jxmpp.stringprep.XmppStringprepException; -@SpecificationReference(document = "XEP-0045", version = "1.34.6") public class MultiUserChatIntegrationTest extends AbstractMultiUserChatIntegrationTest { public MultiUserChatIntegrationTest(SmackIntegrationTestEnvironment environment) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, - InterruptedException, TestNotPossibleException, MucAlreadyJoinedException, MissingMucCreationAcknowledgeException, NotAMucServiceException, XmppStringprepException { + InterruptedException, TestNotPossibleException { super(environment); } + /** + * Asserts that when a user joins a room, they are themselves included on the list of users notified (self-presence). + * + *

    From XEP-0045 § 7.2.2:

    + *
    + * ...the service MUST also send presence from the new participant's occupant JID to the full JIDs of all the + * occupants (including the new occupant) + *
    + * + * @throws Exception when errors occur + */ + @SmackIntegrationTest + public void mucJoinTest() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest-join"); + + MultiUserChat muc = mucManagerOne.getMultiUserChat(mucAddress); + try { + Presence reflectedJoinPresence = muc.join(Resourcepart.from("nick-one")); + + MUCUser mucUser = MUCUser.from(reflectedJoinPresence); + + assertNotNull(mucUser); + assertTrue(mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110)); + assertEquals(mucAddress + "/nick-one", reflectedJoinPresence.getFrom().toString()); + assertEquals(conOne.getUser().asEntityFullJidIfPossible().toString(), reflectedJoinPresence.getTo().toString()); + } finally { + tryDestroy(muc); + } + } + + /** + * Asserts that when a user leaves a room, they are themselves included on the list of users notified (self-presence). + * + *

    From XEP-0045 § 7.14:

    + *
    + * The service MUST then send a presence stanzas of type "unavailable" from the departing user's occupant JID to + * the departing occupant's full JIDs, including a status code of "110" to indicate that this notification is + * "self-presence" + *
    + * + * @throws Exception when errors occur + */ + @SmackIntegrationTest + public void mucLeaveTest() throws Exception { + EntityBareJid mucAddress = getRandomRoom("smack-inttest-leave"); + + MultiUserChat muc = mucManagerOne.getMultiUserChat(mucAddress); + try { + muc.join(Resourcepart.from("nick-one")); + + Presence reflectedLeavePresence = muc.leave(); + + MUCUser mucUser = MUCUser.from(reflectedLeavePresence); + assertNotNull(mucUser); + + assertTrue(mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110)); + assertEquals(mucAddress + "/nick-one", reflectedLeavePresence.getFrom().toString()); + assertEquals(conOne.getUser().asEntityFullJidIfPossible().toString(), reflectedLeavePresence.getTo().toString()); + } finally { + muc.join(Resourcepart.from("nick-one")); // We need to be in the room to destroy the room + tryDestroy(muc); + } + } + @SmackIntegrationTest public void mucTest() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest-message"); @@ -63,14 +119,14 @@ public class MultiUserChatIntegrationTest extends AbstractMultiUserChatIntegrati MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); final String mucMessage = "Smack Integration Test MUC Test Message " + randomString; - final SimpleResultSyncPoint resultSyncPoint = new SimpleResultSyncPoint(); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); mucAsSeenByTwo.addMessageListener(new MessageListener() { @Override public void processMessage(Message message) { String body = message.getBody(); if (mucMessage.equals(body)) { - resultSyncPoint.signal(); + resultSyncPoint.signal(body); } } }); @@ -78,197 +134,63 @@ public class MultiUserChatIntegrationTest extends AbstractMultiUserChatIntegrati createMuc(mucAsSeenByOne, "one-" + randomString); mucAsSeenByTwo.join(Resourcepart.from("two-" + randomString)); mucAsSeenByOne.sendMessage(mucMessage); - try { - assertResult(resultSyncPoint, "Expected " + conTwo.getUser() + " to receive message that was sent by " + conOne.getUser() + " in room " + mucAddress + " (but it did not)."); + resultSyncPoint.waitForResult(timeout); + } catch (TimeoutException e) { + throw new AssertionError("Failed to receive presence", e); } finally { tryDestroy(mucAsSeenByOne); } } - /** - * Asserts that an owner is notified of room destruction when they destroy a room. + /** + * Asserts that a user is notified when a room is destroyed + * + *

    From XEP-0045 § 10.9:

    + *
    + * A room owner MUST be able to destroy a room, especially if the room is persistent... The room removes all users from the room... and destroys the room + *
    * * @throws TimeoutException when roomDestroyed event doesn't get fired * @throws Exception when other errors occur */ - @SmackIntegrationTest(section = "10.9", quote = - "A room owner MUST be able to destroy a room, especially if the room is persistent... The room removes all " + - "users from the room... and destroys the room") - public void mucDestroyOwnerTest() throws TimeoutException, Exception { + @SmackIntegrationTest + public void mucDestroyTest() throws TimeoutException, Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-destroy-owner"); + EntityBareJid mucAddress = getRandomRoom("smack-inttest-destroy"); MultiUserChat muc = mucManagerOne.getMultiUserChat(mucAddress); - createMuc(muc, Resourcepart.from("one-" + randomString)); - - // These would be a test implementation bug, not assertion failure. - if (!mucManagerOne.getJoinedRooms().contains(mucAddress)) { - tryDestroy(muc); - throw new IllegalStateException("Expected user to have joined a room '" + mucAddress + "' (but does not appear to have done so)."); - } + muc.join(Resourcepart.from("nick-one")); final SimpleResultSyncPoint mucDestroyed = new SimpleResultSyncPoint(); - UserStatusListener userStatusListener = new UserStatusListener() { + @SuppressWarnings("deprecation") + DefaultUserStatusListener userStatusListener = new DefaultUserStatusListener() { @Override - public void roomDestroyed(MultiUserChat alternateMUC, String password, String reason) { + public void roomDestroyed(MultiUserChat alternateMUC, String reason) { mucDestroyed.signal(); } }; muc.addUserStatusListener(userStatusListener); + assertEquals(1, mucManagerOne.getJoinedRooms().size()); + assertEquals(1, muc.getOccupantsCount()); + assertNotNull(muc.getNickname()); + try { muc.destroy("Dummy reason", null); - assertResult(mucDestroyed, "Expected " + conOne.getUser() + " to be notified of destruction of room " + mucAddress + " (but was not)."); + mucDestroyed.waitForResult(timeout); } finally { muc.removeUserStatusListener(userStatusListener); } - Set joinedRooms = mucManagerOne.getJoinedRooms(); - assertFalse(muc.isJoined(), "Expected " + conOne.getUser() + " to no longer be in room " + mucAddress + " after it was destroyed, but it is still in."); - assertEquals(0, joinedRooms.size(), "Expected " + conOne.getUser() + " to no longer be in any rooms after " + mucAddress + " was destroyed. But it is still in " + joinedRooms); - assertEquals(0, muc.getOccupantsCount(), "Expected room " + mucAddress + " to no longer have any occupants after it was destroyed (but it has)."); + assertEquals(0, mucManagerOne.getJoinedRooms().size()); + assertEquals(0, muc.getOccupantsCount()); assertNull(muc.getNickname()); } - /** - * Asserts that an occupant of a room is notified when a room is destroyed. - * - * @throws TimeoutException when roomDestroyed event doesn't get fired - * @throws Exception when other errors occur - */ - @SmackIntegrationTest(section = "10.9", quote = - "A room owner MUST be able to destroy a room, especially if the room is persistent... The room removes all " + - "users from the room... and destroys the room") - public void mucDestroyTestOccupant() throws TimeoutException, Exception { - - EntityBareJid mucAddress = getRandomRoom("smack-inttest-destroy-occupant"); - - MultiUserChat mucAsSeenByOwner = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByParticipant = mucManagerTwo.getMultiUserChat(mucAddress); - createMuc(mucAsSeenByOwner, Resourcepart.from("one-" + randomString)); - - // These would be a test implementation bug, not assertion failure. - mucAsSeenByParticipant.join(Resourcepart.from("two-" + randomString)); - if (!mucManagerTwo.getJoinedRooms().contains(mucAddress)) { - tryDestroy(mucAsSeenByOwner); - throw new IllegalStateException("Expected user to have joined a room '" + mucAddress + "' (but does not appear to have done so)."); - } - final SimpleResultSyncPoint mucDestroyed = new SimpleResultSyncPoint(); - - UserStatusListener userStatusListener = new UserStatusListener() { - @Override - public void roomDestroyed(MultiUserChat alternateMUC, String password, String reason) { - mucDestroyed.signal(); - } - }; - - mucAsSeenByParticipant.addUserStatusListener(userStatusListener); - - try { - mucAsSeenByOwner.destroy("Dummy reason", null); - assertResult(mucDestroyed, "Expected " + conTwo.getUser() + " to be notified of destruction of room " + mucAddress + " (but was not)."); - } finally { - mucAsSeenByParticipant.removeUserStatusListener(userStatusListener); - } - - Set joinedRooms = mucManagerTwo.getJoinedRooms(); - assertFalse(mucAsSeenByParticipant.isJoined(), "Expected " + conTwo.getUser() + " to no longer be in room " + mucAddress + " after it was destroyed, but it is still in."); - assertEquals(0, joinedRooms.size(), "Expected " + conTwo.getUser() + " to no longer be in any rooms after " + mucAddress + " was destroyed. But it is still in " + joinedRooms); - assertEquals(0, mucAsSeenByParticipant.getOccupantsCount(), "Expected room " + mucAddress + " to no longer have any occupants after it was destroyed (but it has)."); - assertNull(mucAsSeenByParticipant.getNickname()); - } - - @SmackIntegrationTest - public void mucNameChangeTest() - throws XmppStringprepException, MucAlreadyJoinedException, MissingMucCreationAcknowledgeException, - NotAMucServiceException, NoResponseException, XMPPErrorException, NotConnectedException, - InterruptedException, MucConfigurationNotSupportedException { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-muc-name-change"); - - MultiUserChat muc = mucManagerOne.getMultiUserChat(mucAddress); - createMuc(muc, Resourcepart.from("one-" + randomString)); - - final String newRoomName = "New Room Name (" + randomString + ")"; - - try { - muc.getConfigFormManager() - .setRoomName(newRoomName) - .submitConfigurationForm(); - - MultiUserChatManager mucManager = MultiUserChatManager.getInstanceFor(conTwo); - RoomInfo roomInfo = mucManager.getRoomInfo(muc.getRoom()); - assertEquals(newRoomName, roomInfo.getName()); - } finally { - tryDestroy(muc); - } - } - - @SmackIntegrationTest(section = "8.1", quote = "modify the subject [...] MUST be denied if the of the 'from' address of the request does not match " - + "the bare JID portion of one of the moderators; in this case, the service MUST return a error.") - public void mucTestVisitorNotAllowedToChangeSubject() throws XmppStringprepException, MucAlreadyJoinedException, - MissingMucCreationAcknowledgeException, NotAMucServiceException, NoResponseException, - XMPPErrorException, NotConnectedException, InterruptedException, TestNotPossibleException { - final EntityBareJid mucAddress = getRandomRoom("smack-inttest-visitor-change-subject"); - final MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - final MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - - createMuc(mucAsSeenByOne, nicknameOne); - try { - MucConfigFormManager configFormManager = mucAsSeenByOne.getConfigFormManager(); - if (configFormManager.occupantsAreAllowedToChangeSubject()) { - configFormManager.disallowOccupantsToChangeSubject().submitConfigurationForm(); - } - - mucAsSeenByTwo.join(nicknameTwo); - - final XMPPException.XMPPErrorException e = assertThrows(XMPPException.XMPPErrorException.class, () -> { - mucAsSeenByTwo.changeSubject("Test Subject Change"); - }, "Expected an error after '" + conTwo.getUser() - + "' (that is not a moderator) tried to change the subject of room '" + mucAddress - + "' (but none occurred)."); - assertEquals(StanzaError.Condition.forbidden, e.getStanzaError().getCondition(), - "Unexpected error condition in the (expected) error that was returned to '" - + conTwo.getUser() + "' after it tried to change to subject of room '" - + mucAddress + "' while not being a moderator."); - } catch (MucConfigurationNotSupportedException e) { - throw new TestNotPossibleException(e); - } finally { - tryDestroy(mucAsSeenByOne); - } - } - - @SmackIntegrationTest - public void mucTestChangeRoomName() throws XmppStringprepException, MucAlreadyJoinedException, - MissingMucCreationAcknowledgeException, NotAMucServiceException, NoResponseException, - XMPPErrorException, NotConnectedException, InterruptedException, TestNotPossibleException { - final EntityBareJid mucAddress = getRandomRoom("smack-inttest-change-room-name"); - final MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - - createMuc(mucAsSeenByOne, nicknameOne); - try { - String initialRoomName = "Initial Room Name"; - mucAsSeenByOne.getConfigFormManager().setRoomName(initialRoomName).submitConfigurationForm(); - RoomInfo roomInfo = mucManagerOne.getRoomInfo(mucAddress); - assertEquals(initialRoomName, roomInfo.getName()); - - String newRoomName = "New Room Name"; - mucAsSeenByOne.getConfigFormManager().setRoomName(newRoomName).submitConfigurationForm(); - roomInfo = mucManagerOne.getRoomInfo(mucAddress); - assertEquals(newRoomName, roomInfo.getName()); - } catch (MucConfigurationNotSupportedException e) { - throw new TestNotPossibleException(e); - } finally { - tryDestroy(mucAsSeenByOne); - } - } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatLowLevelIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatLowLevelIntegrationTest.java index e13384940..e0f476306 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatLowLevelIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatLowLevelIntegrationTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015-2024 Florian Schmaus + * Copyright 2015-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,16 +33,13 @@ import org.igniterealtime.smack.inttest.AbstractSmackLowLevelIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.jxmpp.jid.DomainBareJid; import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.jid.parts.Localpart; import org.jxmpp.jid.parts.Resourcepart; -@SpecificationReference(document = "XEP-0048", version = "1.2") public class MultiUserChatLowLevelIntegrationTest extends AbstractSmackLowLevelIntegrationTest { - @SuppressWarnings("this-escape") public MultiUserChatLowLevelIntegrationTest(SmackIntegrationTestEnvironment environment) throws Exception { super(environment); AbstractXMPPConnection connection = getConnectedConnection(); @@ -69,13 +66,7 @@ public class MultiUserChatLowLevelIntegrationTest extends AbstractSmackLowLevelI final MultiUserChat muc = multiUserChatManager.getMultiUserChat(JidCreate.entityBareFrom( Localpart.from(randomMucName), mucComponent)); - MucCreateConfigFormHandle handle; - try { - handle = muc.createOrJoin(mucNickname); - } catch (XMPPException.XMPPErrorException e) { - AbstractMultiUserChatIntegrationTest.mucCreationDisallowedOrThrow(e); - throw new TestNotPossibleException("MUC service " + mucComponent + " does not allow MUC creation", e); - } + MucCreateConfigFormHandle handle = muc.createOrJoin(mucNickname); if (handle != null) { handle.makeInstant(); } @@ -92,7 +83,7 @@ public class MultiUserChatLowLevelIntegrationTest extends AbstractSmackLowLevelI // So we trigger it manually here. MucBookmarkAutojoinManager.getInstanceFor(connection).autojoinBookmarkedConferences(); - assertTrue(muc.isJoined(), "Expected " + connection.getUser() + " to automatically join room " + muc.getRoom() + " after a reconnect, but it did not."); + assertTrue(muc.isJoined()); // If the test went well, leave the MUC muc.leave(); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatOccupantIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatOccupantIntegrationTest.java deleted file mode 100644 index 04ea0253c..000000000 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatOccupantIntegrationTest.java +++ /dev/null @@ -1,1118 +0,0 @@ -/** - * - * Copyright 2015-2024 Florian Schmaus, 2021 Dan Caseley - * - * 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.smackx.muc; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeoutException; -import java.util.stream.Collectors; - -import org.jivesoftware.smack.PresenceListener; -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.StanzaListener; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.filter.FromMatchesFilter; -import org.jivesoftware.smack.packet.Message; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.packet.Stanza; -import org.jivesoftware.smack.packet.StanzaError; -import org.jivesoftware.smack.sm.predicates.ForEveryMessage; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.muc.MultiUserChatException.MissingMucCreationAcknowledgeException; -import org.jivesoftware.smackx.muc.MultiUserChatException.MucAlreadyJoinedException; -import org.jivesoftware.smackx.muc.MultiUserChatException.MucConfigurationNotSupportedException; -import org.jivesoftware.smackx.muc.MultiUserChatException.NotAMucServiceException; -import org.jivesoftware.smackx.muc.packet.MUCItem; -import org.jivesoftware.smackx.muc.packet.MUCUser; - -import org.igniterealtime.smack.inttest.Configuration; -import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; -import org.igniterealtime.smack.inttest.TestNotPossibleException; -import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; -import org.igniterealtime.smack.inttest.util.MultiResultSyncPoint; -import org.igniterealtime.smack.inttest.util.ResultSyncPoint; -import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; -import org.jxmpp.jid.EntityBareJid; -import org.jxmpp.jid.impl.JidCreate; -import org.jxmpp.jid.parts.Resourcepart; -import org.jxmpp.stringprep.XmppStringprepException; - -@SpecificationReference(document = "XEP-0045", version = "1.34.6") -public class MultiUserChatOccupantIntegrationTest extends AbstractMultiUserChatIntegrationTest { - - public MultiUserChatOccupantIntegrationTest(SmackIntegrationTestEnvironment environment) - throws SmackException.NoResponseException, XMPPException.XMPPErrorException, - SmackException.NotConnectedException, InterruptedException, TestNotPossibleException, MucAlreadyJoinedException, MissingMucCreationAcknowledgeException, NotAMucServiceException, XmppStringprepException { - super(environment); - } - - /** - * Asserts that when a user joins a room, all events are received, and in the correct order. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.1 & 7.2.2", quote = "" + - "§ 7.1 The order of events involved in joining a room needs to be consistent so that clients can know which events to expect when. After a client sends presence to join a room, the MUC service MUST send it events in the following order: 1. In-room presence from other occupants 2. In-room presence from the joining entity itself (so-called \"self-presence\") 3. Room history (if any) 4. The room subject [...]" + - "§ 7.2.2 This self-presence MUST NOT be sent to the new occupant until the room has sent the presence of all other occupants to the new occupant ... The service MUST first send the complete list of the existing occupants to the new occupant and only then send the new occupant's own presence to the new occupant") - public void mucJoinEventOrderingTest() throws Exception { - // This implementation deliberately does not use Smack's MUC API when trying to collect the order in which - // stanzas arrive. Instead, it joins a chatroom and listens for its stanzas using basic stanza handling. As - // this uses exactly one stanza listener, that's guaranteed to be invoked in order of stanza arrival, which is - // not necessarily the case when using the MUC API. - EntityBareJid mucAddress = getRandomRoom("smack-inttest-eventordering"); - final String mucSubject = "Subject smack-inttest-eventordering " + randomString; - final String mucMessage = "Message smack-inttest-eventordering " + randomString; - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - - createMuc(mucAsSeenByOne, nicknameOne); - mucAsSeenByOne.changeSubject(mucSubject); // Blocks until confirmed. - - // Send and wait for the message to have been reflected, so that we can be sure it's part of the MUC history. - final SimpleResultSyncPoint messageReflectionSyncPoint = new SimpleResultSyncPoint(); - mucAsSeenByOne.addMessageListener(message -> { - String body = message.getBody(); - if (body == null) return; - - if (body.equals(mucMessage)) { - messageReflectionSyncPoint.signal(); - } - }); - - mucAsSeenByOne.sendMessage(mucMessage); - messageReflectionSyncPoint.waitForResult(timeout); - - final ResultSyncPoint subjectResultSyncPoint = new ResultSyncPoint<>(); - final List results = new ArrayList<>(); - final StanzaListener stanzaListener = stanza -> { - results.add(stanza); - if (stanza instanceof Message && ((Message) stanza).getSubject() != null) { - subjectResultSyncPoint.signal(((Message) stanza).getSubject()); - } - }; - conTwo.addStanzaListener(stanzaListener, FromMatchesFilter.create(mucAddress)); - - try { - mucAsSeenByTwo.join(nicknameTwo); - - subjectResultSyncPoint.waitForResult(timeout); // Wait for subject, as it should be 4th (last) - - assertEquals(4, results.size(), "Unexpected amount of stanzas received by '" + conTwo.getUser() + "' after it joined room '" + mucAddress + "'."); - assertTrue(results.get(0) instanceof Presence, "Expected the first stanza that was received by '" + conTwo.getUser() + "' after it joined room '" + mucAddress + "' to be a presence stanza (but it was not)."); - assertEquals(JidCreate.fullFrom(mucAddress, nicknameOne), results.get(0).getFrom(), "Unexpected 'from' address of the first stanza that was received by '" + conTwo.getUser() + "' after it joined room '" + mucAddress + "'."); - assertTrue(results.get(1) instanceof Presence, "Expected the second stanza that was received by '" + conTwo.getUser() + "' after it joined room '" + mucAddress + "' to be a presence stanza (but it was not)."); - assertEquals(JidCreate.fullFrom(mucAddress, nicknameTwo), results.get(1).getFrom(), "Unexpected 'from' address of the seconds stanza that was received by '" + conTwo.getUser() + "' after it joined room '" + mucAddress + "'."); - assertTrue(results.get(2) instanceof Message, "Expected the third stanza that was received by '" + conTwo.getUser() + "' after it joined room '" + mucAddress + "' to be a message stanza (but it was not)."); - assertEquals(mucMessage, ((Message) results.get(2)).getBody(), "The third stanza that was received by '" + conTwo.getUser() + "' after it joined room '" + mucAddress + "' was expected to be a different stanza."); - assertTrue(results.get(3) instanceof Message, "Expected the fourth stanza that was received by '" + conTwo.getUser() + "' after it joined room '" + mucAddress + "' to be a message stanza (but it was not)."); - assertEquals(mucSubject, ((Message) results.get(3)).getSubject(), "The fourth stanza that was received by '" + conTwo.getUser() + "' after it joined room '" + mucAddress + "' was expected to be a different stanza."); - } finally { - tryDestroy(mucAsSeenByOne); - conTwo.removeStanzaListener(stanzaListener); - } - } - - /** - * Asserts that when a user sends a message to a room without joining, they receive an error and the message is not - * sent to the occupants. - * - *

    From XEP-0045 § 7.2.1:

    - *
    - * In order to participate in the discussions held in a multi-user chat room, a user MUST first become an occupant - * by entering the room - *
    - * - *

    From XEP-0045 § 7.4:

    - *
    - * If the sender is not an occupant of the room, the service SHOULD return a <not-acceptable/> error to the - * sender and SHOULD NOT reflect the message to all occupants - *
    - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.1 & 7.4", quote = - "§ 7.2.1: In order to participate in the discussions held in a multi-user chat room, a user MUST first become an occupant by entering the room [...] " + - "§ 7.4: If the sender is not an occupant of the room, the service SHOULD return a error to the sender and SHOULD NOT reflect the message to all occupants") - public void mucSendBeforeJoiningTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-send-without-joining"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - createMuc(mucAsSeenByOne, Resourcepart.from("one-" + randomString)); - - ResultSyncPoint errorMessageResultSyncPoint = new ResultSyncPoint<>(); - conTwo.addStanzaListener(packet -> errorMessageResultSyncPoint.signal((Message) packet), ForEveryMessage.INSTANCE); - - ResultSyncPoint distributedMessageResultSyncPoint = new ResultSyncPoint<>(); - mucAsSeenByOne.addMessageListener(distributedMessageResultSyncPoint::signal); - - try { - mucAsSeenByTwo.sendMessage("Message without Joining"); - Message response = assertResult(errorMessageResultSyncPoint, "Expected an error to be returned to '" + conTwo.getUser() + "' after it sent a message to room '" + mucAddress + "' without joining it first (but no error was returned)."); - assertEquals(StanzaError.Condition.not_acceptable, response.getError().getCondition(), "Unexpected error condition in the (expected) error that was returned to '" + conTwo.getUser() + "' after it sent a message to room '" + mucAddress + "' without joining it first."); - assertThrows(TimeoutException.class, () -> distributedMessageResultSyncPoint.waitForResult(1000), "Occupant '" + conOne.getUser() + "' should NOT have seen the message that was sent by '" + conTwo.getUser() + "' to room '" + mucAddress + "' without the sender have joined the room (but the message was observed by the occupant)."); - } finally { - tryDestroy(mucAsSeenByOne); - } - } - - /** - * Asserts that when a user joins a room, they are sent presence information about existing participants and - * themselves that includes role and affiliation information and appropriate status codes. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.2", quote = - "If the service is able to add the user to the room, it MUST send presence from all the existing participants' " + - "occupant JIDs to the new occupant's full JID, including extended presence information about roles in a " + - "single element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an " + - " child with the 'role' attribute set to a value of \"moderator\", \"participant\", or \"visitor\", " + - "and with the 'affiliation' attribute set to a value of \"owner\", \"admin\", \"member\", or \"none\" as " + - "appropriate. [...] the \"self-presence\" sent by the room to the new user MUST include a status code of 110 " + - "so that the user knows this presence refers to itself as an occupant [...] The service MUST first send the " + - "complete list of the existing occupants to the new occupant and only then send the new occupant's own " + - "presence to the new occupant.") - public void mucJoinPresenceInformationTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-presenceinfo"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); - - createMuc(mucAsSeenByOne, nicknameOne); - SimpleResultSyncPoint oneSeesTwo = new SimpleResultSyncPoint(); - mucAsSeenByOne.addParticipantListener(presence -> { - if (nicknameTwo.equals(presence.getFrom().getResourceOrEmpty())) { - oneSeesTwo.signal(); - } - }); - mucAsSeenByTwo.join(nicknameTwo); - oneSeesTwo.waitForResult(timeout); - mucAsSeenByOne.grantModerator(nicknameTwo); - - List results = new ArrayList<>(); - mucAsSeenByThree.addParticipantListener(results::add); - - try { - // Will block until all self-presence is received, prior to which all others presences will have been received. - mucAsSeenByThree.join(nicknameThree); - - assertEquals(3, results.size(), "Unexpected amount of occupants seen by '" + conThree + "' in room '" + mucAddress + "' after joining."); // The 3rd will be self-presence. - assertNotNull(MUCUser.from(results.get(0)), "Expected to be able to parse a MUC occupant from '" + results.get(0) + "', but could not. Its syntax is likely incorrect."); // Smack implementation guarantees the "x" element and muc#user namespace - - // The order of all but the last presence (which should be the self-presence) is unpredictable. - MUCItem mucItemSelf = MUCUser.from(results.get(2)).getItem(); - Set others = new HashSet<>(); - others.add(MUCUser.from(results.get(0)).getItem()); - others.add(MUCUser.from(results.get(1)).getItem()); - - assertEquals(MUCAffiliation.none, mucItemSelf.getAffiliation(), "Unexpected MUC affiliation in reflected self-presence of '" + conThree.getUser() + "' joining room '" + mucAddress + "'."); - assertEquals(1, others.stream().filter(item -> MUCAffiliation.owner.equals(item.getAffiliation())).count(), "Unexpected amount of other occupants in room '" + mucAddress + "' (as observed by '" + conThree.getUser() + "') that have the 'owner' affiliation."); - assertEquals(1, others.stream().filter(item -> MUCAffiliation.none.equals(item.getAffiliation())).count(), "Unexpected amount of other occupants in room '" + mucAddress + "' (as observed by '" + conThree.getUser() + "') that have no affiliation."); - - assertEquals(MUCRole.participant, mucItemSelf.getRole(), "Unexpected MUC role in reflected self-presence of '" + conThree.getUser() + "' joining room '" + mucAddress + "'."); - assertEquals(2, others.stream().filter(item -> MUCRole.moderator.equals(item.getRole())).count(), "Unexpected amount of other occupants in room '" + mucAddress + "' (as observed by '" + conThree.getUser() + "') that have the 'moderator' role."); - - assertTrue(MUCUser.from(results.get(2)).getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110), "Expected to find status '" + MUCUser.Status.PRESENCE_TO_SELF_110 + "' in reflected self-presence of '" + conThree.getUser() + "' joining room '" + mucAddress + "' (but did not)."); - } finally { - tryDestroy(mucAsSeenByOne); - } - } - - /** - * Asserts that when a user joins a room, all users are sent presence information about the new participant. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.2", quote = - "the service MUST also send presence from the new participant's occupant JID to the full JIDs of all the " + - "occupants (including the new occupant)") - public void mucJoinPresenceBroadcastTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-presenceinfo"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); - - createMuc(mucAsSeenByOne, nicknameOne); - mucAsSeenByTwo.join(nicknameTwo); - - final MultiResultSyncPoint syncPoint = new MultiResultSyncPoint<>(2); - - mucAsSeenByOne.addParticipantListener(presence -> { - if (nicknameThree.equals(presence.getFrom().getResourceOrEmpty())) { - syncPoint.signal(presence); - } - }); - - mucAsSeenByTwo.addParticipantListener(presence -> { - if (nicknameThree.equals(presence.getFrom().getResourceOrEmpty())) { - syncPoint.signal(presence); - } - }); - - try { - mucAsSeenByThree.join(nicknameThree); - - List results = assertResult(syncPoint, "Expected all occupants of room '" + mucAddress + "' to be notified of '" + conThree.getUser() + "' using nickname '" + nicknameThree + "' joining the room (but one or more did not get notified)"); - assertTrue(results.stream().allMatch( - result -> JidCreate.fullFrom(mucAddress, nicknameThree).equals(result.getFrom())), - "Expected all occupants of room '" + mucAddress + "' to be notified of '" + conThree.getUser() + "' using nickname '" + nicknameThree + "' joining the room (but one or more got notified for a different user)."); - assertTrue(results.stream().anyMatch( - result -> result.getTo().equals(conOne.getUser().asEntityFullJidIfPossible())), - "Expected '" + conOne.getUser().asEntityFullJidIfPossible() + "' to be notified of '" + conThree.getUser() + "' joining room '" + mucAddress + "' (but did not)"); - assertTrue(results.stream().anyMatch( - result -> result.getTo().equals(conTwo.getUser().asEntityFullJidIfPossible())), - "Expected '" + conTwo.getUser().asEntityFullJidIfPossible() + "' to be notified of '" + conThree.getUser() + "' joining room '" + mucAddress + "' (but did not)"); - } finally { - tryDestroy(mucAsSeenByOne); - } - } - - /** - * Asserts that when a user enters a non-anonymous room, the presence notifications contain extended presence - * information. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.3", quote = - "If the room is non-anonymous, the service MUST send the new occupant's full JID to all occupants using " + - "extended presence information in an element qualified by the 'http://jabber.org/protocol/muc#user' " + - "namespace and containing an child with a 'jid' attribute specifying the occupant's full JID. [...]" + - "If the user is entering a room that is non-anonymous (i.e., which informs all occupants of each occupant's " + - "full JID as shown above), the service MUST warn the user by including a status code of \"100\" in the " + - "initial presence that the room sends to the new occupant.") - public void mucJoinNonAnonymousRoomTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-joinnonanonymousroom"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - - createNonAnonymousMuc(mucAsSeenByOne, nicknameOne); - - final ResultSyncPoint participantOneSyncPoint = new ResultSyncPoint<>(); - mucAsSeenByOne.addParticipantListener(presence -> { - if (nicknameTwo.equals(presence.getFrom().getResourceOrEmpty())) { - participantOneSyncPoint.signal(presence); - } - }); - - final ResultSyncPoint participantTwoSyncPoint = new ResultSyncPoint<>(); - mucAsSeenByTwo.addParticipantListener(presence -> { - if (nicknameTwo.equals(presence.getFrom().getResourceOrEmpty())) { - participantTwoSyncPoint.signal(presence); - } - }); - - try { - mucAsSeenByTwo.join(nicknameTwo); - Presence presenceReceivedByOne = assertResult(participantOneSyncPoint, "Expected '" + conOne.getUser() + "' to receive a presence stanza after '" + conTwo.getUser() + "' joined room '" + mucAddress + "' (but did not)."); - Presence presenceReceivedByTwo = assertResult(participantTwoSyncPoint, "Expected '" + conTwo.getUser() + "' to receive a presence stanza after they themselves joined room '" + mucAddress + "' (but did not)."); - - // Check the presence received by participant one for inclusion of full jid of participant two - MUCUser announcedParticipantTwoUser = MUCUser.from(presenceReceivedByOne); - assertNotNull(announcedParticipantTwoUser, "Expected to be able to parse a MUC occupant from '" + presenceReceivedByOne + "', but could not. Its syntax is likely incorrect."); // Smack implementation guarantees the "x" element and muc#user namespace - assertNotNull(announcedParticipantTwoUser.getItem(), "Expected to be able to parse a MUC occupant item from '" + presenceReceivedByOne + "', but could not. Its syntax is likely incorrect."); - assertEquals(conTwo.getUser().asEntityFullJidOrThrow(), announcedParticipantTwoUser.getItem().getJid(), "Expected extended presence information received by '" + conOne.getUser() + "' after '" + conTwo.getUser() + "' joined room '" + mucAddress + "' to include their full JID."); - - // Check the presence received by participant two for inclusion of status 100 - assertTrue(MUCUser.from(presenceReceivedByTwo).getStatus().stream().anyMatch(status -> 100 == status.getCode()), - "Expected to find status '100' in reflected self-presence of '" + conTwo.getUser() + "' joining room '" + mucAddress + "' (but did not)."); - - } finally { - tryDestroy(mucAsSeenByOne); - } - } - - /** - * Asserts that when a user enters a semi-anonymous room, the presence notifications received by occupants that - * are not a moderator does not contain extended presence information. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.4", quote = - "If the room is semi-anonymous, the service MUST send presence from the new occupant to all occupants as " + - "specified above (i.e., unless the room is configured to not broadcast presence from new occupants below a " + - "certain affiliation level as controlled by the \"muc#roomconfig_presencebroadcast\" room configuration " + - "option), but MUST include the new occupant's full JID only in the presence notifications it sends to " + - "occupants with a role of \"moderator\" and not to non-moderator occupants.") - public void mucJoinSemiAnonymousRoomReceivedByNonModeratorTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-seminanonymous-by-non-moderator"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); - - createSemiAnonymousMuc(mucAsSeenByOne, nicknameOne); - - mucAsSeenByTwo.join(nicknameTwo); - - // First pass: participant two is not a moderator yet - final ResultSyncPoint participantTwoSyncPoint = new ResultSyncPoint<>(); - mucAsSeenByTwo.addParticipantListener(presence -> { - if (nicknameThree.equals(presence.getFrom().getResourceOrEmpty())) { - participantTwoSyncPoint.signal(presence); - } - }); - - try { - mucAsSeenByThree.join(nicknameThree); - Presence presenceReceivedByTwo = assertResult(participantTwoSyncPoint, "Expected '" + conTwo.getUser() + "' to receive presence when '" + conThree.getUser() + "' joined room '" + mucAddress + "' (but did not)."); - - // Check the presence received by participant two for exclusion of full jid of participant three - assertNull(MUCUser.from(presenceReceivedByTwo).getItem().getJid(), "Did not expect '" + conTwo.getUser() + "' (who is not a moderator at this stage) to receive the full JID of '" + conThree.getUser() + "' when they joined room '" + mucAddress + "' (but they did)."); - } finally { - tryDestroy(mucAsSeenByOne); - } - } - - /** - * Asserts that when a user enters a semi-anonymous room, the presence notifications contain extended presence - * information when sent to moderators. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.4", quote = - "If the room is semi-anonymous, the service MUST send presence from the new occupant to all occupants as " + - "specified above (i.e., unless the room is configured to not broadcast presence from new occupants below a " + - "certain affiliation level as controlled by the \"muc#roomconfig_presencebroadcast\" room configuration " + - "option), but MUST include the new occupant's full JID only in the presence notifications it sends to " + - "occupants with a role of \"moderator\" and not to non-moderator occupants.") - public void mucJoinSemiAnonymousRoomReceivedByModeratorTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-seminanonymous-by-moderator"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); - - // Second pass: participant two is now a moderator - createSemiAnonymousMuc(mucAsSeenByOne, nicknameOne); - mucAsSeenByTwo.join(nicknameTwo); - - mucAsSeenByOne.grantModerator(nicknameTwo); - final ResultSyncPoint participantTwoSyncPoint = new ResultSyncPoint<>(); - mucAsSeenByTwo.addParticipantListener(presence -> { - if (nicknameThree.equals(presence.getFrom().getResourceOrEmpty())) { - participantTwoSyncPoint.signal(presence); - } - }); - - try { - mucAsSeenByThree.join(nicknameThree); - Presence presenceReceivedByTwo = assertResult(participantTwoSyncPoint, "Expected '" + conTwo.getUser() + "' to receive presence when '" + conThree.getUser() + "' joined room '" + mucAddress + "' (but did not)."); - - // Check the presence received by participant two for inclusion of full jid of participant three - MUCUser announcedParticipantThreeUser = MUCUser.from(presenceReceivedByTwo); - assertEquals(conThree.getUser().asEntityFullJidOrThrow(), announcedParticipantThreeUser.getItem().getJid(), "Expected '" + conTwo.getUser() + "' (who is a moderator at this stage) to receive the full JID of '" + conThree.getUser() + "' when they joined room '" + mucAddress + "' (but they did not)."); - } finally { - tryDestroy(mucAsSeenByOne); - } - } - - /** - * Asserts that a user can not enter a password-protected room without supplying a password. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.5", quote = - "If the room requires a password and the user did not supply one (or the password provided is incorrect), the " + - "service MUST deny access to the room and inform the user that they are unauthorized; this is done by returning " + - "a presence stanza of type \"error\" specifying a error.") - public void mucJoinPasswordProtectedWithoutPasswordRoomTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-enterpasswordprotectedroom"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - - final String correctPassword = StringUtils.insecureRandomString(8); - - createPasswordProtectedMuc(mucAsSeenByOne, nicknameOne, correctPassword); - - try { - // First try: no password - XMPPException.XMPPErrorException noPasswordErrorException = assertThrows( - XMPPException.XMPPErrorException.class, () -> mucAsSeenByTwo.join(nicknameTwo), - "Expected an error to be returned when '" + conTwo.getUser() + "' attempted to join password-protected room '" + mucAddress + "' without a password."); - assertNotNull(noPasswordErrorException.getStanzaError(), - "Expected an error to be returned when '" + conTwo.getUser() + "' attempted to join password-protected room '" + mucAddress + "' without a password."); - assertEquals(StanzaError.Condition.not_authorized, noPasswordErrorException.getStanzaError().getCondition(), - "Unexpected condition in the (expected) error that was returned when '" + conTwo.getUser() + "' attempted to join password-protected room '" + mucAddress + "' without a password."); - } finally { - mucAsSeenByOne.destroy(); - } - } - - /** - * Asserts that a user can not enter a password-protected room without supplying the correct password. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.5", quote = - "If the room requires a password and the user did not supply one (or the password provided is incorrect), the " + - "service MUST deny access to the room and inform the user that they are unauthorized; this is done by returning " + - "a presence stanza of type \"error\" specifying a error.") - public void mucJoinPasswordProtectedRoomWrongPasswordTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-enterpasswordprotectedroom"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - - final String correctPassword = StringUtils.insecureRandomString(8); - - createPasswordProtectedMuc(mucAsSeenByOne, nicknameOne, correctPassword); - - try { - // Second try: wrong password - XMPPException.XMPPErrorException wrongPasswordErrorException = assertThrows( - XMPPException.XMPPErrorException.class, - () -> mucAsSeenByTwo.join(nicknameTwo, correctPassword + "_"), - "Expected an error to be returned when '" + conTwo.getUser() + "' attempted to join password-protected room '" + mucAddress + "' using an incorrect password."); - assertNotNull(wrongPasswordErrorException.getStanzaError(), - "Expected an error to be returned when '" + conTwo.getUser() + "' attempted to join password-protected room '" + mucAddress + "' using an incorrect password."); - assertEquals(StanzaError.Condition.not_authorized, wrongPasswordErrorException.getStanzaError().getCondition(), - "Unexpected condition in the (expected) error that was returned when '" + conTwo.getUser() + "' attempted to join password-protected room '" + mucAddress + "' using an incorrect password."); - } finally { - mucAsSeenByOne.destroy(); - } - } - - /** - * Asserts that a user can enter a password-protected room when supplying the correct password. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.5", quote = - "If the room requires a password and the user did not supply one (or the password provided is incorrect), the " + - "service MUST deny access to the room and inform the user that they are unauthorized; this is done by returning " + - "a presence stanza of type \"error\" specifying a error.") - public void mucJoinPasswordProtectedRoomCorrectPasswordTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-enterpasswordprotectedroom"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - - final String correctPassword = StringUtils.insecureRandomString(8); - - createPasswordProtectedMuc(mucAsSeenByOne, nicknameOne, correctPassword); - - // Set up to receive presence responses on successful join - final ResultSyncPoint participantTwoSyncPoint = new ResultSyncPoint<>(); - mucAsSeenByTwo.addParticipantListener(presence -> { - if (nicknameTwo.equals(presence.getFrom().getResourceOrEmpty())) { - participantTwoSyncPoint.signal(presence); - } - }); - - try { - // Third try: correct password - mucAsSeenByTwo.join(nicknameTwo, correctPassword); - Presence presenceCorrectPassword = assertResult(participantTwoSyncPoint, "Expected '" + conTwo.getUser() + "' to be able to join password-protected room '" + mucAddress + "' using the correct password (but no join-presence was received)."); - assertNull(presenceCorrectPassword.getError(), "Unexpected error in join-presence of '" + conTwo.getUser() + "' after joining password-protected room '" + mucAddress + "' using the correct password: " + presenceCorrectPassword.getError()); - } finally { - mucAsSeenByOne.destroy(); - } - } - - /** - * Asserts that a user can not enter a members-only room while not being a member. - * - * This test does not cover § 9.3, aka the happy path. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.6", quote = - "If the room is members-only but the user is not on the member list, the service MUST deny access to the " + - "room and inform the user that they are not allowed to enter the room; this is done by returning a presence " + - "stanza of type \"error\" specifying a error condition.") - public void mucJoinMembersOnlyRoomTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-entermembersonlyroom"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - - createMembersOnlyMuc(mucAsSeenByOne, nicknameOne); - - try { - XMPPException.XMPPErrorException registrationRequiredErrorException = assertThrows( - XMPPException.XMPPErrorException.class, () -> mucAsSeenByTwo.join(nicknameTwo), - "Expected an error to be returned when non-member '" + conTwo.getUser() + "' tries to join member-online room '" + mucAddress + "' (but an error was not returned)."); - assertNotNull(registrationRequiredErrorException, "Expected an error to be returned when non-member '" + conTwo.getUser() + "' tries to join member-online room '" + mucAddress + "' (but an error was not returned)."); - assertNotNull(registrationRequiredErrorException.getStanzaError(), "Expected an error to be returned when non-member '" + conTwo.getUser() + "' tries to join member-online room '" + mucAddress + "' (but an error was not returned)."); - assertEquals(StanzaError.Condition.registration_required, registrationRequiredErrorException.getStanzaError().getCondition(), - "Unexpected condition in the (expected) error that was returned when non-member '" + conTwo.getUser() + "' joined member-online room '" + mucAddress + "' (."); - } finally { - mucAsSeenByOne.destroy(); - } - } - - /** - * Asserts that a user can not enter a room while being banned. - * - *

    From XEP-0045 § 7.2.7:

    - *
    - * - *
    - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.7", quote = - "If the user has been banned from the room (i.e., has an affiliation of \"outcast\"), the service MUST deny " + - "access to the room and inform the user of the fact that they are banned; this is done by returning a presence " + - "stanza of type \"error\" specifying a error condition.") - public void mucBannedUserJoinRoomTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-banneduser"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - - createMuc(mucAsSeenByOne, nicknameOne); - - mucAsSeenByOne.banUser(conTwo.getUser().asBareJid(), "Insufficient witchcraft"); - - try { - XMPPException.XMPPErrorException forbiddenErrorException = assertThrows( - XMPPException.XMPPErrorException.class, () -> mucAsSeenByTwo.join(nicknameTwo), - "Expected an error to be returned when outcast '" + conTwo.getUser() + "' tries to join room '" + mucAddress + "' (but an error was not returned)."); - assertNotNull(forbiddenErrorException, "Expected an error to be returned when outcast '" + conTwo.getUser() + "' tries to join room '" + mucAddress + "' (but an error was not returned)."); - assertNotNull(forbiddenErrorException.getStanzaError(), "Expected an error to be returned when outcast '" + conTwo.getUser() + "' tries to join room '" + mucAddress + "' (but an error was not returned)."); - assertEquals(StanzaError.Condition.forbidden, forbiddenErrorException.getStanzaError().getCondition(), - "Unexpected condition in the (expected) error to was returned when outcast '" + conTwo.getUser() + "' tried to join room '" + mucAddress + "'."); - } finally { - mucAsSeenByOne.destroy(); - } - } - - /** - * Asserts that a user can not enter a room with the same nickname as another user who is already present. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.8", quote = - "If the room already contains another user with the nickname desired by the user seeking to enter the room " + - "(or if the nickname is reserved by another user on the member list), the service MUST deny access to the " + - "room and inform the user of the conflict; this is done by returning a presence stanza of type \"error\" " + - "specifying a error condition.") - public void mucNicknameConflictJoinRoomTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-nicknameclash"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - - createMuc(mucAsSeenByOne, nicknameOne); - - try { - XMPPException.XMPPErrorException conflictErrorException = assertThrows( - XMPPException.XMPPErrorException.class, () -> mucAsSeenByTwo.join(nicknameOne), - "Expected an error to be returned when '" + conTwo.getUser() + "' tried to join room '" + mucAddress + "' using the nickname '" + nicknameOne + "' that was already in used by another occupant of the room (but an error was not returned)."); - assertNotNull(conflictErrorException, "Expected an error to be returned when '" + conTwo.getUser() + "' tried to join room '" + mucAddress + "' using the nickname '" + nicknameOne + "' that was already in used by another occupant of the room (but an error was not returned)."); - assertNotNull(conflictErrorException.getStanzaError(), "Expected an error to be returned when '" + conTwo.getUser() + "' tried to join room '" + mucAddress + "' using the nickname '" + nicknameOne + "' that was already in used by another occupant of the room (but an error was not returned)."); - assertEquals(StanzaError.Condition.conflict, conflictErrorException.getStanzaError().getCondition(), - "Unexpected condition in the (expected) error that was returned when '" + conTwo.getUser() + "' tried to join room '" + mucAddress + "' using the nickname '" + nicknameOne + "' that was already in used by another occupant of the room."); - } finally { - mucAsSeenByOne.destroy(); - } - } - - /** - * Asserts that a room can not go past the configured maximum number of users, if a non-admin non-owner user - * attempts to join. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.9", quote = - "If the room has reached its maximum number of occupants, the service SHOULD deny access to the room and " + - "inform the user of the restriction; this is done by returning a presence stanza of type \"error\" " + - "specifying a error condition. Alternatively, the room could kick an \"idle user\" " + - "in order to free up space (where the definition of \"idle user\" is up to the implementation).") - public void mucMaxUsersLimitJoinRoomTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-maxusersreached"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); - - createMuc(mucAsSeenByOne, nicknameOne); - setMaxUsers(mucAsSeenByOne, 2); - - // Set up for participant 1 to receive presence responses on join of participant 2 - final ResultSyncPoint participantOneSeesTwoSyncPoint = new ResultSyncPoint<>(); - mucAsSeenByOne.addParticipantListener(presence -> { - if (nicknameTwo.equals(presence.getFrom().getResourceOrEmpty())) { - participantOneSeesTwoSyncPoint.signal(presence); - } - }); - - // Set up for participant 3 to receive presence responses on join of participant 3 - final ResultSyncPoint participantThreeSeesThreeSyncPoint = new ResultSyncPoint<>(); - mucAsSeenByThree.addParticipantListener(presence -> { - if (nicknameThree.equals(presence.getFrom().getResourceOrEmpty())) { - participantThreeSeesThreeSyncPoint.signal(presence); - } - }); - - try { - mucAsSeenByTwo.join(nicknameTwo); - participantOneSeesTwoSyncPoint.waitForResult(timeout); - - assertEquals(2, mucAsSeenByOne.getOccupantsCount(), "Unexpected occupant count as seen by '" + conOne.getUser() + "' in room '" + mucAddress + "' (prior to the join attempt of a third occupant)."); - - // Now user 3 may or may not be able to join the room. The service can either deny access to user three, or - // it can kick user 2. Both strategies would comply with the specification. So the only thing we can - // reasonably test here is whether the room doesn't have more occupants than its max size. - - XMPPException.XMPPErrorException errorException = assertThrows(XMPPException.XMPPErrorException.class, () -> mucAsSeenByThree.join(nicknameThree)); - - final StanzaError.Condition expectedCondition; - switch (sinttestConfiguration.compatibilityMode) { - default: - expectedCondition = StanzaError.Condition.service_unavailable; - break; - case ejabberd: - expectedCondition = StanzaError.Condition.resource_constraint; - break; - } - - StanzaError stanzaError = errorException.getStanzaError(); - assertNotNull(stanzaError); - - assertEquals(expectedCondition, stanzaError.getCondition()); - - // Now we should wait until participant one is informed about the (probably failed) new participant three - // room join. But if joining failed, there will be no such update. All we can reasonably do is wait until - // participant three has received its own presence response. This is not watertight though. - participantThreeSeesThreeSyncPoint.waitForResult(timeout); - - // Irrespective of the way the implementation handles max users, there should still be only 2 users. - assertEquals(2, mucAsSeenByOne.getOccupantsCount(), "Unexpected occupant count as seen by '" + conOne.getUser() + "' in room '" + mucAddress + "' (after the join attempt of a third occupant)."); - - } finally { - mucAsSeenByOne.destroy(); - } - } - - /** - * Asserts that an admin can still join a room that has reached the configured maximum number of users. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.9", quote = - "If the room has reached its maximum number of occupants and a room admin or owner attempts to join, the " + - "room MUST allow the admin or owner to join, up to some reasonable number of additional occupants; this " + - "helps to prevent denial of service attacks caused by stuffing the room with non-admin users.") - public void mucMaxUsersLimitAdminCanStillJoinRoomTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-maxusersreached-adminjoin"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); - - createMuc(mucAsSeenByOne, nicknameOne); - setMaxUsers(mucAsSeenByOne, 2); - - // Set up for participant 1 to receive presence responses on join of participant 2 - // Set up for participant 1 to receive presence responses on join of participant 3 - final ResultSyncPoint participantOneSeesTwoSyncPoint = new ResultSyncPoint<>(); - final ResultSyncPoint participantOneSeesThreeSyncPoint = new ResultSyncPoint<>(); - mucAsSeenByOne.addParticipantListener(presence -> { - if (nicknameTwo.equals(presence.getFrom().getResourceOrEmpty())) { - participantOneSeesTwoSyncPoint.signal(presence); - } else if (nicknameThree.equals(presence.getFrom().getResourceOrEmpty())) { - participantOneSeesThreeSyncPoint.signal(presence); - } - }); - - try { - mucAsSeenByTwo.join(nicknameTwo); - participantOneSeesTwoSyncPoint.waitForResult(timeout); - - assertEquals(2, mucAsSeenByOne.getOccupantsCount(), "Unexpected occupant count in room '" + mucAddress + "' (as observed by '" + conOne.getUser() + "') (prior to an admin attempting to join a room that was already having its maximum number of occupants)."); - - mucAsSeenByOne.grantAdmin(conThree.getUser().asBareJid()); // blocking call - mucAsSeenByThree.join(nicknameThree); - participantOneSeesThreeSyncPoint.waitForResult(timeout); - - assertNotNull(mucAsSeenByOne.getOccupant(JidCreate.entityFullFrom(mucAddress, nicknameThree)), "Expected admin '" + conThree.getUser() + "' to be in room '" + mucAddress + "' (as observed by '" + conOne.getUser() + "'), but was not."); - assertEquals(3, mucAsSeenByOne.getOccupantsCount(), "Unexpected occupant count in room '" + mucAddress + "' (as observed by '" + conOne.getUser() + "') (after an admin joined a room that was already having its maximum number of occupants)"); - } finally { - mucAsSeenByOne.destroy(); - } - } - - /** - * Asserts that an owner can still join a room that has reached the configured maximum number of users. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.9", quote = - "If the room has reached its maximum number of occupants and a room admin or owner attempts to join, the " + - "room MUST allow the admin or owner to join, up to some reasonable number of additional occupants; this " + - "helps to prevent denial of service attacks caused by stuffing the room with non-admin users.") - public void mucMaxUsersLimitOwnerCanStillJoinRoomTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-maxusersreached-ownerjoin"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); - - createMuc(mucAsSeenByOne, nicknameOne); - setMaxUsers(mucAsSeenByOne, 2); - - // Set up for participant 1 to receive presence responses on join of participant 2 - // Set up for participant 1 to receive presence responses on join of participant 3 - final ResultSyncPoint participantOneSeesTwoSyncPoint = new ResultSyncPoint<>(); - final ResultSyncPoint participantOneSeesThreeSyncPoint = new ResultSyncPoint<>(); - mucAsSeenByOne.addParticipantListener(presence -> { - if (nicknameTwo.equals(presence.getFrom().getResourceOrEmpty())) { - participantOneSeesTwoSyncPoint.signal(presence); - } else if (nicknameThree.equals(presence.getFrom().getResourceOrEmpty())) { - participantOneSeesThreeSyncPoint.signal(presence); - } - }); - - try { - mucAsSeenByTwo.join(nicknameTwo); - participantOneSeesTwoSyncPoint.waitForResult(timeout); - - assertEquals(2, mucAsSeenByOne.getOccupantsCount(), "Unexpected occupant count in room '" + mucAddress + "' (as observed by '" + conOne.getUser() + "') (prior to an owner attempting to join a room that was already having its maximum number of occupants)."); - - mucAsSeenByOne.grantOwnership(conThree.getUser().asBareJid()); // blocking call - mucAsSeenByThree.join(nicknameThree); - participantOneSeesThreeSyncPoint.waitForResult(timeout); - - assertNotNull(mucAsSeenByOne.getOccupant(JidCreate.entityFullFrom(mucAddress, nicknameThree)), "Expected owner '" + conThree.getUser() + "' to be in room '" + mucAddress + "' (as observed by '" + conOne.getUser() + "'), but was not."); - assertEquals(3, mucAsSeenByOne.getOccupantsCount(), "Unexpected occupant count in room '" + mucAddress + "' (as observed by '" + conOne.getUser() + "') (after an owner joined a room that was already having its maximum number of occupants)"); - - } finally { - mucAsSeenByOne.destroy(); - } - } - - /** - * Asserts that a room can not be entered while it still being created (locked). - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.10", quote = - "If a user attempts to enter a room while it is \"locked\" (i.e., before the room creator provides an " + - "initial configuration and therefore before the room officially exists), the service MUST refuse entry and " + - "return an error to the user.") - public void mucJoinLockedRoomTest() throws Exception { - if (sinttestConfiguration.compatibilityMode == Configuration.CompatibilityMode.ejabberd) { - throw new TestNotPossibleException("ejabberd does not implement MUC locked rooms as per XEP-0045 § 7.2.10"); - } - - EntityBareJid mucAddress = getRandomRoom("smack-inttest-lockedroom"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - - // Note the absence of handle.makeInstant() here. The room is still being created at this point, until a - // configuration is set. - mucAsSeenByOne.create(nicknameOne); - - try { - XMPPException.XMPPErrorException conflictErrorException = assertThrows( - XMPPException.XMPPErrorException.class, () -> mucAsSeenByTwo.join(nicknameTwo), - "Expected an error to be returned when '" + conTwo.getUser() + "' tried to join room '" + mucAddress + "' that is still being created/is locked (but no error was returned)."); - assertNotNull(conflictErrorException, "Expected an error to be returned when '" + conTwo.getUser() + "' tried to join room '" + mucAddress + "' that is still being created/is locked (but no error was returned)."); - assertNotNull(conflictErrorException.getStanzaError(), "Expected an error to be returned when '" + conTwo.getUser() + "' tried to join room '" + mucAddress + "' that is still being created/is locked (but no error was returned)."); - assertEquals(StanzaError.Condition.item_not_found, conflictErrorException.getStanzaError().getCondition(), - "Unexpected condition in the (expected) error that was returned when '" + conTwo.getUser() + "' tried to join room '" + mucAddress + "' that is still being created/is locked."); - - } finally { - mucAsSeenByOne.destroy(); - } - } - - /** - * Asserts that a user is warned when entering a room that allows public logging. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.2.12", quote = - "If the user is entering a room in which the discussions are logged to a public archive (often accessible " + - "via HTTP), the service SHOULD allow the user to enter the room but MUST also warn the user that the " + - "discussions are logged. This is done by including a status code of \"170\" in the initial presence that the " + - "room sends to the new occupant.") - public void mucJoinRoomWithPublicLoggingTest() throws Exception { - final EntityBareJid mucAddress = getRandomRoom("smack-inttest-publiclogging"); - - final MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - final MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); - - createMuc(mucAsSeenByOne, nicknameOne); - - try { - mucAsSeenByOne.getConfigFormManager() - .enablePublicLogging() - .submitConfigurationForm(); - - Presence twoPresence = mucAsSeenByTwo.join(nicknameTwo); - assertTrue(MUCUser.from(twoPresence).getStatus().contains(MUCUser.Status.create(170)), - "Expected initial presence reflected to '" + conTwo.getUser() + "' when joining room '" + mucAddress + "' to include the status code '170' (but it did not)."); - } catch (MucConfigurationNotSupportedException e) { - throw new TestNotPossibleException(e); - } finally { - mucAsSeenByOne.destroy(); - } - } - - /** - * Asserts that all users in a room are correctly informed about nickname change of a participant. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.6", quote = - "A common feature of chat rooms is the ability for an occupant to change his or her nickname within the room. " + - "In MUC this is done by sending updated presence information to the room, specifically by sending presence to " + - "a new occupant JID in the same room (changing only the resource identifier in the occupant JID). The service " + - "then sends two presence stanzas to the full JID of each occupant (including the occupant who is changing his " + - "or her room nickname), one of type \"unavailable\" for the old nickname and one indicating availability for " + - "the new nickname. The unavailable presence MUST contain the following as extended presence information in an " + - "; element qualified by the 'http://jabber.org/protocol/muc#user' namespace: - The new nickname (in this " + - "case, nick='oldhag') - A status code of 303 This enables the recipients to correlate the old roomnick with " + - "the new roomnick.\n") - public void mucChangeNicknameInformationTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-changenickname"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwoOriginal = Resourcepart.from("two-original-" + randomString); - final Resourcepart nicknameTwoNew = Resourcepart.from("two-new-" + randomString); - - createMuc(mucAsSeenByOne, nicknameOne); - - try { - SimpleResultSyncPoint participantOneSeesTwoEnter = new SimpleResultSyncPoint(); - mucAsSeenByOne.addParticipantListener(presence -> { - if (nicknameTwoOriginal.equals(presence.getFrom().getResourceOrEmpty())) { - participantOneSeesTwoEnter.signal(); - } - }); - - // Have participant two enter the room - mucAsSeenByTwo.join(nicknameTwoOriginal); - participantOneSeesTwoEnter.waitForResult(timeout); - - // Although logic dictates that the 'unavailable' presence stanzas for the old nick should precede the presence - // stanza for the new nick - the specification does not dictate that. So we should allow for the order to be - // reversed. Here we will expect an unavailable and an available presence stanza sent to both participant one - // and participant two. So that adds up to a total of four. - MultiResultSyncPoint participantTwoPresencesSyncPoint = new MultiResultSyncPoint<>(4); - PresenceListener mucPresenceListener = presence -> { - Resourcepart fromResource = presence.getFrom().getResourceOrEmpty(); - if (nicknameTwoOriginal.equals(fromResource) || nicknameTwoNew.equals(fromResource)) { - participantTwoPresencesSyncPoint.signal(presence); - } - }; - mucAsSeenByOne.addParticipantListener(mucPresenceListener); - mucAsSeenByTwo.addParticipantListener(mucPresenceListener); - - // Participant two changes nickname - mucAsSeenByTwo.changeNickname(nicknameTwoNew); - final List partTwoPresencesReceived = participantTwoPresencesSyncPoint.waitForResults( - timeout); - - final List unavailablePresencesReceivedByOne = partTwoPresencesReceived.stream().filter( - presence -> !presence.isAvailable()).filter( - presence -> presence.getTo().equals(conOne.getUser().asEntityFullJidIfPossible())).collect( - Collectors.toList()); - final List unavailablePresencesReceivedByTwo = partTwoPresencesReceived.stream().filter( - presence -> !presence.isAvailable()).filter( - presence -> presence.getTo().equals(conTwo.getUser().asEntityFullJidIfPossible())).collect( - Collectors.toList()); - final List availablePresencesReceivedByOne = partTwoPresencesReceived.stream().filter( - Presence::isAvailable).filter( - presence -> presence.getTo().equals(conOne.getUser().asEntityFullJidIfPossible())).collect( - Collectors.toList()); - final List availablePresencesReceivedByTwo = partTwoPresencesReceived.stream().filter( - Presence::isAvailable).filter( - presence -> presence.getTo().equals(conTwo.getUser().asEntityFullJidIfPossible())).collect( - Collectors.toList()); - - // Validate that both users received both 'available' and 'unavailable' presence stanzas - assertEquals(1, unavailablePresencesReceivedByOne.size(), "Expected '" + conOne.getUser() + "' to have received one 'unavailable' presence when '" + conTwo.getUser() + "' changed its nickname in room '" + mucAddress + "' (but did not)"); - assertEquals(1, unavailablePresencesReceivedByTwo.size(), "Expected '" + conTwo.getUser() + "' to have received one 'unavailable' presence when they changed their nickname in room '" + mucAddress + "' (but did not)"); - assertEquals(1, availablePresencesReceivedByOne.size(), "Expected '" + conOne.getUser() + "' to have received one 'available' presence when '" + conTwo.getUser() + "' changed its nickname in room '" + mucAddress + "' (but did not)"); - assertEquals(1, availablePresencesReceivedByTwo.size(), "Expected '" + conTwo.getUser() + "' to have received one 'available' presence when they changed their nickname in room '" + mucAddress + "' (but did not)"); - - // Validate that the received 'unavailable' presence stanzas contain the status and items elements as specified - assertTrue(MUCUser.from(unavailablePresencesReceivedByOne.get(0)).getStatus().stream().anyMatch(status -> 303 == status.getCode()), - "Expected the 'unavailable' presence of user '" + conTwo.getUser() + "' reflecting their nickname change in room '" + mucAddress + "' as received by '" + conOne.getUser() + "' to include status code '303' (but it did not)."); - assertEquals(nicknameTwoNew, MUCUser.from(unavailablePresencesReceivedByOne.get(0)).getItem().getNick(), - "Expected the 'unavailable' presence of user '" + conTwo.getUser() + "' reflecting their nickname change in room '" + mucAddress + "' as received by '" + conOne.getUser() + "' to include the new nickname (but it did not)."); - assertTrue(MUCUser.from(unavailablePresencesReceivedByTwo.get(0)).getStatus().stream().anyMatch(status -> 303 == status.getCode()), - "Expected the 'unavailable' presence of user '" + conTwo.getUser() + "' reflecting their nickname change in room '" + mucAddress + "' as received by themselves to include status code '303' (but it did not)."); - assertEquals(nicknameTwoNew, MUCUser.from(unavailablePresencesReceivedByTwo.get(0)).getItem().getNick(), - "Expected the 'unavailable' presence of user '" + conTwo.getUser() + "' reflecting their nickname change in room '" + mucAddress + "' as received by themselves to include the new nickname (but it did not)."); - - // Validate that the received 'available' presence stanzas have the new nickname as from - assertEquals(nicknameTwoNew, availablePresencesReceivedByOne.get(0).getFrom().getResourceOrEmpty(), "Expected the 'available' presence of '" + conTwo.getUser() + "' as received by '" + conOne.getUser() + "' in room '" + mucAddress + "' to be sent 'from' their new nickname (but it was not)."); - assertEquals(nicknameTwoNew, availablePresencesReceivedByTwo.get(0).getFrom().getResourceOrEmpty(), "Expected the 'available' presence of '" + conTwo.getUser() + "' as received by themselves in room '" + mucAddress + "' to be sent 'from' their new nickname (but it was not)."); - - } finally { - tryDestroy(mucAsSeenByOne); - } - } - - /** - * Asserts that user can not change nickname to one that is already in use. - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.6", quote = - "If the user attempts to change his or her room nickname to a room nickname that is already in use by " + - "another user (or that is reserved by another user affiliated with the room, e.g., a member or owner), the " + - "service MUST deny the nickname change request and inform the user of the conflict; this is done by " + - "returning a presence stanza of type \"error\" specifying a error condition:") - public void mucBlockChangeNicknameInformationTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-blockchangenickname"); - - MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); - MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - - final Resourcepart nicknameOne = Resourcepart.from("one-" + randomString); - final Resourcepart nicknameTwoOriginal = Resourcepart.from("two-original-" + randomString); - - createMuc(mucAsSeenByOne, nicknameOne); - - SimpleResultSyncPoint participantOneSeesTwoEnter = new SimpleResultSyncPoint(); - mucAsSeenByOne.addParticipantListener(presence -> { - if (nicknameTwoOriginal.equals(presence.getFrom().getResourceOrEmpty())) { - participantOneSeesTwoEnter.signal(); - } - }); - - // Have participant two enter the room - mucAsSeenByTwo.join(nicknameTwoOriginal); - participantOneSeesTwoEnter.waitForResult(timeout); - - try { - // Participant two changes nickname - XMPPException.XMPPErrorException conflictErrorException = assertThrows( - XMPPException.XMPPErrorException.class, () -> mucAsSeenByTwo.changeNickname(nicknameOne), - "Expected an error to be returned when '" + conTwo.getUser() + "' tried to change their nickname in room '" + mucAddress + "' to a nickname that was already in use by another occupant (but no error was returned)."); - assertNotNull(conflictErrorException, "Expected an error to be returned when '" + conTwo.getUser() + "' tried to change their nickname in room '" + mucAddress + "' to a nickname that was already in use by another occupant (but no error was returned)."); - assertNotNull(conflictErrorException.getStanzaError(), "Expected an error to be returned when '" + conTwo.getUser() + "' tried to change their nickname in room '" + mucAddress + "' to a nickname that was already in use by another occupant (but no error was returned)."); - assertEquals(StanzaError.Condition.conflict, conflictErrorException.getStanzaError().getCondition(), - "Unexpected conidtion in the (expected) error to was returned when '" + conTwo.getUser() + "' tried to change their nickname in room '" + mucAddress + "' to a nickname that was already in use by another occupant."); - } finally { - tryDestroy(mucAsSeenByOne); - } - } - - /** - * Asserts that when a user leaves a room, they are themselves included on the list of users notified (self-presence). - * - * @throws Exception when errors occur - */ - @SmackIntegrationTest(section = "7.14", quote = - "The service MUST then send a presence stanzas of type \"unavailable\" from the departing user's occupant " + - "JID to the departing occupant's full JIDs, including a status code of \"110\" to indicate that this " + - "notification is \"self-presence\"") - public void mucLeaveTest() throws Exception { - EntityBareJid mucAddress = getRandomRoom("smack-inttest-leave"); - - MultiUserChat muc = mucManagerOne.getMultiUserChat(mucAddress); - try { - muc.join(Resourcepart.from("nick-one")); - - Presence reflectedLeavePresence = muc.leave(); - - MUCUser mucUser = MUCUser.from(reflectedLeavePresence); - assertNotNull(mucUser, "Expected the reflected 'leave' presence of '" + conOne.getUser() + "' that left room '" + mucAddress + "' to include a valid 'user' child element (but it did not)."); - - assertTrue(mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110), "Expected the reflected 'leave' presence of '" + conOne.getUser() + "' that left room '" + mucAddress + "' to include status '" + MUCUser.Status.PRESENCE_TO_SELF_110 + "' (but it did not)."); - assertEquals(mucAddress + "/nick-one", reflectedLeavePresence.getFrom().toString(), "Unexpected 'from' attribute value in the reflected 'leave' presence of '" + conOne.getUser() + "' that left room '" + mucAddress + "'."); - assertEquals(conOne.getUser().asEntityFullJidIfPossible().toString(), reflectedLeavePresence.getTo().toString(), "Unexpected 'to' attribute value in the reflected 'leave' presence of '" + conOne.getUser() + "' that left room '" + mucAddress + "'."); - } finally { - muc.join(Resourcepart.from("nick-one")); // We need to be in the room to destroy the room - tryDestroy(muc); - } - } -} diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatRolesAffiliationsPrivilegesIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatRolesAffiliationsPrivilegesIntegrationTest.java index 56c8a6dbb..d26e22593 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatRolesAffiliationsPrivilegesIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/MultiUserChatRolesAffiliationsPrivilegesIntegrationTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2021-2024 Florian Schmaus, Dan Caseley + * Copyright 2021 Florian Schmaus, Dan Caseley * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,64 +23,61 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -import java.util.Set; -import java.util.concurrent.TimeoutException; -import java.util.stream.Collectors; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.muc.MultiUserChatException.MissingMucCreationAcknowledgeException; -import org.jivesoftware.smackx.muc.MultiUserChatException.MucAlreadyJoinedException; -import org.jivesoftware.smackx.muc.MultiUserChatException.NotAMucServiceException; import org.jivesoftware.smackx.muc.packet.MUCUser; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.igniterealtime.smack.inttest.util.ResultSyncPoint; -import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityFullJid; import org.jxmpp.jid.Jid; import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.jid.parts.Resourcepart; -import org.jxmpp.stringprep.XmppStringprepException; -@SpecificationReference(document = "XEP-0045", version = "1.34.6") public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends AbstractMultiUserChatIntegrationTest{ public MultiUserChatRolesAffiliationsPrivilegesIntegrationTest(SmackIntegrationTestEnvironment environment) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, - InterruptedException, TestNotPossibleException, MucAlreadyJoinedException, MissingMucCreationAcknowledgeException, NotAMucServiceException, XmppStringprepException { + InterruptedException, TestNotPossibleException { super(environment); } /** - * Asserts that a user who undergoes a role change receives that change as a presence update. + * Asserts that a user who undergoes a role change receives that change as a presence update + * + *

    From XEP-0045 § 5.1.3:

    + *
    + * ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change + * to all occupants... + *
    + * + *

    From XEP-0045 § 9.6:

    + *
    + * The service MUST then send updated presence from this individual to all occupants, indicating the addition of + * moderator status... + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "5.1.3", quote = - "(§ 5.1.3)... a MUC service implementation MUST change the occupant's role to reflect the change and " + - "communicate the change to all occupants [...] (§ 9.6) The service MUST then send updated presence from this " + - "individual to all occupants, indicating the addition of moderator status...") + @SmackIntegrationTest public void mucRoleTestForReceivingModerator() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - final SimpleResultSyncPoint resultSyncPoint = new SimpleResultSyncPoint(); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); mucAsSeenByTwo.addUserStatusListener(new UserStatusListener() { @Override public void moderatorGranted() { - resultSyncPoint.signal(); + resultSyncPoint.signal("done"); } }); @@ -93,21 +90,30 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs // success" in §9.6, since it'll throw on either an error IQ or on no response. mucAsSeenByOne.grantModerator(nicknameTwo); - assertResult(resultSyncPoint, "Expected " + conTwo.getUser() + " to get a presence update after it was granted the role 'moderator' role in " + mucAddress + " (but it did not)."); + resultSyncPoint.waitForResult(timeout); } finally { tryDestroy(mucAsSeenByOne); } } /** - * Asserts that a user who is present when another user undergoes a role change receives that change as a presence update. + * Asserts that a user who is present when another user undergoes a role change receives that change as a presence update + * + *

    From XEP-0045 § 5.1.3:

    + *
    + * ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change + * to all occupants... + *
    + * + *

    From XEP-0045 § 9.6:

    + *
    + * The service MUST then send updated presence from this individual to all occupants, indicating the addition of + * moderator status... + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "9.6", quote = - "(§ 5.1.3)... a MUC service implementation MUST change the occupant's role to reflect the change and " + - "communicate the change to all occupants [...] (§ 9.6) The service MUST then send updated presence from this " + - "individual to all occupants, indicating the addition of moderator status...") + @SmackIntegrationTest public void mucRoleTestForWitnessingModerator() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); @@ -115,12 +121,12 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); - final SimpleResultSyncPoint resultSyncPoint = new SimpleResultSyncPoint(); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); mucAsSeenByThree.addParticipantStatusListener(new ParticipantStatusListener() { @Override public void moderatorGranted(EntityFullJid participant) { - resultSyncPoint.signal(); + resultSyncPoint.signal("done"); } }); @@ -132,8 +138,7 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs mucAsSeenByThree.join(nicknameThree); mucAsSeenByOne.grantModerator(nicknameTwo); - - assertResult(resultSyncPoint, "Expected " + conThree.getUser() + " to get a presence update after another user in the room was granted the 'moderator' role in " + mucAddress + " (but it did not)."); + resultSyncPoint.waitForResult(timeout); } finally { tryDestroy(mucAsSeenByOne); } @@ -141,26 +146,35 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs } /** - * Asserts that a user who undergoes a role change receives that change as a presence update. + * Asserts that a user who undergoes a role change receives that change as a presence update + * + *

    From XEP-0045 § 5.1.3:

    + *
    + * ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change + * to all occupants... + *
    + * + *

    From XEP-0045 § 9.7:

    + *
    + * The service MUST then send updated presence from this individual to all occupants, indicating the removal of + * moderator status... + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "5.1.3", quote = - "(§ 5.1.3)... a MUC service implementation MUST change the occupant's role to reflect the change and " + - "communicate the change to all occupants [...] (§ 9.7) The service MUST then send updated presence from this " + - "individual to all occupants, indicating the removal of moderator status...") + @SmackIntegrationTest public void mucRoleTestForRemovingModerator() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - final SimpleResultSyncPoint resultSyncPoint = new SimpleResultSyncPoint(); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); mucAsSeenByTwo.addUserStatusListener(new UserStatusListener() { @Override public void moderatorRevoked() { - resultSyncPoint.signal(); + resultSyncPoint.signal("done"); } }); @@ -171,22 +185,30 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs mucAsSeenByOne.grantModerator(nicknameTwo); mucAsSeenByOne.revokeModerator(nicknameTwo); - - assertResult(resultSyncPoint, "Expected " + conTwo.getUser() + " to get a presence update after its 'moderator' role in " + mucAddress + " was revoked (but it did not)."); + resultSyncPoint.waitForResult(timeout); } finally { tryDestroy(mucAsSeenByOne); } } /** - * Asserts that a user who is present when another user undergoes a role change receives that change as a presence update. + * Asserts that a user who is present when another user undergoes a role change receives that change as a presence update + * + *

    From XEP-0045 § 5.1.3:

    + *
    + * ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change + * to all occupants... + *
    + * + *

    From XEP-0045 § 9.7:

    + *
    + * The service MUST then send updated presence from this individual to all occupants, indicating the removal of + * moderator status... + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "9.7", quote = - "(§ 5.1.3)... a MUC service implementation MUST change the occupant's role to reflect the change and " + - "communicate the change to all occupants [...] (§ 9.7) The service MUST then send updated presence from this " + - "individual to all occupants, indicating the removal of moderator status...") + @SmackIntegrationTest public void mucRoleTestForWitnessingModeratorRemoval() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); @@ -194,12 +216,12 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); - final SimpleResultSyncPoint resultSyncPoint = new SimpleResultSyncPoint(); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); mucAsSeenByThree.addParticipantStatusListener(new ParticipantStatusListener() { @Override public void moderatorRevoked(EntityFullJid participant) { - resultSyncPoint.signal(); + resultSyncPoint.signal("done"); } }); @@ -212,33 +234,42 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs mucAsSeenByOne.grantModerator(nicknameTwo); mucAsSeenByOne.revokeModerator(nicknameTwo); - assertResult(resultSyncPoint, "Expected " + conThree.getUser() + " to get a presence update after the 'moderator' role of another user in the room was revoked in " + mucAddress + " (but it did not)."); + resultSyncPoint.waitForResult(timeout); } finally { tryDestroy(mucAsSeenByOne); } } /** - * Asserts that a user in an unmoderated room who undergoes an affiliation change receives that change as a presence update. + * Asserts that a user in an unmoderated room who undergoes an afilliation change receives that change as a presence update + * + *

    From XEP-0045 § 5.1.3:

    + *
    + * ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change + * to all occupants... + *
    + * + *

    From XEP-0045 § 8.4:

    + *
    + * The service MUST then send updated presence from this individual to all occupants, indicating the removal of + * voice privileges... + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "5.1.3", quote = - "(§ 5.1.3)... a MUC service implementation MUST change the occupant's role to reflect the change and " + - "communicate the change to all occupants [...] (§ 8.4) The service MUST then send updated presence from " + - "this individual to all occupants, indicating the removal of voice privileges...") + @SmackIntegrationTest public void mucRoleTestForRevokingVoice() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - final SimpleResultSyncPoint resultSyncPoint = new SimpleResultSyncPoint(); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); mucAsSeenByTwo.addUserStatusListener(new UserStatusListener() { @Override public void voiceRevoked() { - resultSyncPoint.signal(); + resultSyncPoint.signal("done"); } }); @@ -247,21 +278,30 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); mucAsSeenByTwo.join(nicknameTwo); mucAsSeenByOne.revokeVoice(nicknameTwo); - assertResult(resultSyncPoint, "Expected " + conTwo.getUser() + " to get a presence update after its 'voice' privilege was revoked in " + mucAddress + " (but it did not)."); + resultSyncPoint.waitForResult(timeout); } finally { tryDestroy(mucAsSeenByOne); } } /** - * Asserts that a user who is present when another user undergoes a role change receives that change as a presence update. + * Asserts that a user who is present when another user undergoes a role change receives that change as a presence update + * + *

    From XEP-0045 § 5.1.3:

    + *
    + * ...a MUC service implementation MUST change the occupant's role to reflect the change and communicate the change + * to all occupants... + *
    + * + *

    From XEP-0045 § 8.4:

    + *
    + * The service MUST then send updated presence from this individual to all occupants, indicating the removal of + * voice privileges... + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "8.4", quote = - "(§ 5.1.3)... a MUC service implementation MUST change the occupant's role to reflect the change and " + - "communicate the change to all occupants [...] (§ 8.4) The service MUST then send updated presence from " + - "this individual to all occupants, indicating the removal of voice privileges...") + @SmackIntegrationTest public void mucRoleTestForWitnessingRevokingVoice() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); @@ -269,12 +309,12 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); - final SimpleResultSyncPoint resultSyncPoint = new SimpleResultSyncPoint(); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); mucAsSeenByThree.addParticipantStatusListener(new ParticipantStatusListener() { @Override public void voiceRevoked(EntityFullJid participant) { - resultSyncPoint.signal(); + resultSyncPoint.signal("done"); } }); @@ -286,34 +326,43 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs mucAsSeenByThree.join(nicknameThree); mucAsSeenByOne.revokeVoice(nicknameTwo); - assertResult(resultSyncPoint, "Expected " + conThree.getUser() + " to get a presence update after another user's 'voice' privilege was revoked in " + mucAddress + " (but it did not)."); + resultSyncPoint.waitForResult(timeout); } finally { tryDestroy(mucAsSeenByOne); } } /** - * Asserts that a user who undergoes an affiliation change receives that change as a presence update. + * Asserts that a user who undergoes an affiliation change receives that change as a presence update + * + *

    From XEP-0045 § 5.2.2:

    + *
    + * ...a MUC service implementation MUST change the user's affiliation to reflect the change and communicate that + * to all occupants... + *
    + * + *

    From XEP-0045 § 10.6:

    + *
    + * If the user is in the room, the service MUST then send updated presence from this individual to all occupants, + * indicating the granting of admin status... + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "5.2.2", quote = - "(§ 5.2.2) ... a MUC service implementation MUST change the user's affiliation to reflect the change and " + - "communicate that to all occupants [...] (§ 10.6) If the user is in the room, the service MUST then send " + - "updated presence from this individual to all occupants, indicating the granting of admin status...") + @SmackIntegrationTest public void mucAffiliationTestForReceivingAdmin() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - final SimpleResultSyncPoint resultSyncPoint = new SimpleResultSyncPoint(); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); mucAsSeenByTwo.addUserStatusListener(new UserStatusListener() { @Override public void adminGranted() { - resultSyncPoint.signal(); + resultSyncPoint.signal("done"); } }); @@ -324,7 +373,7 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs // This implicitly tests "The service MUST add the user to the admin list and then inform the owner of success" in §10.6, since it'll throw on either an error IQ or on no response. mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); - assertResult(resultSyncPoint, "Expected " + conTwo.getUser() + " to get a presence update after its was granted 'admin' affiliation in " + mucAddress + " (but it did not)."); + resultSyncPoint.waitForResult(timeout); } finally { tryDestroy(mucAsSeenByOne); } @@ -332,14 +381,23 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs /** * Asserts that a user who is present when another user undergoes an affiliation change receives that change as a - * presence update. + * presence update + * + *

    From XEP-0045 § 5.2.2:

    + *
    + * ...a MUC service implementation MUST change the user's affiliation to reflect the change and communicate that + * to all occupants... + *
    + * + *

    From XEP-0045 § 10.6:

    + *
    + * If the user is in the room, the service MUST then send updated presence from this individual to all occupants, + * indicating the granting of admin status... + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "10.6", quote = - "(§ 5.2.2) ... a MUC service implementation MUST change the user's affiliation to reflect the change and " + - "communicate that to all occupants [...] (§ 10.6) If the user is in the room, the service MUST then send " + - "updated presence from this individual to all occupants, indicating the granting of admin status...") + @SmackIntegrationTest public void mucAffiliationTestForWitnessingAdmin() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); @@ -347,12 +405,12 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); - final SimpleResultSyncPoint resultSyncPoint = new SimpleResultSyncPoint(); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); mucAsSeenByThree.addParticipantStatusListener(new ParticipantStatusListener() { @Override public void adminGranted(EntityFullJid participant) { - resultSyncPoint.signal(); + resultSyncPoint.signal("done"); } }); @@ -364,34 +422,42 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs mucAsSeenByThree.join(nicknameThree); mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); - assertResult(resultSyncPoint, "Expected " + conThree.getUser() + " to get a presence update after another user was granted 'admin' affiliation in " + mucAddress + " (but it did not)."); + resultSyncPoint.waitForResult(timeout); } finally { tryDestroy(mucAsSeenByOne); } } /** - * Asserts that a user who undergoes an affiliation change receives that change as a presence update. + * Asserts that a user who undergoes an affiliation change receives that change as a presence update + * + *

    From XEP-0045 § 5.2.2:

    + *
    + * ...a MUC service implementation MUST change the user's affiliation to reflect the change and communicate that to + * all occupants... + *
    + * + *

    From XEP-0045 § 10.7:

    + *
    + * If the user is in the room, the service MUST then send updated presence from this individual to all occupants, + * indicating the loss of admin status by sending a presence element... + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "10.7", quote = - "(§ 5.2.2) ... a MUC service implementation MUST change the user's affiliation to reflect the change and " + - "communicate that to all occupants [...] (§ 10.6) If the user is in the room, the service MUST then send " + - "updated presence from this individual to all occupants, indicating the loss of admin status by sending a " + - "presence element...") + @SmackIntegrationTest public void mucAffiliationTestForRemovingAdmin() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); MultiUserChat mucAsSeenByOne = mucManagerOne.getMultiUserChat(mucAddress); MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); - final SimpleResultSyncPoint resultSyncPoint = new SimpleResultSyncPoint(); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); mucAsSeenByTwo.addUserStatusListener(new UserStatusListener() { @Override public void adminRevoked() { - resultSyncPoint.signal(); + resultSyncPoint.signal("done"); } }); @@ -402,7 +468,7 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); mucAsSeenByOne.revokeAdmin(conTwo.getUser().asEntityBareJid()); - assertResult(resultSyncPoint, "Expected " + conTwo.getUser() + " to get a presence update after its 'admin' affiliation was revoked in " + mucAddress + " (but it did not)."); + resultSyncPoint.waitForResult(timeout); } finally { tryDestroy(mucAsSeenByOne); } @@ -425,11 +491,7 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "10.7", quote = - "(§ 5.2.2) ... a MUC service implementation MUST change the user's affiliation to reflect the change and " + - "communicate that to all occupants [...] (§ 10.6) If the user is in the room, the service MUST then send " + - "updated presence from this individual to all occupants, indicating the loss of admin status by sending a " + - "presence element...") + @SmackIntegrationTest public void mucAffiliationTestForWitnessingAdminRemoval() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); @@ -437,12 +499,12 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs MultiUserChat mucAsSeenByTwo = mucManagerTwo.getMultiUserChat(mucAddress); MultiUserChat mucAsSeenByThree = mucManagerThree.getMultiUserChat(mucAddress); - final SimpleResultSyncPoint resultSyncPoint = new SimpleResultSyncPoint(); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); mucAsSeenByThree.addParticipantStatusListener(new ParticipantStatusListener() { @Override public void adminRevoked(EntityFullJid participant) { - resultSyncPoint.signal(); + resultSyncPoint.signal("done"); } }); @@ -455,23 +517,28 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); mucAsSeenByOne.revokeAdmin(conTwo.getUser().asEntityBareJid()); - assertResult(resultSyncPoint, "Expected " + conThree.getUser() + " to get a presence update after another user's 'admin' affiliation was revoked in " + mucAddress + " (but it did not)."); + resultSyncPoint.waitForResult(timeout); } finally { tryDestroy(mucAsSeenByOne); } } /** - * Asserts that a user who gets kicked receives that change as a presence update. + * Asserts that a user who gets kicked receives that change as a presence update + * + *

    From XEP-0045 § 8.2:

    + *
    + * The kick is performed based on the occupant's room nickname and is completed by setting the role of a + * participant or visitor to a value of "none". + * + * The service MUST remove the kicked occupant by sending a presence stanza of type "unavailable" to each kicked + * occupant, including status code 307 in the extended presence information, optionally along with the reason (if + * provided) and the roomnick or bare JID of the user who initiated the kick. + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "8.2", quote = - "The kick is performed based on the occupant's room nickname and is completed by setting the role of a " + - "participant or visitor to a value of \"none\". The service MUST remove the kicked occupant by sending a " + - "presence stanza of type \"unavailable\" to each kicked occupant, including status code 307 in the extended " + - "presence information, optionally along with the reason (if provided) and the roomnick or bare JID of the " + - "user who initiated the kick.") + @SmackIntegrationTest public void mucPresenceTestForGettingKicked() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); @@ -489,33 +556,35 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs mucAsSeenByOne.kickParticipant(nicknameTwo, "Nothing personal. Just a test."); Presence kickPresence = resultSyncPoint.waitForResult(timeout); MUCUser mucUser = MUCUser.from(kickPresence); - assertNotNull(mucUser, "Expected, but unable, to create a MUCUser instance from 'kick' presence: " + kickPresence); + assertNotNull(mucUser); assertAll( - () -> assertTrue(mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110), "Missing self-presence status code in kick presence received by " + conTwo.getUser() + " after being kicked from room " + mucAddress), - () -> assertTrue(mucUser.getStatus().contains(MUCUser.Status.KICKED_307), "Missing kick status code in kick presence received by " + conTwo.getUser() + " after being kicked from room " + mucAddress), - () -> assertEquals(MUCRole.none, mucUser.getItem().getRole(), "Role other than 'none' in kick presence received by " + conTwo.getUser() + " after being kicked from room " + mucAddress) + () -> assertTrue(mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110), "Missing self-presence status code in kick presence"), + () -> assertTrue(mucUser.getStatus().contains(MUCUser.Status.KICKED_307), "Missing kick status code in kick presence"), + () -> assertEquals(MUCRole.none, mucUser.getItem().getRole(), "Role other than 'none' in kick presence") ); Jid itemJid = mucUser.getItem().getJid(); if (itemJid != null) { - assertEquals(conTwo.getUser().asEntityFullJidIfPossible(), itemJid, "Incorrect kicked user in kick presence received by " + conTwo.getUser() + " after being kicked from room " + mucAddress); + assertEquals(conTwo.getUser().asEntityFullJidIfPossible(), itemJid, "Incorrect kicked user in kick presence"); } - } catch (TimeoutException e) { - fail("Expected " + conTwo.getUser() + " to receive a presence update after it was kicked from room " + mucAddress + " (but it did not).", e); } finally { tryDestroy(mucAsSeenByOne); } } /** - * Asserts that a user who is present when another user gets kicked receives that change as a presence update. + * Asserts that a user who is present when another user gets kicked receives that change as a presence update + * + *

    From XEP-0045 § 8.2:

    + *
    + * ...the service MUST then inform all of the remaining occupants that the kicked occupant is no longer in the room + * by sending presence stanzas of type "unavailable" from the individual's roomnick (<room@service/nick>) to all + * the remaining occupants (just as it does when occupants exit the room of their own volition), including the + * status code and optionally the reason and actor. + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "8.2", quote = - "...the service MUST then inform all of the remaining occupants that the kicked occupant is no longer in the " + - "room by sending presence stanzas of type \"unavailable\" from the individual's roomnick " + - "() to all the remaining occupants (just as it does when occupants exit the room of their " + - "own volition), including the status code and optionally the reason and actor.") + @SmackIntegrationTest public void mucPresenceTestForWitnessingKick() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); @@ -536,18 +605,16 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs mucAsSeenByOne.kickParticipant(nicknameTwo, "Nothing personal. Just a test."); Presence kickPresence = resultSyncPoint.waitForResult(timeout); MUCUser mucUser = MUCUser.from(kickPresence); - assertNotNull(mucUser, "Expected, but unable, to create a MUCUser instance from 'kick' presence: " + kickPresence); + assertNotNull(mucUser); assertAll( - () -> assertFalse(mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110), "Incorrect self-presence status code in kick presence received by " + conThree.getUser() + " after another user was kicked from room " + mucAddress), - () -> assertTrue(mucUser.getStatus().contains(MUCUser.Status.KICKED_307), "Missing kick status code in kick presence received by " + conThree.getUser() + " after another user was kicked from room " + mucAddress), - () -> assertEquals(MUCRole.none, mucUser.getItem().getRole(), "Role other than 'none' in kick presence received by " + conThree.getUser() + " after another user was kicked from room " + mucAddress) + () -> assertFalse(mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110), "Incorrect self-presence status code in kick presence"), + () -> assertTrue(mucUser.getStatus().contains(MUCUser.Status.KICKED_307), "Missing kick status code in kick presence"), + () -> assertEquals(MUCRole.none, mucUser.getItem().getRole(), "Role other than 'none' in kick presence") ); Jid itemJid = mucUser.getItem().getJid(); if (itemJid != null) { - assertEquals(conTwo.getUser().asEntityFullJidIfPossible(), itemJid, "Incorrect kicked user in kick presence received by " + conThree.getUser() + " after another user was kicked from room " + mucAddress); + assertEquals(conTwo.getUser().asEntityFullJidIfPossible(), itemJid, "Incorrect kicked user in kick presence"); } - } catch (TimeoutException e) { - fail("Expected " + conThree.getUser() + " to receive a presence update after another user was kicked from room " + mucAddress + " (but it did not).", e); } finally { tryDestroy(mucAsSeenByOne); } @@ -557,12 +624,16 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs /** * Asserts that an affiliation is persistent between visits to the room. * + *

    From XEP-0045 § 5.2:

    + *
    + * These affiliations are long-lived in that they persist across a user's visits to the room and are not affected + * by happenings in the room...Affiliations are granted, revoked, and maintained based on the user's bare JID, not + * the nick as with roles. + *
    + * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "5.2", quote = - "These affiliations are long-lived in that they persist across a user's visits to the room and are not " + - "affected by happenings in the room...Affiliations are granted, revoked, and maintained based on the user's " + - "bare JID, not the nick as with roles.") + @SmackIntegrationTest public void mucTestPersistentAffiliation() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); @@ -586,24 +657,32 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs mucAsSeenByThree.leave(); Presence p2 = mucAsSeenByTwo.join(nicknameTwo); Presence p3 = mucAsSeenByThree.join(nicknameThree); - assertEquals(MUCAffiliation.owner, MUCUser.from(p2).getItem().getAffiliation(), "Unexpected affiliation of " + conTwo.getUser() + " after it re-joined room " + mucAddress); - assertEquals(MUCAffiliation.admin, MUCUser.from(p3).getItem().getAffiliation(), "Unexpected affiliation of " + conThree.getUser() + " after it re-joined room " + mucAddress); + assertEquals(MUCAffiliation.owner, MUCUser.from(p2).getItem().getAffiliation()); + assertEquals(MUCAffiliation.admin, MUCUser.from(p3).getItem().getAffiliation()); } finally { tryDestroy(mucAsSeenByOne); } } /** - * Asserts that a moderator cannot revoke voice from an owner. + * Asserts that a moderator cannot revoke voice from an owner + * + *

    From XEP-0045 § 5.1.1:

    + *
    + * A moderator MUST NOT be able to revoke voice privileges from an admin or owner + *
    + * + *

    From XEP-0045 § 8.4:

    + *
    + * A moderator MUST NOT be able to revoke voice from a user whose affiliation is at or above the moderator's level. + * In addition, a service MUST NOT allow the voice privileges of an admin or owner to be removed by anyone. If a + * moderator attempts to revoke voice privileges from such a user, the service MUST deny the request and return a + * <not-allowed/> error to the sender along with the offending item(s) + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "5.1.1", quote = - "A moderator MUST NOT be able to revoke voice privileges from an admin or owner [...] (§ 8.4) A moderator " + - "MUST NOT be able to revoke voice from a user whose affiliation is at or above the moderator's level. In " + - "addition, a service MUST NOT allow the voice privileges of an admin or owner to be removed by anyone. If a " + - "moderator attempts to revoke voice privileges from such a user, the service MUST deny the request and return " + - "a error to the sender along with the offending item(s)") + @SmackIntegrationTest public void mucTestModeratorCannotRevokeVoiceFromOwner() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); @@ -618,9 +697,8 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs mucAsSeenByTwo.join(nicknameTwo); mucAsSeenByOne.grantModerator(nicknameTwo); XMPPException.XMPPErrorException xe = assertThrows(XMPPException.XMPPErrorException.class, - () -> mucAsSeenByTwo.revokeVoice(nicknameOne), - "Expected an XMPP error when " + conTwo.getUser() + " was trying to revoke the 'voice' privilege of " + conOne.getUser() + " in room " + mucAddress); - assertEquals("not-allowed", xe.getStanzaError().getCondition().toString(), "Unexpected stanza error condition in error returned when " + conTwo.getUser() + " was trying to revoke the 'voice' privilege of " + conOne.getUser() + " in room " + mucAddress); + () -> mucAsSeenByTwo.revokeVoice(nicknameOne)); + assertEquals(xe.getStanzaError().getCondition().toString(), "not-allowed"); } finally { tryDestroy(mucAsSeenByOne); } @@ -630,12 +708,16 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs * Asserts that a moderator cannot revoke moderator privileges from a moderator with a higher affiliation * than themselves. * + *

    From XEP-0045 § 5.1.3 and §5.2.1:

    + *
    + * A moderator SHOULD NOT be allowed to revoke moderation privileges from someone with a higher affiliation than + * themselves (i.e., an unaffiliated moderator SHOULD NOT be allowed to revoke moderation privileges from an admin + * or an owner, and an admin SHOULD NOT be allowed to revoke moderation privileges from an owner) + *
    + * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "5.1.3", quote = - "A moderator SHOULD NOT be allowed to revoke moderation privileges from someone with a higher affiliation " + - "than themselves (i.e., an unaffiliated moderator SHOULD NOT be allowed to revoke moderation privileges from " + - "an admin or an owner, and an admin SHOULD NOT be allowed to revoke moderation privileges from an owner)") + @SmackIntegrationTest public void mucTestModeratorCannotBeRevokedFromHigherAffiliation() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest"); @@ -657,31 +739,32 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs // Admin cannot revoke from Owner XMPPException.XMPPErrorException xe1 = assertThrows(XMPPException.XMPPErrorException.class, - () -> mucAsSeenByTwo.revokeModerator(nicknameOne), - "Expected an XMPP error when " + conTwo.getUser() + " (an admin) was trying to revoke the 'moderator' role of " + conOne.getUser() + " (an owner) in room " + mucAddress); - // Moderator cannot revoke from Owner - XMPPException.XMPPErrorException xe2 = assertThrows(XMPPException.XMPPErrorException.class, - () -> mucAsSeenByThree.revokeModerator(nicknameOne), - "Expected an XMPP error when " + conThree.getUser() + " (a moderator) was trying to revoke the 'moderator' role of " + conOne.getUser() + " (an owner) in room " + mucAddress); + () -> mucAsSeenByTwo.revokeModerator(nicknameOne)); // Moderator cannot revoke from Admin + XMPPException.XMPPErrorException xe2 = assertThrows(XMPPException.XMPPErrorException.class, + () -> mucAsSeenByThree.revokeModerator(nicknameOne)); + // Moderator cannot revoke from Owner XMPPException.XMPPErrorException xe3 = assertThrows(XMPPException.XMPPErrorException.class, - () -> mucAsSeenByThree.revokeModerator(nicknameTwo), - "Expected an XMPP error when " + conThree.getUser() + " (a moderator) was trying to revoke the 'moderator' role of " + conTwo.getUser() + " (an admin) in room " + mucAddress); - assertEquals("not-allowed", xe1.getStanzaError().getCondition().toString(), "Unexpected condition in XMPP error when " + conTwo.getUser() + " (an admin) was trying to revoke the 'moderator' role of " + conOne.getUser() + " (an owner) in room " + mucAddress); - assertEquals("not-allowed", xe2.getStanzaError().getCondition().toString(), "Unexpected condition in XMPP error when " + conThree.getUser() + " (a moderator) was trying to revoke the 'moderator' role of " + conOne.getUser() + " (an owner) in room " + mucAddress); - assertEquals("not-allowed", xe3.getStanzaError().getCondition().toString(), "Unexpected condition in XMPP error when " + conThree.getUser() + " (a moderator) was trying to revoke the 'moderator' role of " + conTwo.getUser() + " (an admin) in room " + mucAddress); + () -> mucAsSeenByThree.revokeModerator(nicknameTwo)); + assertEquals(xe1.getStanzaError().getCondition().toString(), "not-allowed"); + assertEquals(xe2.getStanzaError().getCondition().toString(), "not-allowed"); + assertEquals(xe3.getStanzaError().getCondition().toString(), "not-allowed"); } finally { tryDestroy(mucAsSeenByOne); } } /** - * Asserts that an unmoderated room assigns the correct default roles for a given affiliation. + * Asserts that an unmoderated room assigns the correct default roles for a given affiliation + * + *

    From XEP-0045 § 5.1.2:

    + *
    + * ...the initial default roles that a service SHOULD set based on the user's affiliation... + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "5.1.2", quote = - "...the initial default roles that a service SHOULD set based on the user's affiliation...") + @SmackIntegrationTest public void mucTestDefaultRoleForAffiliationInUnmoderatedRoom() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest-unmoderatedroles"); @@ -693,48 +776,44 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); - final EntityFullJid jidOne = JidCreate.entityFullFrom(mucAddress, nicknameOne); - final EntityFullJid jidTwo = JidCreate.entityFullFrom(mucAddress, nicknameTwo); - final EntityFullJid jidThree = JidCreate.entityFullFrom(mucAddress, nicknameThree); - createMuc(mucAsSeenByOne, nicknameOne); - - final SimpleResultSyncPoint allOccupantsDetectedSyncPoint = new SimpleResultSyncPoint(); - final Set expectedOccupants = Set.of(jidOne, jidTwo, jidThree); - mucAsSeenByOne.addParticipantStatusListener(new ParticipantStatusListener() { - @Override - public void joined(EntityFullJid participant) { - if (mucAsSeenByOne.getOccupants().containsAll(expectedOccupants)) { - allOccupantsDetectedSyncPoint.signal(); - } - } - }); - try { - mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); - mucAsSeenByTwo.join(nicknameTwo); mucAsSeenByThree.join(nicknameThree); - assertResult(allOccupantsDetectedSyncPoint, "Expected " + conOne.getUser() + " to observe all of these occupants in room " + mucAddress + ", but not all of them appear to be in: " + expectedOccupants.stream().map(Object::toString).collect(Collectors.joining(", "))); - assertEquals(MUCRole.moderator, mucAsSeenByOne.getOccupant(JidCreate.entityFullFrom(mucAddress, nicknameOne)).getRole(), - "Unexpected role for occupant " + nicknameOne + " of " + mucAddress); - assertEquals(MUCRole.moderator, mucAsSeenByOne.getOccupant(JidCreate.entityFullFrom(mucAddress, nicknameTwo)).getRole(), - "Unexpected role for occupant " + nicknameTwo + " of " + mucAddress); - assertEquals(MUCRole.participant, mucAsSeenByOne.getOccupant(JidCreate.entityFullFrom(mucAddress, nicknameThree)).getRole(), - "Unexpected role for occupant " + nicknameThree + " of " + mucAddress); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); + mucAsSeenByOne.addParticipantStatusListener(new ParticipantStatusListener() { + @Override + public void adminGranted(EntityFullJid participant) { + resultSyncPoint.signal("done"); + } + }); + mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); + resultSyncPoint.waitForResult(timeout); + + assertEquals(mucAsSeenByOne.getOccupantsCount(), 3); + assertEquals(MUCRole.moderator, mucAsSeenByOne.getOccupant( + JidCreate.entityFullFrom(mucAddress, nicknameOne)).getRole()); + assertEquals(MUCRole.moderator, mucAsSeenByOne.getOccupant( + JidCreate.entityFullFrom(mucAddress, nicknameTwo)).getRole()); + assertEquals(MUCRole.participant, mucAsSeenByOne.getOccupant( + JidCreate.entityFullFrom(mucAddress, nicknameThree)).getRole()); } finally { tryDestroy(mucAsSeenByOne); } } /** - * Asserts that a moderated room assigns the correct default roles for a given affiliation. + * Asserts that a moderated room assigns the correct default roles for a given affiliation + * + *

    From XEP-0045 § 5.1.2:

    + *
    + * ...the initial default roles that a service SHOULD set based on the user's affiliation... + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "5.1.2", quote = - "...the initial default roles that a service SHOULD set based on the user's affiliation...") + @SmackIntegrationTest public void mucTestDefaultRoleForAffiliationInModeratedRoom() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest-moderatedroles"); @@ -746,23 +825,16 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs final Resourcepart nicknameTwo = Resourcepart.from("two-" + randomString); final Resourcepart nicknameThree = Resourcepart.from("three-" + randomString); - final EntityFullJid jidOne = JidCreate.entityFullFrom(mucAddress, nicknameOne); - final EntityFullJid jidTwo = JidCreate.entityFullFrom(mucAddress, nicknameTwo); - final EntityFullJid jidThree = JidCreate.entityFullFrom(mucAddress, nicknameThree); - - createModeratedMuc(mucAsSeenByOne, nicknameOne); - - final SimpleResultSyncPoint allOccupantsDetectedSyncPoint = new SimpleResultSyncPoint(); - final Set expectedOccupants = Set.of(jidOne, jidTwo, jidThree); + final ResultSyncPoint resultSyncPoint = new ResultSyncPoint<>(); mucAsSeenByOne.addParticipantStatusListener(new ParticipantStatusListener() { @Override - public void joined(EntityFullJid participant) { - if (mucAsSeenByOne.getOccupants().containsAll(expectedOccupants)) { - allOccupantsDetectedSyncPoint.signal(); - } + public void adminGranted(EntityFullJid participant) { + resultSyncPoint.signal("done"); } }); + createModeratedMuc(mucAsSeenByOne, nicknameOne); + final MUCRole threeRole; switch (sinttestConfiguration.compatibilityMode) { default: @@ -774,30 +846,34 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs } try { - mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); - mucAsSeenByTwo.join(nicknameTwo); mucAsSeenByThree.join(nicknameThree); + mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); + resultSyncPoint.waitForResult(timeout); - assertResult(allOccupantsDetectedSyncPoint, "Expected " + conOne.getUser() + " to observe all of these occupants in room " + mucAddress + ", but not all of them appear to be in: " + expectedOccupants.stream().map(Object::toString).collect(Collectors.joining(", "))); - assertEquals(MUCRole.moderator, mucAsSeenByOne.getOccupant(JidCreate.entityFullFrom(mucAddress, nicknameOne)).getRole(), - "Unexpected role for occupant " + nicknameOne + " of " + mucAddress); - assertEquals(MUCRole.moderator, mucAsSeenByOne.getOccupant(JidCreate.entityFullFrom(mucAddress, nicknameTwo)).getRole(), - "Unexpected role for occupant " + nicknameTwo + " of " + mucAddress); - assertEquals(threeRole, mucAsSeenByOne.getOccupant(JidCreate.entityFullFrom(mucAddress, nicknameThree)).getRole(), - "Unexpected role for occupant " + nicknameThree + " of " + mucAddress); + assertEquals(mucAsSeenByOne.getOccupantsCount(), 3); + assertEquals(MUCRole.moderator, mucAsSeenByOne.getOccupant( + JidCreate.entityFullFrom(mucAddress, nicknameOne)).getRole()); + assertEquals(MUCRole.moderator, mucAsSeenByOne.getOccupant( + JidCreate.entityFullFrom(mucAddress, nicknameTwo)).getRole()); + assertEquals(threeRole, mucAsSeenByOne.getOccupant( + JidCreate.entityFullFrom(mucAddress, nicknameThree)).getRole()); } finally { tryDestroy(mucAsSeenByOne); } } /** - * Asserts that a members-only room assigns the correct default roles for a given affiliation. + * Asserts that a members-only room assigns the correct default roles for a given affiliation + * + *

    From XEP-0045 § 5.1.2:

    + *
    + * ...the initial default roles that a service SHOULD set based on the user's affiliation... + *
    * * @throws Exception when errors occur */ - @SmackIntegrationTest(section = "5.1.2", quote = - "...the initial default roles that a service SHOULD set based on the user's affiliation...") + @SmackIntegrationTest public void mucTestDefaultRoleForAffiliationInMembersOnlyRoom() throws Exception { EntityBareJid mucAddress = getRandomRoom("smack-inttest-membersonlyroles"); @@ -815,29 +891,26 @@ public class MultiUserChatRolesAffiliationsPrivilegesIntegrationTest extends Abs createMembersOnlyMuc(mucAsSeenByOne, nicknameOne); - final SimpleResultSyncPoint allOccupantsDetectedSyncPoint = new SimpleResultSyncPoint(); - final Set expectedOccupants = Set.of(jidOne, jidTwo, jidThree); + final ResultSyncPoint adminResultSyncPoint = new ResultSyncPoint<>(); mucAsSeenByOne.addParticipantStatusListener(new ParticipantStatusListener() { @Override - public void joined(EntityFullJid participant) { - if (mucAsSeenByOne.getOccupants().containsAll(expectedOccupants)) { - allOccupantsDetectedSyncPoint.signal(); - } + public void adminGranted(EntityFullJid participant) { + adminResultSyncPoint.signal("done"); } }); try { mucAsSeenByOne.grantMembership(conTwo.getUser().asBareJid()); mucAsSeenByOne.grantMembership(conThree.getUser().asBareJid()); - mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); mucAsSeenByTwo.join(nicknameTwo); mucAsSeenByThree.join(nicknameThree); - - assertResult(allOccupantsDetectedSyncPoint, "Expected " + conOne.getUser() + " to observe all of these occupants in room " + mucAddress + ", but not all of them appear to be in: " + expectedOccupants.stream().map(Object::toString).collect(Collectors.joining(", "))); - assertEquals(MUCRole.moderator, mucAsSeenByOne.getOccupant(jidOne).getRole(), "Unexpected role for occupant " + jidOne + " in room " + mucAddress); - assertEquals(MUCRole.moderator, mucAsSeenByOne.getOccupant(jidTwo).getRole(), "Unexpected role for occupant " + jidTwo + " in room " + mucAddress); - assertEquals(MUCRole.participant, mucAsSeenByOne.getOccupant(jidThree).getRole(), "Unexpected role for occupant " + jidThree + " in room " + mucAddress); + mucAsSeenByOne.grantAdmin(conTwo.getUser().asBareJid()); + adminResultSyncPoint.waitForResult(timeout); + assertEquals(mucAsSeenByOne.getOccupantsCount(), 3); + assertEquals(MUCRole.moderator, mucAsSeenByOne.getOccupant(jidOne).getRole()); + assertEquals(MUCRole.moderator, mucAsSeenByOne.getOccupant(jidTwo).getRole()); + assertEquals(MUCRole.participant, mucAsSeenByOne.getOccupant(jidThree).getRole()); } finally { tryDestroy(mucAsSeenByOne); } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/ParticipantStatusIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/ParticipantStatusIntegrationTest.java deleted file mode 100644 index 1bf3fdce4..000000000 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/ParticipantStatusIntegrationTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/** - * - * Copyright 2024 Guus der Kinderen - * - * 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.smackx.muc; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; - -import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; -import org.igniterealtime.smack.inttest.TestNotPossibleException; -import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; -import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; -import org.jxmpp.jid.EntityBareJid; -import org.jxmpp.jid.EntityFullJid; -import org.jxmpp.jid.impl.JidCreate; -import org.jxmpp.jid.parts.Resourcepart; -import org.jxmpp.stringprep.XmppStringprepException; - -/** - * Tests that verify the correct functionality of Smack's {@link ParticipantStatusListener}. - */ -@SpecificationReference(document = "XEP-0045", version = "1.34.6") -public class ParticipantStatusIntegrationTest extends AbstractMultiUserChatIntegrationTest { - - public ParticipantStatusIntegrationTest(SmackIntegrationTestEnvironment environment) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, TestNotPossibleException, MultiUserChatException.MucAlreadyJoinedException, MultiUserChatException.MissingMucCreationAcknowledgeException, XmppStringprepException, MultiUserChatException.NotAMucServiceException { - super(environment); - } - - /** - * Verifies that when a member gets its membership removed in an open room, the appropriate event listener is invoked. - * - * @throws Exception On unexpected results - */ - @SmackIntegrationTest(section = "9.4", quote = "An admin might want to revoke a user's membership [...] The service MUST then send updated presence from this individual to all occupants, indicating the loss of membership by sending a presence element that contains an element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an child with the 'affiliation' attribute set to a value of \"none\".") - public void testMembershipRevokedInOpenRoom() throws Exception { - // Setup test fixture. - final EntityBareJid mucAddress = getRandomRoom("smack-inttest-participantstatus-membership-revoked-open"); - final MultiUserChat mucAsSeenByOwner = mucManagerOne.getMultiUserChat(mucAddress); - final MultiUserChat mucAsSeenByTarget = mucManagerTwo.getMultiUserChat(mucAddress); - - final EntityFullJid mucAddressOwner = JidCreate.entityFullFrom(mucAddress, Resourcepart.from("owner-" + randomString)); - final EntityFullJid mucAddressTarget = JidCreate.entityFullFrom(mucAddress, Resourcepart.from("target-" + randomString)); - - createMuc(mucAsSeenByOwner, mucAddressOwner.getResourcepart()); - try { - mucAsSeenByOwner.grantMembership(conTwo.getUser().asBareJid()); - mucAsSeenByTarget.join(mucAddressTarget.getResourcepart()); - - final SimpleResultSyncPoint ownerSeesRevoke = new SimpleResultSyncPoint(); - mucAsSeenByOwner.addParticipantStatusListener(new ParticipantStatusListener() { - @Override - public void membershipRevoked(EntityFullJid participant) { - if (mucAddressTarget.equals(participant)) { - ownerSeesRevoke.signal(); - } - } - }); - - // Execute system under test. - mucAsSeenByOwner.revokeMembership(conTwo.getUser().asBareJid()); - - // Verify result. - assertResult(ownerSeesRevoke, "Expected '" + conOne.getUser() + "' to be notified of the revocation of membership of '" + conTwo.getUser() + "' (using nickname '" + mucAddressTarget.getResourcepart() + "') in '" + mucAddress + "' (but did not)."); - } finally { - // Clean up test fixture. - tryDestroy(mucAsSeenByOwner); - } - } - - /** - * Verifies that when a member gets its membership removed in a members-only room, the appropriate event listeners are invoked. - * - * @throws Exception On unexpected results - */ - @SmackIntegrationTest(section = "9.4", quote = "An admin might want to revoke a user's membership [...] If the room is members-only, the service MUST remove the user from the room, including a status code of 321 to indicate that the user was removed because of an affiliation change, and inform all remaining occupants") - public void testMembershipRevokedInMemberOnlyRoom() throws Exception { - // Setup test fixture. - final EntityBareJid mucAddress = getRandomRoom("smack-inttest-participantstatus-membership-revoked-membersonly"); - final MultiUserChat mucAsSeenByOwner = mucManagerOne.getMultiUserChat(mucAddress); - final MultiUserChat mucAsSeenByTarget = mucManagerTwo.getMultiUserChat(mucAddress); - - final EntityFullJid mucAddressOwner = JidCreate.entityFullFrom(mucAddress, Resourcepart.from("owner-" + randomString)); - final EntityFullJid mucAddressTarget = JidCreate.entityFullFrom(mucAddress, Resourcepart.from("target-" + randomString)); - - createMembersOnlyMuc(mucAsSeenByOwner, mucAddressOwner.getResourcepart()); - try { - mucAsSeenByOwner.grantMembership(conTwo.getUser().asBareJid()); - mucAsSeenByTarget.join(mucAddressTarget.getResourcepart()); - - final SimpleResultSyncPoint ownerSeesRevoke = new SimpleResultSyncPoint(); - final SimpleResultSyncPoint ownerSeesDeparture = new SimpleResultSyncPoint(); - mucAsSeenByOwner.addParticipantStatusListener(new ParticipantStatusListener() { - @Override - public void membershipRevoked(EntityFullJid participant) { - if (mucAddressTarget.equals(participant)) { - ownerSeesRevoke.signal(); - } - } - - @Override - public void parted(EntityFullJid participant) { - if (mucAddressTarget.equals(participant)) { - ownerSeesDeparture.signal(); - } - } - }); - - // Execute system under test. - mucAsSeenByOwner.revokeMembership(conTwo.getUser().asBareJid()); - - // Verify result. - assertResult(ownerSeesRevoke, "Expected '" + conOne.getUser() + "' to be notified of the revocation of membership of '" + conTwo.getUser() + "' (using nickname '" + mucAddressTarget.getResourcepart() + "') in '" + mucAddress + "' (but did not)."); - assertResult(ownerSeesDeparture, "Expected '" + conOne.getUser() + "' to be notified of '" + conTwo.getUser() + "' (using nickname '" + mucAddressTarget.getResourcepart() + "') departing '" + mucAddress + "' (but did not)."); - } finally { - // Clean up test fixture. - tryDestroy(mucAsSeenByOwner); - } - } -} diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/UserStatusIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/UserStatusIntegrationTest.java deleted file mode 100644 index 201f1ba21..000000000 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/muc/UserStatusIntegrationTest.java +++ /dev/null @@ -1,129 +0,0 @@ -/** - * - * Copyright 2024 Guus der Kinderen - * - * 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.smackx.muc; - -import org.jivesoftware.smack.SmackException; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smackx.muc.packet.MUCUser; - -import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; -import org.igniterealtime.smack.inttest.TestNotPossibleException; -import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; -import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; -import org.jxmpp.jid.EntityBareJid; -import org.jxmpp.jid.EntityFullJid; -import org.jxmpp.jid.impl.JidCreate; -import org.jxmpp.jid.parts.Resourcepart; -import org.jxmpp.stringprep.XmppStringprepException; - -/** - * Tests that verify the correct functionality of Smack's {@link UserStatusListener}. - */ -@SpecificationReference(document = "XEP-0045", version = "1.34.6") -public class UserStatusIntegrationTest extends AbstractMultiUserChatIntegrationTest { - - public UserStatusIntegrationTest(SmackIntegrationTestEnvironment environment) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, TestNotPossibleException, MultiUserChatException.MucAlreadyJoinedException, MultiUserChatException.MissingMucCreationAcknowledgeException, XmppStringprepException, MultiUserChatException.NotAMucServiceException { - super(environment); - } - - /** - * Verifies that when a member gets its membership removed in an open room, the appropriate event listener is invoked. - * - * @throws Exception On unexpected results - */ - @SmackIntegrationTest(section = "9.4", quote = "An admin might want to revoke a user's membership [...] The service MUST then send updated presence from this individual to all occupants, indicating the loss of membership by sending a presence element that contains an element qualified by the 'http://jabber.org/protocol/muc#user' namespace and containing an child with the 'affiliation' attribute set to a value of \"none\".") - public void testMembershipRevokedInOpenRoom() throws Exception { - // Setup test fixture. - final EntityBareJid mucAddress = getRandomRoom("smack-inttest-userstatus-membership-revoked-membersonly"); - final MultiUserChat mucAsSeenByOwner = mucManagerOne.getMultiUserChat(mucAddress); - final MultiUserChat mucAsSeenByTarget = mucManagerTwo.getMultiUserChat(mucAddress); - - final EntityFullJid mucAddressOwner = JidCreate.entityFullFrom(mucAddress, Resourcepart.from("owner-" + randomString)); - final EntityFullJid mucAddressTarget = JidCreate.entityFullFrom(mucAddress, Resourcepart.from("target-" + randomString)); - - createMuc(mucAsSeenByOwner, mucAddressOwner.getResourcepart()); - try { - mucAsSeenByOwner.grantMembership(conTwo.getUser().asBareJid()); - mucAsSeenByTarget.join(mucAddressTarget.getResourcepart()); - - final SimpleResultSyncPoint targetSeesRevoke = new SimpleResultSyncPoint(); - mucAsSeenByTarget.addUserStatusListener(new UserStatusListener() { - @Override - public void membershipRevoked() { - targetSeesRevoke.signal(); - } - }); - - // Execute system under test. - mucAsSeenByOwner.revokeMembership(conTwo.getUser().asBareJid()); - - // Verify result. - assertResult(targetSeesRevoke, "Expected '" + conTwo.getUser() + "' (using nickname '" + mucAddressTarget.getResourcepart() + "') to be notified that their membership status was removed by '" + conOne.getUser() + "' (using nickname '" + mucAddressOwner.getResourcepart() + "') in '" + mucAddress + "' (but did not)."); - } finally { - // Clean up test fixture. - tryDestroy(mucAsSeenByOwner); - } - } - - /** - * Verifies that when a member gets its membership removed in a members-only room, the appropriate event listeners are invoked. - * - * @throws Exception On unexpected results - */ - @SmackIntegrationTest(section = "9.4", quote = "An admin might want to revoke a user's membership [...] If the room is members-only, the service MUST remove the user from the room, including a status code of 321 to indicate that the user was removed because of an affiliation change, and inform all remaining occupants") - public void testMembershipRevokedInMemberOnlyRoom() throws Exception { - // Setup test fixture. - final EntityBareJid mucAddress = getRandomRoom("smack-inttest-userstatus-membership-revoked-membersonly"); - final MultiUserChat mucAsSeenByOwner = mucManagerOne.getMultiUserChat(mucAddress); - final MultiUserChat mucAsSeenByTarget = mucManagerTwo.getMultiUserChat(mucAddress); - - final EntityFullJid mucAddressOwner = JidCreate.entityFullFrom(mucAddress, Resourcepart.from("owner-" + randomString)); - final EntityFullJid mucAddressTarget = JidCreate.entityFullFrom(mucAddress, Resourcepart.from("target-" + randomString)); - - createMembersOnlyMuc(mucAsSeenByOwner, mucAddressOwner.getResourcepart()); - try { - mucAsSeenByOwner.grantMembership(conTwo.getUser().asBareJid()); - mucAsSeenByTarget.join(mucAddressTarget.getResourcepart()); - - final SimpleResultSyncPoint targetSeesRevoke = new SimpleResultSyncPoint(); - final SimpleResultSyncPoint targetSeesRemove = new SimpleResultSyncPoint(); - mucAsSeenByTarget.addUserStatusListener(new UserStatusListener() { - @Override - public void removed(MUCUser mucUser, Presence presence) { - targetSeesRemove.signal(); - } - - @Override - public void membershipRevoked() { - targetSeesRevoke.signal(); - } - }); - - // Execute system under test. - mucAsSeenByOwner.revokeMembership(conTwo.getUser().asBareJid()); - - // Verify result. - assertResult(targetSeesRemove, "Expected '" + conTwo.getUser() + "' (using nickname '" + mucAddressTarget.getResourcepart() + "') to be notified that it is removed from '" + mucAddress + "' which is a member-only room, as their membership status was removed by '" + conOne.getUser() + "' (using nickname '" + mucAddressOwner.getResourcepart() + "') (but did not)."); - assertResult(targetSeesRevoke, "Expected '" + conTwo.getUser() + "' (using nickname '" + mucAddressTarget.getResourcepart() + "') to be notified that their membership status was removed by '" + conOne.getUser() + "' (using nickname '" + mucAddressOwner.getResourcepart() + "') in '" + mucAddress + "' (but did not)."); - } finally { - // Clean up test fixture. - tryDestroy(mucAsSeenByOwner); - } - } -} diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/AbstractTwoUsersOmemoIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/AbstractTwoUsersOmemoIntegrationTest.java index 995fc14a8..1720c0725 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/AbstractTwoUsersOmemoIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/AbstractTwoUsersOmemoIntegrationTest.java @@ -17,7 +17,7 @@ package org.jivesoftware.smackx.omemo; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import java.io.IOException; @@ -51,9 +51,7 @@ public abstract class AbstractTwoUsersOmemoIntegrationTest extends AbstractOmemo alice = OmemoManagerSetupHelper.prepareOmemoManager(conOne); bob = OmemoManagerSetupHelper.prepareOmemoManager(conTwo); - // TODO is this a test assertion, or a bug in the test implementation (in which case an Exception should be thrown instead). - assertNotEquals(alice.getDeviceId(), bob.getDeviceId(), - "Expected device ID for " + conOne.getUser() + " to differ from that of " + conTwo.getUser() + " (but they did not)"); + assertFalse(alice.getDeviceId().equals(bob.getDeviceId())); // Subscribe presences IntegrationTestRosterUtil.ensureBothAccountsAreSubscribedToEachOther(alice.getConnection(), bob.getConnection(), timeout); @@ -61,10 +59,8 @@ public abstract class AbstractTwoUsersOmemoIntegrationTest extends AbstractOmemo OmemoManagerSetupHelper.trustAllIdentitiesWithTests(alice, bob); // Alice trusts Bob's devices OmemoManagerSetupHelper.trustAllIdentitiesWithTests(bob, alice); // Bob trusts Alice' and Mallory's devices - assertEquals(bob.getOwnFingerprint(), alice.getActiveFingerprints(bob.getOwnJid()).get(bob.getOwnDevice()), - "Expected fingerprint of " + conTwo.getUser() + "'s device as known to " + conOne.getUser() + " to be equal to " + conTwo.getUser() + "'s own fingerprint (but it was not)."); - assertEquals(alice.getOwnFingerprint(), bob.getActiveFingerprints(alice.getOwnJid()).get(alice.getOwnDevice()), - "Expected fingerprint of " + conOne.getUser() + "'s device as known to " + conTwo.getUser() + " to be equal to " + conOne.getUser() + "'s own fingerprint (but it was not)."); + assertEquals(bob.getOwnFingerprint(), alice.getActiveFingerprints(bob.getOwnJid()).get(bob.getOwnDevice())); + assertEquals(alice.getOwnFingerprint(), bob.getActiveFingerprints(alice.getOwnJid()).get(alice.getOwnDevice())); } @AfterClass diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/MessageEncryptionIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/MessageEncryptionIntegrationTest.java index 5b489aef7..2efd1fb1a 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/MessageEncryptionIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/MessageEncryptionIntegrationTest.java @@ -29,14 +29,12 @@ import org.jivesoftware.smackx.omemo.element.OmemoBundleElement; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; /** * Simple OMEMO message encryption integration test. * During this test Alice sends an encrypted message to Bob. Bob decrypts it and sends a response to Alice. * It is checked whether the messages can be decrypted, and if used up pre-keys result in renewed bundles. */ -@SpecificationReference(document = "XEP-0384", version = "0.3.0") public class MessageEncryptionIntegrationTest extends AbstractTwoUsersOmemoIntegrationTest { public MessageEncryptionIntegrationTest(SmackIntegrationTestEnvironment environment) diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoMamDecryptionTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoMamDecryptionTest.java index f14fd1990..442643071 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoMamDecryptionTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoMamDecryptionTest.java @@ -35,13 +35,11 @@ import org.jivesoftware.smackx.omemo.util.MessageOrOmemoMessage; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; /** * This test sends a message from Alice to Bob, while Bob has automatic decryption disabled. * Then Bob fetches his Mam archive and decrypts the result. */ -@SpecificationReference(document = "XEP-0384", version = "0.3.0") public class OmemoMamDecryptionTest extends AbstractTwoUsersOmemoIntegrationTest { public OmemoMamDecryptionTest(SmackIntegrationTestEnvironment environment) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, @@ -73,12 +71,11 @@ public class OmemoMamDecryptionTest extends AbstractTwoUsersOmemoIntegrationTest alicesConnection.sendStanza(encrypted.buildMessage(messageBuilder, bob.getOwnJid())); MamManager.MamQuery query = bobsMamManager.queryArchive(MamManager.MamQueryArgs.builder().limitResultsToJid(alice.getOwnJid()).build()); - assertEquals(1, query.getMessageCount(), "Unexpected message count in MAM query result of " + bob.getConnection().getUser()); + assertEquals(1, query.getMessageCount()); List decryptedMamQuery = bob.decryptMamQueryResult(query); - assertEquals(1, decryptedMamQuery.size(), "Unexpected decrypted message count in MAM query result of " + bob.getConnection().getUser()); - assertEquals(body, decryptedMamQuery.get(decryptedMamQuery.size() - 1).getOmemoMessage().getBody(), - "Expected decrypted body of message retrieved via a MAM query to be equal to the original body that was sent (but it was not)."); + assertEquals(1, decryptedMamQuery.size()); + assertEquals(body, decryptedMamQuery.get(decryptedMamQuery.size() - 1).getOmemoMessage().getBody()); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoManagerSetupHelper.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoManagerSetupHelper.java index 7fdf53165..1a8093d63 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoManagerSetupHelper.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/OmemoManagerSetupHelper.java @@ -21,8 +21,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; +import java.util.HashMap; import java.util.List; -import java.util.Map; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException.NotConnectedException; @@ -54,7 +54,7 @@ public class OmemoManagerSetupHelper { } alice.requestDeviceListUpdateFor(bob.getOwnJid()); - Map fingerprints = alice.getActiveFingerprints(bob.getOwnJid()); + HashMap fingerprints = alice.getActiveFingerprints(bob.getOwnJid()); for (OmemoDevice device : fingerprints.keySet()) { OmemoFingerprint fingerprint = fingerprints.get(device); @@ -67,7 +67,7 @@ public class OmemoManagerSetupHelper { SmackException.NoResponseException, CannotEstablishOmemoSessionException, CorruptedOmemoKeyException, XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException, IOException { alice.requestDeviceListUpdateFor(bob.getOwnJid()); - Map fps1 = alice.getActiveFingerprints(bob.getOwnJid()); + HashMap fps1 = alice.getActiveFingerprints(bob.getOwnJid()); assertFalse(fps1.isEmpty()); assertAllDevicesAreUndecided(alice, fps1); @@ -75,7 +75,7 @@ public class OmemoManagerSetupHelper { trustAllIdentities(alice, bob); - Map fps2 = alice.getActiveFingerprints(bob.getOwnJid()); + HashMap fps2 = alice.getActiveFingerprints(bob.getOwnJid()); assertEquals(fps1.size(), fps2.size()); assertTrue(Maps.difference(fps1, fps2).areEqual()); @@ -95,28 +95,28 @@ public class OmemoManagerSetupHelper { return manager; } - public static void assertAllDevicesAreUndecided(OmemoManager manager, Map devices) { + public static void assertAllDevicesAreUndecided(OmemoManager manager, HashMap devices) { for (OmemoDevice device : devices.keySet()) { // All fingerprints MUST be neither decided, nor trusted. assertFalse(manager.isDecidedOmemoIdentity(device, devices.get(device))); } } - public static void assertAllDevicesAreUntrusted(OmemoManager manager, Map devices) { + public static void assertAllDevicesAreUntrusted(OmemoManager manager, HashMap devices) { for (OmemoDevice device : devices.keySet()) { // All fingerprints MUST be neither decided, nor trusted. assertFalse(manager.isTrustedOmemoIdentity(device, devices.get(device))); } } - public static void assertAllDevicesAreDecided(OmemoManager manager, Map devices) { + public static void assertAllDevicesAreDecided(OmemoManager manager, HashMap devices) { for (OmemoDevice device : devices.keySet()) { // All fingerprints MUST be neither decided, nor trusted. assertTrue(manager.isDecidedOmemoIdentity(device, devices.get(device))); } } - public static void assertAllDevicesAreTrusted(OmemoManager manager, Map devices) { + public static void assertAllDevicesAreTrusted(OmemoManager manager, HashMap devices) { for (OmemoDevice device : devices.keySet()) { // All fingerprints MUST be neither decided, nor trusted. assertTrue(manager.isTrustedOmemoIdentity(device, devices.get(device))); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/ReadOnlyDeviceIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/ReadOnlyDeviceIntegrationTest.java index b4daa8640..94c671962 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/ReadOnlyDeviceIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/ReadOnlyDeviceIntegrationTest.java @@ -32,9 +32,7 @@ import org.jivesoftware.smackx.omemo.exceptions.UndecidedOmemoIdentityException; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; -@SpecificationReference(document = "XEP-0384", version = "0.3.0") public class ReadOnlyDeviceIntegrationTest extends AbstractTwoUsersOmemoIntegrationTest { public ReadOnlyDeviceIntegrationTest(SmackIntegrationTestEnvironment environment) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, TestNotPossibleException { diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/SessionRenegotiationIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/SessionRenegotiationIntegrationTest.java index 0b3b15e79..c4a649911 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/SessionRenegotiationIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/omemo/SessionRenegotiationIntegrationTest.java @@ -24,9 +24,7 @@ import org.jivesoftware.smack.packet.MessageBuilder; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; -@SpecificationReference(document = "XEP-0384", version = "0.3.0") public class SessionRenegotiationIntegrationTest extends AbstractTwoUsersOmemoIntegrationTest { public SessionRenegotiationIntegrationTest(SmackIntegrationTestEnvironment environment) diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox/OXSecretKeyBackupIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox/OXSecretKeyBackupIntegrationTest.java index 93f936785..60e3361ad 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox/OXSecretKeyBackupIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox/OXSecretKeyBackupIntegrationTest.java @@ -38,7 +38,6 @@ import org.jivesoftware.smackx.ox.exception.MissingUserIdOnKeyException; import org.jivesoftware.smackx.ox.exception.NoBackupFoundException; import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore; import org.jivesoftware.smackx.ox.store.filebased.FileBasedOpenPgpStore; -import org.jivesoftware.smackx.ox.util.OpenPgpPubSubUtil; import org.jivesoftware.smackx.pubsub.PubSubException; import org.bouncycastle.openpgp.PGPException; @@ -49,11 +48,9 @@ import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.AfterClass; import org.igniterealtime.smack.inttest.annotations.BeforeClass; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.key.protection.UnprotectedKeysProtector; -@SpecificationReference(document = "XEP-0374", version = "0.2.0") public class OXSecretKeyBackupIntegrationTest extends AbstractOpenPgpIntegrationTest { private static final String sessionId = StringUtils.randomString(10); @@ -104,7 +101,7 @@ public class OXSecretKeyBackupIntegrationTest extends AbstractOpenPgpIntegration org.apache.commons.io.FileUtils.deleteDirectory(beforePath); } - @SmackIntegrationTest(section = "5") + @SmackIntegrationTest public void test() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException, IOException, InterruptedException, PubSubException.NotALeafNodeException, SmackException.NoResponseException, SmackException.NotConnectedException, XMPPException.XMPPErrorException, @@ -123,43 +120,38 @@ public class OXSecretKeyBackupIntegrationTest extends AbstractOpenPgpIntegration assertNull(self.getSigningKeyFingerprint()); OpenPgpV4Fingerprint keyFingerprint = openPgpManager.generateAndImportKeyPair(alice); + assertEquals(keyFingerprint, self.getSigningKeyFingerprint()); - try { - assertEquals(keyFingerprint, self.getSigningKeyFingerprint()); - assertTrue(self.getSecretKeys().contains(keyFingerprint.getKeyId())); + assertTrue(self.getSecretKeys().contains(keyFingerprint.getKeyId())); - PGPSecretKeyRing beforeSec = beforeStore.getSecretKeyRing(alice, keyFingerprint); - assertNotNull(beforeSec); + PGPSecretKeyRing beforeSec = beforeStore.getSecretKeyRing(alice, keyFingerprint); + assertNotNull(beforeSec); - PGPPublicKeyRing beforePub = beforeStore.getPublicKeyRing(alice, keyFingerprint); - assertNotNull(beforePub); + PGPPublicKeyRing beforePub = beforeStore.getPublicKeyRing(alice, keyFingerprint); + assertNotNull(beforePub); - OpenPgpSecretKeyBackupPassphrase backupPassphrase = + OpenPgpSecretKeyBackupPassphrase backupPassphrase = openPgpManager.backupSecretKeyToServer(availableSecretKeys -> availableSecretKeys); - FileBasedOpenPgpStore afterStore = new FileBasedOpenPgpStore(afterPath); - afterStore.setKeyRingProtector(new UnprotectedKeysProtector()); - PainlessOpenPgpProvider afterProvider = new PainlessOpenPgpProvider(afterStore); - openPgpManager.setOpenPgpProvider(afterProvider); + FileBasedOpenPgpStore afterStore = new FileBasedOpenPgpStore(afterPath); + afterStore.setKeyRingProtector(new UnprotectedKeysProtector()); + PainlessOpenPgpProvider afterProvider = new PainlessOpenPgpProvider(afterStore); + openPgpManager.setOpenPgpProvider(afterProvider); - OpenPgpV4Fingerprint fingerprint = openPgpManager.restoreSecretKeyServerBackup(() -> backupPassphrase); + OpenPgpV4Fingerprint fingerprint = openPgpManager.restoreSecretKeyServerBackup(() -> backupPassphrase); - assertEquals(keyFingerprint, fingerprint); + assertEquals(keyFingerprint, fingerprint); - assertTrue(self.getSecretKeys().contains(keyFingerprint.getKeyId())); + assertTrue(self.getSecretKeys().contains(keyFingerprint.getKeyId())); - assertEquals(keyFingerprint, self.getSigningKeyFingerprint()); + assertEquals(keyFingerprint, self.getSigningKeyFingerprint()); - PGPSecretKeyRing afterSec = afterStore.getSecretKeyRing(alice, keyFingerprint); - assertNotNull(afterSec); - assertArrayEquals(beforeSec.getEncoded(), afterSec.getEncoded()); + PGPSecretKeyRing afterSec = afterStore.getSecretKeyRing(alice, keyFingerprint); + assertNotNull(afterSec); + assertArrayEquals(beforeSec.getEncoded(), afterSec.getEncoded()); - PGPPublicKeyRing afterPub = afterStore.getPublicKeyRing(alice, keyFingerprint); - assertNotNull(afterPub); - assertArrayEquals(beforePub.getEncoded(), afterPub.getEncoded()); - } finally { - OpenPgpPubSubUtil.deletePublicKeyNode(alicePepManager, keyFingerprint); - OpenPgpPubSubUtil.deletePubkeysListNode(alicePepManager); - } + PGPPublicKeyRing afterPub = afterStore.getPublicKeyRing(alice, keyFingerprint); + assertNotNull(afterPub); + assertArrayEquals(beforePub.getEncoded(), afterPub.getEncoded()); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingIntegrationTest.java index 4467dde1f..683bc199a 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingIntegrationTest.java @@ -33,20 +33,17 @@ import org.jivesoftware.smackx.ox.OpenPgpManager; import org.jivesoftware.smackx.ox.crypto.PainlessOpenPgpProvider; import org.jivesoftware.smackx.ox.element.SigncryptElement; import org.jivesoftware.smackx.ox.store.filebased.FileBasedOpenPgpStore; -import org.jivesoftware.smackx.ox.util.OpenPgpPubSubUtil; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.AfterClass; import org.igniterealtime.smack.inttest.annotations.BeforeClass; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; import org.pgpainless.decryption_verification.OpenPgpMetadata; import org.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.key.protection.UnprotectedKeysProtector; -@SpecificationReference(document = "XEP-0374", version = "0.2.0") public class OXInstantMessagingIntegrationTest extends AbstractOpenPgpIntegrationTest { private static final String sessionId = StringUtils.randomString(10); @@ -140,33 +137,26 @@ public class OXInstantMessagingIntegrationTest extends AbstractOpenPgpIntegratio aliceFingerprint = aliceOpenPgp.generateAndImportKeyPair(alice); bobFingerprint = bobOpenPgp.generateAndImportKeyPair(bob); - try { - aliceOpenPgp.announceSupportAndPublish(); - bobOpenPgp.announceSupportAndPublish(); + aliceOpenPgp.announceSupportAndPublish(); + bobOpenPgp.announceSupportAndPublish(); - OpenPgpContact bobForAlice = aliceOpenPgp.getOpenPgpContact(bob.asEntityBareJidIfPossible()); - OpenPgpContact aliceForBob = bobOpenPgp.getOpenPgpContact(alice.asEntityBareJidIfPossible()); + OpenPgpContact bobForAlice = aliceOpenPgp.getOpenPgpContact(bob.asEntityBareJidIfPossible()); + OpenPgpContact aliceForBob = bobOpenPgp.getOpenPgpContact(alice.asEntityBareJidIfPossible()); - bobForAlice.updateKeys(aliceConnection); + bobForAlice.updateKeys(aliceConnection); - assertFalse(bobForAlice.isTrusted(bobFingerprint)); - assertFalse(aliceForBob.isTrusted(aliceFingerprint)); + assertFalse(bobForAlice.isTrusted(bobFingerprint)); + assertFalse(aliceForBob.isTrusted(aliceFingerprint)); - bobForAlice.trust(bobFingerprint); - aliceForBob.trust(aliceFingerprint); + bobForAlice.trust(bobFingerprint); + aliceForBob.trust(aliceFingerprint); - assertTrue(bobForAlice.isTrusted(bobFingerprint)); - assertTrue(aliceForBob.isTrusted(aliceFingerprint)); + assertTrue(bobForAlice.isTrusted(bobFingerprint)); + assertTrue(aliceForBob.isTrusted(aliceFingerprint)); - aliceInstantMessaging.sendOxMessage(bobForAlice, body); + aliceInstantMessaging.sendOxMessage(bobForAlice, body); - bobReceivedMessage.waitForResult(timeout); - } finally { - OpenPgpPubSubUtil.deletePublicKeyNode(alicePepManager, aliceFingerprint); - OpenPgpPubSubUtil.deletePubkeysListNode(alicePepManager); - OpenPgpPubSubUtil.deletePublicKeyNode(bobPepManager, bobFingerprint); - OpenPgpPubSubUtil.deletePubkeysListNode(bobPepManager); - } + bobReceivedMessage.waitForResult(timeout); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/package-info.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/package-info.java index bce3b6064..7ebe86244 120000 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/package-info.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/package-info.java @@ -1 +1 @@ -../../../../../../../smack-java11-full/src/main/java/org/jivesoftware/smackx/package-info.java \ No newline at end of file +../../../../../../../smack-java8-full/src/main/java/org/jivesoftware/smackx/package-info.java \ No newline at end of file diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/ping/PingIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/ping/PingIntegrationTest.java index a2cbce7ce..65c683093 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/ping/PingIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/ping/PingIntegrationTest.java @@ -35,10 +35,8 @@ import org.jivesoftware.smack.XMPPConnection; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.jxmpp.jid.Jid; -@SpecificationReference(document = "XEP-0199", version = "2.0.1") public class PingIntegrationTest extends AbstractSmackIntegrationTest { public PingIntegrationTest(SmackIntegrationTestEnvironment environment) { diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/pubsub/PubSubIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/pubsub/PubSubIntegrationTest.java index d3f990a4a..1890caf2d 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/pubsub/PubSubIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/pubsub/PubSubIntegrationTest.java @@ -34,10 +34,8 @@ import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.TestNotPossibleException; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.jxmpp.jid.DomainBareJid; -@SpecificationReference(document = "XEP-0060", version = "1.26.0") public class PubSubIntegrationTest extends AbstractSmackIntegrationTest { private final PubSubManager pubSubManagerOne; @@ -84,10 +82,21 @@ public class PubSubIntegrationTest extends AbstractSmackIntegrationTest { } } + /** + + */ + /** * Asserts that an error is returned when a publish request to a node that is both * 'notification-only' as well as 'transient' contains an item element. * + *

    From XEP-0060 § 7.1.3.6:

    + *
    + * If the event type is notification + transient and the publisher provides an item, + * the service MUST bounce the publication request with a <bad-request/> error + * and a pubsub-specific error condition of <item-forbidden/>. + *
    + * * @throws NoResponseException if there was no response from the remote entity. * @throws XMPPErrorException if there was an XMPP error returned. * @throws NotConnectedException if the XMPP connection is not connected. @@ -95,9 +104,7 @@ public class PubSubIntegrationTest extends AbstractSmackIntegrationTest { * @see * 7.1.3.6 Request Does Not Match Configuration */ - @SmackIntegrationTest(section = "7.1.3.6", quote = - "If the event type is notification + transient and the publisher provides an item, the service MUST bounce " + - "the publication request with a error and a pubsub-specific error condition of .") + @SmackIntegrationTest public void transientNotificationOnlyNodeWithItemTest() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { final String nodename = "sinttest-transient-notificationonly-withitem-nodename-" + testRunId; final String itemId = "sinttest-transient-notificationonly-withitem-itemid-" + testRunId; @@ -113,7 +120,7 @@ public class PubSubIntegrationTest extends AbstractSmackIntegrationTest { // Add a dummy payload. If there is no payload, but just an item ID, then ejabberd will *not* return an error, // which I believe to be non-compliant behavior (although, granted, the XEP is not very clear about this). A user // which sends an empty item with ID to an node that is configured to be notification-only and transient probably - // does something wrong, as the item's ID will never appear anywhere. Hence, it would be nice if the user would be + // does something wrong, as the item's ID will never appear anywhere. Hence it would be nice if the user would be // made aware of this issue by returning an error. Sadly ejabberd does not do so. // See also https://github.com/processone/ejabberd/issues/2864#issuecomment-500741915 final StandardExtensionElement dummyPayload = StandardExtensionElement.builder("dummy-payload", @@ -125,9 +132,9 @@ public class PubSubIntegrationTest extends AbstractSmackIntegrationTest { Item item = new PayloadItem<>(itemId, dummyPayload); leafNode.publish(item); - }, "Expected an error after publishing item " + itemId + " (but none occurred)."); - assertEquals(StanzaError.Type.MODIFY, e.getStanzaError().getType(), "Unexpected error type"); - assertNotNull(e.getStanzaError().getExtension("item-forbidden", "http://jabber.org/protocol/pubsub#errors"), "Expected error to contain 'item-forbidden', but it did not."); + }); + assertEquals(StanzaError.Type.MODIFY, e.getStanzaError().getType()); + assertNotNull(e.getStanzaError().getExtension("item-forbidden", "http://jabber.org/protocol/pubsub#errors")); } finally { pubSubManagerOne.deleteNode(nodename); diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/softwareInfo/SoftwareInfoIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/softwareInfo/SoftwareInfoIntegrationTest.java index f01371f10..3bf111f53 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/softwareInfo/SoftwareInfoIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/softwareInfo/SoftwareInfoIntegrationTest.java @@ -31,13 +31,10 @@ import org.jivesoftware.smackx.softwareinfo.form.SoftwareInfoForm; import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; -import org.igniterealtime.smack.inttest.annotations.AfterClass; import org.igniterealtime.smack.inttest.annotations.BeforeClass; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.igniterealtime.smack.inttest.util.IntegrationTestRosterUtil; -@SpecificationReference(document = "XEP-0232", version = "0.3") public class SoftwareInfoIntegrationTest extends AbstractSmackIntegrationTest { public final SoftwareInfoManager sim1; @@ -55,11 +52,6 @@ public class SoftwareInfoIntegrationTest extends AbstractSmackIntegrationTest { IntegrationTestRosterUtil.ensureBothAccountsAreSubscribedToEachOther(conOne, conTwo, timeout); } - @AfterClass - public void cleanUp() throws Exception { - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); - } - @SmackIntegrationTest public void test() throws Exception { SoftwareInfoForm softwareInfoSent = createSoftwareInfoForm(); @@ -70,8 +62,7 @@ public class SoftwareInfoIntegrationTest extends AbstractSmackIntegrationTest { } }); SoftwareInfoForm softwareInfoFormReceived = sim2.fromJid(conOne.getUser()); - assertEquals(softwareInfoSent, softwareInfoFormReceived, - "Expected " + conOne.getUser() + "'s software version info as received by " + conTwo.getUser() + " to be equal to what " + conOne.getUser() + " publishes (but it is not)."); + assertEquals(softwareInfoSent, softwareInfoFormReceived); } private static SoftwareInfoForm createSoftwareInfoForm() throws URISyntaxException { diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/usertune/UserTuneIntegrationTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/usertune/UserTuneIntegrationTest.java index e204031c4..653bded72 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/usertune/UserTuneIntegrationTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/usertune/UserTuneIntegrationTest.java @@ -17,6 +17,7 @@ package org.jivesoftware.smackx.usertune; import java.net.URI; +import java.util.concurrent.TimeoutException; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException.NotLoggedInException; @@ -31,12 +32,10 @@ import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest; import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment; import org.igniterealtime.smack.inttest.annotations.AfterClass; import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest; -import org.igniterealtime.smack.inttest.annotations.SpecificationReference; import org.igniterealtime.smack.inttest.util.IntegrationTestRosterUtil; import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint; import org.junit.jupiter.api.Assertions; -@SpecificationReference(document = "XEP-0118", version = "1.3.0") public class UserTuneIntegrationTest extends AbstractSmackIntegrationTest { private final UserTuneManager utm1; @@ -98,7 +97,6 @@ public class UserTuneIntegrationTest extends AbstractSmackIntegrationTest { Assertions.assertNotNull(result, "Expected to receive a PEP notification, but did not."); } finally { unregisterListener(utm2, userTuneListener); - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); } } @@ -140,10 +138,16 @@ public class UserTuneIntegrationTest extends AbstractSmackIntegrationTest { registerListenerAndWait(utm2, ServiceDiscoveryManager.getInstanceFor(conTwo), userTuneListener); // Wait for the data to be received. - assertResult(userTuneReceived, "Expected " + conTwo.getUser() + " to receive a PEP notification from " + conOne.getUser() + ", but did not."); + try { + Object result = userTuneReceived.waitForResult(timeout); + + // Explicitly assert the success case. + Assertions.assertNotNull(result, "Expected to receive a PEP notification, but did not."); + } catch (TimeoutException e) { + Assertions.fail("Expected to receive a PEP notification, but did not."); + } } finally { unregisterListener(utm2, userTuneListener); - IntegrationTestRosterUtil.ensureBothAccountsAreNotInEachOthersRoster(conOne, conTwo); } } diff --git a/smack-integration-test/src/main/java/org/jivesoftware/smackx/xdata/FormTest.java b/smack-integration-test/src/main/java/org/jivesoftware/smackx/xdata/FormTest.java index 9e127b85e..64b4db597 100644 --- a/smack-integration-test/src/main/java/org/jivesoftware/smackx/xdata/FormTest.java +++ b/smack-integration-test/src/main/java/org/jivesoftware/smackx/xdata/FormTest.java @@ -128,29 +128,28 @@ public class FormTest extends AbstractSmackIntegrationTest { completedForm.setAnswer("time", true); completedForm.setAnswer("age", 20); // Create a new message to send with the completed form - Message msg3 = StanzaBuilder.buildMessage() + msg2 = StanzaBuilder.buildMessage() .to(conOne.getUser().asBareJid()) - .setThread(msg2.getThread()) + .setThread(msg.getThread()) .ofType(Message.Type.chat) .setBody("To enter a case please fill out this form and send it back to me") // Add the completed form to the message .addExtension(completedForm.getDataFormToSubmit()) .build(); // Send the message with the completed form - conTwo.sendStanza(msg3); + conTwo.sendStanza(msg2); // Get the message with the completed form - Message msg4 = collector.nextResult(); - assertNotNull(msg4, "Message not found"); + Message msg3 = collector.nextResult(); + assertNotNull(msg3, "Message not found"); // Retrieve the completed form - final DataForm completedForm2 = DataForm.from(msg4); + final DataForm completedForm2 = DataForm.from(msg3); assertNotNull(completedForm2); assertNotNull(completedForm2.getField("name")); assertNotNull(completedForm2.getField("description")); assertEquals( - "Credit card number invalid", - completedForm2.getField("name").getValues().get(0).toString() - ); + completedForm2.getField("name").getValues().get(0).toString(), + "Credit card number invalid"); assertNotNull(completedForm2.getField("time")); assertNotNull(completedForm2.getField("age")); assertEquals("20", completedForm2.getField("age").getValues().get(0).toString(), "The age is bad"); diff --git a/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/ConfigurationTest.java b/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/ConfigurationTest.java deleted file mode 100644 index 727b8a756..000000000 --- a/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/ConfigurationTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * - * Copyright 2024 Guus der Kinderen - * - * 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.igniterealtime.smack.inttest; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.Test; - -/** - * Verifies the functionality that's implemented in {@link Configuration}. - */ -public class ConfigurationTest { - @Test - public void testNormalizeXepUpperCaseNoSeperator() { - // Setup test fixture. - final String input = "XEP0001"; - - // Execute system under test. - final String output = Configuration.normalizeSpecification(input); - - // Verify results. - assertEquals("XEP0001", output); - } - - @Test - public void testNormalizeXepLowerCaseNoSeperator() { - // Setup test fixture. - final String input = "xep0001"; - - // Execute system under test. - final String output = Configuration.normalizeSpecification(input); - - // Verify results. - assertEquals("XEP0001", output); - } - - @Test - public void testNormalizeXepUpperCaseDash() { - // Setup test fixture. - final String input = "XEP-0001"; - - // Execute system under test. - final String output = Configuration.normalizeSpecification(input); - - // Verify results. - assertEquals("XEP0001", output); - } - - @Test - public void testNormalizeXepLowerCaseDash() { - // Setup test fixture. - final String input = "xep-0001"; - - // Execute system under test. - final String output = Configuration.normalizeSpecification(input); - - // Verify results. - assertEquals("XEP0001", output); - } - - @Test - public void testNormalizeXepUpperCaseSpace() { - // Setup test fixture. - final String input = "XEP 0001"; - - // Execute system under test. - final String output = Configuration.normalizeSpecification(input); - - // Verify results. - assertEquals("XEP0001", output); - } - - @Test - public void testNormalizeXepLowerCaseSpace() { - // Setup test fixture. - final String input = "xep 0001"; - - // Execute system under test. - final String output = Configuration.normalizeSpecification(input); - - // Verify results. - assertEquals("XEP0001", output); - } -} diff --git a/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/SmackIntegrationTestFrameWorkTest.java b/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/SmackIntegrationTestFrameWorkTest.java index fbdfa8cef..48b827770 100644 --- a/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/SmackIntegrationTestFrameWorkTest.java +++ b/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/SmackIntegrationTestFrameWorkTest.java @@ -31,26 +31,26 @@ import org.junit.jupiter.api.Test; public class SmackIntegrationTestFrameWorkTest { private static class ValidLowLevelList { - @SuppressWarnings({"unused", "MethodCanBeStatic"}) + @SuppressWarnings("unused") public void test(List connections) { } } private static class InvalidLowLevelList { - @SuppressWarnings({"unused", "MethodCanBeStatic"}) + @SuppressWarnings("unused") public void test(List connections, boolean invalid) { } } private static class ValidLowLevelVarargs { - @SuppressWarnings({"unused", "MethodCanBeStatic"}) + @SuppressWarnings("unused") public void test(AbstractXMPPConnection connectionOne, AbstractXMPPConnection connectionTwo, AbstractXMPPConnection connectionThree) { } } private static class InvalidLowLevelVarargs { - @SuppressWarnings({"unused", "MethodCanBeStatic"}) + @SuppressWarnings("unused") public void test(AbstractXMPPConnection connectionOne, Integer invalid, AbstractXMPPConnection connectionTwo, AbstractXMPPConnection connectionThree) { } @@ -97,7 +97,7 @@ public class SmackIntegrationTestFrameWorkTest { } private static class ValidUnconnectedConnectionSource { - @SuppressWarnings({"unused", "MethodCanBeStatic"}) + @SuppressWarnings("unused") public void test(AbstractSmackLowLevelIntegrationTest.UnconnectedConnectionSource source) { } } diff --git a/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/SmackIntegrationTestXmppConnectionManagerTest.java b/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/SmackIntegrationTestXmppConnectionManagerTest.java index d8aa16015..7a2de6097 100644 --- a/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/SmackIntegrationTestXmppConnectionManagerTest.java +++ b/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/SmackIntegrationTestXmppConnectionManagerTest.java @@ -43,7 +43,7 @@ public class SmackIntegrationTestXmppConnectionManagerTest { ModularXmppClientToServerConnection.class, ModularXmppClientToServerConnectionConfiguration.class, ModularXmppClientToServerConnectionConfiguration.Builder.class) - .applyExtraConfiguration(b -> b.removeAllModules().addModule(XmppTcpTransportModuleDescriptor.class)) + .applyExtraConfguration(b -> b.removeAllModules().addModule(XmppTcpTransportModuleDescriptor.class)) .build(); Configuration sinttestConfiguration = Configuration.builder().setService("example.org").build(); diff --git a/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/util/MultiResultSyncPointTest.java b/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/util/MultiResultSyncPointTest.java deleted file mode 100644 index 5a4db37c4..000000000 --- a/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/util/MultiResultSyncPointTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * - * Copyright 2024 Guus der Kinderen - * - * 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.igniterealtime.smack.inttest.util; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -import java.util.List; -import java.util.concurrent.BrokenBarrierException; -import java.util.concurrent.CyclicBarrier; -import java.util.concurrent.TimeoutException; - -import org.jivesoftware.smack.util.Async; - -import org.junit.jupiter.api.Test; - -public class MultiResultSyncPointTest { - @Test - public void testResultSyncPoint() throws Exception { - final String result1 = "r1"; - final String result2 = "r2"; - final CyclicBarrier barrier = new CyclicBarrier(2); - final MultiResultSyncPoint rsp = new MultiResultSyncPoint<>(2); - Async.go(new Async.ThrowingRunnable() { - @Override - public void runOrThrow() throws InterruptedException, BrokenBarrierException { - barrier.await(); - rsp.signal(result1); - rsp.signal(result2); - } - }); - barrier.await(); - List receivedResult = rsp.waitForResults(60 * 1000); - assertTrue(receivedResult.contains(result1)); - assertTrue(receivedResult.contains(result2)); - } - - @Test - public void exceptionTestResultSyncPoint() throws Exception { - final CyclicBarrier barrier = new CyclicBarrier(2); - final ResultSyncPoint rsp = new ResultSyncPoint<>(); - Async.go(new Async.ThrowingRunnable() { - @Override - public void runOrThrow() throws InterruptedException, BrokenBarrierException { - barrier.await(); - rsp.signal(new MultiResultSyncPointTest.TestException()); - } - }); - barrier.await(); - assertThrows(MultiResultSyncPointTest.TestException.class, () -> rsp.waitForResult(60 * 1000)); - } - - @Test - public void testTimeout() throws Exception { - final MultiResultSyncPoint rsp = new MultiResultSyncPoint<>(2); - try { - rsp.waitForResults(100); - fail("A timeout exception should have been thrown."); - } catch (TimeoutException e) { - // Expected - } - } - - @Test - public void testTimeoutWithOneResult() throws Exception { - final String result1 = "partial"; - final CyclicBarrier barrier = new CyclicBarrier(2); - final MultiResultSyncPoint rsp = new MultiResultSyncPoint<>(2); - Async.go(new Async.ThrowingRunnable() { - @Override - public void runOrThrow() throws InterruptedException, BrokenBarrierException { - barrier.await(); - rsp.signal(result1); - } - }); - barrier.await(); - try { - rsp.waitForResults(100); - fail("A timeout exception should have been thrown."); - } catch (TimeoutException e) { - // Expected - } - } - - private static class TestException extends Exception { - - /** - * - */ - private static final long serialVersionUID = 1L; - - } -} diff --git a/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/util/ResultSyncPointTest.java b/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/util/ResultSyncPointTest.java index c6e22bd72..589880204 100644 --- a/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/util/ResultSyncPointTest.java +++ b/smack-integration-test/src/test/java/org/igniterealtime/smack/inttest/util/ResultSyncPointTest.java @@ -18,11 +18,9 @@ package org.igniterealtime.smack.inttest.util; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.fail; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; -import java.util.concurrent.TimeoutException; import org.jivesoftware.smack.util.Async; @@ -62,17 +60,6 @@ public class ResultSyncPointTest { assertThrows(TestException.class, () -> rsp.waitForResult(60 * 1000)); } - @Test - public void testTimeout() throws Exception { - final MultiResultSyncPoint rsp = new MultiResultSyncPoint<>(2); - try { - rsp.waitForResults(100); - fail("A timeout exception should have been thrown."); - } catch (TimeoutException e) { - // Expected - } - } - private static class TestException extends Exception { /** diff --git a/smack-java11-full/build.gradle b/smack-java8-full/build.gradle similarity index 91% rename from smack-java11-full/build.gradle rename to smack-java8-full/build.gradle index 4f4bf0652..7607d3c02 100644 --- a/smack-java11-full/build.gradle +++ b/smack-java8-full/build.gradle @@ -1,7 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' -} - description = """\ Full Smack library for Java SE.""" @@ -10,7 +6,7 @@ dependencies { api project(':smack-debug') api project(':smack-experimental') api project(':smack-extensions') - api project(':smack-java11') + api project(':smack-java8') api project(':smack-legacy') api project(':smack-omemo') api project(':smack-openpgp') @@ -48,7 +44,6 @@ task convertModularXmppClientToServerConnectionStateGraphDotToPng(type: Exec) { executable 'dot' args "-Tpng", "-o", "${outputs.files.first()}", "${inputs.files.first()}" } -copyJavadocDocFiles.dependsOn convertModularXmppClientToServerConnectionStateGraphDotToPng task cleanGenerateFiles(type: Delete) { delete 'src/javadoc/org/jivesoftware/smack/full/doc-files/ModularXmppClientToServerConnectionStateGraph.dot', 'src/javadoc/org/jivesoftware/smack/full/doc-files/ModularXmppClientToServerConnectionStateGraph.png' diff --git a/smack-java11-full/src/javadoc/org/jivesoftware/smack/full/doc-files/.gitignore b/smack-java8-full/src/javadoc/org/jivesoftware/smack/full/doc-files/.gitignore similarity index 100% rename from smack-java11-full/src/javadoc/org/jivesoftware/smack/full/doc-files/.gitignore rename to smack-java8-full/src/javadoc/org/jivesoftware/smack/full/doc-files/.gitignore diff --git a/smack-examples/src/main/java/org/igniterealtime/smack/examples/BoshConnectionTest.java b/smack-java8-full/src/main/java/org/jivesoftware/smack/full/BoshConnectionTest.java similarity index 65% rename from smack-examples/src/main/java/org/igniterealtime/smack/examples/BoshConnectionTest.java rename to smack-java8-full/src/main/java/org/jivesoftware/smack/full/BoshConnectionTest.java index 3d18c7365..4063c72ff 100644 --- a/smack-examples/src/main/java/org/igniterealtime/smack/examples/BoshConnectionTest.java +++ b/smack-java8-full/src/main/java/org/jivesoftware/smack/full/BoshConnectionTest.java @@ -2,23 +2,19 @@ * * Copyright 2022 Florian Schmaus. * - * This file is part of smack-examples. + * 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 * - * smack-examples is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * 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.igniterealtime.smack.examples; +package org.jivesoftware.smack.full; import java.io.IOException; diff --git a/smack-java11-full/src/main/java/org/jivesoftware/smack/full/ModularXmppClientToServerConnectionTool.java b/smack-java8-full/src/main/java/org/jivesoftware/smack/full/ModularXmppClientToServerConnectionTool.java similarity index 100% rename from smack-java11-full/src/main/java/org/jivesoftware/smack/full/ModularXmppClientToServerConnectionTool.java rename to smack-java8-full/src/main/java/org/jivesoftware/smack/full/ModularXmppClientToServerConnectionTool.java diff --git a/smack-java8-full/src/main/java/org/jivesoftware/smack/full/WebSocketConnectionTest.java b/smack-java8-full/src/main/java/org/jivesoftware/smack/full/WebSocketConnectionTest.java new file mode 100644 index 000000000..54c3d30d5 --- /dev/null +++ b/smack-java8-full/src/main/java/org/jivesoftware/smack/full/WebSocketConnectionTest.java @@ -0,0 +1,110 @@ +/** + * + * Copyright 2021 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.full; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Date; +import java.util.logging.Logger; + +import org.jivesoftware.smack.SmackConfiguration; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; + +import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection; +import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnectionConfiguration; +import org.jivesoftware.smack.debugger.ConsoleDebugger; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.websocket.XmppWebSocketTransportModuleDescriptor; +import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; + +import org.jxmpp.util.XmppDateTime; + +public class WebSocketConnectionTest { + + static { + SmackConfiguration.DEBUG = true; + } + + public static void main(String[] args) + throws URISyntaxException, SmackException, IOException, XMPPException, InterruptedException { + String jid, password, websocketEndpoint, messageTo = null; + if (args.length < 3 || args.length > 4) { + throw new IllegalArgumentException(); + } + + jid = args[0]; + password = args[1]; + websocketEndpoint = args[2]; + if (args.length >= 4) { + messageTo = args[3]; + } + + testWebSocketConnection(jid, password, websocketEndpoint, messageTo); + } + + public static void testWebSocketConnection(String jid, String password, String websocketEndpoint) + throws URISyntaxException, SmackException, IOException, XMPPException, InterruptedException { + testWebSocketConnection(jid, password, websocketEndpoint, null); + } + + public static void testWebSocketConnection(String jid, String password, String websocketEndpoint, String messageTo) + throws URISyntaxException, SmackException, IOException, XMPPException, InterruptedException { + ModularXmppClientToServerConnectionConfiguration.Builder builder = ModularXmppClientToServerConnectionConfiguration.builder(); + builder.removeAllModules() + .setXmppAddressAndPassword(jid, password) + .setDebuggerFactory(ConsoleDebugger.Factory.INSTANCE) + ; + + XmppWebSocketTransportModuleDescriptor.Builder websocketBuilder = XmppWebSocketTransportModuleDescriptor.getBuilder(builder); + websocketBuilder.explicitlySetWebSocketEndpointAndDiscovery(websocketEndpoint, false); + builder.addModule(websocketBuilder.build()); + + ModularXmppClientToServerConnectionConfiguration config = builder.build(); + ModularXmppClientToServerConnection connection = new ModularXmppClientToServerConnection(config); + + connection.setReplyTimeout(5 * 60 * 1000); + + connection.addConnectionStateMachineListener((event, c) -> { + Logger.getAnonymousLogger().info("Connection event: " + event); + }); + + connection.connect(); + + connection.login(); + + if (messageTo != null) { + Message message = connection.getStanzaFactory().buildMessageStanza() + .to(messageTo) + .setBody("It is alive! " + XmppDateTime.formatXEP0082Date(new Date())) + .build() + ; + connection.sendStanza(message); + } + + Thread.sleep(1000); + + connection.disconnect(); + + ModularXmppClientToServerConnection.Stats connectionStats = connection.getStats(); + ServiceDiscoveryManager.Stats serviceDiscoveryManagerStats = ServiceDiscoveryManager.getInstanceFor(connection).getStats(); + + // CHECKSTYLE:OFF + System.out.println("WebSocket successfully finished, yeah!\n" + connectionStats + '\n' + serviceDiscoveryManagerStats); + // CHECKSTYLE:ON + } +} diff --git a/smack-java11-full/src/main/java/org/jivesoftware/smack/full/package-info.java b/smack-java8-full/src/main/java/org/jivesoftware/smack/full/package-info.java similarity index 100% rename from smack-java11-full/src/main/java/org/jivesoftware/smack/full/package-info.java rename to smack-java8-full/src/main/java/org/jivesoftware/smack/full/package-info.java diff --git a/smack-java11-full/src/main/java/org/jivesoftware/smackx/SmackExtensions.java b/smack-java8-full/src/main/java/org/jivesoftware/smackx/SmackExtensions.java similarity index 94% rename from smack-java11-full/src/main/java/org/jivesoftware/smackx/SmackExtensions.java rename to smack-java8-full/src/main/java/org/jivesoftware/smackx/SmackExtensions.java index 186562bba..8ec3ad057 100644 --- a/smack-java11-full/src/main/java/org/jivesoftware/smackx/SmackExtensions.java +++ b/smack-java8-full/src/main/java/org/jivesoftware/smackx/SmackExtensions.java @@ -18,7 +18,7 @@ package org.jivesoftware.smackx; /** * This is just a dummy class, please head over to {@link org.jivesoftware.smackx} for more information on Smack - * extensions. The dummy class causes javadoc generate the HTML for smackx.package-info.java, which would otherwise be + * extensions. The dummy class causes javadoc generate the HTML for smackx.pacakge-info.java, which would otherwise be * not generated, as org.jivesoftware.smackx is an empty package (see * JDK-4492654). */ diff --git a/smack-java11-full/src/main/java/org/jivesoftware/smackx/package-info.java b/smack-java8-full/src/main/java/org/jivesoftware/smackx/package-info.java similarity index 94% rename from smack-java11-full/src/main/java/org/jivesoftware/smackx/package-info.java rename to smack-java8-full/src/main/java/org/jivesoftware/smackx/package-info.java index 0769f65ba..8b3550028 100644 --- a/smack-java11-full/src/main/java/org/jivesoftware/smackx/package-info.java +++ b/smack-java8-full/src/main/java/org/jivesoftware/smackx/package-info.java @@ -71,7 +71,7 @@ * Extended Stanza Addressing * XEP-0033 * - * Allows to include headers in stanzas in order to specify multiple recipients or sub-addresses. + * Allows to include headers in stanzas in order to specifiy multiple recipients or sub-addresses. * * * Multi User Chat @@ -206,18 +206,6 @@ * Transfer files between two users over XMPP. * * - * URL Address Information - * XEP-0103 - * {@link org.jivesoftware.smackx.urldata.element} - * Provide information about an Uniform Resource Locator (URL), and a protocol signaling retrieval states. - * - * - * HTTP Scheme for URL Data - * XEP-0104 - * - * A schema description for detailed information about HTTP URLs. - * - * * User Mood * XEP-0107 * @@ -370,12 +358,6 @@ * Allows sending a MUC invitation directly from the user to the contact with mediation by the room. * * - * Jingle Content Thumbnails - * XEP-0264 - * {@link org.jivesoftware.smackx.thumbnails.element} - * Defines a way for a client to supply a preview image for Jingle content. - * - * * Message Carbons * XEP-0280 * {@link org.jivesoftware.smackx.carbons} @@ -477,7 +459,7 @@ * Data Forms Geolocation Element * XEP-0350 * - * Allows to include XEP-0080 geolocation data in XEP-0004 data forms. + * Allows to include XEP-0080 gelocation data in XEP-0004 data forms. * * * Client State Indication @@ -511,7 +493,7 @@ * * * References - * XEP-0372 + * XEP-0372 * * Add references like mentions or external data to stanzas. * @@ -589,12 +571,6 @@ * Declare body elements of a message as ignorable fallback for naive legacy clients. * * - * File metadata element - * XEP-0446 - * {@link org.jivesoftware.smackx.file_metadata.element} - * Defines a generic file metadata element to be used in other specifications. - * - * * Google GCM JSON payload * * @@ -608,6 +584,12 @@ * Multi-User Chats for mobile XMPP applications and specific environment. * * + * Group Chat Invitations + * + * + * Send invitations to other users to join a group chat room. + * + * * Jive Properties * * diff --git a/smack-java11-full/src/test/java/org/jivesoftware/smack/full/ExtensionElementQNameDeclaredTest.java b/smack-java8-full/src/test/java/org/jivesoftware/smack/full/ExtensionElementQNameDeclaredTest.java similarity index 100% rename from smack-java11-full/src/test/java/org/jivesoftware/smack/full/ExtensionElementQNameDeclaredTest.java rename to smack-java8-full/src/test/java/org/jivesoftware/smack/full/ExtensionElementQNameDeclaredTest.java diff --git a/smack-java11-full/src/test/java/org/jivesoftware/smack/full/ModularXmppClientToServerConnectionStateGraphTest.java b/smack-java8-full/src/test/java/org/jivesoftware/smack/full/ModularXmppClientToServerConnectionStateGraphTest.java similarity index 100% rename from smack-java11-full/src/test/java/org/jivesoftware/smack/full/ModularXmppClientToServerConnectionStateGraphTest.java rename to smack-java8-full/src/test/java/org/jivesoftware/smack/full/ModularXmppClientToServerConnectionStateGraphTest.java diff --git a/smack-java11-full/src/test/resources/state-graph.dot b/smack-java8-full/src/test/resources/state-graph.dot similarity index 100% rename from smack-java11-full/src/test/resources/state-graph.dot rename to smack-java8-full/src/test/resources/state-graph.dot diff --git a/smack-java11/build.gradle b/smack-java8/build.gradle similarity index 67% rename from smack-java11/build.gradle rename to smack-java8/build.gradle index d3d157ad1..d26aa5ce3 100644 --- a/smack-java11/build.gradle +++ b/smack-java8/build.gradle @@ -1,11 +1,7 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' -} - description = """\ -Smack for Java 11 (or higher). +Smack for Java7 (or higher). This is a pseudo-artifact that pulls all the required dependencies to -run Smack on Java 11 (or higher) JVMs. Usually you want to add additional +run Smack on Java 7 (or higher) JVMs. Usually you want to add additional dependencies to smack-tcp, smack-extensions and smack-experimental.""" dependencies { diff --git a/smack-java11/src/main/java/org/jivesoftware/smack/java7/Java7SmackInitializer.java b/smack-java8/src/main/java/org/jivesoftware/smack/java7/Java7SmackInitializer.java similarity index 100% rename from smack-java11/src/main/java/org/jivesoftware/smack/java7/Java7SmackInitializer.java rename to smack-java8/src/main/java/org/jivesoftware/smack/java7/Java7SmackInitializer.java diff --git a/smack-java11/src/main/java/org/jivesoftware/smack/java7/XmppHostnameVerifier.java b/smack-java8/src/main/java/org/jivesoftware/smack/java7/XmppHostnameVerifier.java similarity index 98% rename from smack-java11/src/main/java/org/jivesoftware/smack/java7/XmppHostnameVerifier.java rename to smack-java8/src/main/java/org/jivesoftware/smack/java7/XmppHostnameVerifier.java index a03cd097a..16e1c5668 100644 --- a/smack-java11/src/main/java/org/jivesoftware/smack/java7/XmppHostnameVerifier.java +++ b/smack-java8/src/main/java/org/jivesoftware/smack/java7/XmppHostnameVerifier.java @@ -1,6 +1,6 @@ /** * - * Copyright 2015-2024 Florian Schmaus + * Copyright 2015 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,8 +23,8 @@ import java.security.Principal; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; -import java.util.ArrayList; import java.util.Collection; +import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.logging.Level; @@ -135,7 +135,7 @@ public class XmppHostnameVerifier implements HostnameVerifier { private static void matchDns(String name, X509Certificate cert) throws CertificateException { Collection> subjAltNames = cert.getSubjectAlternativeNames(); if (subjAltNames != null) { - List nonMatchingDnsAltnames = new ArrayList<>(); + List nonMatchingDnsAltnames = new LinkedList<>(); for (List san : subjAltNames) { if (((Integer) san.get(0)).intValue() != ALTNAME_DNS) { continue; @@ -253,7 +253,7 @@ public class XmppHostnameVerifier implements HostnameVerifier { if (subjectAlternativeNames == null) { throw new CertificateException("No subject alternative names present"); } - List nonMatchingIpAltnames = new ArrayList<>(); + List nonMatchingIpAltnames = new LinkedList<>(); for (List san : subjectAlternativeNames) { if (((Integer) san.get(0)).intValue() != ALTNAME_IP) { continue; diff --git a/smack-java11/src/main/java/org/jivesoftware/smack/java7/package-info.java b/smack-java8/src/main/java/org/jivesoftware/smack/java7/package-info.java similarity index 100% rename from smack-java11/src/main/java/org/jivesoftware/smack/java7/package-info.java rename to smack-java8/src/main/java/org/jivesoftware/smack/java7/package-info.java diff --git a/smack-java11/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/Java7Base64Encoder.java b/smack-java8/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/Java7Base64Encoder.java similarity index 100% rename from smack-java11/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/Java7Base64Encoder.java rename to smack-java8/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/Java7Base64Encoder.java diff --git a/smack-java11/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/Java7Base64UrlSafeEncoder.java b/smack-java8/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/Java7Base64UrlSafeEncoder.java similarity index 100% rename from smack-java11/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/Java7Base64UrlSafeEncoder.java rename to smack-java8/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/Java7Base64UrlSafeEncoder.java diff --git a/smack-java11/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/package-info.java b/smack-java8/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/package-info.java similarity index 100% rename from smack-java11/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/package-info.java rename to smack-java8/src/main/java/org/jivesoftware/smack/util/stringencoder/java7/package-info.java diff --git a/smack-java11/src/main/java/org/jivesoftware/smack/util/stringencoder/package-info.java b/smack-java8/src/main/java/org/jivesoftware/smack/util/stringencoder/package-info.java similarity index 100% rename from smack-java11/src/main/java/org/jivesoftware/smack/util/stringencoder/package-info.java rename to smack-java8/src/main/java/org/jivesoftware/smack/util/stringencoder/package-info.java diff --git a/smack-jingle-old/build.gradle b/smack-jingle-old/build.gradle index 63e732bee..5651864f2 100644 --- a/smack-jingle-old/build.gradle +++ b/smack-jingle-old/build.gradle @@ -1,7 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' -} - description = """\ Smack Jingle API. Warning: This API is beta, outdated and currenlty unmaintained.""" diff --git a/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/nat/STUNResolverTest.java b/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/nat/STUNResolverTest.java index febac9374..5d9425a92 100644 --- a/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/nat/STUNResolverTest.java +++ b/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/nat/STUNResolverTest.java @@ -99,7 +99,7 @@ public class STUNResolverTest extends SmackTestCase { stunResolver.addCandidate(cand3); stunResolver.addCandidate(cand4); - assertEquals(candH, stunResolver.getPreferredCandidate()); + assertEquals(stunResolver.getPreferredCandidate(), candH); } /** @@ -127,7 +127,7 @@ public class STUNResolverTest extends SmackTestCase { iceResolver.addCandidate(cand3); iceResolver.addCandidate(cand4); - assertEquals(candH, iceResolver.getPreferredCandidate()); + assertEquals(iceResolver.getPreferredCandidate(), candH); } /** diff --git a/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/nat/TransportCandidateTest.java b/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/nat/TransportCandidateTest.java index 763d52877..36830e911 100644 --- a/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/nat/TransportCandidateTest.java +++ b/smack-jingle-old/src/integration-test/java/org/jivesoftware/smackx/jingle/nat/TransportCandidateTest.java @@ -65,7 +65,7 @@ public class TransportCandidateTest extends SmackTestCase { candList.add(cand4); Collections.sort(candList); - assertEquals(candH, candList.get(candList.size() - 1)); + assertEquals(candList.get(candList.size() - 1), candH); } protected int getMaxConnections() { diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleManager.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleManager.java index f4ad1c0a8..acd9a5796 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleManager.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleManager.java @@ -540,7 +540,7 @@ public class JingleManager implements JingleSessionListener { // } /** * When the session request is acceptable, this method should be invoked. It - * will create an JingleSession which allows the negotiation to proceed. + * will create an JingleSession which allows the negotiation to procede. * * @param request the remote request that is being accepted. * @return the session which manages the rest of the negotiation. @@ -560,7 +560,7 @@ public class JingleManager implements JingleSessionListener { /** * When the session request is acceptable, this method should be invoked. It - * will create an JingleSession which allows the negotiation to proceed. + * will create an JingleSession which allows the negotiation to procede. * This method use JingleMediaManager to select the supported Payload types. * * @param request the remote request that is being accepted. diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleNegotiator.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleNegotiator.java index d944679b8..656faad25 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleNegotiator.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleNegotiator.java @@ -221,7 +221,7 @@ public abstract class JingleNegotiator { * <transport> * * This way, each segment of a Jingle stanza has a corresponding negotiator that know how to deal with that - * part of the Jingle packet. It also allows us to support Jingle packets of arbitrary complexity. + * part of the Jingle packet. It also allows us to support Jingle packets of arbitraty complexity. * * Each parent calls dispatchIncomingPacket for each of its children. The children then pass back a List of * results that will get sent when we reach the top level negotiator (JingleSession). diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleSession.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleSession.java index cb141e837..dabc962b0 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleSession.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleSession.java @@ -431,7 +431,7 @@ public final class JingleSession extends JingleNegotiator implements MediaReceiv /** * Complete and send a packet. Complete all the null fields in a Jingle - * response, using the session information we have. + * reponse, using the session information we have. * * @param jout * the Jingle stanza we want to complete and send @@ -445,7 +445,7 @@ public final class JingleSession extends JingleNegotiator implements MediaReceiv /** * Complete and send a packet. Complete all the null fields in a Jingle - * response, using the session information we have or some info from the + * reponse, using the session information we have or some info from the * incoming packet. * * @param iq The Jingle stanza we are responding to @@ -1097,7 +1097,7 @@ public final class JingleSession extends JingleNegotiator implements MediaReceiv } /** - * This is the starting point for initiating a new session. + * This is the starting point for intitiating a new session. * * @throws IllegalStateException if an illegal state was encountered * @throws SmackException if Smack detected an exceptional situation. diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleSessionState.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleSessionState.java index 5a1f7660a..a1bc7263b 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleSessionState.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/JingleSessionState.java @@ -56,7 +56,7 @@ public abstract class JingleSessionState { /** * Process an incoming Jingle Packet. - * When you look at the GoF State pattern this method roughly corresponds to example on p310: ProcessOctet() + * When you look at the GoF State pattern this method roughly corresponds to example on p310: ProcessOctect() * * @param session the jingle session. * @param jingle the jingle stanza. diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/listeners/CreatedJingleSessionListener.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/listeners/CreatedJingleSessionListener.java index dda67f72e..294e321cd 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/listeners/CreatedJingleSessionListener.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/listeners/CreatedJingleSessionListener.java @@ -19,7 +19,7 @@ package org.jivesoftware.smackx.jingleold.listeners; import org.jivesoftware.smackx.jingleold.JingleSession; /** - * Interface used to dispatch an event when a Jingle session is created. + * Inteface used to dispatch a event when a Jingle session is created. * * @author Thiago Camargo */ diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/listeners/JingleSessionListener.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/listeners/JingleSessionListener.java index 768cc42c9..fb754e489 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/listeners/JingleSessionListener.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/listeners/JingleSessionListener.java @@ -33,7 +33,7 @@ public interface JingleSessionListener extends JingleListener { * Notification that the session has been established. Arguments specify * the payload type and transport to use. * - * @param pt the Payload type to use + * @param pt the Payload tyep to use * @param remoteCandidate the remote candidate to use for connecting to the remote * service. * @param localCandidate the local candidate where we must listen for connections diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/media/JingleMediaSession.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/media/JingleMediaSession.java index 7df3c2f06..2956a265a 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/media/JingleMediaSession.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/media/JingleMediaSession.java @@ -25,7 +25,7 @@ import org.jivesoftware.smackx.jingleold.nat.TransportCandidate; /** * Public Abstract Class provides a clear interface between Media Session and Jingle API. *

    - * When a Jingle Session is fully established, we will have a Payload Type and two transport candidates defined for it. + * When a Jingle Session is fully stablished, we will have a Payload Type and two transport candidates defined for it. * Smack Jingle API don't implement Media Transmit and Receive methods. * But provides an interface to let the user implements it using another API. For instance: JMF. *

    @@ -153,7 +153,7 @@ public abstract class JingleMediaSession { public abstract void startReceive(); /** - * Set transmit activity. If the active is true, the instance should transmit. + * Set transmit activity. If the active is true, the instance should trasmit. * If it is set to false, the instance should pause transmit. * * @param active TODO javadoc me please @@ -173,7 +173,7 @@ public abstract class JingleMediaSession { /** * Called when new Media is received. * - * @param participant the participant. + * @param participant the particpant. */ public void mediaReceived(String participant) { for (MediaReceivedListener mediaReceivedListener : mediaReceivedListeners) { diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/media/PayloadType.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/media/PayloadType.java index 08675d8b4..c7dd7b8e0 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/media/PayloadType.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/media/PayloadType.java @@ -322,7 +322,7 @@ public class PayloadType { } /** - * Set tha sampling clockRate for a payload type. + * Set tha sampling clockRate for a playload type. * * @param rate The sampling clockRate */ diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/JMFInit.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/JMFInit.java index c86734cc2..ed86a85de 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/JMFInit.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/JMFInit.java @@ -43,7 +43,6 @@ public class JMFInit extends Frame implements Runnable { private boolean visible = false; - @SuppressWarnings({"this-escape", "DoNotCall"}) public JMFInit(String[] args, boolean visible) { super("Initializing JMF..."); diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jmf/AudioChannel.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jmf/AudioChannel.java index 61340f80e..88cb3a649 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jmf/AudioChannel.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jmf/AudioChannel.java @@ -322,7 +322,7 @@ public class AudioChannel { String encoding = codecFormat.getEncoding(); if (encoding.equalsIgnoreCase(AudioFormat.GSM) || encoding.equalsIgnoreCase(AudioFormat.GSM_RTP)) { - return milliseconds * 4; // 1 byte per millisecond + return milliseconds * 4; // 1 byte per millisec } else if (encoding.equalsIgnoreCase(AudioFormat.ULAW) || encoding.equalsIgnoreCase(AudioFormat.ULAW_RTP)) { diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jmf/AudioMediaSession.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jmf/AudioMediaSession.java index 22013df8b..42525c68d 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jmf/AudioMediaSession.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jmf/AudioMediaSession.java @@ -53,7 +53,6 @@ public class AudioMediaSession extends JingleMediaSession { * @param locator media locator * @param jingleSession the jingle session. */ - @SuppressWarnings("this-escape") public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, String locator, JingleSession jingleSession) { super(payloadType, remote, local, locator == null ? "dsound://" : locator, jingleSession); diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jspeex/AudioMediaSession.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jspeex/AudioMediaSession.java index 2874327ca..555836732 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jspeex/AudioMediaSession.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/jspeex/AudioMediaSession.java @@ -71,17 +71,17 @@ public class AudioMediaSession extends JingleMediaSession implements MediaSessio * @throws NoProcessorException if there is no media processor. * @throws UnsupportedFormatException if the format is not supported. * @throws IOException if an I/O error occurred. - * @throws GeneralSecurityException if there was a general security exception. + * @throws GeneralSecurityException if there was a geneeral security exception. */ public static MediaSession createSession(String localhost, int localPort, String remoteHost, int remotePort, MediaSessionListener eventHandler, int quality, boolean secure, boolean micOn) throws NoProcessorException, UnsupportedFormatException, IOException, GeneralSecurityException { SpeexFormat.setFramesPerPacket(1); - /* + /** * The master key. Hardcoded for now. */ byte[] masterKey = new byte[] {(byte) 0xE1, (byte) 0xF9, 0x7A, 0x0D, 0x3E, 0x01, (byte) 0x8B, (byte) 0xE0, (byte) 0xD6, 0x4F, (byte) 0xA3, 0x2C, 0x06, (byte) 0xDE, 0x41, 0x39}; - /* + /** * The master salt. Hardcoded for now. */ byte[] masterSalt = new byte[] {0x0E, (byte) 0xC6, 0x75, (byte) 0xAD, 0x49, (byte) 0x8A, (byte) 0xFE, (byte) 0xEB, (byte) 0xB6, (byte) 0x96, 0x0B, 0x3A, (byte) 0xAB, (byte) 0xE6}; @@ -104,7 +104,6 @@ public class AudioMediaSession extends JingleMediaSession implements MediaSessio * @param locator media locator * @param jingleSession the jingle session. */ - @SuppressWarnings("this-escape") public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, String locator, JingleSession jingleSession) { super(payloadType, remote, local, locator == null ? "dsound://" : locator, jingleSession); diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/sshare/ScreenShareSession.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/sshare/ScreenShareSession.java index 2cae0fc22..8a33211e0 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/sshare/ScreenShareSession.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/sshare/ScreenShareSession.java @@ -66,7 +66,6 @@ public class ScreenShareSession extends JingleMediaSession { * @param locator media locator * @param jingleSession the jingle session. */ - @SuppressWarnings("this-escape") public ScreenShareSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final String locator, JingleSession jingleSession) { super(payloadType, remote, local, "Screen", jingleSession); diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/sshare/api/ImageReceiver.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/sshare/api/ImageReceiver.java index ed3010be7..c3642d6dd 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/sshare/api/ImageReceiver.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/sshare/api/ImageReceiver.java @@ -48,7 +48,6 @@ public class ImageReceiver extends Canvas { private int remotePort; private ImageDecoder decoder; - @SuppressWarnings("this-escape") public ImageReceiver(final InetAddress remoteHost, final int remotePort, final int localPort, int width, int height) { tiles = new BufferedImage[width][height]; diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/sshare/api/OctTreeQuantizer.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/sshare/api/OctTreeQuantizer.java index cff438024..bb6e7ff27 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/sshare/api/OctTreeQuantizer.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/sshare/api/OctTreeQuantizer.java @@ -76,7 +76,6 @@ public class OctTreeQuantizer implements Quantizer { private int colors = 0; private final List> colorList; - @SuppressWarnings({"JdkObsolete", "this-escape"}) public OctTreeQuantizer() { setup(256); colorList = new ArrayList<>(MAX_LEVEL + 1); diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/test/TestMediaSession.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/test/TestMediaSession.java index edfa5a83a..1bb4cf746 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/test/TestMediaSession.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/mediaimpl/test/TestMediaSession.java @@ -37,7 +37,6 @@ public class TestMediaSession extends JingleMediaSession { * @param locator media locator * @param jingleSession the jingle session. */ - @SuppressWarnings("this-escape") public TestMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final String locator, JingleSession jingleSession) { super(payloadType, remote, local, "Test", jingleSession); diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/FixedResolver.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/FixedResolver.java index 0a21ac4aa..d1ea13fad 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/FixedResolver.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/FixedResolver.java @@ -38,7 +38,6 @@ public class FixedResolver extends TransportResolver { * @param ip the IP address. * @param port the port number. */ - @SuppressWarnings("this-escape") public FixedResolver(String ip, int port) { super(); setFixedCandidate(ip, port); diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/ICEResolver.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/ICEResolver.java index 95fce2b6c..f286f5f38 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/ICEResolver.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/ICEResolver.java @@ -56,7 +56,6 @@ public class ICEResolver extends TransportResolver { static Map negociatorsMap = new HashMap<>(); // ICENegociator iceNegociator = null; - @SuppressWarnings("this-escape") public ICEResolver(XMPPConnection connection, String server, int port) { super(); this.connection = connection; diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/STUNResolver.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/STUNResolver.java index 7eb49df5e..b0b010f81 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/STUNResolver.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/STUNResolver.java @@ -23,7 +23,6 @@ import java.net.SocketException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; -import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -136,7 +135,7 @@ public class STUNResolver extends TransportResolver { * @param stunConfigStream An InputStream with the configuration file. * @return A list of loaded servers */ - public List loadSTUNServers(java.io.InputStream stunConfigStream) { + public ArrayList loadSTUNServers(java.io.InputStream stunConfigStream) { ArrayList serversList = new ArrayList<>(); String serverName; int serverPort; @@ -212,7 +211,7 @@ public class STUNResolver extends TransportResolver { * * @return a list of services */ - public List loadSTUNServers() { + public ArrayList loadSTUNServers() { ArrayList serversList = new ArrayList<>(); // Load the STUN configuration @@ -249,7 +248,7 @@ public class STUNResolver extends TransportResolver { * * @return the best STUN server that can be used. */ - private static STUNService bestSTUNServer(List listServers) { + private static STUNService bestSTUNServer(ArrayList listServers) { if (listServers.isEmpty()) { return null; } else { diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TcpUdpBridgeClient.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TcpUdpBridgeClient.java index 3451b7c1c..8e3936719 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TcpUdpBridgeClient.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TcpUdpBridgeClient.java @@ -45,7 +45,6 @@ public class TcpUdpBridgeClient { private DatagramSocket localUdpSocket; private Socket localTcpSocket; - @SuppressWarnings("this-escape") public TcpUdpBridgeClient(String remoteTcpHost, String remoteUdpHost, int remoteTcpPort, int remoteUdpPort) { this.remoteTcpHost = remoteTcpHost; this.remoteUdpHost = remoteUdpHost; diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TcpUdpBridgeServer.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TcpUdpBridgeServer.java index d5abc6bee..2ff8744b5 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TcpUdpBridgeServer.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TcpUdpBridgeServer.java @@ -48,7 +48,6 @@ public class TcpUdpBridgeServer { private Socket localTcpSocket; private ServerSocket serverTcpSocket; - @SuppressWarnings("this-escape") public TcpUdpBridgeServer(String remoteTcpHost, String remoteUdpHost, int remoteTcpPort, int remoteUdpPort) { this.remoteTcpHost = remoteTcpHost; this.remoteUdpHost = remoteUdpHost; diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TransportCandidate.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TransportCandidate.java index a9f3f7f8a..103286862 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TransportCandidate.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TransportCandidate.java @@ -17,13 +17,13 @@ package org.jivesoftware.smackx.jingleold.nat; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -661,13 +661,21 @@ public abstract class TransportCandidate { String local = id.substring(0, keySplitIndex) + ";" + localUser; String remote = id.substring(keySplitIndex) + ";" + remoteUser; - if (session.getConnection().getUser().equals(session.getInitiator())) { - this.send = local.getBytes(StandardCharsets.UTF_8); - this.receive = remote.getBytes(StandardCharsets.UTF_8); - } else { - this.receive = local.getBytes(StandardCharsets.UTF_8); - this.send = remote.getBytes(StandardCharsets.UTF_8); + try { + if (session.getConnection().getUser().equals(session.getInitiator())) { + + this.send = local.getBytes("UTF-8"); + this.receive = remote.getBytes("UTF-8"); + } else { + this.receive = local.getBytes("UTF-8"); + this.send = remote.getBytes("UTF-8"); + } } + catch (UnsupportedEncodingException e) { + LOGGER.log(Level.WARNING, "exception", e); + } + + } @SuppressWarnings("UnusedVariable") @@ -698,7 +706,7 @@ public abstract class TransportCandidate { long delay = 100 / replyTries; - String[] str = new String(packet.getData(), StandardCharsets.UTF_8).split(";"); + String[] str = new String(packet.getData(), "UTF-8").split(";"); String pass = str[0]; String[] address = str[1].split(":"); String ip = address[0]; @@ -706,7 +714,13 @@ public abstract class TransportCandidate { if (pass.equals(candidate.getPassword()) && !accept) { - byte[] cont = (password + ";" + candidate.getIp() + ":" + candidate.getPort()).getBytes(StandardCharsets.UTF_8); + byte[] cont = null; + try { + cont = (password + ";" + candidate.getIp() + ":" + candidate.getPort()).getBytes("UTF-8"); + } + catch (UnsupportedEncodingException e) { + LOGGER.log(Level.WARNING, "exception", e); + } packet.setData(cont); packet.setLength(cont.length); @@ -764,24 +778,31 @@ public abstract class TransportCandidate { DatagramListener listener = new DatagramListener() { @Override public boolean datagramReceived(DatagramPacket datagramPacket) { - LOGGER.fine("ECHO Received to: " + candidate.getIp() + ":" + candidate.getPort() + " data: " + new String(datagramPacket.getData(), StandardCharsets.UTF_8)); - String[] str = new String(datagramPacket.getData(), StandardCharsets.UTF_8).split(";"); - String pass = str[0]; - String[] addr = str[1].split(":"); - String ip = addr[0]; - String pt = addr[1]; - // CHECKSTYLE:OFF - if (pass.equals(password) - && transportCandidate.getIp().indexOf(ip) != -1 - && transportCandidate.getPort() == Integer.parseInt(pt)) { - // CHECKSTYLE:ON - LOGGER.fine("ECHO OK: " + candidate.getIp() + ":" + candidate.getPort() + " <-> " + transportCandidate.getIp() + ":" + transportCandidate.getPort()); - TestResult testResult = new TestResult(); - testResult.setResult(true); - ended = true; - fireTestResult(testResult, transportCandidate); - return true; + try { + LOGGER.fine("ECHO Received to: " + candidate.getIp() + ":" + candidate.getPort() + " data: " + new String(datagramPacket.getData(), "UTF-8")); + String[] str = new String(datagramPacket.getData(), "UTF-8").split(";"); + String pass = str[0]; + String[] addr = str[1].split(":"); + String ip = addr[0]; + String pt = addr[1]; + + // CHECKSTYLE:OFF + if (pass.equals(password) + && transportCandidate.getIp().indexOf(ip) != -1 + && transportCandidate.getPort() == Integer.parseInt(pt)) { + // CHECKSTYLE:ON + LOGGER.fine("ECHO OK: " + candidate.getIp() + ":" + candidate.getPort() + " <-> " + transportCandidate.getIp() + ":" + transportCandidate.getPort()); + TestResult testResult = new TestResult(); + testResult.setResult(true); + ended = true; + fireTestResult(testResult, transportCandidate); + return true; + } + + } + catch (UnsupportedEncodingException e) { + LOGGER.log(Level.WARNING, "exception", e); } LOGGER.fine("ECHO Wrong Data: " + datagramPacket.getAddress().getHostAddress() + ":" + datagramPacket.getPort()); @@ -791,7 +812,13 @@ public abstract class TransportCandidate { addListener(listener); - byte[] content = new String(password + ";" + getIp() + ":" + getPort()).getBytes(StandardCharsets.UTF_8); + byte[] content = null; + try { + content = new String(password + ";" + getIp() + ":" + getPort()).getBytes("UTF-8"); + } + catch (UnsupportedEncodingException e) { + LOGGER.log(Level.WARNING, "exception", e); + } DatagramPacket packet = new DatagramPacket(content, content.length); diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TransportNegotiator.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TransportNegotiator.java index c61ffd46f..127a7364c 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TransportNegotiator.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TransportNegotiator.java @@ -95,7 +95,7 @@ public abstract class TransportNegotiator extends JingleNegotiator { * * @param session The Jingle session * @param transResolver The JingleTransportManager to use - * @param parentNegotiator the parent negotiator. + * @param parentNegotiator the parent ngeotiator. */ public TransportNegotiator(JingleSession session, TransportResolver transResolver, ContentNegotiator parentNegotiator) { super(session); @@ -311,7 +311,7 @@ public abstract class TransportNegotiator extends JingleNegotiator { // Sleep for some time, waiting for the candidates checks int totalTime = CANDIDATES_ACCEPT_PERIOD + TransportResolver.CHECK_TIMEOUT; - int tries = (int) Math.ceil(totalTime / 1000.0); + int tries = (int) Math.ceil(totalTime / 1000); for (int i = 0; i < tries - 1; i++) { try { @@ -478,7 +478,7 @@ public abstract class TransportNegotiator extends JingleNegotiator { * * @return The list of valid (ie, already checked) remote candidates. */ - final List getValidRemoteCandidatesList() { + final ArrayList getValidRemoteCandidatesList() { synchronized (validRemoteCandidates) { return new ArrayList<>(validRemoteCandidates); } @@ -872,7 +872,7 @@ public abstract class TransportNegotiator extends JingleNegotiator { @Override public TransportCandidate getBestRemoteCandidate() { // Hopefully, we only have one validRemoteCandidate - List cands = getValidRemoteCandidatesList(); + ArrayList cands = getValidRemoteCandidatesList(); if (!cands.isEmpty()) { LOGGER.fine("RAW CAND"); return cands.get(0); @@ -930,7 +930,7 @@ public abstract class TransportNegotiator extends JingleNegotiator { public TransportCandidate getBestRemoteCandidate() { ICECandidate result = null; - List cands = getValidRemoteCandidatesList(); + ArrayList cands = getValidRemoteCandidatesList(); if (!cands.isEmpty()) { int highest = -1; ICECandidate chose = null; diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TransportResolver.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TransportResolver.java index 9393dd1c3..75c1e2f71 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TransportResolver.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/nat/TransportResolver.java @@ -210,7 +210,7 @@ public abstract class TransportResolver { * * @return the list of listeners */ - public List getListenersList() { + public ArrayList getListenersList() { synchronized (listeners) { return new ArrayList<>(listeners); } @@ -236,7 +236,7 @@ public abstract class TransportResolver { } /** - * Trigger an event notifying the initialization of the resolution process. + * Trigger a event notifying the initialization of the resolution process. */ private void triggerResolveInit() { Iterator iter = getListenersList().iterator(); @@ -250,7 +250,7 @@ public abstract class TransportResolver { } /** - * Trigger an event notifying the obtainment of all the candidates. + * Trigger a event notifying the obtainment of all the candidates. */ private void triggerResolveEnd() { Iterator iter = getListenersList().iterator(); diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/Jingle.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/Jingle.java index 9ac5270f6..d904f0d34 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/Jingle.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/Jingle.java @@ -71,7 +71,6 @@ public class Jingle extends IQ { * @param mi the jingle content info * @param sid the sid. */ - @SuppressWarnings("this-escape") public Jingle(final List contents, final JingleContentInfo mi, final String sid) { this(); @@ -94,7 +93,6 @@ public class Jingle extends IQ { * * @param content a content */ - @SuppressWarnings("this-escape") public Jingle(final JingleContent content) { this(); @@ -114,7 +112,6 @@ public class Jingle extends IQ { * * @param info The content info */ - @SuppressWarnings("this-escape") public Jingle(final JingleContentInfo info) { this(); @@ -134,7 +131,6 @@ public class Jingle extends IQ { * * @param action The action. */ - @SuppressWarnings("this-escape") public Jingle(final JingleActionEnum action) { this(null, null, null); this.action = action; diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleContentDescription.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleContentDescription.java index 53eee1d8a..3df98e574 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleContentDescription.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleContentDescription.java @@ -105,7 +105,7 @@ public abstract class JingleContentDescription implements ExtensionElement { * * @return a list for the audio payloads in the packet. */ - public List getJinglePayloadTypesList() { + public ArrayList getJinglePayloadTypesList() { synchronized (payloads) { return new ArrayList<>(payloads); } @@ -116,7 +116,7 @@ public abstract class JingleContentDescription implements ExtensionElement { * * @return a list of PayloadType.Audio */ - public List getAudioPayloadTypesList() { + public ArrayList getAudioPayloadTypesList() { ArrayList result = new ArrayList<>(); Iterator jinglePtsIter = getJinglePayloadTypes(); @@ -184,7 +184,6 @@ public abstract class JingleContentDescription implements ExtensionElement { * * @param pt the payload type. */ - @SuppressWarnings("this-escape") public Audio(final JinglePayloadType pt) { super(); addJinglePayloadType(pt); diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleContentInfo.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleContentInfo.java index caed15f9d..9d5d7795b 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleContentInfo.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleContentInfo.java @@ -99,7 +99,6 @@ public class JingleContentInfo implements ExtensionElement { public static final String NAMESPACE = "urn:xmpp:tmp:jingle:apps:rtp"; - @SuppressWarnings("this-escape") public Audio(final ContentInfo mi) { super(mi); setNamespace(NAMESPACE); diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleDescription.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleDescription.java index f2d2fdf82..4e143f266 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleDescription.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleDescription.java @@ -191,7 +191,6 @@ public abstract class JingleDescription implements ExtensionElement { * * @param pt the payload type. */ - @SuppressWarnings("this-escape") public Audio(final PayloadType pt) { super(); addPayloadType(pt); diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleTransport.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleTransport.java index 1162df9d9..40553ea27 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleTransport.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/packet/JingleTransport.java @@ -55,7 +55,6 @@ public class JingleTransport implements ExtensionElement { * * @param candidate A transport candidate element to add. */ - @SuppressWarnings("this-escape") public JingleTransport(final JingleTransportCandidate candidate) { super(); addCandidate(candidate); @@ -203,7 +202,6 @@ public class JingleTransport implements ExtensionElement { * * @param candidate the jmf transport candidate */ - @SuppressWarnings("this-escape") public JingleTransportCandidate(final TransportCandidate candidate) { super(); setMediaTransport(candidate); @@ -274,7 +272,6 @@ public class JingleTransport implements ExtensionElement { public static class Ice extends JingleTransport { public static final String NAMESPACE = "urn:xmpp:tmp:jingle:transports:ice-udp"; - @SuppressWarnings("this-escape") public Ice() { super(); setNamespace(NAMESPACE); @@ -362,7 +359,6 @@ public class JingleTransport implements ExtensionElement { public static class RawUdp extends JingleTransport { public static final String NAMESPACE = "http://www.xmpp.org/extensions/xep-0177.html#ns"; - @SuppressWarnings("this-escape") public RawUdp() { super(); setNamespace(NAMESPACE); diff --git a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleTransportProvider.java b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleTransportProvider.java index b81e4f201..0edb7d887 100644 --- a/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleTransportProvider.java +++ b/smack-jingle-old/src/main/java/org/jivesoftware/smackx/jingleold/provider/JingleTransportProvider.java @@ -88,7 +88,7 @@ public abstract class JingleTransportProvider extends ExtensionElementProvider listeners = new ArrayList<>(); private final Map> presenceMap = new HashMap<>(); // The roster is marked as initialized when at least a single roster packet - // has been received and processed. + // has been recieved and processed. boolean rosterInitialized = false; /** @@ -181,7 +181,7 @@ public class AgentRoster { /** * Returns true if the specified XMPP address is an agent in the workgroup. * - * @param jid the XMPP address of the agent (e.g."jsmith@example.com"). The + * @param jid the XMPP address of the agent (eg "jsmith@example.com"). The * address can be in any valid format (e.g. "domain/resource", "user@domain" * or "user@domain/resource"). * @return true if the XMPP address is an agent in the workgroup. @@ -203,12 +203,12 @@ public class AgentRoster { /** * Returns the presence info for a particular agent, or null if the agent - * is unavailable (offline) or if no presence information is available. + * is unavailable (offline) or if no presence information is available.

    * * @param user a fully qualified xmpp JID. The address could be in any valid format (e.g. * "domain/resource", "user@domain" or "user@domain/resource"). * @return the agent's current presence, or null if the agent is unavailable - * or if no presence information is available. + * or if no presence information is available.. */ public Presence getPresence(Jid user) { Jid key = getPresenceMapKey(user); diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/AgentSession.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/AgentSession.java index 0cdf52f9d..4c2e57c52 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/AgentSession.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/AgentSession.java @@ -349,9 +349,15 @@ public class AgentSession { new StanzaTypeFilter(Presence.class), FromMatchesFilter.create(workgroupJID)), presence); presence = collector.nextResultOrThrow(); + + // We can safely update this iv since we didn't get any error + this.online = online; } // Otherwise the user is going offline... else { + // Update this iv now since we don't care at this point of any error + this.online = online; + presence = connection.getStanzaFactory().buildPresenceStanza() .ofType(Presence.Type.unavailable) .to(workgroupJID) @@ -704,11 +710,10 @@ public class AgentSession { } } - @SuppressWarnings("JavaUtilDate") private void fireOfferRequestEvent(OfferRequestProvider.OfferRequestPacket requestPacket) { Offer offer = new Offer(this.connection, this, requestPacket.getUserID(), requestPacket.getUserJID(), this.getWorkgroupJID(), - new Date(new Date().getTime() + (requestPacket.getTimeout() * 1000L)), + new Date(new Date().getTime() + (requestPacket.getTimeout() * 1000)), requestPacket.getSessionID(), requestPacket.getMetaData(), requestPacket.getContent()); synchronized (offerListeners) { @@ -718,7 +723,6 @@ public class AgentSession { } } - @SuppressWarnings("JavaUtilDate") private void fireOfferRevokeEvent(OfferRevokeProvider.OfferRevokePacket orp) { RevokedOffer revokedOffer = new RevokedOffer(orp.getUserJID(), orp.getUserID(), this.getWorkgroupJID(), orp.getSessionID(), orp.getReason(), new Date()); diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/Offer.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/Offer.java index 3449cd69b..ece31d9c6 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/Offer.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/Offer.java @@ -125,7 +125,7 @@ public class Offer { } /** - * The fully qualified name of the workgroup (e.g.support@example.com). + * The fully qualified name of the workgroup (eg support@example.com). * * @return the name of the workgroup. */ @@ -137,7 +137,7 @@ public class Offer { * The date when the offer will expire. The agent must {@link #accept()} * the offer before the expiration date or the offer will lapse and be * routed to another agent. Alternatively, the agent can {@link #reject()} - * the offer at any time if they don't wish to accept it. + * the offer at any time if they don't wish to accept it.. * * @return the date at which this offer expires. */ diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/OfferListener.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/OfferListener.java index a33c6797b..93de6bf8f 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/OfferListener.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/agent/OfferListener.java @@ -37,7 +37,7 @@ public interface OfferListener { void offerReceived (Offer request); /** - * The implementing class instance will be notified via this when the AgentSession has received + * The implementing class instance will be notified via this when the AgentSessino has received * a revocation of a previously extended offer. * * @param revokedOffer the RevokedOffer instance embodying the details of the revoked offer diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/ext/history/AgentChatHistory.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/ext/history/AgentChatHistory.java index 3fc5f4a1e..87b03daf4 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/ext/history/AgentChatHistory.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/ext/history/AgentChatHistory.java @@ -54,7 +54,6 @@ public class AgentChatHistory extends IQ { private final List agentChatSessions = new ArrayList<>(); - @SuppressWarnings("JavaUtilDate") public AgentChatHistory(EntityBareJid agentJID, int maxSessions, Date startDate) { this(); this.agentJID = agentJID; @@ -117,7 +116,6 @@ public class AgentChatHistory extends IQ { return agentChatHistory; } - @SuppressWarnings("JavaUtilDate") private static AgentChatSession parseChatSetting(XmlPullParser parser) throws XmlPullParserException, IOException { boolean done = false; diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/DepartQueuePacket.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/DepartQueuePacket.java index 8917ebe3e..abe8771ca 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/DepartQueuePacket.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/DepartQueuePacket.java @@ -53,7 +53,6 @@ public class DepartQueuePacket extends IQ { * @param workgroup the workgroup to depart. * @param user the user to make depart from the queue. */ - @SuppressWarnings("this-escape") public DepartQueuePacket(EntityBareJid workgroup, EntityJid user) { super("depart-queue", "http://jabber.org/protocol/workgroup"); this.user = user; diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/QueueDetails.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/QueueDetails.java index f29eb7738..19d7a0e3b 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/QueueDetails.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/packet/QueueDetails.java @@ -145,7 +145,6 @@ public final class QueueDetails implements ExtensionElement { */ public static class Provider extends ExtensionElementProvider { - @SuppressWarnings("JavaUtilDate") @Override public QueueDetails parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) throws XmlPullParserException, diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/settings/ChatSetting.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/settings/ChatSetting.java index 499d3fac5..00a227c61 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/settings/ChatSetting.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/settings/ChatSetting.java @@ -22,7 +22,6 @@ public class ChatSetting { private String value; private int type; - @SuppressWarnings("this-escape") public ChatSetting(String key, String value, int type) { setKey(key); setValue(value); diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/settings/ChatSettings.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/settings/ChatSettings.java index 8613deb96..ddec1a662 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/settings/ChatSettings.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/settings/ChatSettings.java @@ -66,7 +66,6 @@ public class ChatSettings extends IQ { settings = new ArrayList<>(); } - @SuppressWarnings("this-escape") public ChatSettings(String key) { this(); setKey(key); diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/user/Workgroup.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/user/Workgroup.java index a9f7b400c..59ad7c4dc 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/user/Workgroup.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/user/Workgroup.java @@ -91,7 +91,7 @@ public class Workgroup { /** * Creates a new workgroup instance using the specified workgroup JID - * (e.g.support@workgroup.example.com) and XMPP connection. The connection must have + * (eg support@workgroup.example.com) and XMPP connection. The connection must have * undergone a successful login before being used to construct an instance of * this class. * @@ -99,7 +99,6 @@ public class Workgroup { * @param connection an XMPP connection which must have already undergone a * successful login. */ - @SuppressWarnings("this-escape") public Workgroup(EntityBareJid workgroupJID, XMPPConnection connection) { // Login must have been done before passing in connection. if (!connection.isAuthenticated()) { @@ -137,8 +136,8 @@ public class Workgroup { } }); - /* - * Internal handling of an invitation. Receiving an invitation removes the user from the queue. + /** + * Internal handling of an invitation.Recieving an invitation removes the user from the queue. */ MultiUserChatManager.getInstanceFor(connection).addInvitationListener( new org.jivesoftware.smackx.muc.InvitationListener() { @@ -163,7 +162,7 @@ public class Workgroup { } /** - * Returns the name of this workgroup (e.g.support@example.com). + * Returns the name of this workgroup (eg support@example.com). * * @return the name of the workgroup. */ @@ -736,9 +735,9 @@ public class Workgroup { } /** - * Asks the workgroup for its Properties. + * Asks the workgroup for it's Properties. * - * @param jid the jid of the user whose information you would like the workgroup to retrieve. + * @param jid the jid of the user who's information you would like the workgroup to retreive. * @return the WorkgroupProperties for the specified workgroup. * @throws XMPPErrorException if there was an XMPP error returned. * @throws NoResponseException if there was no response from the remote entity. diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/util/MetaDataUtils.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/util/MetaDataUtils.java index 24370229f..29170b479 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/util/MetaDataUtils.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/workgroup/util/MetaDataUtils.java @@ -19,7 +19,7 @@ package org.jivesoftware.smackx.workgroup.util; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; -import java.util.LinkedHashMap; +import java.util.Hashtable; import java.util.List; import java.util.Map; @@ -45,7 +45,6 @@ public class MetaDataUtils { * @throws XmlPullParserException if an error occurs while parsing the XML. * @throws IOException if an error occurs while parsing the XML. */ - @SuppressWarnings("MixedMutabilityReturnType") public static Map> parseMetaData(XmlPullParser parser) throws XmlPullParserException, IOException { XmlPullParser.Event eventType = parser.getEventType(); @@ -53,7 +52,7 @@ public class MetaDataUtils { if ((eventType == XmlPullParser.Event.START_ELEMENT) && parser.getName().equals(MetaData.ELEMENT_NAME) && parser.getNamespace().equals(MetaData.NAMESPACE)) { - Map> metaData = new LinkedHashMap<>(); + Map> metaData = new Hashtable<>(); eventType = parser.next(); diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/RosterExchangeManager.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/RosterExchangeManager.java index 25461a3cd..baac6db8c 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/RosterExchangeManager.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/RosterExchangeManager.java @@ -42,7 +42,7 @@ import org.jxmpp.jid.Jid; /** * - * Manages Roster exchanges. A RosterExchangeManager provides high level access to send + * Manages Roster exchanges. A RosterExchangeManager provides a high level access to send * rosters, roster groups and roster entries to XMPP clients. It also provides an easy way * to hook up custom logic when entries are received from another XMPP client through * RosterExchangeListeners. @@ -106,7 +106,7 @@ public class RosterExchangeManager { * Removes a listener from roster exchanges. The listener will be fired anytime roster * entries are received from remote XMPP clients. * - * @param rosterExchangeListener a roster exchange listener. + * @param rosterExchangeListener a roster exchange listener.. */ public void removeRosterListener(RosterExchangeListener rosterExchangeListener) { rosterExchangeListeners.remove(rosterExchangeListener); diff --git a/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/packet/RosterExchange.java b/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/packet/RosterExchange.java index 6ee6771f1..291393660 100644 --- a/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/packet/RosterExchange.java +++ b/smack-legacy/src/main/java/org/jivesoftware/smackx/xroster/packet/RosterExchange.java @@ -70,7 +70,6 @@ public class RosterExchange implements ExtensionElement { * * @param roster the roster to send to other XMPP entity. */ - @SuppressWarnings("this-escape") public RosterExchange(Roster roster) { // Add all the roster entries to the new RosterExchange for (RosterEntry rosterEntry : roster.getEntries()) { diff --git a/smack-omemo-signal-integration-test/build.gradle b/smack-omemo-signal-integration-test/build.gradle index 58414a4d6..a499edc0c 100644 --- a/smack-omemo-signal-integration-test/build.gradle +++ b/smack-omemo-signal-integration-test/build.gradle @@ -1,16 +1,17 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.application-conventions' -} +apply plugin: 'application' description = """\ Smack integration tests for OMEMO using libsignal.""" -application { - mainClass = 'org.igniterealtime.smack.inttest.smack_omemo_signal.SmackOmemoSignalIntegrationTestFramework' -} +mainClassName = 'org.igniterealtime.smack.inttest.smack_omemo_signal.SmackOmemoSignalIntegrationTestFramework' +applicationDefaultJvmArgs = ["-enableassertions"] dependencies { api project(':smack-integration-test') api project(':smack-omemo-signal') } + +run { + // Pass all system properties down to the "application" run + systemProperties System.getProperties() +} diff --git a/smack-omemo-signal-integration-test/src/main/java/org/igniterealtime/smack/inttest/smack_omemo_signal/SmackOmemoSignalIntegrationTestFramework.java b/smack-omemo-signal-integration-test/src/main/java/org/igniterealtime/smack/inttest/smack_omemo_signal/SmackOmemoSignalIntegrationTestFramework.java index d79154e4a..aa17e3593 100644 --- a/smack-omemo-signal-integration-test/src/main/java/org/igniterealtime/smack/inttest/smack_omemo_signal/SmackOmemoSignalIntegrationTestFramework.java +++ b/smack-omemo-signal-integration-test/src/main/java/org/igniterealtime/smack/inttest/smack_omemo_signal/SmackOmemoSignalIntegrationTestFramework.java @@ -27,7 +27,6 @@ import java.security.InvalidKeyException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; -import java.security.Security; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; @@ -39,15 +38,10 @@ import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException; import org.jivesoftware.smackx.omemo.signal.SignalOmemoService; -import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.igniterealtime.smack.inttest.SmackIntegrationTestFramework; public class SmackOmemoSignalIntegrationTestFramework { - static { - Security.addProvider(new BouncyCastleProvider()); - } - public static void main(String[] args) throws InvalidKeyException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchProviderException, SmackException, diff --git a/smack-omemo-signal/build.gradle b/smack-omemo-signal/build.gradle index dd5fd4602..eb7006984 100644 --- a/smack-omemo-signal/build.gradle +++ b/smack-omemo-signal/build.gradle @@ -1,8 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} - description=""" Smack API for XEP-0384: OMEMO Encryption using libsignal """ @@ -12,10 +7,6 @@ dependencies { api project(":smack-extensions") api project(":smack-omemo") implementation 'org.signal:libsignal-client:0.26.0' - - // TODO: Migrate Junit4 tests to Junit5. - testImplementation "org.junit.vintage:junit-vintage-engine:$junitVersion" - testFixturesApi(testFixtures(project(":smack-core"))) testImplementation project(path: ":smack-omemo", configuration: "testRuntime") } diff --git a/smack-omemo-signal/src/main/java/org/jivesoftware/smackx/omemo/signal/SignalOmemoKeyUtil.java b/smack-omemo-signal/src/main/java/org/jivesoftware/smackx/omemo/signal/SignalOmemoKeyUtil.java index fb748d5b4..808e600b9 100644 --- a/smack-omemo-signal/src/main/java/org/jivesoftware/smackx/omemo/signal/SignalOmemoKeyUtil.java +++ b/smack-omemo-signal/src/main/java/org/jivesoftware/smackx/omemo/signal/SignalOmemoKeyUtil.java @@ -39,7 +39,7 @@ import org.signal.libsignal.protocol.state.SignedPreKeyRecord; import org.signal.libsignal.protocol.util.Medium; import java.io.IOException; -import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.TreeMap; @@ -57,7 +57,6 @@ public class SignalOmemoKeyUtil extends OmemoKeyUtil generateOmemoPreKeys(int currentPreKeyId, int count) { List preKeyRecords = generatePreKeys(currentPreKeyId, count); TreeMap map = new TreeMap<>(); @@ -68,13 +67,12 @@ public class SignalOmemoKeyUtil extends OmemoKeyUtil generatePreKeys(int start, int count) { - List results = new ArrayList<>(count); + List results = new LinkedList<>(); start--; for (int i=0;i loadOmemoPreKeys(OmemoDevice userDevice) throws IOException { - Map preKeys = getCache(userDevice).preKeys; + TreeMap preKeys = getCache(userDevice).preKeys; if (preKeys.isEmpty() && persistent != null) { preKeys.putAll(persistent.loadOmemoPreKeys(userDevice)); @@ -295,9 +293,8 @@ public class CachingOmemoStore loadOmemoSignedPreKeys(OmemoDevice userDevice) throws IOException { - Map sigPreKeys = getCache(userDevice).signedPreKeys; + TreeMap sigPreKeys = getCache(userDevice).signedPreKeys; if (sigPreKeys.isEmpty() && persistent != null) { sigPreKeys.putAll(persistent.loadOmemoSignedPreKeys(userDevice)); @@ -344,7 +341,7 @@ public class CachingOmemoStore loadAllRawSessionsOf(OmemoDevice userDevice, BareJid contact) throws IOException { + public HashMap loadAllRawSessionsOf(OmemoDevice userDevice, BareJid contact) throws IOException { HashMap sessions = getCache(userDevice).sessions.get(contact); if (sessions == null) { sessions = new HashMap<>(); diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/FileBasedOmemoStore.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/FileBasedOmemoStore.java index b05ffddb9..62b742db5 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/FileBasedOmemoStore.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/FileBasedOmemoStore.java @@ -125,14 +125,12 @@ public abstract class FileBasedOmemoStore loadOmemoPreKeys(OmemoDevice userDevice) throws IOException { File preKeyDirectory = hierarchy.getPreKeysDirectory(userDevice); TreeMap preKeys = new TreeMap<>(); @@ -241,7 +234,6 @@ public abstract class FileBasedOmemoStore loadOmemoSignedPreKeys(OmemoDevice userDevice) throws IOException { File signedPreKeysDirectory = hierarchy.getSignedPreKeysDirectory(userDevice); TreeMap signedPreKeys = new TreeMap<>(); @@ -298,7 +290,6 @@ public abstract class FileBasedOmemoStore loadAllRawSessionsOf(OmemoDevice userDevice, BareJid contact) throws IOException { File contactsDirectory = hierarchy.getContactsDir(userDevice, contact); HashMap sessions = new HashMap<>(); @@ -526,7 +517,6 @@ public abstract class FileBasedOmemoStore stack = new Stack<>(); diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoManager.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoManager.java index 5745204ba..92889f14e 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoManager.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoManager.java @@ -25,7 +25,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Random; import java.util.Set; import java.util.SortedSet; @@ -634,7 +633,7 @@ public final class OmemoManager extends Manager { * @throws SmackException.NoResponseException if there was no response from the remote entity. * @throws IOException if an I/O error occurred. */ - public synchronized Map getActiveFingerprints(BareJid contact) + public synchronized HashMap getActiveFingerprints(BareJid contact) throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, CannotEstablishOmemoSessionException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, IOException { @@ -642,7 +641,7 @@ public final class OmemoManager extends Manager { throw new SmackException.NotLoggedInException(); } - Map fingerprints = new HashMap<>(); + HashMap fingerprints = new HashMap<>(); OmemoCachedDeviceList deviceList = getOmemoService().getOmemoStoreBackend().loadCachedDeviceList(getOwnDevice(), contact); diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoMessage.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoMessage.java index 9f13b13c2..e2eb8635a 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoMessage.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoMessage.java @@ -22,7 +22,6 @@ import static org.jivesoftware.smackx.omemo.util.OmemoConstants.OMEMO_NAMESPACE_ import java.util.HashMap; import java.util.HashSet; -import java.util.Map; import java.util.Set; import org.jivesoftware.smack.packet.Message; @@ -79,7 +78,7 @@ public class OmemoMessage { */ public static class Sent extends OmemoMessage { private final Set intendedDevices = new HashSet<>(); - private final Map skippedDevices = new HashMap<>(); + private final HashMap skippedDevices = new HashMap<>(); /** * Create a new outgoing OMEMO message. @@ -91,7 +90,7 @@ public class OmemoMessage { * @param skippedDevices devices which were skipped during encryption process because encryption * failed for some reason */ - Sent(OmemoElement element, byte[] key, byte[] iv, Set intendedDevices, Map skippedDevices) { + Sent(OmemoElement element, byte[] key, byte[] iv, Set intendedDevices, HashMap skippedDevices) { super(element, key, iv); this.intendedDevices.addAll(intendedDevices); this.skippedDevices.putAll(skippedDevices); @@ -111,7 +110,7 @@ public class OmemoMessage { * * @return map of skipped recipients and reasons for that. */ - public Map getSkippedDevices() { + public HashMap getSkippedDevices() { return skippedDevices; } diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoService.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoService.java index 4573a44ab..82266bf2a 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoService.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/OmemoService.java @@ -30,7 +30,6 @@ import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Random; import java.util.Set; import java.util.logging.Level; @@ -795,7 +794,7 @@ public abstract class OmemoService bundlesList = getOmemoStoreBackend().keyUtil().BUNDLE.bundles(bundleElement, contactsDevice); + HashMap bundlesList = getOmemoStoreBackend().keyUtil().BUNDLE.bundles(bundleElement, contactsDevice); int randomIndex = new Random().nextInt(bundlesList.size()); T_Bundle randomPreKeyBundle = new ArrayList<>(bundlesList.values()).get(randomIndex); @@ -894,7 +893,7 @@ public abstract class OmemoService signedPreKeys = loadOmemoSignedPreKeys(userDevice); + TreeMap signedPreKeys = loadOmemoSignedPreKeys(userDevice); if (signedPreKeys.size() == 0) { changeSignedPreKey(userDevice); } @@ -238,7 +237,7 @@ public abstract class OmemoStore 0) { - Map newKeys = generateOmemoPreKeys(startId + 1, newKeysCount); + TreeMap newKeys = generateOmemoPreKeys(startId + 1, newKeysCount); storeOmemoPreKeys(userDevice, newKeys); } } @@ -416,7 +415,6 @@ public abstract class OmemoStore generateOmemoPreKeys(int startId, int count) { return keyUtil().generateOmemoPreKeys(startId, count); } @@ -451,7 +449,7 @@ public abstract class OmemoStore preKeyHashMap) throws IOException { + public void storeOmemoPreKeys(OmemoDevice userDevice, TreeMap preKeyHashMap) throws IOException { for (Map.Entry entry : preKeyHashMap.entrySet()) { storeOmemoPreKey(userDevice, entry.getKey(), entry.getValue()); } @@ -474,7 +472,6 @@ public abstract class OmemoStore loadOmemoPreKeys(OmemoDevice userDevice) throws IOException; /** @@ -500,8 +497,6 @@ public abstract class OmemoStore loadOmemoSignedPreKeys(OmemoDevice userDevice) throws IOException; /** @@ -557,7 +552,7 @@ public abstract class OmemoStore loadAllRawSessionsOf(OmemoDevice userDevice, BareJid contact) throws IOException; + public abstract HashMap loadAllRawSessionsOf(OmemoDevice userDevice, BareJid contact) throws IOException; /** * Store a crypto-lib specific session to storage. diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/element/OmemoBundleElement.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/element/OmemoBundleElement.java index 610e07515..217c27f6d 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/element/OmemoBundleElement.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/element/OmemoBundleElement.java @@ -47,8 +47,8 @@ public abstract class OmemoBundleElement implements ExtensionElement { private byte[] signedPreKeySignature; private final String identityKeyB64; private byte[] identityKey; - private final Map preKeysB64; - private Map preKeys; + private final HashMap preKeysB64; + private HashMap preKeys; /** * Constructor to create a Bundle Element from base64 Strings. @@ -57,9 +57,9 @@ public abstract class OmemoBundleElement implements ExtensionElement { * @param signedPreKeyB64 base64 encoded signedPreKey * @param signedPreKeySigB64 base64 encoded signedPreKeySignature * @param identityKeyB64 base64 encoded identityKey - * @param preKeysB64 Map of base64 encoded preKeys + * @param preKeysB64 HashMap of base64 encoded preKeys */ - public OmemoBundleElement(int signedPreKeyId, String signedPreKeyB64, String signedPreKeySigB64, String identityKeyB64, Map preKeysB64) { + public OmemoBundleElement(int signedPreKeyId, String signedPreKeyB64, String signedPreKeySigB64, String identityKeyB64, HashMap preKeysB64) { if (signedPreKeyId < 0) { throw new IllegalArgumentException("signedPreKeyId MUST be greater than or equal to 0."); } @@ -81,9 +81,9 @@ public abstract class OmemoBundleElement implements ExtensionElement { * @param signedPreKey signedPreKey * @param signedPreKeySig signedPreKeySignature * @param identityKey identityKey - * @param preKeys Map of preKeys + * @param preKeys HashMap of preKeys */ - public OmemoBundleElement(int signedPreKeyId, byte[] signedPreKey, byte[] signedPreKeySig, byte[] identityKey, Map preKeys) { + public OmemoBundleElement(int signedPreKeyId, byte[] signedPreKey, byte[] signedPreKeySig, byte[] identityKey, HashMap preKeys) { this(signedPreKeyId, signedPreKey != null ? Base64.encodeToString(signedPreKey) : null, signedPreKeySig != null ? Base64.encodeToString(signedPreKeySig) : null, @@ -95,12 +95,12 @@ public abstract class OmemoBundleElement implements ExtensionElement { this.preKeys = preKeys; } - private static Map base64EncodePreKeys(Map preKeys) { + private static HashMap base64EncodePreKeys(HashMap preKeys) { if (preKeys == null) { return null; } - Map converted = new HashMap<>(); + HashMap converted = new HashMap<>(); for (Integer id : preKeys.keySet()) { converted.put(id, Base64.encodeToString(preKeys.get(id))); } @@ -155,12 +155,12 @@ public abstract class OmemoBundleElement implements ExtensionElement { } /** - * Return the Map of preKeys in the bundle. + * Return the HashMap of preKeys in the bundle. * The map uses the preKeys ids as key and the preKeys as value. * * @return preKeys Pre-Keys contained in the bundle */ - public Map getPreKeys() { + public HashMap getPreKeys() { if (preKeys == null) { preKeys = new HashMap<>(); for (int id : preKeysB64.keySet()) { diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/element/OmemoBundleElement_VAxolotl.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/element/OmemoBundleElement_VAxolotl.java index e3ae2d8aa..bcf616111 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/element/OmemoBundleElement_VAxolotl.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/element/OmemoBundleElement_VAxolotl.java @@ -18,7 +18,7 @@ package org.jivesoftware.smackx.omemo.element; import static org.jivesoftware.smackx.omemo.util.OmemoConstants.OMEMO_NAMESPACE_V_AXOLOTL; -import java.util.Map; +import java.util.HashMap; /** * OMEMO device bundle as described by the protocol. @@ -29,11 +29,11 @@ import java.util.Map; */ public class OmemoBundleElement_VAxolotl extends OmemoBundleElement { - public OmemoBundleElement_VAxolotl(int signedPreKeyId, String signedPreKeyB64, String signedPreKeySigB64, String identityKeyB64, Map preKeysB64) { + public OmemoBundleElement_VAxolotl(int signedPreKeyId, String signedPreKeyB64, String signedPreKeySigB64, String identityKeyB64, HashMap preKeysB64) { super(signedPreKeyId, signedPreKeyB64, signedPreKeySigB64, identityKeyB64, preKeysB64); } - public OmemoBundleElement_VAxolotl(int signedPreKeyId, byte[] signedPreKey, byte[] signedPreKeySig, byte[] identityKey, Map preKeys) { + public OmemoBundleElement_VAxolotl(int signedPreKeyId, byte[] signedPreKey, byte[] signedPreKeySig, byte[] identityKey, HashMap preKeys) { super(signedPreKeyId, signedPreKey, signedPreKeySig, identityKey, preKeys); } diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/element/OmemoHeaderElement.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/element/OmemoHeaderElement.java index 050adf033..4270d8ec5 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/element/OmemoHeaderElement.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/element/OmemoHeaderElement.java @@ -57,7 +57,7 @@ public abstract class OmemoHeaderElement implements XmlElement { return sid; } - public List getKeys() { + public ArrayList getKeys() { return new ArrayList<>(keys); } diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/exceptions/CannotEstablishOmemoSessionException.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/exceptions/CannotEstablishOmemoSessionException.java index 161dbc38f..2d4e65513 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/exceptions/CannotEstablishOmemoSessionException.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/exceptions/CannotEstablishOmemoSessionException.java @@ -18,7 +18,6 @@ package org.jivesoftware.smackx.omemo.exceptions; import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import org.jivesoftware.smackx.omemo.internal.OmemoDevice; @@ -33,8 +32,8 @@ import org.jxmpp.jid.BareJid; public class CannotEstablishOmemoSessionException extends Exception { private static final long serialVersionUID = 3165844730283295249L; - private final Map> failures = new HashMap<>(); - private final Map> successes = new HashMap<>(); + private final HashMap> failures = new HashMap<>(); + private final HashMap> successes = new HashMap<>(); public CannotEstablishOmemoSessionException(OmemoDevice failed, Throwable reason) { super(); @@ -42,7 +41,7 @@ public class CannotEstablishOmemoSessionException extends Exception { } public void addFailures(CannotEstablishOmemoSessionException otherFailures) { - for (Map.Entry> entry : otherFailures.getFailures().entrySet()) { + for (Map.Entry> entry : otherFailures.getFailures().entrySet()) { getFailsOfContact(entry.getKey()).putAll(entry.getValue()); } } @@ -51,16 +50,16 @@ public class CannotEstablishOmemoSessionException extends Exception { getSuccessesOfContact(success.getJid()).add(success); } - public Map> getFailures() { + public HashMap> getFailures() { return failures; } - public Map> getSuccesses() { + public HashMap> getSuccesses() { return successes; } - private Map getFailsOfContact(BareJid contact) { - Map h = failures.get(contact); + private HashMap getFailsOfContact(BareJid contact) { + HashMap h = failures.get(contact); if (h == null) { h = new HashMap<>(); failures.put(contact, h); @@ -68,8 +67,8 @@ public class CannotEstablishOmemoSessionException extends Exception { return h; } - private List getSuccessesOfContact(BareJid contact) { - List suc = successes.get(contact); + private ArrayList getSuccessesOfContact(BareJid contact) { + ArrayList suc = successes.get(contact); if (suc == null) { suc = new ArrayList<>(); successes.put(contact, suc); @@ -84,8 +83,8 @@ public class CannotEstablishOmemoSessionException extends Exception { * @return true if the exception requires to be thrown */ public boolean requiresThrowing() { - for (Map.Entry> entry : failures.entrySet()) { - List suc = successes.get(entry.getKey()); + for (Map.Entry> entry : failures.entrySet()) { + ArrayList suc = successes.get(entry.getKey()); if (suc == null || suc.isEmpty()) { return true; } diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/internal/OmemoAesCipher.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/internal/OmemoAesCipher.java index 4edb10c4d..aee330764 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/internal/OmemoAesCipher.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/internal/OmemoAesCipher.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017 Paul Schaub, 2019-2023 Florian Schmaus + * Copyright 2017 Paul Schaub, 2019-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,7 +47,7 @@ public class OmemoAesCipher { String message = "Unable to perform " + OmemoConstants.Crypto.CIPHERMODE + " operation requires by OMEMO. Ensure that a suitable crypto provider for is available." + " For example Bouncycastle on Android (BouncyCastleProvider)"; - throw new AssertionError(message, e); + throw new AssertionError(message); } } diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/package-info.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/package-info.java index d4e6fbddd..b8e0016ba 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/package-info.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/package-info.java @@ -143,7 +143,7 @@ * *

    * The `setup()` method registers the service as a singleton. You can later access the instance by calling - * `SignalOmemoService.getInstance()`. The service can only be registered once. Subsequent calls will throw an + * `SignalOmemoService.getInstace()`. The service can only be registered once. Subsequent calls will throw an * {@link IllegalStateException}. *

    *

    2. Set an OmemoStore

    diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/util/OmemoKeyUtil.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/util/OmemoKeyUtil.java index 39f9ace13..607181552 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/util/OmemoKeyUtil.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/util/OmemoKeyUtil.java @@ -119,8 +119,8 @@ public abstract class OmemoKeyUtil bundles(OmemoBundleElement bundle, OmemoDevice contact) throws CorruptedOmemoKeyException { - Map bundles = new HashMap<>(); + public HashMap bundles(OmemoBundleElement bundle, OmemoDevice contact) throws CorruptedOmemoKeyException { + HashMap bundles = new HashMap<>(); for (int deviceId : bundle.getPreKeys().keySet()) { try { bundles.put(deviceId, bundleFromOmemoBundle(bundle, contact, deviceId)); @@ -211,8 +211,6 @@ public abstract class OmemoKeyUtil generateOmemoPreKeys(int startId, int count); /** @@ -340,8 +338,8 @@ public abstract class OmemoKeyUtil preKeyPublicKeysForBundle(Map preKeyHashMap) { - Map out = new HashMap<>(); + public HashMap preKeyPublicKeysForBundle(TreeMap preKeyHashMap) { + HashMap out = new HashMap<>(); for (Map.Entry e : preKeyHashMap.entrySet()) { out.put(e.getKey(), preKeyForBundle(e.getValue())); } diff --git a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/util/OmemoMessageBuilder.java b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/util/OmemoMessageBuilder.java index 5144b4f02..0810fe1d1 100644 --- a/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/util/OmemoMessageBuilder.java +++ b/smack-omemo/src/main/java/org/jivesoftware/smackx/omemo/util/OmemoMessageBuilder.java @@ -83,7 +83,7 @@ public class OmemoMessageBuilder bundles = keyUtil.BUNDLE.bundles(bundle, device); + HashMap bundles = keyUtil.BUNDLE.bundles(bundle, device); assertEquals("There must be 100 bundles in the HashMap.", 100, bundles.size()); assertNotNull(keyUtil.BUNDLE.identityKey(bundle)); diff --git a/smack-omemo/src/test/java/org/jivesoftware/smackx/omemo/OmemoServiceTest.java b/smack-omemo/src/test/java/org/jivesoftware/smackx/omemo/OmemoServiceTest.java index 0f228b161..67dd244b6 100644 --- a/smack-omemo/src/test/java/org/jivesoftware/smackx/omemo/OmemoServiceTest.java +++ b/smack-omemo/src/test/java/org/jivesoftware/smackx/omemo/OmemoServiceTest.java @@ -50,7 +50,6 @@ public class OmemoServiceTest extends SmackTestSuite { * @throws XmppStringprepException if the provided string is invalid. */ @Test - @SuppressWarnings("JavaUtilDate") public void isStaleDeviceTest() throws XmppStringprepException { OmemoDevice user = new OmemoDevice(JidCreate.bareFrom("alice@wonderland.lit"), 123); OmemoDevice other = new OmemoDevice(JidCreate.bareFrom("bob@builder.tv"), 444); diff --git a/smack-omemo/src/test/java/org/jivesoftware/smackx/omemo/OmemoStoreTest.java b/smack-omemo/src/test/java/org/jivesoftware/smackx/omemo/OmemoStoreTest.java index 22b626054..909aad68c 100644 --- a/smack-omemo/src/test/java/org/jivesoftware/smackx/omemo/OmemoStoreTest.java +++ b/smack-omemo/src/test/java/org/jivesoftware/smackx/omemo/OmemoStoreTest.java @@ -27,8 +27,8 @@ import static junit.framework.TestCase.assertTrue; import java.io.IOException; import java.util.Arrays; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; -import java.util.Map; import java.util.TreeMap; import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException; @@ -174,7 +174,7 @@ public abstract class OmemoStoreTest before = store.generateOmemoPreKeys(1, 10); + TreeMap before = store.generateOmemoPreKeys(1, 10); assertEquals("The store must have no prekeys before this test.", 0, store.loadOmemoPreKeys(alice).size()); store.storeOmemoPreKeys(alice, before); @@ -247,8 +247,8 @@ public abstract class OmemoStoreTest sessions = store.loadAllRawSessionsOf(alice, bob.getJid()); + HashMap sessions = store.loadAllRawSessionsOf(alice, bob.getJid()); assertNotNull(sessions); assertEquals(0, sessions.size()); } diff --git a/smack-openpgp/build.gradle b/smack-openpgp/build.gradle index 1a1fcaafe..cde598465 100644 --- a/smack-openpgp/build.gradle +++ b/smack-openpgp/build.gradle @@ -1,8 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} - description = """\ Smack API for XEP-0373: OpenPGP for XMPP.""" @@ -13,13 +8,10 @@ dependencies { api project(':smack-extensions') api project(':smack-experimental') - api 'org.pgpainless:pgpainless-core:1.5.3' + api 'org.pgpainless:pgpainless-core:1.3.1' testImplementation "org.bouncycastle:bcprov-jdk18on:${bouncyCastleVersion}" testFixturesApi(testFixtures(project(":smack-core"))) testImplementation group: 'commons-io', name: 'commons-io', version: "$commonsIoVersion" - - // TODO: Migrate Junit4 tests to Junit5. - testImplementation "org.junit.vintage:junit-vintage-engine:$junitVersion" } diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpContact.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpContact.java index c575fc5b7..b7ffa0e71 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpContact.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpContact.java @@ -362,7 +362,6 @@ public class OpenPgpContact { * @throws SmackException.NoResponseException in case the server doesn't respond. * @throws IOException IO is dangerous. */ - @SuppressWarnings("JavaUtilDate") public void updateKeys(XMPPConnection connection, PublicKeysListElement metadata) throws InterruptedException, SmackException.NotConnectedException, SmackException.NoResponseException, IOException { diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java index b4a22c7cc..645f5bb66 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpManager.java @@ -246,7 +246,6 @@ public final class OpenPgpManager extends Manager { * @throws SmackException.NotLoggedInException if we are not logged in. * @throws PGPException if something goes wrong during key loading/generating */ - @SuppressWarnings("JavaUtilDate") public void announceSupportAndPublish() throws NoSuchAlgorithmException, NoSuchProviderException, InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpSelf.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpSelf.java index c9f6d6d17..6ada87150 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpSelf.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/OpenPgpSelf.java @@ -71,7 +71,6 @@ public class OpenPgpSelf extends OpenPgpContact { * @throws IOException IO is dangerous * @throws PGPException PGP is brittle */ - @SuppressWarnings("JavaUtilDate") public PGPSecretKeyRing getSigningKeyRing() throws IOException, PGPException { PGPSecretKeyRingCollection secretKeyRings = getSecretKeys(); if (secretKeyRings == null) { diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/crypto/PainlessOpenPgpProvider.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/crypto/PainlessOpenPgpProvider.java index 304e3e006..2fa3bbe77 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/crypto/PainlessOpenPgpProvider.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/crypto/PainlessOpenPgpProvider.java @@ -220,7 +220,7 @@ public class PainlessOpenPgpProvider implements OpenPgpProvider { cipherStream.close(); plainText.close(); - OpenPgpMetadata info = cipherStream.getMetadata().toLegacyMetadata(); + OpenPgpMetadata info = cipherStream.getResult(); OpenPgpMessage.State state; if (info.isSigned()) { diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/EncryptedOpenPgpContentElement.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/EncryptedOpenPgpContentElement.java index ecf49010f..a79dc8997 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/EncryptedOpenPgpContentElement.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/EncryptedOpenPgpContentElement.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017-2024 Florian Schmaus, 2018 Paul Schaub. + * Copyright 2017-2019 Florian Schmaus, 2018 Paul Schaub. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,7 +45,6 @@ public abstract class EncryptedOpenPgpContentElement extends OpenPgpContentEleme this.rpad = Objects.requireNonNull(rpad); } - @SuppressWarnings("JavaUtilDate") protected EncryptedOpenPgpContentElement(Set to, List payload) { super(Objects.requireNonNullNorEmpty( to, "Encrypted OpenPGP content elements must have at least one 'to' attribute."), diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpContentElement.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpContentElement.java index 07d9327cb..974185573 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpContentElement.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/OpenPgpContentElement.java @@ -132,7 +132,7 @@ public abstract class OpenPgpContentElement implements ExtensionElement { * @param type of the ExtensionElement. * @return the extension, or null if it doesn't exist. */ - @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) + @SuppressWarnings("unchecked") public PE getExtension(String elementName, String namespace) { if (namespace == null) { return null; diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/PublicKeysListElement.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/PublicKeysListElement.java index 3f97d83e8..d4b9e81c7 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/PublicKeysListElement.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/element/PublicKeysListElement.java @@ -40,7 +40,7 @@ public final class PublicKeysListElement implements ExtensionElement { private final Map metadata; - private PublicKeysListElement(Map metadata) { + private PublicKeysListElement(TreeMap metadata) { this.metadata = Collections.unmodifiableMap(Objects.requireNonNull(metadata)); } @@ -48,8 +48,7 @@ public final class PublicKeysListElement implements ExtensionElement { return new Builder(); } - @SuppressWarnings("NonApiType") - public Map getMetadata() { + public TreeMap getMetadata() { return new TreeMap<>(metadata); } @@ -73,7 +72,7 @@ public final class PublicKeysListElement implements ExtensionElement { public static final class Builder { - private final Map metadata = new TreeMap<>(); + private final TreeMap metadata = new TreeMap<>(); private Builder() { // Empty @@ -134,13 +133,12 @@ public final class PublicKeysListElement implements ExtensionElement { return xml; } - @SuppressWarnings("JavaUtilDate") @Override public int hashCode() { return getV4Fingerprint().hashCode() + 3 * getDate().hashCode(); } - @SuppressWarnings({"UndefinedEquals", "JavaUtilDate"}) + @SuppressWarnings("UndefinedEquals") // TODO: Fix the UndefinedEquals due using Date.equals(Date) @Override public boolean equals(Object o) { diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/OpenPgpContentElementProvider.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/OpenPgpContentElementProvider.java index 616ac8779..9bba1ef5e 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/OpenPgpContentElementProvider.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/provider/OpenPgpContentElementProvider.java @@ -1,6 +1,6 @@ /** * - * Copyright 2017-2024 Florian Schmaus, 2018 Paul Schaub. + * Copyright 2017-2021 Florian Schmaus, 2018 Paul Schaub. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,9 +18,9 @@ package org.jivesoftware.smackx.ox.provider; import java.io.IOException; import java.text.ParseException; -import java.util.ArrayList; import java.util.Date; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.logging.Level; @@ -87,7 +87,7 @@ public abstract class OpenPgpContentElementProvider to = new HashSet<>(); Date timestamp = null; String rpad = null; - List payload = new ArrayList<>(); + List payload = new LinkedList<>(); outerloop: while (true) { XmlPullParser.Event tag = parser.next(); diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/store/filebased/FileBasedOpenPgpMetadataStore.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/store/filebased/FileBasedOpenPgpMetadataStore.java index d1f0b2d6b..9d20e2cfa 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/store/filebased/FileBasedOpenPgpMetadataStore.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/store/filebased/FileBasedOpenPgpMetadataStore.java @@ -118,7 +118,6 @@ public class FileBasedOpenPgpMetadataStore extends AbstractOpenPgpMetadataStore } } - @SuppressWarnings("JavaUtilDate") static void writeFingerprintsAndDates(Map data, File destination) throws IOException { if (data == null || data.isEmpty()) { diff --git a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/util/OpenPgpPubSubUtil.java b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/util/OpenPgpPubSubUtil.java index 1ba31495d..0e418d80b 100644 --- a/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/util/OpenPgpPubSubUtil.java +++ b/smack-openpgp/src/main/java/org/jivesoftware/smackx/ox/util/OpenPgpPubSubUtil.java @@ -124,7 +124,6 @@ public class OpenPgpPubSubUtil { * @throws SmackException.NotConnectedException if we are not connected. * @throws SmackException.NoResponseException if the server doesn't respond. */ - @SuppressWarnings("JavaUtilDate") public static void publishPublicKey(PepManager pepManager, PubkeyElement pubkeyElement, OpenPgpV4Fingerprint fingerprint) throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException { @@ -409,7 +408,7 @@ public class OpenPgpPubSubUtil { * which are not subscribed to the node owner. Therefore this method fetches the node directly and puts it * into the {@link PubSubManager}s node map. * - * Note: Due to the lack of a disco#info query, it might happen, that the node doesn't exist on the server, + * Note: Due to the alck of a disco#info query, it might happen, that the node doesn't exist on the server, * even though we add it to the node map. * * @see Ejabberd bug tracker about the issue @@ -465,7 +464,8 @@ public class OpenPgpPubSubUtil { } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException | NoSuchFieldException e) { - throw new LinkageError("Using reflections to create a LeafNode and put it into PubSubManagers nodeMap failed.", e); + LOGGER.log(Level.SEVERE, "Using reflections to create a LeafNode and put it into PubSubManagers nodeMap failed.", e); + throw new AssertionError(e); } } } diff --git a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/OpenPgpElementTest.java b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/OpenPgpElementTest.java index a958d1adb..2c54a0d55 100644 --- a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/OpenPgpElementTest.java +++ b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/OpenPgpElementTest.java @@ -51,7 +51,6 @@ public class OpenPgpElementTest extends SmackTestSuite { private final Set recipients; // 2014-07-10T15:06:00.000+00:00 - @SuppressWarnings("JavaUtilDate") private static final Date testDate = new Date(1405004760000L); public OpenPgpElementTest() throws XmppStringprepException { diff --git a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/OpenPgpStoreTest.java b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/OpenPgpStoreTest.java index 30e3f05af..d64c1522c 100644 --- a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/OpenPgpStoreTest.java +++ b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/OpenPgpStoreTest.java @@ -300,7 +300,6 @@ public class OpenPgpStoreTest extends SmackTestSuite { */ @Test - @SuppressWarnings("JavaUtilDate") public void t10_meta_emptyStoreTest() throws IOException { assertNotNull(openPgpStoreInstance1.getAnnouncedFingerprintsOf(alice)); assertTrue(openPgpStoreInstance1.getAnnouncedFingerprintsOf(alice).isEmpty()); @@ -325,7 +324,6 @@ public class OpenPgpStoreTest extends SmackTestSuite { } @Test - @SuppressWarnings("JavaUtilDate") public void t11_key_fetchDateTest() throws IOException { Map fetchDates1 = openPgpStoreInstance1.getPublicKeyFetchDates(alice); diff --git a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PainlessOpenPgpProviderTest.java b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PainlessOpenPgpProviderTest.java index 41319bd6f..5f1210367 100644 --- a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PainlessOpenPgpProviderTest.java +++ b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PainlessOpenPgpProviderTest.java @@ -72,7 +72,6 @@ public class PainlessOpenPgpProviderTest extends SmackTestSuite { } @Test - @SuppressWarnings("JavaUtilDate") public void encryptDecryptTest() throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, IOException, MissingUserIdOnKeyException, XmlPullParserException { // Initialize diff --git a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PublicKeysListElementTest.java b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PublicKeysListElementTest.java index eb7f3922c..319c60bcf 100644 --- a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PublicKeysListElementTest.java +++ b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox/PublicKeysListElementTest.java @@ -70,7 +70,6 @@ public class PublicKeysListElementTest extends SmackTestSuite { } @Test - @SuppressWarnings("JavaUtilDate") public void listBuilderRefusesDuplicatesTest() { PublicKeysListElement.Builder builder = PublicKeysListElement.builder(); String fp40 = "49545320414c4c2041424f555420444120484558"; diff --git a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManagerTest.java b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManagerTest.java index 668a14204..7854aedce 100644 --- a/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManagerTest.java +++ b/smack-openpgp/src/test/java/org/jivesoftware/smackx/ox_im/OXInstantMessagingManagerTest.java @@ -66,7 +66,6 @@ public class OXInstantMessagingManagerTest extends SmackTestSuite { } @Test - @SuppressWarnings("JavaUtilDate") public void test() throws IOException, PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException, SmackException, MissingUserIdOnKeyException, InterruptedException, XMPPException, XmlPullParserException { diff --git a/smack-repl/build.gradle b/smack-repl/build.gradle index 9b60cd9fb..70e055ab7 100644 --- a/smack-repl/build.gradle +++ b/smack-repl/build.gradle @@ -1,32 +1,35 @@ plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id "com.github.alisiikh.scalastyle" version "3.5.0" + id "com.github.alisiikh.scalastyle_2.12" version "2.0.2" } description = """\ A REPL (Read-Eval-Print-Loop) for Smack, or, in other words, a CLI (Command Line Interface) for Smack.""" apply plugin: 'scala' -apply plugin: 'com.github.alisiikh.scalastyle' +apply plugin: 'com.github.alisiikh.scalastyle_2.12' ext { - scalaVersion = '2.13.13' + scalaVersion = '2.13.6' } dependencies { - api project(':smack-examples') + // Smack's integration test framework (sintest) depends on + // smack-java*-full and since we may want to use parts of sinttest + // in the REPL, we simply depend sinttest. + api project(':smack-integration-test') + api project(':smack-omemo-signal') implementation "org.scala-lang:scala-library:$scalaVersion" - implementation "com.lihaoyi:ammonite_$scalaVersion:3.0.0-M1" + implementation "com.lihaoyi:ammonite_$scalaVersion:2.4.0" } -scalastyle { +scalaStyle { config = new File(rootConfigDir, 'scalaStyle.xml') verbose = true - failOnWarning = true + failOnViolation = true } -check.dependsOn(scalastyleCheck) +check.dependsOn(scalaStyleCheck) task printClasspath(dependsOn: assemble) { doLast { diff --git a/smack-repl/scala.repl b/smack-repl/scala.repl index 0e0dee4db..1da355d19 100644 --- a/smack-repl/scala.repl +++ b/smack-repl/scala.repl @@ -5,5 +5,4 @@ import org.jivesoftware.smack.util.TLSUtils import org.jivesoftware.smack.tcp._ import org.jxmpp.jid.impl.JidCreate -import org.igniterealtime.smack.examples._ -import org.igniterealtime.smack.examples.IoT._ +import org.igniterealtime.smack.smackrepl.IoT._ diff --git a/smack-examples/src/main/java/org/igniterealtime/smack/examples/DoX.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/DoX.java similarity index 94% rename from smack-examples/src/main/java/org/igniterealtime/smack/examples/DoX.java rename to smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/DoX.java index cd3745437..093a5aea9 100644 --- a/smack-examples/src/main/java/org/igniterealtime/smack/examples/DoX.java +++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/DoX.java @@ -2,9 +2,9 @@ * * Copyright 2019 Florian Schmaus * - * This file is part of smack-examples. + * This file is part of smack-repl. * - * smack-examples is free software; you can redistribute it and/or modify + * smack-repl is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.igniterealtime.smack.examples; +package org.igniterealtime.smack.smackrepl; import java.io.IOException; diff --git a/smack-examples/src/main/java/org/igniterealtime/smack/examples/IoT.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/IoT.java similarity index 98% rename from smack-examples/src/main/java/org/igniterealtime/smack/examples/IoT.java rename to smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/IoT.java index 12c74fb2a..66a968c31 100644 --- a/smack-examples/src/main/java/org/igniterealtime/smack/examples/IoT.java +++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/IoT.java @@ -2,9 +2,9 @@ * * Copyright 2016 Florian Schmaus * - * This file is part of smack-examples. + * This file is part of smack-repl. * - * smack-examples is free software; you can redistribute it and/or modify + * smack-repl is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.igniterealtime.smack.examples; +package org.igniterealtime.smack.smackrepl; import java.util.Collections; import java.util.List; diff --git a/smack-examples/src/main/java/org/igniterealtime/smack/examples/Nio.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/Nio.java similarity index 96% rename from smack-examples/src/main/java/org/igniterealtime/smack/examples/Nio.java rename to smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/Nio.java index 81ef164cb..09d296bb5 100644 --- a/smack-examples/src/main/java/org/igniterealtime/smack/examples/Nio.java +++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/Nio.java @@ -2,9 +2,9 @@ * * Copyright 2018-2021 Florian Schmaus * - * This file is part of smack-examples. + * This file is part of smack-repl. * - * smack-examples is free software; you can redistribute it and/or modify + * smack-repl is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.igniterealtime.smack.examples; +package org.igniterealtime.smack.smackrepl; import java.io.BufferedWriter; import java.io.IOException; diff --git a/smack-examples/src/main/java/org/igniterealtime/smack/examples/OmemoClient.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/OmemoClient.java similarity index 97% rename from smack-examples/src/main/java/org/igniterealtime/smack/examples/OmemoClient.java rename to smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/OmemoClient.java index 9c8652107..dc4b343e6 100644 --- a/smack-examples/src/main/java/org/igniterealtime/smack/examples/OmemoClient.java +++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/OmemoClient.java @@ -2,9 +2,9 @@ * * Copyright 2019 Paul Schaub * - * This file is part of smack-examples. + * This file is part of smack-repl. * - * smack-examples is free software; you can redistribute it and/or modify + * smack-repl is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.igniterealtime.smack.examples; +package org.igniterealtime.smack.smackrepl; import java.io.IOException; import java.nio.file.Files; @@ -185,7 +185,7 @@ public class OmemoClient { BareJid contact = JidCreate.bareFrom(com[1]); - Map devices; + HashMap devices; try { devices = omemoManager.getActiveFingerprints(contact); } catch (CorruptedOmemoKeyException | CannotEstablishOmemoSessionException | SmackException.NoResponseException e) { diff --git a/smack-examples/src/main/java/org/igniterealtime/smack/examples/TlsTest.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/TlsTest.java similarity index 96% rename from smack-examples/src/main/java/org/igniterealtime/smack/examples/TlsTest.java rename to smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/TlsTest.java index 0e924fa9a..08bd25b6d 100644 --- a/smack-examples/src/main/java/org/igniterealtime/smack/examples/TlsTest.java +++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/TlsTest.java @@ -2,9 +2,9 @@ * * Copyright 2016 Florian Schmaus * - * This file is part of smack-examples. + * This file is part of smack-repl. * - * smack-examples is free software; you can redistribute it and/or modify + * smack-repl is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.igniterealtime.smack.examples; +package org.igniterealtime.smack.smackrepl; import java.io.IOException; import java.security.KeyManagementException; diff --git a/smack-examples/src/main/java/org/igniterealtime/smack/examples/WebSocketConnection.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/WebSocketConnection.java similarity index 95% rename from smack-examples/src/main/java/org/igniterealtime/smack/examples/WebSocketConnection.java rename to smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/WebSocketConnection.java index 9e4e5856f..f693fb739 100644 --- a/smack-examples/src/main/java/org/igniterealtime/smack/examples/WebSocketConnection.java +++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/WebSocketConnection.java @@ -2,9 +2,9 @@ * * Copyright 2021 Florian Schmaus * - * This file is part of smack-examples. + * This file is part of smack-repl. * - * smack-examples is free software; you can redistribute it and/or modify + * smack-repl is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.igniterealtime.smack.examples; +package org.igniterealtime.smack.smackrepl; import java.io.IOException; import java.net.URISyntaxException; diff --git a/smack-examples/src/main/java/org/igniterealtime/smack/examples/XmppTools.java b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/XmppTools.java similarity index 96% rename from smack-examples/src/main/java/org/igniterealtime/smack/examples/XmppTools.java rename to smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/XmppTools.java index 70bb9f1f2..eeb6c7a40 100644 --- a/smack-examples/src/main/java/org/igniterealtime/smack/examples/XmppTools.java +++ b/smack-repl/src/main/java/org/igniterealtime/smack/smackrepl/XmppTools.java @@ -1,10 +1,10 @@ /** * - * Copyright 2016-2024 Florian Schmaus + * Copyright 2016-2021 Florian Schmaus * - * This file is part of smack-examples. + * This file is part of smack-repl. * - * smack-examples is free software; you can redistribute it and/or modify + * smack-repl is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. @@ -18,7 +18,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package org.igniterealtime.smack.examples; +package org.igniterealtime.smack.smackrepl; import java.io.IOException; import java.security.KeyManagementException; @@ -136,7 +136,6 @@ public class XmppTools { // CHECKSTYLE:ON } - @SuppressWarnings("JavaUtilDate") public static void sendItsAlive(String to, XMPPConnection connection) throws XmppStringprepException, NotConnectedException, InterruptedException { if (to == null) { diff --git a/smack-resolver-dnsjava/build.gradle b/smack-resolver-dnsjava/build.gradle index b4e6b85cf..b17683ecc 100644 --- a/smack-resolver-dnsjava/build.gradle +++ b/smack-resolver-dnsjava/build.gradle @@ -1,8 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} - description = """\ DNS SRV with dnsjava Use dnsjava for DNS SRV lookups.""" diff --git a/smack-resolver-javax/build.gradle b/smack-resolver-javax/build.gradle index f724be154..4caefb6f5 100644 --- a/smack-resolver-javax/build.gradle +++ b/smack-resolver-javax/build.gradle @@ -1,7 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' -} - description = """\ DNS SRV with Java7 Use javax.naming for DNS SRV lookups. The javax.naming API is availabe in JavaSE diff --git a/smack-resolver-javax/src/main/java/org/jivesoftware/smack/util/dns/javax/JavaxResolver.java b/smack-resolver-javax/src/main/java/org/jivesoftware/smack/util/dns/javax/JavaxResolver.java index 1ca3b5721..ea508f0fe 100644 --- a/smack-resolver-javax/src/main/java/org/jivesoftware/smack/util/dns/javax/JavaxResolver.java +++ b/smack-resolver-javax/src/main/java/org/jivesoftware/smack/util/dns/javax/JavaxResolver.java @@ -1,6 +1,6 @@ /** * - * Copyright 2013-2024 Florian Schmaus + * Copyright 2013-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,12 +40,11 @@ import org.minidns.record.SRV; /** * A DNS resolver (mostly for SRV records), which makes use of the API provided in the javax.* namespace. - * Note that using JavaxResolver requires applications using newer Java versions (at least 11) to declare a dependency on the "sun.jdk" module. + * Note that using JavaxResovler requires applications using newer Java versions (at least 11) to declare a dependency on the "sun.jdk" module. * * @author Florian Schmaus * */ -@SuppressWarnings("JdkObsolete") public class JavaxResolver extends DNSResolver implements SmackInitializer { private static JavaxResolver instance; @@ -84,7 +83,6 @@ public class JavaxResolver extends DNSResolver implements SmackInitializer { } @Override - @SuppressWarnings("BanJNDI") protected List lookupSrvRecords0(DnsName name, List lookupFailures, DnssecMode dnssecMode) { Attribute srvAttribute; diff --git a/smack-resolver-minidns-dox/build.gradle b/smack-resolver-minidns-dox/build.gradle index f8ebf7d3b..de740cf84 100644 --- a/smack-resolver-minidns-dox/build.gradle +++ b/smack-resolver-minidns-dox/build.gradle @@ -1,8 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} - description = """\ DNS over XMPP (DoX) support using MiniDNS.""" diff --git a/smack-resolver-minidns/build.gradle b/smack-resolver-minidns/build.gradle index c1fb68a28..22809986c 100644 --- a/smack-resolver-minidns/build.gradle +++ b/smack-resolver-minidns/build.gradle @@ -1,8 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} - description = """\ DNS SRV with minidns Use minidns for DNS SRV lookups. For platforms that don't provide the diff --git a/smack-sasl-javax/build.gradle b/smack-sasl-javax/build.gradle index 9f2eecc89..e6fffd631 100644 --- a/smack-sasl-javax/build.gradle +++ b/smack-sasl-javax/build.gradle @@ -1,7 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' -} - description = """\ SASL with javax.security.sasl Use javax.security.sasl for SASL.""" diff --git a/smack-sasl-javax/src/main/java/org/jivesoftware/smack/sasl/javax/SASLExternalMechanism.java b/smack-sasl-javax/src/main/java/org/jivesoftware/smack/sasl/javax/SASLExternalMechanism.java index fdc7822a8..f0c409c49 100644 --- a/smack-sasl-javax/src/main/java/org/jivesoftware/smack/sasl/javax/SASLExternalMechanism.java +++ b/smack-sasl-javax/src/main/java/org/jivesoftware/smack/sasl/javax/SASLExternalMechanism.java @@ -24,7 +24,7 @@ package org.jivesoftware.smack.sasl.javax; * to the implementer to determine how to do this. Here is one method: * * Create a java keystore with your SSL certificate in it: - * keytool -genkey -alias username -dname "cn=username,ou=organizationalUnit,o=organizationalName,l=locality,s=state,c=country" + * keytool -genkey -alias username -dname "cn=username,ou=organizationalUnit,o=organizationaName,l=locality,s=state,c=country" * * Next, set the System Properties: *
      @@ -38,7 +38,7 @@ package org.jivesoftware.smack.sasl.javax; * simply provide the one in the keyStore. * * Also worth noting is the EXTERNAL mechanism in Smack is not enabled by default. - * To enable it, the implementer will need to call SASLAuthentication.supportSASLMechanism("EXTERNAL"); + * To enable it, the implementer will need to call SASLAuthentication.supportSASLMechamism("EXTERNAL"); * * @author Jay Kline */ diff --git a/smack-sasl-provided/build.gradle b/smack-sasl-provided/build.gradle index 65f10b3b1..a9f3724d0 100644 --- a/smack-sasl-provided/build.gradle +++ b/smack-sasl-provided/build.gradle @@ -1,8 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} - description = """\ SASL with Smack provided code Use Smack provided code for SASL.""" diff --git a/smack-sasl-provided/src/main/java/org/jivesoftware/smack/sasl/provided/SASLDigestMD5Mechanism.java b/smack-sasl-provided/src/main/java/org/jivesoftware/smack/sasl/provided/SASLDigestMD5Mechanism.java index 284ef767b..2b1a89d0a 100644 --- a/smack-sasl-provided/src/main/java/org/jivesoftware/smack/sasl/provided/SASLDigestMD5Mechanism.java +++ b/smack-sasl-provided/src/main/java/org/jivesoftware/smack/sasl/provided/SASLDigestMD5Mechanism.java @@ -30,7 +30,7 @@ public class SASLDigestMD5Mechanism extends SASLMechanism { public static final String NAME = DIGESTMD5; - private static final String INITIAL_NONCE = "00000001"; + private static final String INITAL_NONCE = "00000001"; /** * The only 'qop' value supported by this implementation @@ -159,7 +159,7 @@ public class SASLDigestMD5Mechanism extends SASLMechanism { + ",realm=\"" + serviceName + '"' + ",nonce=\"" + nonce + '"' + ",cnonce=\"" + cnonce + '"' - + ",nc=" + INITIAL_NONCE + + ",nc=" + INITAL_NONCE + ",qop=auth" + ",digest-uri=\"" + digestUri + '"' + ",response=" + responseValue @@ -218,7 +218,7 @@ public class SASLDigestMD5Mechanism extends SASLMechanism { kd_argument.append(':'); kd_argument.append(nonce); kd_argument.append(':'); - kd_argument.append(INITIAL_NONCE); + kd_argument.append(INITAL_NONCE); kd_argument.append(':'); kd_argument.append(cnonce); kd_argument.append(':'); diff --git a/smack-streammanagement/build.gradle b/smack-streammanagement/build.gradle index 73eb2139e..c06c423d9 100644 --- a/smack-streammanagement/build.gradle +++ b/smack-streammanagement/build.gradle @@ -1,8 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} - description = """\ Smack support for XMPP Stream Management (XEP-0198).""" diff --git a/smack-tcp/build.gradle b/smack-tcp/build.gradle index db2ee6bc2..a0cffad6b 100644 --- a/smack-tcp/build.gradle +++ b/smack-tcp/build.gradle @@ -1,8 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} - description = """\ Smack for standard XMPP connections over TCP.""" diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/sm/predicates/tcp/package-info.java b/smack-tcp/src/main/java/org/jivesoftware/smack/sm/predicates/tcp/package-info.java index d6f94b910..15e022848 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/sm/predicates/tcp/package-info.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/sm/predicates/tcp/package-info.java @@ -16,6 +16,6 @@ */ /** - * XMPPTCPConnection Stream Management Predicates. + * XMPPTCPConnection Stream Managment Predicates. */ package org.jivesoftware.smack.sm.predicates.tcp; diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java index 1e622bedc..38d2d3e55 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -186,7 +187,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { private static boolean useSmResumptionDefault = true; /** - * The stream ID of the stream that is currently resumable, i.e. the stream we hold the state + * The stream ID of the stream that is currently resumable, ie. the stream we hold the state * for in {@link #clientHandledStanzasCount}, {@link #serverHandledStanzasCount} and * {@link #unacknowledgedStanzas}. */ @@ -202,7 +203,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { private Failed smResumptionFailed; /** - * Represents the state of stream management. + * Represents the state of stream magement. *

      * This boolean is marked volatile as it is read by various threads, including the reader thread via {@link #isSmEnabled()}. *

      @@ -294,7 +295,6 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { * * @param config the connection configuration. */ - @SuppressWarnings("this-escape") public XMPPTCPConnection(XMPPTCPConnectionConfiguration config) { super(config); this.config = config; @@ -415,7 +415,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { // bind IQ may trigger a SM ack request, which would be invalid in the pre resource bound state. smEnabledSyncPoint = false; - List previouslyUnackedStanzas = new ArrayList(); + List previouslyUnackedStanzas = new LinkedList(); if (unacknowledgedStanzas != null) { // There was a previous connection with SM enabled but that was either not resumable or // failed to resume. Make sure that we (re-)send the unacknowledged stanzas. @@ -1162,8 +1162,8 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { } catch (Exception e) { // Set running to false since this thread will exit here and notifyConnectionError() will wait until - // the reader and writer thread's 'running' value is false. Hence, we need to set it to false before calling - // notifyConnectionError() below, even though run() also sets it to false. Therefore, do not remove this. + // the reader and writer thread's 'running' value is false. Hence we need to set it to false before calling + // notifyConnetctionError() below, even though run() also sets it to false. Therefore, do not remove this. running = false; String ignoreReasonThread = null; @@ -1256,7 +1256,8 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { final boolean smResumptionPossible = isSmResumptionPossible(); // Don't throw a NotConnectedException is there is an resumable stream available if (!smResumptionPossible) { - throw new NotConnectedException(XMPPTCPConnection.this, "done=true smResumptionPossible=false"); + throw new NotConnectedException(XMPPTCPConnection.this, "done=" + done + + " smResumptionPossible=" + smResumptionPossible); } } } @@ -1644,8 +1645,8 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { private void sendSmAcknowledgementInternal() throws NotConnectedException, InterruptedException { AckAnswer ackAnswer = new AckAnswer(clientHandledStanzasCount); // Do net put an ack to the queue if it has already been shutdown. Some servers, like ejabberd, like to request - // an ack even after we have sent a stream close (and hence the queue was shutdown). If we would not check here, - // then the ack would dangle around in the queue, and be sent on the next re-connection attempt even before the + // an ack even after we have send a stream close (and hance the queue was shutdown). If we would not check here, + // then the ack would dangle around in the queue, and be send on the next re-connection attempt even before the // stream open. packetWriter.queue.putIfNotShutdown(ackAnswer); } diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java index fabfa4d6f..bd194fcda 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java @@ -1,6 +1,6 @@ /** * - * Copyright 2019-2024 Florian Schmaus + * Copyright 2019-2021 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -369,11 +369,11 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM newPendingOutputFilterData |= outputResult.pendingFilterData; outputFilterInputData = outputResult.filteredOutputData; if (outputFilterInputData != null) { - ((java.nio.Buffer) outputFilterInputData).flip(); + outputFilterInputData.flip(); } } - // It is ok if outputFilterInputData is 'null' here, this is expected behavior. + // It is ok if outpuFilterInputData is 'null' here, this is expected behavior. if (outputFilterInputData != null && outputFilterInputData.hasRemaining()) { filteredOutgoingBuffer = outputFilterInputData; } else { @@ -459,7 +459,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM } int bytesRead; - ((java.nio.Buffer) incomingBuffer).clear(); + incomingBuffer.clear(); try { bytesRead = selectedSocketChannel.read(incomingBuffer); } catch (IOException e) { @@ -474,7 +474,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM // read() may return -1 if the input side of a socket is shut down. // Note that we do not call notifyConnectionError() here because the connection may be // cleanly shutdown which would also cause read() to return '-1. I assume that this socket - // will be selected again, on which read() would throw an IOException, which will be caught + // will be selected again, on which read() would throw an IOException, which will be catched // and invoke notifyConnectionError() (see a few lines above). /* IOException exception = new IOException("NIO read() returned " + bytesRead); @@ -503,7 +503,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM ByteBuffer filteredIncomingBuffer = incomingBuffer; for (ListIterator it = connectionInternal.getXmppInputOutputFilterEndIterator(); it.hasPrevious();) { - ((java.nio.Buffer) filteredIncomingBuffer).flip(); + filteredIncomingBuffer.flip(); ByteBuffer newFilteredIncomingBuffer; try { @@ -518,8 +518,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM filteredIncomingBuffer = newFilteredIncomingBuffer; } - ((java.nio.Buffer) filteredIncomingBuffer).flip(); - final int bytesReadAfterFilter = filteredIncomingBuffer.remaining(); + final int bytesReadAfterFilter = filteredIncomingBuffer.flip().remaining(); totalBytesReadAfterFilter += bytesReadAfterFilter; @@ -634,7 +633,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM @Override protected void loadConnectionEndpoints(LookupConnectionEndpointsSuccess lookupConnectionEndpointsSuccess) { // The API contract stats that we will be given the instance we handed out with lookupConnectionEndpoints, - // which must be of type DiscoveredTcpEndpoints here. Hence, if we can not cast it, then there is an internal + // which must be of type DiscoveredTcpEndpoints here. Hence if we can not cast it, then there is an internal // Smack error. discoveredTcpEndpoints = (DiscoveredTcpEndpoints) lookupConnectionEndpointsSuccess; } @@ -712,7 +711,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM // Add OP_WRITE to the interested Ops, since we have now new things to write. Note that this may cause // multiple reactor threads to race to the channel selected callback in case we perform this right after - // a select() returned with this selection key in the selected-key set. Hence, we use tryLock() in the + // a select() returned with this selection key in the selected-key set. Hence we use tryLock() in the // channel selected callback to keep the invariant that only exactly one thread is performing the // callback. // Note that we need to perform setInterestedOps() *without* holding the channelSelectedCallbackLock, as @@ -777,7 +776,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM // TODO: It appears this should be done in a generic way. I'd assume we always // have to wait for stream features after the connection was established. If this is true then consider // moving this into State.AbstractTransport. But I am not yet 100% positive that this is the case for every - // transport. Hence, keep it here for now. + // transport. Hence keep it here for now. connectionInternal.newStreamOpenWaitForFeaturesSequence("stream features after initial connection"); return new TcpSocketConnectedResult(remoteAddress); @@ -981,7 +980,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM ByteBuffer[] outputDataArray = pendingOutputData.toArray(new ByteBuffer[pendingOutputData.size()]); - ((java.nio.Buffer) myNetData).clear(); + myNetData.clear(); while (true) { SSLEngineResult result; @@ -1038,7 +1037,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM newCapacity = 2 * myNetData.capacity(); } ByteBuffer newMyNetData = ByteBuffer.allocateDirect(newCapacity); - ((java.nio.Buffer) myNetData).flip(); + myNetData.flip(); newMyNetData.put(myNetData); myNetData = newMyNetData; continue; @@ -1061,12 +1060,12 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM int accumulatedDataBytes = pendingInputData.remaining() + inputData.remaining(); accumulatedData = ByteBuffer.allocate(accumulatedDataBytes); accumulatedData.put(pendingInputData) - .put(inputData); - ((java.nio.Buffer) accumulatedData).flip(); + .put(inputData) + .flip(); pendingInputData = null; } - ((java.nio.Buffer) peerAppData).clear(); + peerAppData.clear(); while (true) { SSLEngineResult result; @@ -1091,7 +1090,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM // A delegated task is asynchronously running. Take care of the remaining accumulatedData. addAsPendingInputData(accumulatedData); // Return here, as the async task created by handleHandshakeStatus will continue calling the - // channelSelectedCallback. + // cannelSelectedCallback. return null; case NEED_UNWRAP: continue; @@ -1115,7 +1114,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM switch (engineResultStatus) { case OK: // SSLEngine's unwrap() may not consume all bytes from the source buffer. If this is the case, then - // simply perform another unwrap until accumulatedData has no remaining bytes. + // simply perform another unwrap until accumlatedData has no remaining bytes. if (accumulatedData.hasRemaining()) { continue; } @@ -1144,8 +1143,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM // higher layer. That is, here 'byteBuffer' is typically 'incomingBuffer', which is a direct buffer only // allocated once per connection for performance reasons and hence re-used for read() calls. pendingInputData = ByteBuffer.allocate(byteBuffer.remaining()); - pendingInputData.put(byteBuffer); - ((java.nio.Buffer) pendingInputData).flip(); + pendingInputData.put(byteBuffer).flip(); pendingInputFilterData = pendingInputData.hasRemaining(); } diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModuleDescriptor.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModuleDescriptor.java index 0dc5d40a4..c48d8c546 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModuleDescriptor.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModuleDescriptor.java @@ -1,6 +1,6 @@ /** * - * Copyright 2019-2024 Florian Schmaus + * Copyright 2019-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -65,8 +65,6 @@ public class XmppTcpTransportModuleDescriptor extends ModularXmppClientToServerC public static final class Builder extends ModularXmppClientToServerConnectionModuleDescriptor.Builder { - // Invoked via reflection. - @SuppressWarnings("UnusedMethod") private Builder(ModularXmppClientToServerConnectionConfiguration.Builder connectionConfigurationBuilder) { super(connectionConfigurationBuilder); } diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/rce/RemoteXmppTcpConnectionEndpoints.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/rce/RemoteXmppTcpConnectionEndpoints.java index d46344d93..2b2514dbb 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/rce/RemoteXmppTcpConnectionEndpoints.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/rce/RemoteXmppTcpConnectionEndpoints.java @@ -169,7 +169,7 @@ public class RemoteXmppTcpConnectionEndpoints { * * @param domain the domain. * @param domainType the XMPP domain type, server or client. - * @param lookupFailures a list that will be populated with all failures that occurred during lookup. + * @param lookupFailures a list that will be populated with all failures that oocured during lookup. * @param dnssecMode the DNSSEC mode. * @param dnsResolver the DNS resolver to use. * @return a list of resolved host addresses for this domain. diff --git a/smack-websocket-java11/build.gradle b/smack-websocket-java11/build.gradle index c019f214c..9439bad20 100644 --- a/smack-websocket-java11/build.gradle +++ b/smack-websocket-java11/build.gradle @@ -1,7 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' -} - description = """\ Smack for XMPP connections over WebSocket (RFC 7395) using java.net.http.WebSocket.""" diff --git a/smack-websocket-okhttp/build.gradle b/smack-websocket-okhttp/build.gradle index 9e7b2fb46..6f83f2c83 100644 --- a/smack-websocket-okhttp/build.gradle +++ b/smack-websocket-okhttp/build.gradle @@ -1,8 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} - description = """\ Smack for XMPP connections over WebSocket (RFC 7395) using OkHttp.""" diff --git a/smack-websocket/build.gradle b/smack-websocket/build.gradle index 73dfab23b..1ef60c233 100644 --- a/smack-websocket/build.gradle +++ b/smack-websocket/build.gradle @@ -1,8 +1,3 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} - description = """\ Smack for XMPP connections over WebSocket (RFC 7395).""" diff --git a/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/WebSocketConnectionAttemptState.java b/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/WebSocketConnectionAttemptState.java index 222aafc65..80f58ab42 100644 --- a/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/WebSocketConnectionAttemptState.java +++ b/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/WebSocketConnectionAttemptState.java @@ -51,7 +51,7 @@ public final class WebSocketConnectionAttemptState { /** * Establish a websocket connection with one of the discoveredRemoteConnectionEndpoints.
      * - * @return {@link AbstractWebSocket} with which connection is established + * @return {@link AbstractWebSocket} with which connection is establised * @throws InterruptedException if the calling thread was interrupted */ @SuppressWarnings({"incomplete-switch", "MissingCasesInEnumSwitch"}) diff --git a/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/XmppWebSocketTransportModule.java b/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/XmppWebSocketTransportModule.java index 55236858c..9cfa8fe2f 100644 --- a/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/XmppWebSocketTransportModule.java +++ b/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/XmppWebSocketTransportModule.java @@ -135,7 +135,7 @@ public final class XmppWebSocketTransportModule // TODO: It appears this should be done in a generic way. I'd assume we always // have to wait for stream features after the connection was established. But I - // am not yet 100% positive that this is the case for every transport. Hence, keep it here for now(?). + // am not yet 100% positive that this is the case for every transport. Hence keep it here for now(?). // See also similar comment in XmppTcpTransportModule. // Maybe move this into ConnectedButUnauthenticated state's transitionInto() method? That seems to be the // right place. @@ -157,7 +157,7 @@ public final class XmppWebSocketTransportModule final WebSocketRemoteConnectionEndpoint connectedEndpoint; public WebSocketConnectedResult(WebSocketRemoteConnectionEndpoint connectedEndpoint) { - super("WebSocket connection established with endpoint: " + connectedEndpoint); + super("WebSocket connection establised with endpoint: " + connectedEndpoint); this.connectedEndpoint = connectedEndpoint; } } @@ -271,7 +271,6 @@ public final class XmppWebSocketTransportModule asyncButOrderedOutgoingElementsQueue.performAsyncButOrdered(outgoingElementsQueue, () -> { for (TopLevelStreamElement topLevelStreamElement; (topLevelStreamElement = outgoingElementsQueue.poll()) != null;) { websocket.send(topLevelStreamElement); - connectionInternal.fireFirstLevelElementSendListeners(topLevelStreamElement); } }); } diff --git a/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/impl/AbstractWebSocket.java b/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/impl/AbstractWebSocket.java index 6924cc6bd..bbe4ac749 100644 --- a/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/impl/AbstractWebSocket.java +++ b/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/impl/AbstractWebSocket.java @@ -16,25 +16,17 @@ */ package org.jivesoftware.smack.websocket.impl; -import java.io.IOException; -import java.util.logging.Level; import java.util.logging.Logger; import javax.net.ssl.SSLSession; -import javax.xml.namespace.QName; import org.jivesoftware.smack.SmackFuture; import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal; import org.jivesoftware.smack.debugger.SmackDebugger; import org.jivesoftware.smack.packet.TopLevelStreamElement; import org.jivesoftware.smack.packet.XmlEnvironment; -import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smack.websocket.WebSocketException; -import org.jivesoftware.smack.websocket.elements.WebSocketCloseElement; -import org.jivesoftware.smack.websocket.elements.WebSocketOpenElement; import org.jivesoftware.smack.websocket.rce.WebSocketRemoteConnectionEndpoint; -import org.jivesoftware.smack.xml.XmlPullParser; -import org.jivesoftware.smack.xml.XmlPullParserException; public abstract class AbstractWebSocket { @@ -103,34 +95,28 @@ public abstract class AbstractWebSocket { static String getStreamFromOpenElement(String openElement) { String streamElement = openElement.replaceFirst("\\A\\s*\\z", " xmlns:stream='http://etherx.jabber.org/streams'>") - .replaceFirst(">\\s*\\z", " xmlns:stream='http://etherx.jabber.org/streams'>"); - + .replaceFirst("/>\\s*\\z", " xmlns:stream='http://etherx.jabber.org/streams'>"); return streamElement; } + // TODO: Make this method less fragile, e.g. by parsing a little bit into the element to ensure that this is an + // element qualified by the correct namespace. static boolean isOpenElement(String text) { - XmlPullParser parser; - try { - parser = PacketParserUtils.getParserFor(text); - QName qname = parser.getQName(); - return qname.equals(WebSocketOpenElement.QNAME); - } catch (XmlPullParserException | IOException e) { - LOGGER.log(Level.WARNING, "Could not inspect \"" + text + "\" for open element", e); - return false; + if (text.startsWith(" element qualified by the correct namespace. The fragility comes due the fact that the element could, + // inter alia, be specified as + // static boolean isCloseElement(String text) { - XmlPullParser parser; - try { - parser = PacketParserUtils.getParserFor(text); - QName qname = parser.getQName(); - return qname.equals(WebSocketCloseElement.QNAME); - } catch (XmlPullParserException | IOException e) { - LOGGER.log(Level.WARNING, "Could not inspect \"" + text + "\" for close element", e); - return false; + if (text.startsWith("")) { + return true; } + return false; } protected void onWebSocketFailure(Throwable throwable) { diff --git a/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/rce/WebSocketRemoteConnectionEndpointLookup.java b/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/rce/WebSocketRemoteConnectionEndpointLookup.java index 658814916..347180f69 100644 --- a/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/rce/WebSocketRemoteConnectionEndpointLookup.java +++ b/smack-websocket/src/main/java/org/jivesoftware/smack/websocket/rce/WebSocketRemoteConnectionEndpointLookup.java @@ -77,7 +77,7 @@ public final class WebSocketRemoteConnectionEndpointLookup { public Result(List lookupFailures) { // The list of endpoints needs to be mutable, because maybe a user supplied endpoint will be added to it. - // Hence, we do not use Collections.emptyList() as argument for the discovered endpoints. + // Hence we do not use Collections.emptyList() as argument for the discovered endpoints. this(new ArrayList<>(1), new ArrayList<>(1), lookupFailures); } @@ -99,7 +99,7 @@ public final class WebSocketRemoteConnectionEndpointLookup { // TODO: Remove the following methods since the fields are already public? Or make the fields private and use // the methods? I tend to remove the methods, as their method name is pretty long. But OTOH the fields reference - // mutable datastructures, which is uncommon to be public. + // mutable datastructes, which is uncommon to be public. public List getDiscoveredSecureRemoteConnectionEndpoints() { return discoveredSecureEndpoints; } diff --git a/smack-websocket/src/test/java/org/jivesoftware/smack/websocket/impl/AbstractWebSocketTest.java b/smack-websocket/src/test/java/org/jivesoftware/smack/websocket/impl/AbstractWebSocketTest.java index 5280efe7b..23f274616 100644 --- a/smack-websocket/src/test/java/org/jivesoftware/smack/websocket/impl/AbstractWebSocketTest.java +++ b/smack-websocket/src/test/java/org/jivesoftware/smack/websocket/impl/AbstractWebSocketTest.java @@ -24,20 +24,18 @@ import org.junit.jupiter.api.Test; public final class AbstractWebSocketTest { private static final String OPEN_ELEMENT = ""; - private static final String OPEN_ELEMENT_EXPANDED = ""; private static final String OPEN_STREAM = ""; private static final String CLOSE_ELEMENT = ""; @Test public void getStreamFromOpenElementTest() { - assertEquals(OPEN_STREAM, AbstractWebSocket.getStreamFromOpenElement(OPEN_ELEMENT)); - assertEquals(OPEN_STREAM, AbstractWebSocket.getStreamFromOpenElement(OPEN_ELEMENT_EXPANDED)); + String generatedOpenStream = AbstractWebSocket.getStreamFromOpenElement(OPEN_ELEMENT); + assertEquals(generatedOpenStream, OPEN_STREAM); } @Test public void isOpenElementTest() { assertTrue(AbstractWebSocket.isOpenElement(OPEN_ELEMENT)); - assertTrue(AbstractWebSocket.isOpenElement(OPEN_ELEMENT_EXPANDED)); assertFalse(AbstractWebSocket.isOpenElement(OPEN_STREAM)); } diff --git a/smack-xmlparser-stax/build.gradle b/smack-xmlparser-stax/build.gradle index 9cc67deda..b25ce2e9a 100644 --- a/smack-xmlparser-stax/build.gradle +++ b/smack-xmlparser-stax/build.gradle @@ -1,6 +1,7 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' -} +// Note that this is also declared in the main build.gradle for +// subprojects, but since evaluationDependsOnChildren is enabled we +// need to declare it here too to have bundle{bnd{...}} available +apply plugin: 'biz.aQute.bnd.builder' description = """\ Smack XML parser using Stax.""" diff --git a/smack-xmlparser-xpp3/build.gradle b/smack-xmlparser-xpp3/build.gradle index 8c5063117..f0a9f56c6 100644 --- a/smack-xmlparser-xpp3/build.gradle +++ b/smack-xmlparser-xpp3/build.gradle @@ -1,7 +1,7 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} +// Note that this is also declared in the main build.gradle for +// subprojects, but since evaluationDependsOnChildren is enabled we +// need to declare it here too to have bundle{bnd{...}} available +apply plugin: 'biz.aQute.bnd.builder' description = """\ Smack XML parser using XPP3.""" diff --git a/smack-xmlparser/build.gradle b/smack-xmlparser/build.gradle index 9686ae87b..513a2b153 100644 --- a/smack-xmlparser/build.gradle +++ b/smack-xmlparser/build.gradle @@ -1,7 +1,7 @@ -plugins { - id 'org.igniterealtime.smack.java-common-conventions' - id 'org.igniterealtime.smack.android-conventions' -} +// Note that this is also declared in the main build.gradle for +// subprojects, but since evaluationDependsOnChildren is enabled we +// need to declare it here too to have bundle{bnd{...}} available +apply plugin: 'biz.aQute.bnd.builder' description = """\ Smack XML parser fundamentals""" diff --git a/smack-xmlparser/src/main/java/org/jivesoftware/smack/xml/XmlPullParser.java b/smack-xmlparser/src/main/java/org/jivesoftware/smack/xml/XmlPullParser.java index fd5a5acfc..c49ac66ae 100644 --- a/smack-xmlparser/src/main/java/org/jivesoftware/smack/xml/XmlPullParser.java +++ b/smack-xmlparser/src/main/java/org/jivesoftware/smack/xml/XmlPullParser.java @@ -110,7 +110,7 @@ public interface XmlPullParser { String getAttributeNamespace(int index); /** - * Returns the localpart of the attribute's name or null in case the index does not refer to an + * Returns the loacalpart of the attribute's name or null in case the index does not refer to an * attribute. * * @param index the attribute index. diff --git a/version b/version index da70b5b12..891d39303 100644 --- a/version +++ b/version @@ -1 +1 @@ -4.5.0-beta5-SNAPSHOT +4.5.0-alpha2-SNAPSHOT