diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..26e468f33 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,7 @@ +Thank you for your contribution! + +Before creating a Pull Request, please make sure to +* read https://github.com/igniterealtime/Smack/wiki/Guidelines-for-Smack-Developers-and-Contributors +* run `gradle check` successfully in order to make sure that your code does not break any JUnit tests and is conform to the projects code style. +* (if applicable) mention any Jira issue codes (eg. `SMACK-XXX`) in the *body* of your commit message (not the header), so that Jira automatically links the PR to the issue. +* squash your commits if possible/sensible. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..fa9bb447a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,96 @@ +name: CI + +on: [push, pull_request] + +jobs: + build: + name: Build Smack + + runs-on: ubuntu-24.04 + strategy: + matrix: + java: + - 17 + - 21 + env: + PRIMARY_JAVA_VERSION: 21 + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up JDK ${{ matrix.java }} + uses: actions/setup-java@v3 + with: + java-version: ${{ matrix.java }} + distribution: temurin + + # Caches + - name: Cache Maven + uses: actions/cache@v2 + with: + path: ~/.m2/repository + key: maven-${{ hashFiles('**/build.gradle') }} + restore-keys: | + maven- + - name: Cache Gradle + uses: actions/cache@v2 + with: + path: ~/.gradle/caches + key: gradle-caches-${{ hashFiles('**/build.gradle') }} + restore-keys: + gradle-caches + - name: Cache Android SDK + uses: actions/cache@v2 + with: + path: | + ~/.android/sdk + key: android-${{ hashFiles('build.gradle') }} + restore-keys: | + android- + + # Pre-reqs + - name: Install GraphViz + run: sudo apt update && sudo apt install graphviz + - name: Install Android SDK Manager + uses: android-actions/setup-android@v3 + - name: Install Android SDK + run: | + sdkmanager "platforms;android-23" + + # Testing + - name: Gradle Check + run: ./gradlew check --stacktrace + + # Test local publish + - name: Gradle publish + run: ./gradlew publishToMavenLocal --stacktrace + + # Javadoc + - name: Javadoc + if: ${{ matrix.java == env.PRIMARY_JAVA_VERSION }} + run: ./gradlew javadocAll --stacktrace + + # Test Coverage Report + - name: Aggregated Jacoco Test Coverage Report + 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 + + # Upload build artifacts + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: smack-java-${{ matrix.java }} + path: | + smack-*/build/libs/*.jar + !**/*-test-fixtures.jar + !**/*-tests.jar diff --git a/.gitignore b/.gitignore index 8eeb443be..ec8037f60 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ # IntelliJ .idea *.iml +*.ipr +*.iws +!.idea/icon.svg # Mac OS X .DS_Store @@ -9,13 +12,13 @@ .project .settings .gradle -gradle.properties build/ core/build/ debug/build/ experimental/build/ extensions/build/ +out/ bin/ core/bin @@ -25,3 +28,5 @@ extensions/bin target/ .metadata + +local.properties diff --git a/.idea/icon.svg b/.idea/icon.svg new file mode 100644 index 000000000..1d9b3fb6f --- /dev/null +++ b/.idea/icon.svg @@ -0,0 +1,89 @@ + +image/svg+xml \ No newline at end of file diff --git a/.mailmap b/.mailmap new file mode 100644 index 000000000..4045d19c0 --- /dev/null +++ b/.mailmap @@ -0,0 +1,27 @@ +Paul Schaub +Aditya Borikar +Anno van Vliet +Daryl E. Herzmann +Damian Minkov +Craig Hesling +Dave Stanley +Marcel Heckel +Candy Lohse +Luca Stucchi +Luke Granger-Brown +Florian Kimmann +Adam Stawicki +Andrey Sokolov +Andri Khrisharyadi +Andriy Tsykholyas +Fernando Ramirez +Marcel Heckel +Robin Collier +Thibaut Le Guilly +Thomas Pocreau +Vadim Fite +Vaibhav Ranglani +Xiaowei YAN + +Guus der Kinderen guus +Jesus Fuentes Jesus diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0cd8d9556..000000000 --- a/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: android -android: - components: - - android-8 -install: gradle assemble -script: gradle check - diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..b413e7f75 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,1888 @@ +# 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 + +- [SMACK-926](https://igniterealtime.atlassian.net/browse/SMACK-926) Memory-leak in ServiceDiscoveryManager +- [SMACK-925](https://igniterealtime.atlassian.net/browse/SMACK-925) MultiUserChat Presence interceptors do not intercept + +# 4.4.5 -- 2022-03-02 + +### Bug + +- [SMACK-923](https://igniterealtime.atlassian.net/browse/SMACK-923) Smack reactor should immediately handle scheduled actions that are due in zero milliseconds +- [SMACK-921](https://igniterealtime.atlassian.net/browse/SMACK-921) XmlStringBuilder.attribute\(String name, Enum value\) should use value.toString\(\) \(and not value.name\(\)\) +- [SMACK-920](https://igniterealtime.atlassian.net/browse/SMACK-920) SASL GSSAPI mechanism should be marked to not require a password +- [SMACK-918](https://igniterealtime.atlassian.net/browse/SMACK-918) Self presences in MUC are no longer handled correctly + +### Improvement + +- [SMACK-922](https://igniterealtime.atlassian.net/browse/SMACK-922) Support 'optional text' and arbitrary element in Jingle 'reason' element +- [SMACK-919](https://igniterealtime.atlassian.net/browse/SMACK-919) PubSub ItemProvider should ignore character data in s + +## 4.4.4 -- 2021-11-01 + +### Bug + +- [SMACK-916](https://igniterealtime.atlassian.net/browse/SMACK-916) - + XMPPErrorException.stanza is missing a getter method +- [SMACK-915](https://igniterealtgime.atlassian.net/browse/SMACK-915) - + Smack does not process MUC destroy message if they contain + \'status\' +- [SMACK-914](https://igniterealtime.atlassian.net/browse/SMACK-914) - + MultiUserChat may be become unjoinable due to a race condition +- [SMACK-913](https://igniterealtime.atlassian.net/browse/SMACK-913) - + MultiUserChat.serviceSupportsStableIds\\(\\) may throws a + NullPointerException +- [SMACK-912](https://igniterealtime.atlassian.net/browse/SMACK-912) - + Smack does not start the local SOCKS5 proxy automatically +- [SMACK-910](https://igniterealtime.atlassian.net/browse/SMACK-910) - + FormNode and FormNodeProvide should handle non-existent DataForm +- [SMACK-909](https://igniterealtime.atlassian.net/browse/SMACK-909) - + Must use the raw character data of a form field in entity caps hash + calculation + +## 4.4.3 -- 2021-07-06 + +### Bug + +- [SMACK-905](https://igniterealtime.atlassian.net/browse/SMACK-905) - + The class org.jivesoftware.smackx.offline.packet.OfflineMessageInfo + has no ELEMENT, NAMESPACE or QNAME member +- [SMACK-907](https://igniterealtime.atlassian.net/browse/SMACK-907) - + Possible NPE in MultipleRecipientManager + +## 4.4.2 -- 2021-03-25 + +### Bug + +- [SMACK-903](https://igniterealtime.atlassian.net/browse/SMACK-903) - + StaxXmlPullParser.getNamespace() may throws IllegalArgumentException +- [SMACK-904](https://igniterealtime.atlassian.net/browse/SMACK-904) - + XEP-0096 file transfer fails because of a hidden ClastCastException + +## 4.4.1 -- 2021-03-03 + +### Bug + +- [SMACK-895](https://igniterealtime.atlassian.net/browse/SMACK-895) - + BoBIQ#getIQChildElementBuilder throws NPE when the BoB data does not + contain 'max-age'. +- [SMACK-896](https://igniterealtime.atlassian.net/browse/SMACK-896) - + BoBDataExtension is missing getter for BoBData and ContentId +- [SMACK-897](https://igniterealtime.atlassian.net/browse/SMACK-897) - + DirectoryRosterStore.readEntry() should also catch + IllegalArgumentException +- [SMACK-898](https://igniterealtime.atlassian.net/browse/SMACK-898) - + AbstractProvider should also consider TypeVariable +- [SMACK-899](https://igniterealtime.atlassian.net/browse/SMACK-899) - + NullPointerException in EntityCapsManager.addCapsExtension +- [SMACK-900](https://igniterealtime.atlassian.net/browse/SMACK-900) - + NPE in DataForm.Builder.addItem() +- [SMACK-902](https://igniterealtime.atlassian.net/browse/SMACK-902) - + DataFormProvider should retrieve the type of fields from + \ elements if possible + +### Improvement + +- [SMACK-901](https://igniterealtime.atlassian.net/browse/SMACK-901) - + BoBDataExtension.from() should also allow IQs + +## 4.4.0 -- 2020-12-06 + +### Bug + +- [SMACK-561](https://igniterealtime.atlassian.net/browse/SMACK-561) - + Smack should not reply with multiple stream types after stream + initiation is offered +- [SMACK-624](https://igniterealtime.atlassian.net/browse/SMACK-624) - + AdHocCommandManager\'s session sweeping thread does never stop +- [SMACK-729](https://igniterealtime.atlassian.net/browse/SMACK-729) - + Not all providers from smack-legacy.jar are loaded +- [SMACK-770](https://igniterealtime.atlassian.net/browse/SMACK-770) - + There is no Bits of Binary Extension Element provider registered +- [SMACK-848](https://igniterealtime.atlassian.net/browse/SMACK-848) - + Make MultiUserChat.leave() wait for response +- [SMACK-874](https://igniterealtime.atlassian.net/browse/SMACK-874) - + PacketParserUtilsTest#invalidXMLInMessageBody() fails on non-english + machines +- [SMACK-881](https://igniterealtime.atlassian.net/browse/SMACK-881) - + Deadlock between reader and writer if Stream Mangement unacked + stanza queue is full +- [SMACK-888](https://igniterealtime.atlassian.net/browse/SMACK-888) - + MUC roomDestroyed() callback is not invoked + +### New Feature + +- [SMACK-257](https://igniterealtime.atlassian.net/browse/SMACK-257) - + Add support for XEP-0118: User Tune +- [SMACK-636](https://igniterealtime.atlassian.net/browse/SMACK-636) - + Add support for XEP-0319: Last User Interaction in Presence +- [SMACK-743](https://igniterealtime.atlassian.net/browse/SMACK-743) - + Add support for XEP-0384: OMEMO Encryption +- [SMACK-801](https://igniterealtime.atlassian.net/browse/SMACK-801) - + Update Smack to Java 8 +- [SMACK-824](https://igniterealtime.atlassian.net/browse/SMACK-824) - + Add support for XEP-0221: Data Forms Media Element +- [SMACK-862](https://igniterealtime.atlassian.net/browse/SMACK-862) - + Add support for XEP-0418: DNS Queries over XMPP (DoX) +- [SMACK-871](https://igniterealtime.atlassian.net/browse/SMACK-871) - + Add support for XEP-0350: Data Forms Geolocation Element +- [SMACK-872](https://igniterealtime.atlassian.net/browse/SMACK-872) - + Add support for XEP-0315: Data Forms XML Element +- [SMACK-878](https://igniterealtime.atlassian.net/browse/SMACK-878) - + Add support for XEP-0328: JID Prep +- [SMACK-884](https://igniterealtime.atlassian.net/browse/SMACK-884) - + Add support for XEP-0422: Message Fastening +- [SMACK-885](https://igniterealtime.atlassian.net/browse/SMACK-885) - + Add support for XEP-0420 Stanza Content Encryption +- [SMACK-889](https://igniterealtime.atlassian.net/browse/SMACK-889) - + Add support for XEP-0428: Fallback Indication + +### Improvement + +- [SMACK-591](https://igniterealtime.atlassian.net/browse/SMACK-591) - + Replace XPP3 by SmackXmlPullParser (wrapping Stax\'s XmlStreamReader + and XPP3 on Android) +- [SMACK-650](https://igniterealtime.atlassian.net/browse/SMACK-650) - + Enable Java8\'s javadoc doclint +- [SMACK-651](https://igniterealtime.atlassian.net/browse/SMACK-651) - + Perform sound cross-compilation: Use newer javac\'s \--release + feature +- [SMACK-718](https://igniterealtime.atlassian.net/browse/SMACK-718) - + Prevent extremely long reply timeouts from being set +- [SMACK-821](https://igniterealtime.atlassian.net/browse/SMACK-821) - + Make Forwarded a generic type +- [SMACK-822](https://igniterealtime.atlassian.net/browse/SMACK-822) - + Add API for XEP-0313 § 6.2 Advanced configuration via Ad-Hoc + commands +- [SMACK-825](https://igniterealtime.atlassian.net/browse/SMACK-825) - + Discourage Stanza.getExtension(String, String) in favor of + Stanza.getExtension(Class\) +- [SMACK-826](https://igniterealtime.atlassian.net/browse/SMACK-826) - + Add support for XEP-0373:\" OpenPGP for XMPP\" and XEP-0374: + \"OpenPGP for XMPP Instant Messaging\" +- [SMACK-828](https://igniterealtime.atlassian.net/browse/SMACK-828) - + Add support for XEP-0107: User Mood +- [SMACK-836](https://igniterealtime.atlassian.net/browse/SMACK-836) - + Save a ServiceDiscoveryManager instance in a private field of + MultiUserChatManger +- [SMACK-839](https://igniterealtime.atlassian.net/browse/SMACK-839) - + Provider.parse() should not throw a generic Exception, but instead + IOException and XmlPullParserException +- [SMACK-852](https://igniterealtime.atlassian.net/browse/SMACK-852) - + Message thread and subject should be designed and implemented as + ExtensionElements +- [SMACK-854](https://igniterealtime.atlassian.net/browse/SMACK-854) - + Rename smack-java7 to smack-java8 +- [SMACK-866](https://igniterealtime.atlassian.net/browse/SMACK-866) - + Remove all tabs from the source code and add checkstyle rule that + enforces no-tabs +- [SMACK-867](https://igniterealtime.atlassian.net/browse/SMACK-867) - + Extend HttpFileUploadManager by methods with InputStream parameter +- [SMACK-882](https://igniterealtime.atlassian.net/browse/SMACK-882) - + Add support for MUC status code 333 +- [SMACK-883](https://igniterealtime.atlassian.net/browse/SMACK-883) - + Add generic MUC callback for \"participant left\" caused by + unavailable presences +- [SMACK-890](https://igniterealtime.atlassian.net/browse/SMACK-890) - + Update Message Archive Management (XEP-0313) support to + urn:xmpp:mam:2 +- [SMACK-892](https://igniterealtime.atlassian.net/browse/SMACK-892) - + Smack performs unnecessary escaping in XML text + +### Task + +- [SMACK-750](https://igniterealtime.atlassian.net/browse/SMACK-750) - + Raise Smack\'s minimum required Android SDK level to 19 (Android + 4.4, Kit Kat, 2013-10) +- [SMACK-840](https://igniterealtime.atlassian.net/browse/SMACK-840) - + Remove smack-compression-jzlib, as it is obsolete (Smack uses Java 7 + de- and inflate API now) + +## 4.3.4 -- 2019-05-27 + +### Bug + +- [SMACK-861](https://igniterealtime.atlassian.net/browse/SMACK-861) - + Potential NPE in Roster.getPresencesInternal(BareJid) +- [SMACK-863](https://igniterealtime.atlassian.net/browse/SMACK-863) - + ServiceDiscoveryManger does not use the main identity, causing + setIdentity() to have no effect +- [SMACK-864](https://igniterealtime.atlassian.net/browse/SMACK-864) - + Potential Denial of Service (DOS) by remote entities caused by + unlimited threads for asynchronous operations +- [SMACK-865](https://igniterealtime.atlassian.net/browse/SMACK-865) - + Some Manager.getInsanceFor() methods are missing the + \'synchronized\' keyword +- [SMACK-868](https://igniterealtime.atlassian.net/browse/SMACK-868) - + XHTMLText.appendOpenBodyTag() produces invalid XML +- [SMACK-870](https://igniterealtime.atlassian.net/browse/SMACK-870) - + TLS X.509 certificate verification should be performed with the ACE + representation of the XMPP service domain when possible + +### Improvement + +- [SMACK-869](https://igniterealtime.atlassian.net/browse/SMACK-869) - + Exceptions in async tasks should not go uncaught to the call stack + to avoid program termination + +## 4.3.3 -- 2019-03-14 + +### Bug + +- [SMACK-856](https://igniterealtime.atlassian.net/browse/SMACK-856) - + Smack fails under JDK 11 because com.sun.jndi.dns.DnsContextFactory + is not inaccessible + +### Improvement + +- [SMACK-858](https://igniterealtime.atlassian.net/browse/SMACK-858) - + Dependency version specifier of jxmpp and MiniDNS include + alpha/beta/\... versions of the follow up version when Maven is used +- [SMACK-859](https://igniterealtime.atlassian.net/browse/SMACK-859) - + MultiUserChat enter() should reset the timeout of the collector + waiting for the final self presence to prevent timeouts for large + MUCs + +## 4.3.2 -- 2019-02-22 + +### Bug + +- [SMACK-842](https://igniterealtime.atlassian.net/browse/SMACK-842) - + The RFC 3920 xml-not-well-formed error condition should be handled + in stream error not a stanza error +- [SMACK-843](https://igniterealtime.atlassian.net/browse/SMACK-843) - + ManManager.pagePrevious() pages into the wrong direction +- [SMACK-844](https://igniterealtime.atlassian.net/browse/SMACK-844) - + Check if bounded unacknowledged stanzas queue is full before adding + to it to avoid IllegalStateException +- [SMACK-845](https://igniterealtime.atlassian.net/browse/SMACK-845) - + Ensure that IQ response \'to\' address and ID are set correctly +- [SMACK-846](https://igniterealtime.atlassian.net/browse/SMACK-846) - + XMPPTCPConnection does not wait for stream features after + authentication if compression is disabled +- [SMACK-848](https://igniterealtime.atlassian.net/browse/SMACK-848) - + Make MultiUserChat.leave() wait for response +- [SMACK-850](https://igniterealtime.atlassian.net/browse/SMACK-850) - + DeliveryReceiptManager should not send receipts with messages of + type \'groupchat\' +- [SMACK-855](https://igniterealtime.atlassian.net/browse/SMACK-855) - + XMPPTCPConnection sometimes has two writer threads running + +### Improvement + +- [SMACK-847](https://igniterealtime.atlassian.net/browse/SMACK-847) - + Make TCP socket connection attempt interruptable +- [SMACK-849](https://igniterealtime.atlassian.net/browse/SMACK-849) - + Smack Local SOCKS5 Proxy thread should be marked as daemon thread + +## 4.3.1 -- 2018-10-14 + +### Bug + +- [SMACK-833](https://igniterealtime.atlassian.net/browse/SMACK-833) - + XMLUtil.prettyFormatXml() throws on some Android devices + +### Improvement + +- [SMACK-829](https://igniterealtime.atlassian.net/browse/SMACK-829) - + Disconnect BOSH client on shutdown +- [SMACK-838](https://igniterealtime.atlassian.net/browse/SMACK-838) - + FormField.getFirstValue() throws IndexOutOfBoundsException if there + are no values + +## 4.3.0 -- 2018-08-02 + +### Bug + +- [SMACK-759](https://igniterealtime.atlassian.net/browse/SMACK-759) - + PubSubManager.getLeafNode() throws + PubSubAssertionError.DiscoInfoNodeAssertionError if node exists but + its not a PubSub Node +- [SMACK-814](https://igniterealtime.atlassian.net/browse/SMACK-814) - + NPE when using Node.getAffiliationsAsOwner() +- [SMACK-815](https://igniterealtime.atlassian.net/browse/SMACK-815) - + XEP-0184: DeliveryReceipt requires ID, although the XEP defines it + as optional attribute +- [SMACK-818](https://igniterealtime.atlassian.net/browse/SMACK-818) - + EntityCapsManager sends presences with multiple CapsExtension + causing disco#info lookup to fail +- [SMACK-819](https://igniterealtime.atlassian.net/browse/SMACK-819) - + ConcurrentModification Exception in MultiUserChatManager.java +- [SMACK-820](https://igniterealtime.atlassian.net/browse/SMACK-820) - + DNSUtil.setDaneProvider() does not set the DANE provider + +### Task + +- [SMACK-769](https://igniterealtime.atlassian.net/browse/SMACK-769) - + Rename XMPPError to StanzaError +- [SMACK-776](https://igniterealtime.atlassian.net/browse/SMACK-776) - + Remove deprecated reconnection callbacks in ConnectionListener + +### Improvement + +- [SMACK-761](https://igniterealtime.atlassian.net/browse/SMACK-761) - + Adopt ChatStateManager to new Chat API (chat2) +- [SMACK-812](https://igniterealtime.atlassian.net/browse/SMACK-812) - + Enable ModifierOrder checkstyle check +- [SMACK-816](https://igniterealtime.atlassian.net/browse/SMACK-816) - + SimplePayload should infer the XML element name and namespace + +## 4.2.4 -- 2018-04-15 + +### Bug + +- [SMACK-804](https://igniterealtime.atlassian.net/browse/SMACK-804) - + ServiceAdministrationManager does not use correct form actions +- [SMACK-805](https://igniterealtime.atlassian.net/browse/SMACK-805) - + ServiceDiscoveryManager.findService() only considers the first + service by feature +- [SMACK-813](https://igniterealtime.atlassian.net/browse/SMACK-813) - + Smack uses hostname instead of XMPP service name for SNI + +### New Feature + +- [SMACK-794](https://igniterealtime.atlassian.net/browse/SMACK-794) - + Add support for XEP-0394: Message Markup +- [SMACK-795](https://igniterealtime.atlassian.net/browse/SMACK-795) - + Add support for XEP-0382: Spoiler messages +- [SMACK-799](https://igniterealtime.atlassian.net/browse/SMACK-799) - + Add support for XEP-0372: References +- [SMACK-800](https://igniterealtime.atlassian.net/browse/SMACK-800) - + Add support for XEP-0392: Consistent Color Generation + +### Improvement + +- [SMACK-802](https://igniterealtime.atlassian.net/browse/SMACK-802) - + Rename and deprecate: addPacketSendingListener(), + removePacketSendingListener(), addPacketInterceptor() and + removePacketInterceptor() +- [SMACK-809](https://igniterealtime.atlassian.net/browse/SMACK-809) - + Make Roster\'s non-roster presence map second-level map bounded + +## 4.2.3 -- 2018-02-07 + +### Bug + +- [SMACK-788](https://igniterealtime.atlassian.net/browse/SMACK-788) - + NullPointerException if hostAddresses is null +- [SMACK-789](https://igniterealtime.atlassian.net/browse/SMACK-789) - + AffiliationsExtension toXml() produces invalid XML +- [SMACK-790](https://igniterealtime.atlassian.net/browse/SMACK-790) - + Some HTTP File Upload elements are not correctly parsed and + serialized +- [SMACK-791](https://igniterealtime.atlassian.net/browse/SMACK-791) - + NumberFormatException in IpAddressUtil.isIPv4LiteralAddress +- [SMACK-796](https://igniterealtime.atlassian.net/browse/SMACK-796) - + SOCKS5 authentication erroneously uses \'user\' when it should use + \'passwd\', causes authentication to fail + +## 4.2.2 -- 2017-11-25 + +### Bug + +- [SMACK-775](https://igniterealtime.atlassian.net/browse/SMACK-775) - + Create callback interface for ReconnectionManager +- [SMACK-778](https://igniterealtime.atlassian.net/browse/SMACK-778) - + ReconnectionManager.reconnect() can throw NotConnectedException +- [SMACK-779](https://igniterealtime.atlassian.net/browse/SMACK-779) - + smack-android erroneously depends on smack-omemo and + smack-omemo-signal +- [SMACK-780](https://igniterealtime.atlassian.net/browse/SMACK-780) - + PushNotificationManager\'s isSupported logic does query the server, + whereas it should query the bare JID +- [SMACK-781](https://igniterealtime.atlassian.net/browse/SMACK-781) - + MiniDnsResolver does not correctly handle the case when NOERROR is + returned together with an empty answer section. +- [SMACK-782](https://igniterealtime.atlassian.net/browse/SMACK-782) - + MultiUserChat does not remove the subject listener causing a memory + leak +- [SMACK-783](https://igniterealtime.atlassian.net/browse/SMACK-783) - + InvitationRejectionListener fires multiple times +- [SMACK-784](https://igniterealtime.atlassian.net/browse/SMACK-784) - + StringUtils.numbersAndLetters has the numbers twice, resulting in a + lower entropy +- [SMACK-785](https://igniterealtime.atlassian.net/browse/SMACK-785) - + OfflineMessageManager.getMessages() does count the pending messages + incorrectly, causing an unnecessary delay +- [SMACK-786](https://igniterealtime.atlassian.net/browse/SMACK-786) - + Race condition when resuming a stream +- [SMACK-787](https://igniterealtime.atlassian.net/browse/SMACK-787) - + Presence.getPriority() may return Integer.MIN_VALUE. + +## 4.2.1 -- 2017-08-14 + +### Bug + +- [SMACK-749](https://igniterealtime.atlassian.net/browse/SMACK-749) - + SCRAM-SHA-1 and SCRAM-SHA-1-PLUS SASL mechanisms have the same + priority, causing SASL authentication failures +- [SMACK-755](https://igniterealtime.atlassian.net/browse/SMACK-755) - + DIGEST-MD5 sometimes causes malformed request server response +- [SMACK-756](https://igniterealtime.atlassian.net/browse/SMACK-756) - + IoTIsFriendResponse has invalid name and produces invalid XML +- [SMACK-759](https://igniterealtime.atlassian.net/browse/SMACK-759) - + PubSubManager.getLeafNode() throws + PubSubAssertionError.DiscoInfoNodeAssertionError if node exists but + its not a PubSub Node +- [SMACK-764](https://igniterealtime.atlassian.net/browse/SMACK-764) - + NPE in hashCode() in Occupant when jid is null +- [SMACK-766](https://igniterealtime.atlassian.net/browse/SMACK-766) - + Smack possibly includes \'ask\' attribute in roster items when + sending requests +- [SMACK-768](https://igniterealtime.atlassian.net/browse/SMACK-768) - + Smack throws NoResponse timeout when waiting for IQ although there + was a response +- [SMACK-771](https://igniterealtime.atlassian.net/browse/SMACK-771) - + XMPPTCPConnection should use KeyManagerFactory.getDefaultAlgorithm() + instead of KeyManagerFactory.getInstance(\"sunX509\"); +- [SMACK-772](https://igniterealtime.atlassian.net/browse/SMACK-772) - + HostAddress must deal with \'fqdn\' being null. +- [SMACK-773](https://igniterealtime.atlassian.net/browse/SMACK-773) - + Allow roster pushes from our full JID for backwards compatibility +- [SMACK-774](https://igniterealtime.atlassian.net/browse/SMACK-774) - + HTTP File Upload\'s SlotRequest metadata should be attributes not + child elements + +### New Feature + +- [SMACK-746](https://igniterealtime.atlassian.net/browse/SMACK-746) - + Add support for XEP-0380: Explicit Message Encryption +- [SMACK-758](https://igniterealtime.atlassian.net/browse/SMACK-758) - + Add support for XEP-0334: Message Processing Hints +- [SMACK-760](https://igniterealtime.atlassian.net/browse/SMACK-760) - + Smack does not allow custom extension elements in SM\'s \ + +### Improvement + +- [SMACK-752](https://igniterealtime.atlassian.net/browse/SMACK-752) - + XEP-0357 Push Notification enable IQ uses wrong form type: Should be + \'submit\' instead of \'form\' +- [SMACK-754](https://igniterealtime.atlassian.net/browse/SMACK-754) - + Allow MUC room subject changes from the MUCs bare JID +- [SMACK-777](https://igniterealtime.atlassian.net/browse/SMACK-777) - + MamManager should use the user\'s bare JID to check if MAM is + supported + +## 4.2.0 -- 2017-03-10 + +## Sub-task + +- [SMACK-639](https://igniterealtime.atlassian.net/browse/SMACK-639) - + Add support for pre-approved subscription requests (RFC 6121 § 3.4) + +### Bug + +- [SMACK-306](https://igniterealtime.atlassian.net/browse/SMACK-306) - + loadRosterOnLogin has non-trivial side effect on getRoster +- [SMACK-416](https://igniterealtime.atlassian.net/browse/SMACK-416) - + Refactor PEP to make it use the existing pubsub API. +- [SMACK-674](https://igniterealtime.atlassian.net/browse/SMACK-674) - + PubSub Affiliation extension element is missing \'jid\' attribute, + and is using wrong element name \'subscription\' +- [SMACK-682](https://igniterealtime.atlassian.net/browse/SMACK-682) - + Add support for \"XEP-0360: Nonzas (are not Stanzas)\" +- [SMACK-683](https://igniterealtime.atlassian.net/browse/SMACK-683) - + Using a Proxy with XMPPTCPConnection failes with \"SocketException: + Unconnected sockets not implemented\" +- [SMACK-691](https://igniterealtime.atlassian.net/browse/SMACK-691) - + Add support for MUCItem\'s Actor \'nick\' +- [SMACK-705](https://igniterealtime.atlassian.net/browse/SMACK-705) - + PubSub\'s Affiliation.getElementName() returns wrong name +- [SMACK-722](https://igniterealtime.atlassian.net/browse/SMACK-722) - + SASL X-OAUTH2 implementation incorrectly performs Base64 encoding + twice +- [SMACK-723](https://igniterealtime.atlassian.net/browse/SMACK-723) - + Support \"Caps Optimizations\" (XEP-0115 § 8.4) +- [SMACK-724](https://igniterealtime.atlassian.net/browse/SMACK-724) - + Do not re-use the Socket after connect() failed. +- [SMACK-725](https://igniterealtime.atlassian.net/browse/SMACK-725) - + ReconnectionManager should handle AlreadyConnectedException and + AlreadyLoggedInException not as failure +- [SMACK-741](https://igniterealtime.atlassian.net/browse/SMACK-741) - + Ad-hoc command \'note\' element \'type\' attribute should be treated + as optional +- [SMACK-745](https://igniterealtime.atlassian.net/browse/SMACK-745) - + Memory leak in MultiUserChat + +### New Feature + +- [SMACK-366](https://igniterealtime.atlassian.net/browse/SMACK-366) - + Add support for DNSSEC. +- [SMACK-610](https://igniterealtime.atlassian.net/browse/SMACK-610) - + Add support for XEP-0080: User Location +- [SMACK-619](https://igniterealtime.atlassian.net/browse/SMACK-619) - + Add roomDestroyed to MUC UserStatusListener +- [SMACK-625](https://igniterealtime.atlassian.net/browse/SMACK-625) - + Add support for XEP-313: Message Archive Management +- [SMACK-675](https://igniterealtime.atlassian.net/browse/SMACK-675) - + Add support for PubSub affiliation actions as owner +- [SMACK-677](https://igniterealtime.atlassian.net/browse/SMACK-677) - + Add support for SASL \'authzid\' (Authorization Identity) +- [SMACK-690](https://igniterealtime.atlassian.net/browse/SMACK-690) - + Add support for DNS-Based Authentication of Named Entities (DANE, + RFC 6698) +- [SMACK-731](https://igniterealtime.atlassian.net/browse/SMACK-731) - + Add support for XEP-0191: Blocking Command +- [SMACK-732](https://igniterealtime.atlassian.net/browse/SMACK-732) - + Smack should be able to handle \"single equals sign\" SASL responses +- [SMACK-740](https://igniterealtime.atlassian.net/browse/SMACK-740) - + Add support for Multi-User Chat Light +- [SMACK-742](https://igniterealtime.atlassian.net/browse/SMACK-742) - + Add support for XEP-0133: Service Administration +- [SMACK-747](https://igniterealtime.atlassian.net/browse/SMACK-747) - + Add support for XEP-0363: HTTP File Upload + +### Task + +- [SMACK-638](https://igniterealtime.atlassian.net/browse/SMACK-638) - + Call connection creation listeners from within + AbstractXMPPConnection\'s constructor +- [SMACK-644](https://igniterealtime.atlassian.net/browse/SMACK-644) - + Throw exception if account creation or password change is performed + over insecure connections +- [SMACK-655](https://igniterealtime.atlassian.net/browse/SMACK-655) - + Enable StreamManagement by default + +### Improvement + +- [SMACK-372](https://igniterealtime.atlassian.net/browse/SMACK-372) - + Make package protected methods in PEPItem public +- [SMACK-572](https://igniterealtime.atlassian.net/browse/SMACK-572) - + Rejoin MUC rooms after reconnect +- [SMACK-628](https://igniterealtime.atlassian.net/browse/SMACK-628) - + Rework Roster handling with anonymous connections +- [SMACK-629](https://igniterealtime.atlassian.net/browse/SMACK-629) - + Rework how Smack handles anonymous connections +- [SMACK-631](https://igniterealtime.atlassian.net/browse/SMACK-631) - + Improve ParsingExceptionCallback, allow it to be a functional + interface +- [SMACK-632](https://igniterealtime.atlassian.net/browse/SMACK-632) - + Make Smack interruptible +- [SMACK-633](https://igniterealtime.atlassian.net/browse/SMACK-633) - + Allow clean and graceful disconnects (stream closing) +- [SMACK-634](https://igniterealtime.atlassian.net/browse/SMACK-634) - + Use jxmpp-jid, add Jid class to replace String\'s being used as JIDs +- [SMACK-646](https://igniterealtime.atlassian.net/browse/SMACK-646) - + Add support for MUC roomnick rewrite +- [SMACK-647](https://igniterealtime.atlassian.net/browse/SMACK-647) - + Don\'t automatically call login() on connect() if the connection was + authenticated before +- [SMACK-648](https://igniterealtime.atlassian.net/browse/SMACK-648) - + Improve MultiUserChat API +- [SMACK-657](https://igniterealtime.atlassian.net/browse/SMACK-657) - + Rename RosterEntry.getStatus and RosterPacket.ItemStatus to + ItemAskStatus +- [SMACK-663](https://igniterealtime.atlassian.net/browse/SMACK-663) - + Roster should be fully loaded when + Roster.getInstanceFor(XMPPConnection) is called with a authenticated + connection +- [SMACK-665](https://igniterealtime.atlassian.net/browse/SMACK-665) - + Rename \'serviceName\' to \'xmppServiceDomain\' +- [SMACK-666](https://igniterealtime.atlassian.net/browse/SMACK-666) - + Typo in \'RosterEntries.rosterEntires()\', change to + \'RosterEntries.rosterEntries()\' +- [SMACK-703](https://igniterealtime.atlassian.net/browse/SMACK-703) - + Limit the stored presences of entities not in Roster +- [SMACK-704](https://igniterealtime.atlassian.net/browse/SMACK-704) - + Pass down Message stanza in ChatStateListener +- [SMACK-711](https://igniterealtime.atlassian.net/browse/SMACK-711) - + Improve the logging of TCP connection attempts. +- [SMACK-720](https://igniterealtime.atlassian.net/browse/SMACK-720) - + Improve support for Tor and Hidden Services. +- [SMACK-721](https://igniterealtime.atlassian.net/browse/SMACK-721) - + Report illegal Stream Management states to avoid OOM Exception +- [SMACK-727](https://igniterealtime.atlassian.net/browse/SMACK-727) - + Add partial support for the IoT XEPs (XEP-0323, -0324, -0325, -0347) +- [SMACK-733](https://igniterealtime.atlassian.net/browse/SMACK-733) - + Handle outgoing \'unavailable\' Presences in Roster +- [SMACK-736](https://igniterealtime.atlassian.net/browse/SMACK-736) - + Add support for Chat Markers (XEP-0333) +- [SMACK-737](https://igniterealtime.atlassian.net/browse/SMACK-737) - + Add support for Bits of Binary (XEP-0231) +- [SMACK-738](https://igniterealtime.atlassian.net/browse/SMACK-738) - + Add support for Push Notifications (XEP-0357) + +## 4.1.9 -- 2016-11-19 + +### Bug + +- [SMACK-739](https://igniterealtime.atlassian.net/browse/SMACK-739) - + Smack starts SASL step without TLS in case STARTTLS is stripped even + if SecurityMode.Required is used +- [SMACK-735](https://igniterealtime.atlassian.net/browse/SMACK-735) - + Smack sometimes sends invalid SCRAM-SHA1 nonce + +## 4.1.8 -- 2016-07-30 + +### Bug + +- [SMACK-722](https://igniterealtime.atlassian.net/browse/SMACK-722) - + SASL X-OAUTH2 implementation incorrectly performs Base64 encoding + twice +- [SMACK-724](https://igniterealtime.atlassian.net/browse/SMACK-724) - + Do not re-use the Socket after connect() failed. +- [SMACK-725](https://igniterealtime.atlassian.net/browse/SMACK-725) - + ReconnectionManager should handle AlreadyConnectedException and + AlreadyLoggedInException not as failure +- [SMACK-726](https://igniterealtime.atlassian.net/browse/SMACK-726) - + \'purge\' and \'remove\' IQ of XEP-0013 must be of type \'set\' + +## 4.1.7 -- 2016-04-14 + +### Bug + +- [SMACK-712](https://igniterealtime.atlassian.net/browse/SMACK-712) - + XMPPTCPConnection\'s setEnabledSSL(Protocols\|Ciphers) has no effect +- [SMACK-716](https://igniterealtime.atlassian.net/browse/SMACK-716) - + EntityTimeManager.getTime() does not set the recipients JID +- [SMACK-719](https://igniterealtime.atlassian.net/browse/SMACK-719) - + XMPPError should use Locale.US in toUpperCase() + +### Improvement + +- [SMACK-715](https://igniterealtime.atlassian.net/browse/SMACK-715) - + Add Roster.setRosterLoadedAtLoginDefault(boolean) + +## 4.1.6 -- 2016-01-23 + +### Bug + +- [SMACK-705](https://igniterealtime.atlassian.net/browse/SMACK-705) - + PubSub\'s Affiliation.getElementName() returns wrong name +- [SMACK-706](https://igniterealtime.atlassian.net/browse/SMACK-706) - + Smack may sends \ and \ twice if Stream Management + is used and a previous SM state exists +- [SMACK-707](https://igniterealtime.atlassian.net/browse/SMACK-707) - + Infinite loop of NullPointerExceptions in Socks5Proxy +- [SMACK-708](https://igniterealtime.atlassian.net/browse/SMACK-708) - + DeliveryReceipt(Manager) should ensure that receipts (and requests) + have an ID set +- [SMACK-709](https://igniterealtime.atlassian.net/browse/SMACK-709) - + Don\'t request delivery receipts for messages without a body +- [SMACK-710](https://igniterealtime.atlassian.net/browse/SMACK-710) - + SASL DIGEST-MD5 backslash must be quoted + +## 4.1.5 -- 2015-11-22 + +### Bug + +- [SMACK-698](https://igniterealtime.atlassian.net/browse/SMACK-698) - + Time creates invalid XML +- [SMACK-700](https://igniterealtime.atlassian.net/browse/SMACK-700) - + Duplicate stanzas in unacknowledgedStanzas queue when stream is + resumed +- [SMACK-702](https://igniterealtime.atlassian.net/browse/SMACK-702) - + RejectedExecutionException in AbstractXMPPConnection.processPacket() + causes connection Termination + +## 4.1.4 -- 2015-09-14 + +### Bug + +- [SMACK-688](https://igniterealtime.atlassian.net/browse/SMACK-688) - + Reset carbons state if session got not resumed or cleanly + disconnected +- [SMACK-689](https://igniterealtime.atlassian.net/browse/SMACK-689) - + PEPPubSub creates malformed XML +- [SMACK-693](https://igniterealtime.atlassian.net/browse/SMACK-693) - + MultiUserChat\'s UserStatusListener is not getting triggered +- [SMACK-695](https://igniterealtime.atlassian.net/browse/SMACK-695) - + JSON and GCM parser does an erroneous extra next() +- [SMACK-697](https://igniterealtime.atlassian.net/browse/SMACK-697) - + PrivacyListManager should handle the case where not default and + active list are currently set + +### Improvement + +- [SMACK-686](https://igniterealtime.atlassian.net/browse/SMACK-686) - + Provide a hint that connect() needs to be called prior login() in + NotConnectedException +- [SMACK-687](https://igniterealtime.atlassian.net/browse/SMACK-687) - + Update to jxmpp 0.4.2 +- [SMACK-696](https://igniterealtime.atlassian.net/browse/SMACK-696) - + Drop stream state after stream error + +## 4.1.3 -- 2015-07-15 + +### Bug + +- [SMACK-679](https://igniterealtime.atlassian.net/browse/SMACK-679) - + Memory leak in Socks5BytestreamManager. Should use weak map for + \'managers\' +- [SMACK-680](https://igniterealtime.atlassian.net/browse/SMACK-680) - + XHTML bodies are un-escaped after parsing +- [SMACK-681](https://igniterealtime.atlassian.net/browse/SMACK-681) - + Roster presence callbacks may not be invoked right after login + +## 4.1.2 -- 2015-06-27 + +### Bug + +- [SMACK-664](https://igniterealtime.atlassian.net/browse/SMACK-664) - + Invalid IQ error response to OfferRequestPacket and + OfferRevokePacket +- [SMACK-668](https://igniterealtime.atlassian.net/browse/SMACK-668) - + ReconnectionManager\'s value of \'attempts\' is not reset after + successful reconnection +- [SMACK-669](https://igniterealtime.atlassian.net/browse/SMACK-669) - + Only add Entity Capabilities extension to available presences +- [SMACK-670](https://igniterealtime.atlassian.net/browse/SMACK-670) - + SASLMechanism.authenticate should treat an empty byte array like + \'null\' byte array +- [SMACK-672](https://igniterealtime.atlassian.net/browse/SMACK-672) - + Memory leak caused by RosterGroup declaring a strong reference to + XMPPConnection +- [SMACK-673](https://igniterealtime.atlassian.net/browse/SMACK-673) - + VCard API does not support all elements +- [SMACK-676](https://igniterealtime.atlassian.net/browse/SMACK-676) - + ConcurrentModificationException in ServerPingWithAlarmManager +- [SMACK-678](https://igniterealtime.atlassian.net/browse/SMACK-678) - + Login hangs if starttls advertised, but security is set to + \'disabled\' and compression is also advertised + +### Improvement + +- [SMACK-667](https://igniterealtime.atlassian.net/browse/SMACK-667) - + Request Stream Mangement Acknowledgement after re-sending unack\'ed + stanzas after stream resumption +- [SMACK-671](https://igniterealtime.atlassian.net/browse/SMACK-671) - + Don\'t disable Scoks5BytestreamManager on connection termination + +## 4.1.1 -- 2015-05-09 + +### Bug + +- [SMACK-649](https://igniterealtime.atlassian.net/browse/SMACK-649) - + DIGEST-MD5 challenge/response parsing must handle linear white + spaces after the comma +- [SMACK-652](https://igniterealtime.atlassian.net/browse/SMACK-652) - + SynchronizationPoint should use signalAll +- [SMACK-653](https://igniterealtime.atlassian.net/browse/SMACK-653) - + Integer overflow if both client and server don\'t specify a max + resumption time +- [SMACK-654](https://igniterealtime.atlassian.net/browse/SMACK-654) - + isSmResumptionPossible() returns wrong values +- [SMACK-656](https://igniterealtime.atlassian.net/browse/SMACK-656) - + DeliveryReceipts auto add should use packet interceptors and should + not be requested for messages with ACKs. +- [SMACK-659](https://igniterealtime.atlassian.net/browse/SMACK-659) - + Memory leak caused by RosterEntry declaring a strong reference to + XMPPConnection +- [SMACK-660](https://igniterealtime.atlassian.net/browse/SMACK-660) - + ReconnectionManager\'s RANDOM_INCREASING_DELAY is erroneously using + a fixed value. +- [SMACK-661](https://igniterealtime.atlassian.net/browse/SMACK-661) - + Add method to set ProxyInfo in ConnectionConfiguration.Builder +- [SMACK-662](https://igniterealtime.atlassian.net/browse/SMACK-662) - + RosterEntry.setName() does not change the name + +## 4.1.0 -- 2015-03-29 + +## Sub-task + +- [SMACK-398](https://igniterealtime.atlassian.net/browse/SMACK-398) - + Implement SCRAM support + +### Bug + +- [SMACK-65](https://igniterealtime.atlassian.net/browse/SMACK-65) - + Packet parsing should look for depth +- [SMACK-237](https://igniterealtime.atlassian.net/browse/SMACK-237) - + Handle more vCard values (XEP-0054) +- [SMACK-383](https://igniterealtime.atlassian.net/browse/SMACK-383) - + Allow the garbage collection of all object instances of a closed and + unreferenced connection +- [SMACK-424](https://igniterealtime.atlassian.net/browse/SMACK-424) - + Add a MultiUserChat.presenceChanged callback method to be informed + if a presence within a MUC has changed (joined, leaved, status + change) +- [SMACK-542](https://igniterealtime.atlassian.net/browse/SMACK-542) - + MUC: RoomInfo should hold more data if the result contains a + FORM_TYPE field +- [SMACK-549](https://igniterealtime.atlassian.net/browse/SMACK-549) - + MUCUser#getStatus should be a List +- [SMACK-564](https://igniterealtime.atlassian.net/browse/SMACK-564) - + Some tests fail with Java 8 +- [SMACK-570](https://igniterealtime.atlassian.net/browse/SMACK-570) - + Smack does not support resourceparts which contain the \'@\' + character. +- [SMACK-571](https://igniterealtime.atlassian.net/browse/SMACK-571) - + Don\'t remove the MUC listeners after a disconnect() , keep state of + Connection between disconnect() and connect()/login() +- [SMACK-573](https://igniterealtime.atlassian.net/browse/SMACK-573) - + MessageEventManager treats error replies as message events +- [SMACK-583](https://igniterealtime.atlassian.net/browse/SMACK-583) - + PacketListeners may not be invoked in delivery order +- [SMACK-585](https://igniterealtime.atlassian.net/browse/SMACK-585) - + XMPPTCPConnection does not set \'host\' and \'port\' +- [SMACK-590](https://igniterealtime.atlassian.net/browse/SMACK-590) - + Don\'t use IQReplyFilter for the bind set/result exchange +- [SMACK-597](https://igniterealtime.atlassian.net/browse/SMACK-597) - + PingManager.getLastReceivedPong() always returns -1 +- [SMACK-604](https://igniterealtime.atlassian.net/browse/SMACK-604) - + MUCUser must support multiple status codes +- [SMACK-620](https://igniterealtime.atlassian.net/browse/SMACK-620) - + Smack should use a safe SAX parser, e.g. with entity reference + expansion disabled +- [SMACK-635](https://igniterealtime.atlassian.net/browse/SMACK-635) - + Typo DNSUtil.init() prevents DNS SRV lookups to fail in some cases +- [SMACK-643](https://igniterealtime.atlassian.net/browse/SMACK-643) - + Smack should not set the service name to the vale of the \'from\' + attribute of the opening stream element received from the service + +### Improvement + +- [SMACK-340](https://igniterealtime.atlassian.net/browse/SMACK-340) - + Should make the wait/timeouts on SASL authentication configurable. +- [SMACK-402](https://igniterealtime.atlassian.net/browse/SMACK-402) - + Update obsolete \"Message Delivery Receipts\" support from + (JEP\|XEP)-0022 to XEP-0184 +- [SMACK-453](https://igniterealtime.atlassian.net/browse/SMACK-453) - + Add support for all primitive types in + IntrospectionProvider.decode() +- [SMACK-521](https://igniterealtime.atlassian.net/browse/SMACK-521) - + Clear PacketWriters queue when the connection is shut down +- [SMACK-532](https://igniterealtime.atlassian.net/browse/SMACK-532) - + Evaluate if its possible to guarantee the order of listeners by + using a LinkedHashMap +- [SMACK-566](https://igniterealtime.atlassian.net/browse/SMACK-566) - + Create public method that parses Strings/CharSequences to messages, + IQs and presence instances +- [SMACK-587](https://igniterealtime.atlassian.net/browse/SMACK-587) - + Subprojects should uses versions when importing the OSGi smack-core + components +- [SMACK-595](https://igniterealtime.atlassian.net/browse/SMACK-595) - + Add an API to send a stanza and wait asynchronously for a response +- [SMACK-599](https://igniterealtime.atlassian.net/browse/SMACK-599) - + Provide string messages to all exceptions thrown by Smack +- [SMACK-600](https://igniterealtime.atlassian.net/browse/SMACK-600) - + RoomInfo Class should add the information from the Identity element. +- [SMACK-608](https://igniterealtime.atlassian.net/browse/SMACK-608) - + Add support for XMPP error conditions text +- [SMACK-622](https://igniterealtime.atlassian.net/browse/SMACK-622) - + Add support for \'optional\' in session stream features +- [SMACK-626](https://igniterealtime.atlassian.net/browse/SMACK-626) - + Add support for \'ofrom\' Extended Stanza Addressing type +- [SMACK-627](https://igniterealtime.atlassian.net/browse/SMACK-627) - + Smack should allow null usernames under certain circumstances +- [SMACK-645](https://igniterealtime.atlassian.net/browse/SMACK-645) - + Roster should not leak internal state e.g. presences + +### New Feature + +- [SMACK-234](https://igniterealtime.atlassian.net/browse/SMACK-234) - + Add support for SASL EXTERNAL: PKI (Client SSL Cert) Support +- [SMACK-333](https://igniterealtime.atlassian.net/browse/SMACK-333) - + Implement XEP-0198: Stream Management +- [SMACK-378](https://igniterealtime.atlassian.net/browse/SMACK-378) - + Give access to the socket outside the XMPPconnection +- [SMACK-581](https://igniterealtime.atlassian.net/browse/SMACK-581) - + Add support for \"Result Set Management\" (XEP-59) +- [SMACK-607](https://igniterealtime.atlassian.net/browse/SMACK-607) - + Add support for XEP-0352: Client State Indication +- [SMACK-612](https://igniterealtime.atlassian.net/browse/SMACK-612) - + Add support for XEP-0141: Data Forms Layout +- [SMACK-621](https://igniterealtime.atlassian.net/browse/SMACK-621) - + Add support for XEP-0122: Data Forms Validation +- [SMACK-623](https://igniterealtime.atlassian.net/browse/SMACK-623) - + Add API to retrieve the subscriptions of a PubSub node as owner + +### Task + +- [SMACK-365](https://igniterealtime.atlassian.net/browse/SMACK-365) - + SmackConfiguration should only report errors if the file fails to + load, not when it fails to load for a specific classloader. +- [SMACK-371](https://igniterealtime.atlassian.net/browse/SMACK-371) - + Some MUC tasks are using stanza\'s as defined in an older version of + the spec. Fails to work on some servers. +- [SMACK-569](https://igniterealtime.atlassian.net/browse/SMACK-569) - + Move Message Event code to legacy subproject +- [SMACK-578](https://igniterealtime.atlassian.net/browse/SMACK-578) - + Remove decorators for \"Legacy Delayed Delivery\" (XEP-91) in favor + of Delayed Delivery (XEP-203) +- [SMACK-579](https://igniterealtime.atlassian.net/browse/SMACK-579) - + FileTransferManager and FileTransferNegoiator should use + WeakHashMaps and extend Manager +- [SMACK-582](https://igniterealtime.atlassian.net/browse/SMACK-582) - + Change ReceiptReceivedListener.onReceiptReceived parameters +- [SMACK-637](https://igniterealtime.atlassian.net/browse/SMACK-637) - + Move Roster and Chat code to new smack-im subproject + +## 4.0.7 -- 2015-02-20 + +### Bug + +- [SMACK-635](https://igniterealtime.atlassian.net/browse/SMACK-635) - + Typo DNSUtil.init() prevents DNS SRV lookups to fail in some cases +- [SMACK-643](https://igniterealtime.atlassian.net/browse/SMACK-643) - + Smack should not set the service name to the vale of the \'from\' + attribute of the opening stream element received from the service + +## 4.0.6 -- 2014-11-23 + +### Bug + +- [SMACK-616](https://igniterealtime.atlassian.net/browse/SMACK-616) - + Smack should fallback to using host with default port if DNS SRV + lookup fails +- [SMACK-617](https://igniterealtime.atlassian.net/browse/SMACK-617) - + Message Digest in EntityCapsManager should be synchronized + +## 4.0.5 -- 2014-10-22 + +### Bug + +- [SMACK-609](https://igniterealtime.atlassian.net/browse/SMACK-609) - + PingManager.ping(String, long) does not respect timeout +- [SMACK-613](https://igniterealtime.atlassian.net/browse/SMACK-613) - + Parsing exception causes infinite loop if the exception is not + thrown + +## 4.0.4 -- 2014-09-05 + +### Bug + +- [SMACK-596](https://igniterealtime.atlassian.net/browse/SMACK-596) - + Smack should load roster before sending the initial presence +- [SMACK-598](https://igniterealtime.atlassian.net/browse/SMACK-598) - + Smack should allow the empty string as content of message body + element +- [SMACK-601](https://igniterealtime.atlassian.net/browse/SMACK-601) - + PubSub ItemProvider does only process the outermost namespace + definition when creating PayloadItems +- [SMACK-602](https://igniterealtime.atlassian.net/browse/SMACK-602) - + PacketCollector must handle InterruptException +- [SMACK-603](https://igniterealtime.atlassian.net/browse/SMACK-603) - + XMPPError.Condition.equals() should be null-safe + +## 4.0.3 -- 2014-08-16 + +### Bug + +- [SMACK-589](https://igniterealtime.atlassian.net/browse/SMACK-589) - + FormField.Option toXML() produces malformed XML +- [SMACK-592](https://igniterealtime.atlassian.net/browse/SMACK-592) - + OfflineMessagesManager.getMessages() does send request before + collector is set up and could leak collector +- [SMACK-594](https://igniterealtime.atlassian.net/browse/SMACK-594) - + PrivateData Bookmarks.toXML() returns invalid XML + +### Improvement + +- [SMACK-539](https://igniterealtime.atlassian.net/browse/SMACK-539) - + Verify ConnectionConfiguration parameters +- [SMACK-588](https://igniterealtime.atlassian.net/browse/SMACK-588) - + Typo in org.jivesoftware.smackx.pubsub.ConfigureForm: + s/isSubscibe/isSubscribe/ +- [SMACK-593](https://igniterealtime.atlassian.net/browse/SMACK-593) - + Smack should prefer full flush over sync flush when using + compression + +## 4.0.2 -- 2014-07-27 + +### Improvement + +- [SMACK-576](https://igniterealtime.atlassian.net/browse/SMACK-576) - + smack-resolver-javax should become a OSGi ServiceComponent +- [SMACK-586](https://igniterealtime.atlassian.net/browse/SMACK-586) - + Extend API to configure a HostnameVerifier + +## 4.0.1 -- 2014-07-20 + +## Sub-task + +- [SMACK-346](https://igniterealtime.atlassian.net/browse/SMACK-346) - + Bug in return code for rejection handling in FileTransferManager + +### Bug + +- [SMACK-574](https://igniterealtime.atlassian.net/browse/SMACK-574) - + Documentation still refers at some places to Connection +- [SMACK-575](https://igniterealtime.atlassian.net/browse/SMACK-575) - + PingManager schedules pings after pingInterval when it should be use + nextPingIn instead +- [SMACK-577](https://igniterealtime.atlassian.net/browse/SMACK-577) - + Bookmarks and FormField toXml() methods do not properly escape XML +- [SMACK-583](https://igniterealtime.atlassian.net/browse/SMACK-583) - + PacketListeners may not be invoked in delivery order + +### Improvement + +- [SMACK-576](https://igniterealtime.atlassian.net/browse/SMACK-576) - + smack-resolver-javax should become a OSGi ServiceComponent + +### New Feature + +- [SMACK-580](https://igniterealtime.atlassian.net/browse/SMACK-580) - + Add support for retrieving a PubSub node\'s affiliations + +## 4.0.0 -- 2014-06-08 + +## Sub-task + +- [SMACK-399](https://igniterealtime.atlassian.net/browse/SMACK-399) - + Add support for Roster Versioning (was XEP-0237, now in RFC 6121) +- [SMACK-400](https://igniterealtime.atlassian.net/browse/SMACK-400) - + Change xml-not-well-formed to not-well-formed +- [SMACK-401](https://igniterealtime.atlassian.net/browse/SMACK-401) - + Remove \ +- [SMACK-445](https://igniterealtime.atlassian.net/browse/SMACK-445) - + XMPPError class is based on deprecated XEP-0086 + +### Bug + +- [SMACK-357](https://igniterealtime.atlassian.net/browse/SMACK-357) - + Error in SASL authentication when SASL authzid parameter is null +- [SMACK-410](https://igniterealtime.atlassian.net/browse/SMACK-410) - + Any valid SSL server certificate can be used to perform a + man-in-the-middle attack +- [SMACK-411](https://igniterealtime.atlassian.net/browse/SMACK-411) - + ServiceDiscoveryManager identities should be non-static and kept in + a Set to allow multiple identities as per XEP-30 +- [SMACK-414](https://igniterealtime.atlassian.net/browse/SMACK-414) - + Smack does not announce the support for XEP-54 aka vcard-temp +- [SMACK-427](https://igniterealtime.atlassian.net/browse/SMACK-427) - + Typo in code - StreamInitiation.setSesssionID() +- [SMACK-467](https://igniterealtime.atlassian.net/browse/SMACK-467) - + Don\'t use the default locale for machine-readable output, use + Locale.US instead +- [SMACK-531](https://igniterealtime.atlassian.net/browse/SMACK-531) - + Add missing namespace attribute to XHTML-IM body tags +- [SMACK-533](https://igniterealtime.atlassian.net/browse/SMACK-533) - + Smack should prevent IQ response spoofing +- [SMACK-535](https://igniterealtime.atlassian.net/browse/SMACK-535) - + jul.properties should only configure the \'org.igniterealtime\' + namespace +- [SMACK-538](https://igniterealtime.atlassian.net/browse/SMACK-538) - + ParseRoster does not check the sender of the roster and for pending + roster queries +- [SMACK-541](https://igniterealtime.atlassian.net/browse/SMACK-541) - + XHTMLExtensionProvider relies on incorrect behavior of MXParser, + violating the contract of the XMLPullParser interface +- [SMACK-543](https://igniterealtime.atlassian.net/browse/SMACK-543) - + packet.Time is not thread-safe +- [SMACK-546](https://igniterealtime.atlassian.net/browse/SMACK-546) - + PubSub\'s Item needs to escape its XML payload +- [SMACK-548](https://igniterealtime.atlassian.net/browse/SMACK-548) - + PingManager notifies pingFailedListeners multiple times +- [SMACK-551](https://igniterealtime.atlassian.net/browse/SMACK-551) - + ChatManager throws NPE, when Message has no \'from\' attribute +- [SMACK-554](https://igniterealtime.atlassian.net/browse/SMACK-554) - + Memory leak in BookmarkManager +- [SMACK-555](https://igniterealtime.atlassian.net/browse/SMACK-555) - + VCardProvider should consider some elements as optional +- [SMACK-558](https://igniterealtime.atlassian.net/browse/SMACK-558) - + connect() must wait until the stream features have been parsed +- [SMACK-559](https://igniterealtime.atlassian.net/browse/SMACK-559) - + Roster entries without a group are not updated +- [SMACK-560](https://igniterealtime.atlassian.net/browse/SMACK-560) - + Race condition in PacketWriter +- [SMACK-567](https://igniterealtime.atlassian.net/browse/SMACK-567) - + XMPPConnection leaks listenerExecutor ExecutorService + +### Improvement + +- [SMACK-343](https://igniterealtime.atlassian.net/browse/SMACK-343) - + Make Smack jar an OSGi bundle. +- [SMACK-356](https://igniterealtime.atlassian.net/browse/SMACK-356) - + There is no way to reliably end a Chat and have a new one created. +- [SMACK-454](https://igniterealtime.atlassian.net/browse/SMACK-454) - + Follow XEP-0170 recommendation: Compression before Resource Binding +- [SMACK-459](https://igniterealtime.atlassian.net/browse/SMACK-459) - + Add option to configure the default identity in + ServiceDiscoveryManager +- [SMACK-465](https://igniterealtime.atlassian.net/browse/SMACK-465) - + Replace custom wrapped Throwable in XMPPException with + Exception.cause +- [SMACK-468](https://igniterealtime.atlassian.net/browse/SMACK-468) - + Don\'t throw an IOException in IBBStreams when the stream got closed + by the remote +- [SMACK-536](https://igniterealtime.atlassian.net/browse/SMACK-536) - + JUL Loggers should become final +- [SMACK-537](https://igniterealtime.atlassian.net/browse/SMACK-537) - + Move XMPP Ping code to smackx, add keep-alive functionality to + PingManager +- [SMACK-545](https://igniterealtime.atlassian.net/browse/SMACK-545) - + Change API to the style mentioned in Smack\'s Code Guidelines +- [SMACK-547](https://igniterealtime.atlassian.net/browse/SMACK-547) - + Consistent behavior for \"from\" attribute on outgoing stanzas +- [SMACK-556](https://igniterealtime.atlassian.net/browse/SMACK-556) - + Make ConnectionConfigration getters public +- [SMACK-557](https://igniterealtime.atlassian.net/browse/SMACK-557) - + Provide a MultiUserChat method to create \*or\* join a room +- [SMACK-568](https://igniterealtime.atlassian.net/browse/SMACK-568) - + Don\'t exclude groupchat messages without body element in + MultiUserChat MessageListeners + +### New Feature + +- [SMACK-53](https://igniterealtime.atlassian.net/browse/SMACK-53) - + Add support for XEP-0092: Software Version +- [SMACK-71](https://igniterealtime.atlassian.net/browse/SMACK-71) - + Create new FromFilter that checks for exact matching +- [SMACK-187](https://igniterealtime.atlassian.net/browse/SMACK-187) - + Add HTTP Binding support (BOSH / XEP-0124) +- [SMACK-265](https://igniterealtime.atlassian.net/browse/SMACK-265) - + Move to a newer build process with artifacts published to maven + central repo +- [SMACK-426](https://igniterealtime.atlassian.net/browse/SMACK-426) - + Improve XMPPException +- [SMACK-544](https://igniterealtime.atlassian.net/browse/SMACK-544) - + Add support for XEP-0079: Advanced Message Processing +- [SMACK-552](https://igniterealtime.atlassian.net/browse/SMACK-552) - + Add support for \"HTTP over XMPP transport\" aka. XEP-0332 + +### Task + +- [SMACK-371](https://igniterealtime.atlassian.net/browse/SMACK-371) - + Some MUC tasks are using stanza\'s as defined in an older version of + the spec. Fails to work on some servers. +- [SMACK-432](https://igniterealtime.atlassian.net/browse/SMACK-432) - + Code cleanup of deprecated methods +- [SMACK-446](https://igniterealtime.atlassian.net/browse/SMACK-446) - + Remove non-SASL authentication code + +## 3.4.1 -- 2014-02-09 + +### Bug + +- [SMACK-540](https://igniterealtime.atlassian.net/browse/SMACK-540) - + Memory leak in MultiUserChat + +## 3.4.0 -- 2014-02-02 + +### Bug Fixes + +- [SMACK-442](https://igniterealtime.atlassian.net/browse/SMACK-442) - + Manager\'s should also handle connectionClosedOnError() +- [SMACK-443](https://igniterealtime.atlassian.net/browse/SMACK-443) - + ReconnectionSuccessful listeners are invoked twice on reconnection + if connect() failed before +- [SMACK-452](https://igniterealtime.atlassian.net/browse/SMACK-452) - + PacketParserUtils.parseStreamError() is not aware of optional text + element and therefore failes to parse stream error\'s correctly. + Prevents ReconnectionManager from reconnecting. +- [SMACK-458](https://igniterealtime.atlassian.net/browse/SMACK-458) - + Smack\'s Managers should not remove itself when the connection is + closed or should re-add themselfs if the connection get reconnected +- [SMACK-462](https://igniterealtime.atlassian.net/browse/SMACK-462) - + Prevent duplicate manager instances by using the manager\'s + constructor in the ConnectionCreationListener\'s connectionCreated +- [SMACK-463](https://igniterealtime.atlassian.net/browse/SMACK-463) - + packet listeners silently fail when preceding listener caused + exception +- [SMACK-524](https://igniterealtime.atlassian.net/browse/SMACK-524) - + Use correct block-size definition for IBB transfers +- [SMACK-525](https://igniterealtime.atlassian.net/browse/SMACK-525) - + NPE in XMPPConnection.notifyConnectionError +- [SMACK-529](https://igniterealtime.atlassian.net/browse/SMACK-529) - + Add support for XEP-0280 \"Message Carbons\" +- [SMACK-530](https://igniterealtime.atlassian.net/browse/SMACK-530) - + DNSUtilTest requires an internet connection to work, it should be + moved to integration tests. + +### New Feature + +- [SMACK-286](https://igniterealtime.atlassian.net/browse/SMACK-286) - + Need to change ProviderManager to support loading smack.providers + from alternative locations +- [SMACK-387](https://igniterealtime.atlassian.net/browse/SMACK-387) - + Allow configuration of ChatManager to be able to allow message + handling to be customized. +- [SMACK-403](https://igniterealtime.atlassian.net/browse/SMACK-403) - + Add support for XEP-0297 \"Stanza Forwarding\" +- [SMACK-434](https://igniterealtime.atlassian.net/browse/SMACK-434) - + Create a project to contain non production ready implementations of + specifications + +### Improvement + +- [SMACK-343](https://igniterealtime.atlassian.net/browse/SMACK-343) - + Make Smack jar an OSGi bundle. +- [SMACK-381](https://igniterealtime.atlassian.net/browse/SMACK-381) - + Separate the configuration for smack extension related classes from + the smack jar. +- [SMACK-444](https://igniterealtime.atlassian.net/browse/SMACK-444) - + Allow \'null\' for TruststorePath and TruststorePassword in + ServerTrustManager +- [SMACK-456](https://igniterealtime.atlassian.net/browse/SMACK-456) - + Add the causing exception to the XMPPExceptions thrown in + XMPPConnection +- [SMACK-457](https://igniterealtime.atlassian.net/browse/SMACK-457) - + Remove unnecessary printStackTrace() in XMPPConnection +- [SMACK-460](https://igniterealtime.atlassian.net/browse/SMACK-460) - + ServiceDiscoveryManager should not use the constructor in + connectionCreated() +- [SMACK-461](https://igniterealtime.atlassian.net/browse/SMACK-461) - + Remove incorrect deprecated marker for + DiscoverInfo.Identity.setType() +- [SMACK-464](https://igniterealtime.atlassian.net/browse/SMACK-464) - + Make it clear that PacketListener\'s added with + XMPPConnection.addPacketListener() are only for received packets +- [SMACK-534](https://igniterealtime.atlassian.net/browse/SMACK-534) - + Convert all System.out and printStackTrace calls to use Java util + logging. +- [SMACK-339](https://igniterealtime.atlassian.net/browse/SMACK-339) - + Allow ConnectionListeners to be added before XMPPConnection is + connected. Currently throws exception +- [SMACK-373](https://igniterealtime.atlassian.net/browse/SMACK-373) - + Don\'t remove listeners after a disconnect() , keep state of + XMPPConnection between disconnect() and connect()/login() +- [SMACK-434](https://igniterealtime.atlassian.net/browse/SMACK-434) - + Create a project to contain non production ready implementations of + specifications +- [SMACK-526](https://igniterealtime.atlassian.net/browse/SMACK-526) - + Deprecate all PEP related classes. + +## 3.3.1 -- 2013-10-06 + +### Bug Fixes + +- [SMACK-428](https://igniterealtime.atlassian.net/browse/SMACK-428) - + RosterEntry overrides equals, but not hashcode. +- [SMACK-438](https://igniterealtime.atlassian.net/browse/SMACK-438) - + Possible NPE in + MultiUserChat.InvitationsMonitor.getInvitationsMonitor() +- [SMACK-441](https://igniterealtime.atlassian.net/browse/SMACK-441) - + Memory leak in KeepAliveManager +- [SMACK-447](https://igniterealtime.atlassian.net/browse/SMACK-447) - + Compression is not enabled for Java7ZlibInputOutputStream +- [SMACK-448](https://igniterealtime.atlassian.net/browse/SMACK-448) - + Java7ZlibInputOutputStream does not work. Deflater.DEFAULT_STRATEGY + is used as compression level when it should use + Deflater.DEFAULT_COMPRESSION +- [SMACK-450](https://igniterealtime.atlassian.net/browse/SMACK-450) - + VCard.load() throws null pointer exception if there is no VCard for + the user +- [SMACK-455](https://igniterealtime.atlassian.net/browse/SMACK-455) - + Multiple items doesn\`t not parse correctly in a pubsub message + +### New Feature + +- [SMACK-425](https://igniterealtime.atlassian.net/browse/SMACK-425) - + Collect (parser) Exceptions and unparseable stanzas. Provide a + callback method so that the user is notified about them if he wants + to + +### Improvement + +- [SMACK-369](https://igniterealtime.atlassian.net/browse/SMACK-369) - + Exceptions during login should get thrown back up to the caller. +- [SMACK-439](https://igniterealtime.atlassian.net/browse/SMACK-439) - + Improve documentation for MultiUserChat.InvitationsListener +- [SMACK-451](https://igniterealtime.atlassian.net/browse/SMACK-451) - + PingManager entry in META-INF/smack.providers is within Ad-Hoc + Command section +- [SMACK-431](https://igniterealtime.atlassian.net/browse/SMACK-431) - + Enable Entity Caps as default for new connections and write + extensions documentation html page +- [SMACK-405](https://igniterealtime.atlassian.net/browse/SMACK-405) - + Cleanup of redundant code in XMPPConnection.shutdown() + +## 3.3.0 -- 2013-05-04 + +### Bug Fixes + +- [SMACK-225](https://igniterealtime.atlassian.net/browse/SMACK-225) - + Improper handeling of DNS SRV records +- [SMACK-238](https://igniterealtime.atlassian.net/browse/SMACK-238) - + The vCard avatar type always return jpg +- [SMACK-270](https://igniterealtime.atlassian.net/browse/SMACK-270) - + Fix for a memory leak in MUC with MUC.finalize() +- [SMACK-278](https://igniterealtime.atlassian.net/browse/SMACK-278) - + Deadlock during Smack disconnect +- [SMACK-342](https://igniterealtime.atlassian.net/browse/SMACK-342) - + VCards causes ConcurrentModificationException +- [SMACK-344](https://igniterealtime.atlassian.net/browse/SMACK-344) - + Bug in SASL authentication mechanism when SRV records are being + used. +- [SMACK-351](https://igniterealtime.atlassian.net/browse/SMACK-351) - + Rework File Transfer +- [SMACK-352](https://igniterealtime.atlassian.net/browse/SMACK-352) - + Update the licensing headers in various files. +- [SMACK-355](https://igniterealtime.atlassian.net/browse/SMACK-355) - + IO Error if smack cant use port for local proxy +- [SMACK-371](https://igniterealtime.atlassian.net/browse/SMACK-371) - + Some MUC tasks are using stanza\'s as defined in an older version of + the spec. Fails to work on some servers. +- [SMACK-375](https://igniterealtime.atlassian.net/browse/SMACK-375) - + Node strings in the discovery info packets are not escaped as in the + other packets +- [SMACK-382](https://igniterealtime.atlassian.net/browse/SMACK-382) - + Prevent memory leak in AdHocCommandManager +- [SMACK-384](https://igniterealtime.atlassian.net/browse/SMACK-384) - + Endless waiting for connection to be established +- [SMACK-390](https://igniterealtime.atlassian.net/browse/SMACK-390) - + Smack login will fail if a bad delay packet is received +- [SMACK-392](https://igniterealtime.atlassian.net/browse/SMACK-392) - + In ant build, compile-test target doesn\'t work. +- [SMACK-394](https://igniterealtime.atlassian.net/browse/SMACK-394) - + Erroneous cast in IBBInputStream\'s read() method +- [SMACK-395](https://igniterealtime.atlassian.net/browse/SMACK-395) - + Socks5BytestreamManager\'s establishConnection() should still try to + use the local streamhost proxy if the server doesn\'t provide one +- [SMACK-404](https://igniterealtime.atlassian.net/browse/SMACK-404) - + Smack uses the wrong method to decode Base64 Strings +- [SMACK-413](https://igniterealtime.atlassian.net/browse/SMACK-413) - + VCardProvider incorrectly parses binary value of avatars +- [SMACK-415](https://igniterealtime.atlassian.net/browse/SMACK-415) - + ItemProvider relies on incorrect behavior of MXParser, violating the + contract of the XMLPullParser interface +- [SMACK-417](https://igniterealtime.atlassian.net/browse/SMACK-417) - + If both PacketReader and PacketWriter fail at the same time, + connectionClosedonError() is called two times + +### New Features + +- [SMACK-331](https://igniterealtime.atlassian.net/browse/SMACK-331) - + Add support for XEP-0184: Message Delivery Receipts +- [SMACK-345](https://igniterealtime.atlassian.net/browse/SMACK-345) - + Inproved detection of last activity +- [SMACK-361](https://igniterealtime.atlassian.net/browse/SMACK-361) - + Add support for XEP-0115 Entity Capabilities +- [SMACK-376](https://igniterealtime.atlassian.net/browse/SMACK-376) - + Setting a custom trust manager to control certificates from outside +- [SMACK-388](https://igniterealtime.atlassian.net/browse/SMACK-388) - + XEP-199 XMPP Ping support + +### Improvements + +- [SMACK-341](https://igniterealtime.atlassian.net/browse/SMACK-341) - + Update the PacketCollector and ConnectionDetachedPacketCollector to + use the java concurrent classes. +- [SMACK-358](https://igniterealtime.atlassian.net/browse/SMACK-358) - + Support additional properties for account creation in test cases. +- [SMACK-363](https://igniterealtime.atlassian.net/browse/SMACK-363) - + Code Cleanup +- [SMACK-377](https://igniterealtime.atlassian.net/browse/SMACK-377) - + avoid unnecessary DNS requests in XMPPconnection +- [SMACK-379](https://igniterealtime.atlassian.net/browse/SMACK-379) - + Sessions were removed from the specification but Smack still uses + them. Should be updated to reflect the spec changes. +- [SMACK-385](https://igniterealtime.atlassian.net/browse/SMACK-385) - + Reusing KeyStore in order to reduce memory usage +- [SMACK-389](https://igniterealtime.atlassian.net/browse/SMACK-389) - + Add java.util.zip.Deflater(In\|Out)putStream as Java7 API native + alternative to JZlib +- [SMACK-391](https://igniterealtime.atlassian.net/browse/SMACK-391) - + Improve date parsing in StringUtils and make + DelayInformationProvider use StringUtils for date parsing. +- [SMACK-412](https://igniterealtime.atlassian.net/browse/SMACK-412) - + Replace the whitespace ping with a XEP-0199 ping +- [SMACK-419](https://igniterealtime.atlassian.net/browse/SMACK-419) - + PacketWriter: Only flush the BufferedWriter if the packet queue is + empty +- [SMACK-423](https://igniterealtime.atlassian.net/browse/SMACK-423) - + Investigate whether unhandled packets should still parse the child + xml into a string as content +- [SMACK-430](https://igniterealtime.atlassian.net/browse/SMACK-430) - + Throw an exception if + FileTransferManager.createOutgoingFileTransfer() was used with a + bare JID + +## 3.2.2 -- 2011-12-23 + +### Bug Fixes + +- [SMACK-263](https://igniterealtime.atlassian.net/browse/SMACK-263) - + Set file info in all send\* methods +- [SMACK-322](https://igniterealtime.atlassian.net/browse/SMACK-322) - + NPE in XMPPConnection +- [SMACK-324](https://igniterealtime.atlassian.net/browse/SMACK-324) - + Investigate SASL issue with jabberd2 servers +- [SMACK-338](https://igniterealtime.atlassian.net/browse/SMACK-338) - + IBB filetransfer doesn\'t work as expected +- [SMACK-346](https://igniterealtime.atlassian.net/browse/SMACK-346) - + Bug in return code for rejection handling in FileTransferManager +- [SMACK-348](https://igniterealtime.atlassian.net/browse/SMACK-348) - + Documentation error - broken link +- [SMACK-349](https://igniterealtime.atlassian.net/browse/SMACK-349) - + Smack\'s IBB sends too much data in a packet +- [SMACK-350](https://igniterealtime.atlassian.net/browse/SMACK-350) - + Bytestream is not working in Spark 2.6.3 from XP to W7 +- [SMACK-353](https://igniterealtime.atlassian.net/browse/SMACK-353) - + Thread leak in the FaultTolerantNegotiator +- [SMACK-362](https://igniterealtime.atlassian.net/browse/SMACK-362) - + smack throw NoSuchElementException if the muc#roominfo_subject has + no values + +### Improvements + +- [SMACK-343](https://igniterealtime.atlassian.net/browse/SMACK-343) - + Make Smack jar an OSGi bundle. +- [SMACK-354](https://igniterealtime.atlassian.net/browse/SMACK-354) - + Provide milliseconds in timestamp colum debugwindow + +## 3.2.1 -- 2011-07-04 + +### Bug Fixes + +- [SMACK-129](https://igniterealtime.atlassian.net/browse/SMACK-129) - + MultiUserChat will Store Messages in its PacketCollector + irregardless of whether or not they are being read +- [SMACK-230](https://igniterealtime.atlassian.net/browse/SMACK-230) - + Disconnect Can Cause Null Pointer Exception +- [SMACK-273](https://igniterealtime.atlassian.net/browse/SMACK-273) - + Bug in RoomListenerMultiplexor.java +- [SMACK-329](https://igniterealtime.atlassian.net/browse/SMACK-329) - + XHTMLText uses improper format for br tag +- [SMACK-338](https://igniterealtime.atlassian.net/browse/SMACK-338) - + IBB filetransfer doesn\'t work as expected +- [SMACK-324](https://igniterealtime.atlassian.net/browse/SMACK-324) - + Investigate SASL issue with jabberd2 servers + +## 3.2.0 -- 2011-05-03 + +### New Features + +- [SMACK-272](https://igniterealtime.atlassian.net/browse/SMACK-272) - + Add support for pubsub (XEP-0060) +- [SMACK-296](https://igniterealtime.atlassian.net/browse/SMACK-296) - + Add support for XEP-0224: Attention +- [SMACK-319](https://igniterealtime.atlassian.net/browse/SMACK-319) - + Add common interfaces for SOCKS5 Bytestreams and In-Band Bytestreams + +### Improvements + +- [SMACK-137](https://igniterealtime.atlassian.net/browse/SMACK-137) - + File Transfer Settings +- [SMACK-156](https://igniterealtime.atlassian.net/browse/SMACK-156) - + Add the ability to register for roster events before logging in +- [SMACK-261](https://igniterealtime.atlassian.net/browse/SMACK-261) - + Minor Jingle cleanup to better support Jingle in Spark +- [SMACK-277](https://igniterealtime.atlassian.net/browse/SMACK-277) - + Update XMLUnit to the latest version +- [SMACK-282](https://igniterealtime.atlassian.net/browse/SMACK-282) - + Support SASL-related error conditions. +- [SMACK-283](https://igniterealtime.atlassian.net/browse/SMACK-283) - + Investigate why Jingle is connecting to stun.xten.net +- [SMACK-285](https://igniterealtime.atlassian.net/browse/SMACK-285) - + Add support for Nicks +- [SMACK-289](https://igniterealtime.atlassian.net/browse/SMACK-289) - + There is no way of retrieving items from a pubsub node when the user + has multiple subscriptions. +- [SMACK-294](https://igniterealtime.atlassian.net/browse/SMACK-294) - + Handle empty roster groups and no goups in the same way +- [SMACK-295](https://igniterealtime.atlassian.net/browse/SMACK-295) - + Fire reconnectionSuccessful event when session is established +- [SMACK-297](https://igniterealtime.atlassian.net/browse/SMACK-297) - + add configuration for local Socks5 proxy +- [SMACK-298](https://igniterealtime.atlassian.net/browse/SMACK-298) - + Respond to all incoming Socks5 bytestream requests +- [SMACK-299](https://igniterealtime.atlassian.net/browse/SMACK-299) - + Improve accepting of Socks5 bytestream requests +- [SMACK-300](https://igniterealtime.atlassian.net/browse/SMACK-300) - + improve local Socks5 proxy implemetation +- [SMACK-301](https://igniterealtime.atlassian.net/browse/SMACK-301) - + support for bytestream packets to query Socks5 proxy for network + address +- [SMACK-302](https://igniterealtime.atlassian.net/browse/SMACK-302) - + Improve establishing of Socks5 bytestreams +- [SMACK-303](https://igniterealtime.atlassian.net/browse/SMACK-303) - + integrate of the extracted Socks5 bytestream API in file transfer + API +- [SMACK-304](https://igniterealtime.atlassian.net/browse/SMACK-304) - + Extend the IQ API to create empty IQ results and IQ error response + packets +- [SMACK-307](https://igniterealtime.atlassian.net/browse/SMACK-307) - + Improve Message Parser Robustness and Message Body I18N +- [SMACK-309](https://igniterealtime.atlassian.net/browse/SMACK-309) - + Fully implement XEP-0047 In-Band Bytestreams +- [SMACK-310](https://igniterealtime.atlassian.net/browse/SMACK-310) - + Add Support for Localized Message Subjects + +### Bug Fixes + +- [SMACK-163](https://igniterealtime.atlassian.net/browse/SMACK-163) - + Fix NPE in RoomInfo when subject has not value +- [SMACK-207](https://igniterealtime.atlassian.net/browse/SMACK-207) - + Parsing of messages may disconnect Smack/Spark +- [SMACK-225](https://igniterealtime.atlassian.net/browse/SMACK-225) - + Improper handeling of DNS SRV records +- [SMACK-232](https://igniterealtime.atlassian.net/browse/SMACK-232) - + Better handling of Roster error +- [SMACK-243](https://igniterealtime.atlassian.net/browse/SMACK-243) - + Packet with wrong date format makes Smack to disconnect +- [SMACK-264](https://igniterealtime.atlassian.net/browse/SMACK-264) - + fix for NPE in SASLMechanism.java +- [SMACK-269](https://igniterealtime.atlassian.net/browse/SMACK-269) - + Smack 3.1.0 creates a new chat for every incoming message +- [SMACK-271](https://igniterealtime.atlassian.net/browse/SMACK-271) - + Deadlock in XMPPConnection while login and parsing stream features +- [SMACK-275](https://igniterealtime.atlassian.net/browse/SMACK-275) - + Patch: Fix for broken SASL DIGEST-MD5 implementation +- [SMACK-280](https://igniterealtime.atlassian.net/browse/SMACK-280) - + The authentification should use the XMPPConnection#sendPacket method + and work transparent with packets and packet listeners. +- [SMACK-288](https://igniterealtime.atlassian.net/browse/SMACK-288) - + The parsing of the result for a LeafNode.getItems() call is + incorrect. It creates a DefaultPacketExtension instead of an Item + for every other item in the result. +- [SMACK-290](https://igniterealtime.atlassian.net/browse/SMACK-290) - + Deadlock while getting Roster before it\'s initialized +- [SMACK-291](https://igniterealtime.atlassian.net/browse/SMACK-291) - + RosterGroup modifications should depend on roster push +- [SMACK-293](https://igniterealtime.atlassian.net/browse/SMACK-293) - + Support optional roster subscription attribute +- [SMACK-305](https://igniterealtime.atlassian.net/browse/SMACK-305) - + RosterEntry#getGroups causing a roster reload +- [SMACK-308](https://igniterealtime.atlassian.net/browse/SMACK-308) - + Multiple errors in pubsub GetItemsRequest +- [SMACK-312](https://igniterealtime.atlassian.net/browse/SMACK-312) - + Only fire RosterListener#entriesUpdated for RosterEntries that + changed +- [SMACK-327](https://igniterealtime.atlassian.net/browse/SMACK-327) - + getFeatures() method on DiscoverInfo is improperly set to be package + protected instead of public +- [SMACK-328](https://igniterealtime.atlassian.net/browse/SMACK-328) - + Number format exception while parsing dates. +- [SMACK-332](https://igniterealtime.atlassian.net/browse/SMACK-332) - + Smack 3.2.0b2 shows wrong version in Smack Dubugger Window +- [SMACK-334](https://igniterealtime.atlassian.net/browse/SMACK-334) - + Error in form for FileTransferNegotiator + +## 3.1.0 -- 2008-11-20 + +### New Features + +- [SMACK-142](https://igniterealtime.atlassian.net/browse/SMACK-142) - + Added support for Kerberos/NTLM. **(6 votes)** +- [SMACK-210](https://igniterealtime.atlassian.net/browse/SMACK-210) - + Added support for MD5 SASL. **(1 vote)** +- [SMACK-256](https://igniterealtime.atlassian.net/browse/SMACK-256) - + Added support for new sophisticated TLS mechanisms including + SmartCard and Apple\'s KeychainStore. +- [SMACK-242](https://igniterealtime.atlassian.net/browse/SMACK-242) - + Added support for JEP-50: Ad-hoc commands. +- [SMACK-251](https://igniterealtime.atlassian.net/browse/SMACK-251) - + Added support for XEP-0163: Personal Eventing Protocol. **(1 vote)** +- [SMACK-226](https://igniterealtime.atlassian.net/browse/SMACK-226) - + XMLConnection can now be used with an http/socks proxy. **(2 + votes)** +- [SMACK-254](https://igniterealtime.atlassian.net/browse/SMACK-254) - + Loading the Roster during login is now optional. +- [SMACK-255](https://igniterealtime.atlassian.net/browse/SMACK-255) - + Added ability to set mime type for avatar. +- [SMACK-235](https://igniterealtime.atlassian.net/browse/SMACK-235) - + Improved performance of Roster class. +- [SMACK-241](https://igniterealtime.atlassian.net/browse/SMACK-241) - + Updated Base64 implementation to match Openfire\'s. +- [SMACK-240](https://igniterealtime.atlassian.net/browse/SMACK-240) - + Updated Jingle implementation to newest version. +- [SMACK-246](https://igniterealtime.atlassian.net/browse/SMACK-246) - + Improve Jingle logging using commons-logging +- [SMACK-244](https://igniterealtime.atlassian.net/browse/SMACK-244) - + Updated JSTUN to 0.7.2. +- [SMACK-259](https://igniterealtime.atlassian.net/browse/SMACK-259) - + Updated XPP library to latest version. + +### Bug Fixes + +- [SMACK-231](https://igniterealtime.atlassian.net/browse/SMACK-231) - + IBB Outputstream was not being flushed before it was closed. +- [SMACK-236](https://igniterealtime.atlassian.net/browse/SMACK-236) - + Renamed stanza error \"unexpected-condition\" to + \"unexpected-request\". +- [SMACK-258](https://igniterealtime.atlassian.net/browse/SMACK-258) - + Fixed disconnection issue when parsing SASL success that contained a + payload. +- [SMACK-175](https://igniterealtime.atlassian.net/browse/SMACK-175) - + Fixed typo in RosterPacket.ItemStatus constant. +- [SMACK-260](https://igniterealtime.atlassian.net/browse/SMACK-260) - + Added handling of error presence packets + +## 3.0.3 -- 2007-05-31 + +### New Features + +- [SMACK-99](https://igniterealtime.atlassian.net/browse/SMACK-99) - + Added support for multiple message bodies and message body + languages. +- [SMACK-218](https://igniterealtime.atlassian.net/browse/SMACK-218) - + Implemented GSSAPI for single-sign on. + +### Bug Fixes + +- [SMACK-219](https://igniterealtime.atlassian.net/browse/SMACK-219) - + The getPresence method was not working correctly with offline + presence. +- [SMACK-224](https://igniterealtime.atlassian.net/browse/SMACK-224) - + SASL authenticion was using the XMPP domain instead of the FQDN. + +## 3.0.2 -- 2007-05-03 + +### Bug Fixes + +- [SMACK-212](https://igniterealtime.atlassian.net/browse/SMACK-212) - + Jingle can\'t establish session if only one side has a relay service +- [SMACK-213](https://igniterealtime.atlassian.net/browse/SMACK-213) - + RTP Bridge Resolver get wrong localhost address in certain + situations +- [SMACK-214](https://igniterealtime.atlassian.net/browse/SMACK-214) - + Presences with a negative priority of -1 are not sending the + priority to the server + +## 3.0.1 -- 2007-04-12 + +### Bug Fixes + +- [SMACK-211](https://igniterealtime.atlassian.net/browse/SMACK-211) - + Jingle ICE with relay sometimes closed sessions. +- Upgraded bundled version of JSTUN. + +## 3.0.0 -- 2007-03-31 + +### Important Changes + +- Java 5 is now required. +- Several API changes are not backwards compatible. In particular, + connection handling has been significantly updated, the GroupChat + class has been dropped in favor of the standardized MultiUserChat, + and the Chat class has an updated API. + +### New Features + +- [SMACK-74](https://igniterealtime.atlassian.net/browse/SMACK-74) - + Added support for unavailable presences with status text. **(4 + votes)** +- [SMACK-191](https://igniterealtime.atlassian.net/browse/SMACK-191) - + RosterListener API improvements. +- [SMACK-194](https://igniterealtime.atlassian.net/browse/SMACK-194) - + Roster.getPresence(String) now considers mode after priority to + determine the presence value to return. +- [SMACK-195](https://igniterealtime.atlassian.net/browse/SMACK-195) - + Added the ability to disconnect with a custom presence value (for + offline status). +- [SMACK-200](https://igniterealtime.atlassian.net/browse/SMACK-200) - + Added convenience methods to Presence class. +- [SMACK-31](https://igniterealtime.atlassian.net/browse/SMACK-31) - + Added support for privacy lists. **(4 votes)** +- [SMACK-94](https://igniterealtime.atlassian.net/browse/SMACK-94) - + Added support for last activity of online users. **(1 vote)** +- [SMACK-121](https://igniterealtime.atlassian.net/browse/SMACK-121) - + Added support for stream errors. +- [SMACK-136](https://igniterealtime.atlassian.net/browse/SMACK-136) - + Added support for XEP-0048: bookmark storage. +- [SMACK-144](https://igniterealtime.atlassian.net/browse/SMACK-144) - + Added bookmark manager for central bookmark management. +- [SMACK-150](https://igniterealtime.atlassian.net/browse/SMACK-150) - + Added support for handling node features in disco. +- [SMACK-167](https://igniterealtime.atlassian.net/browse/SMACK-167) - + Added support for XEP-0106: JID Escaping +- [SMACK-171](https://igniterealtime.atlassian.net/browse/SMACK-171) - + The presence of available contacts is now changed to offline when + the connection is closed. +- [SMACK-172](https://igniterealtime.atlassian.net/browse/SMACK-172) - + Added support for re-connection when the connection is abruptly + closed. +- [SMACK-182](https://igniterealtime.atlassian.net/browse/SMACK-182) - + ProviderManager is now pluggable (for Eclipse ECF). +- [SMACK-185](https://igniterealtime.atlassian.net/browse/SMACK-185) - + Added the workgroup API to Smack. +- [SMACK-206](https://igniterealtime.atlassian.net/browse/SMACK-206) - + Added the option to specify the username to use for the automated + test cases. +- [SMACK-208](https://igniterealtime.atlassian.net/browse/SMACK-208) - + Added a max queue size for outgoing packets to prevent memory issues + during extreme load. +- [SMACK-209](https://igniterealtime.atlassian.net/browse/SMACK-209) - + Initial Jingle support implemented. + +### Bug Fixes + +- [SMACK-6](https://igniterealtime.atlassian.net/browse/SMACK-6) - + Don\'t force use of collectors in Chat class. +- [SMACK-10](https://igniterealtime.atlassian.net/browse/SMACK-10) - + Flush pending packets before closing the connection. **(4 votes)** +- [SMACK-51](https://igniterealtime.atlassian.net/browse/SMACK-51) - + Use unique Thread names among connections. +- [SMACK-54](https://igniterealtime.atlassian.net/browse/SMACK-54) - + Add #equals and #hashCode to Occupant. +- [SMACK-86](https://igniterealtime.atlassian.net/browse/SMACK-86) - + Made presence checks case in-sensitive. +- [SMACK-93](https://igniterealtime.atlassian.net/browse/SMACK-93) - + XHTML provider wasn\'t handling some tags correctly. +- [SMACK-138](https://igniterealtime.atlassian.net/browse/SMACK-138) - + Added caching to file transfer negotiation operations. +- [SMACK-143](https://igniterealtime.atlassian.net/browse/SMACK-143) - + Updated XMPPError to be compliant with RFC3920. +- [SMACK-145](https://igniterealtime.atlassian.net/browse/SMACK-145) - + XHTML parsing could fail in some cases. +- [SMACK-146](https://igniterealtime.atlassian.net/browse/SMACK-146) - + DNS lookups were failing with some DNS servers. +- [SMACK-147](https://igniterealtime.atlassian.net/browse/SMACK-147) - + Removed invisibility presence mode. +- [SMACK-148](https://igniterealtime.atlassian.net/browse/SMACK-148) - + Socks 5 listening thread was not cleaning up correctly. **(2 + votes)** +- [SMACK-149](https://igniterealtime.atlassian.net/browse/SMACK-149) - + Fixed possible memory leaking in PacketReader. +- [SMACK-151](https://igniterealtime.atlassian.net/browse/SMACK-151) - + Now use getBytes(\"UTF-8\") instead of getBytes(). +- [SMACK-152](https://igniterealtime.atlassian.net/browse/SMACK-152) - + The FN field is duplicated when loading vCards from the server. +- [SMACK-153](https://igniterealtime.atlassian.net/browse/SMACK-153) - + Optimized performance by replacing StringBuffer with StringBuilder. +- [SMACK-154](https://igniterealtime.atlassian.net/browse/SMACK-154) - + Fixed roster test cases that were sometimes failing. +- [SMACK-155](https://igniterealtime.atlassian.net/browse/SMACK-155) - + Optimized MUC performance by reducing number of packet collectors + and listeners. +- [SMACK-158](https://igniterealtime.atlassian.net/browse/SMACK-158) - + FileTransfer isDone() method was returning true even when the + transfer was refused. +- [SMACK-159](https://igniterealtime.atlassian.net/browse/SMACK-159) - + Filenames were not escaped for file transfers. +- [SMACK-160](https://igniterealtime.atlassian.net/browse/SMACK-160) - + Now use stream:feature to discover registration support. +- [SMACK-161](https://igniterealtime.atlassian.net/browse/SMACK-161) - + Improved connection speed. +- [SMACK-162](https://igniterealtime.atlassian.net/browse/SMACK-162) - + Fixed NPE in SmackConfiguration. +- [SMACK-163](https://igniterealtime.atlassian.net/browse/SMACK-163) - + Fixed NPE in RoomInfo when subject was null. +- [SMACK-164](https://igniterealtime.atlassian.net/browse/SMACK-164) - + Contact name was not being escaped. +- [SMACK-165](https://igniterealtime.atlassian.net/browse/SMACK-165) - + Listeners were not being removed from PacketReader. +- [SMACK-166](https://igniterealtime.atlassian.net/browse/SMACK-166) - + Packet reader thread was freezing when parsing an error text with no + description. +- [SMACK-168](https://igniterealtime.atlassian.net/browse/SMACK-168) - + Fixed possible delay in PacketReader when negotiating TLS. +- [SMACK-173](https://igniterealtime.atlassian.net/browse/SMACK-173) - + Renamed ConnectionEstablishedListener to ConnectionCreationListener. +- [SMACK-176](https://igniterealtime.atlassian.net/browse/SMACK-176) - + Fixed incorrect property initialization. +- [SMACK-177](https://igniterealtime.atlassian.net/browse/SMACK-177) - + Removed synchronization from Roster. +- [SMACK-178](https://igniterealtime.atlassian.net/browse/SMACK-178) - + Added NodeInformation#getNodeIdentities() to return identities of + hosted nodes +- [SMACK-181](https://igniterealtime.atlassian.net/browse/SMACK-181) - + Improved parsing of certificates to get signed domains. +- [SMACK-183](https://igniterealtime.atlassian.net/browse/SMACK-183) - + Documentation fixes. +- [SMACK-184](https://igniterealtime.atlassian.net/browse/SMACK-184) - + Simplified XMPPConnection constructors. +- [SMACK-203](https://igniterealtime.atlassian.net/browse/SMACK-203) - + NULL thread IDs would cause an error inside of the Chat Manager. +- [SMACK-205](https://igniterealtime.atlassian.net/browse/SMACK-205) - + Fixed PacketReader concurrency problems. +- [SMACK-188](https://igniterealtime.atlassian.net/browse/SMACK-188) - + Resources are now closed after reading the keystore. +- [SMACK-189](https://igniterealtime.atlassian.net/browse/SMACK-189) - + The listener was remaining blocked forever in some cases. +- [SMACK-190](https://igniterealtime.atlassian.net/browse/SMACK-190) - + Exceptions while notifying packet reader listeners was stopping the + notification thread. +- [SMACK-192](https://igniterealtime.atlassian.net/browse/SMACK-192) - + Roster.getPresence(String) now forces use of the bare JID. +- [SMACK-193](https://igniterealtime.atlassian.net/browse/SMACK-193) - + New presence packets now default to a null presence mode. +- [SMACK-196](https://igniterealtime.atlassian.net/browse/SMACK-196) - + Now set closed to true at the start of the connection shutdown + method and not the end. +- [SMACK-197](https://igniterealtime.atlassian.net/browse/SMACK-197) - + The source build was failing. +- [SMACK-198](https://igniterealtime.atlassian.net/browse/SMACK-198) - + File transfer streams were not being closed properly in some cases. +- [SMACK-199](https://igniterealtime.atlassian.net/browse/SMACK-199) - + MultiUserChat invitation listeners are no longer removed on + disconnects. +- [SMACK-201](https://igniterealtime.atlassian.net/browse/SMACK-201) - + Roster no longer exposes that it implements ConnectionListener. + +## 2.2.1 -- 2006-06-12 + +- [SMACK-141](https://igniterealtime.atlassian.net/browse/SMACK-141) - + Fixed SSL exception while creating new XMPPConnections. **(1 vote)** +- [SMACK-127](https://igniterealtime.atlassian.net/browse/SMACK-127) - + Fixed incorrect file transfer progress. +- [SMACK-130](https://igniterealtime.atlassian.net/browse/SMACK-130) - + Fixed VCard escaping problem that was crashing connections. +- [SMACK-134](https://igniterealtime.atlassian.net/browse/SMACK-134) - + VCards were not being saved when avatar was the only element. +- [SMACK-131](https://igniterealtime.atlassian.net/browse/SMACK-131) - + Illegal XML characters are now properly escaped in the presence + status. +- [SMACK-133](https://igniterealtime.atlassian.net/browse/SMACK-133) - + Illegal XML characters are now properly escaped in groups names. +- [SMACK-132](https://igniterealtime.atlassian.net/browse/SMACK-132) - + Fixed IBB problem triggered when buffersize was increased. +- [SMACK-135](https://igniterealtime.atlassian.net/browse/SMACK-135) - + Moved to new Base64 implementation to fix line break issue in old + implementation. + +## 2.2.0 -- 2006-03-09 + +- [SMACK-122](https://igniterealtime.atlassian.net/browse/SMACK-122) - + Added support for JEP-96: File Transfer. **(1 vote)** +- [SMACK-72](https://igniterealtime.atlassian.net/browse/SMACK-72) - + Added support for JEP-47: In-Band Bytestreams. **(2 votes)** +- [SMACK-122](https://igniterealtime.atlassian.net/browse/SMACK-122) - + Added support for JEP-65: SOCKS5 Bytestreams. **(1 vote)** +- [SMACK-112](https://igniterealtime.atlassian.net/browse/SMACK-112) - + Added support for JEP-38 Stream Compression. +- [SMACK-117](https://igniterealtime.atlassian.net/browse/SMACK-117) - + Added support for JEP-33: Extended Stanza Addressing. +- [SMACK-27](https://igniterealtime.atlassian.net/browse/SMACK-27) - + Certification validation is now pluggable. +- [SMACK-118](https://igniterealtime.atlassian.net/browse/SMACK-118) - + Added methods to dynamically remove providers. +- [SMACK-125](https://igniterealtime.atlassian.net/browse/SMACK-125) - + Added support for deaf occupant in MUC rooms. +- [SMACK-109](https://igniterealtime.atlassian.net/browse/SMACK-109) - + Optimized client performance. **(1 vote)** +- [SMACK-113](https://igniterealtime.atlassian.net/browse/SMACK-113) - + Added support for choosing if TLS should be used or not. +- [SMACK-114](https://igniterealtime.atlassian.net/browse/SMACK-114) - + Added support for choosing if SASL should be used or not. +- [SMACK-123](https://igniterealtime.atlassian.net/browse/SMACK-123) - + A thread is no longer used for packet writer listeners. +- [SMACK-110](https://igniterealtime.atlassian.net/browse/SMACK-110) - + Resource binding and session establishment are now requested only if + the server offered them. +- [SMACK-111](https://igniterealtime.atlassian.net/browse/SMACK-111) - + Fixed concurrency issue with date formatter. +- [SMACK-116](https://igniterealtime.atlassian.net/browse/SMACK-116) - + Fixed vCard issues. +- [SMACK-119](https://igniterealtime.atlassian.net/browse/SMACK-119) - + Fixed AccessControlException when using vCard from an applet. +- [SMACK-120](https://igniterealtime.atlassian.net/browse/SMACK-120) - + Listener thread was not being shutdown properly. +- [SMACK-124](https://igniterealtime.atlassian.net/browse/SMACK-124) - + Parsing resource binding packets was requiring smackx.jar file to be + in the classpath. +- [SMACK-97](https://igniterealtime.atlassian.net/browse/SMACK-97) - + Fixed functional test failures in PresencePriorityTest and + RosterTest. diff --git a/DEVELOPING.md b/DEVELOPING.md new file mode 100644 index 000000000..1716d6050 --- /dev/null +++ b/DEVELOPING.md @@ -0,0 +1,163 @@ +# Building Smack + +## Linux + +Building Smack is as simple as + +``` +git clone git@github.com:igniterealtime/Smack.git +cd Smack +gradle assemble +``` + +## Mac + +Smack requires a case-sensitive file system in order to build. Unfortunately, the macOS operating system is case-insensitive by default. +To get around this, you can create a case-sensitive disk image to work from. + +1. Launch Disk Utility (Applications > Utilities) +2. Click the +, or go to Edit > Add APFS Volume +3. Give it a name, e.g. "Smack" +4. Change the format to "APFS (Case-sensitive)" +5. Click Add + +It'll auto-mount into /Volumes, e.g. /Volumes/Smack + +```bash +cd /Volumes/Smack +git clone git@github.com:igniterealtime/Smack.git +cd Smack +gradle assemble +``` + +## Windows + +Smack requires a case-sensitive file system in order to build. Unfortunately, Windows NTFS is case-insensitive by default. +To get around this, you can set specific folders as case-sensitive (requires Windows 10 v1803 or higher). + +In an Administrator console: + +```batch +fsutil.exe file SetCaseSensitiveInfo C:\git\Smack enable +cd \git\Smack +git clone git@github.com:igniterealtime/Smack.git +cd Smack +gradle assemble +``` + +# IDE Config + +### Eclipse + +Import IDE settings from `./resources/eclipse/` to configure proper ordering of imports and correct formatting that should pass the CheckStyle rules. + +### IntelliJ IDEA + +Import Java Code Style settings from `./resources/intellij/smack_formatter.xml` to configure import optimisation and code formatting to pass the CheckStyle rules when building or submitting PRs. + +_We've noticed, at time of writing, that IntelliJ often requires a restart when applying new rules - no amount of OK/Apply will do the trick._ + +# Smack Providers + +Providers are responsible for parsing the XMPP XML stream into new Java objects. + +## Provider Design + +Assume you want to parse the following stanza extension element + +```xml + + Foo is greater then Bar + + +``` + +then the related provider would look like this + +```java +public MyExtension parse(XmlPullParser parser, int initialDepth) { + MyElement myElement = null; + MyInfo myInfo = null; + String attrFoo = parser.getAttributeValue("", "attrFoo"); + + // Main parsing loop, use a loop label instead of "boolean done" + outerloop: while(true) { + // Make sure to have already parse all attributes of the outermost element, + // i.e. 'attrFoo' of 'myExtension' in this example. Then advance the parser + XmlPullParser.Event event = parser.next(); + + // Use switch/case of int instead of a if/else-if cascade + switch (event) { + case START_ELEMENT: + // Determine the name of the element which start tag we are seeing + String name = parser.getName(); + // We can use switch/case of Strings since Java7, make use of its advantages + // and collect the values of the sub elements. If the sub elements are more + // complex then those of this example, consider creating extra *private static* + // parsing methods for them. + switch(name) { + case "myElement": + // You should only use XmlPullParser.nextText() when the element is + // required to have a text. + myElement = new MyElement(parser.nextText()); + break; + case "myInfo"; + // Use ParserUtils to parse Java primitives + boolenan alpha = ParserUtils.getBooleanAttribute(parser, "alpha"); + int delta = ParserUtils.getIntegerAttribute(parser, "delta"); + myInfo = new MyInfo(alpha, delta); + break; + } + break; + case END_ELEMENT: + // The abort condition with the break labeled loop statement + if (parser.getDepth() == initialDepth) { + break outerloop; + } + break; + default: + // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement. + break; + } + } + + // Create the actual class at the very end, design the classes as immutable as possible + return new MyExtension(attrFoo, myElement, myInfo); +} +``` + +## Common Pitfalls + +Use a `long` instead of `int` when the XML schema says `xs:unsignedInt`, because Java's `int` range is to small for this XML numeric data type. + +# Stanzas +## General Rules + +All classes which subclass `TopLevelStreamElement` and `ExtensionElement` must either + +1. be immutable (and ideally provide a Builder) +2. implement `TypedCloneable` + +and must be `Serializable`. +The reason that it must be either 1. or 2. is that it makes no sense to clone an inmutable instance. +The preferred option is 1. + +Note that there is legacy code in Smack which does not follow these rules. Patches are welcome. + +## ExtensionElement + +Extension elements are XML elements that are used in various parts and levels of stanzas. + +## The static `from(Stanza)` Method + +Every ExtensionElement class must have a static `from()` method that retrieves that extension for a given Stanza (if any). + +Sample Code + +```java +public static RSMSet from(Stanza) { + return packet.getExtension(ELEMENT, NAMESPACE); +} +``` + +Sometimes certain ExtensionElement's are only found in one stanza type, in that case, specify the parameter type. For example `public static CarbonExtension getFrom(Message)`. diff --git a/LICENSE b/LICENSE index f433b1a53..d64569567 100644 --- a/LICENSE +++ b/LICENSE @@ -175,3 +175,28 @@ of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..4689ef8af --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ +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/NOTICE b/NOTICE new file mode 100644 index 000000000..495ab3409 --- /dev/null +++ b/NOTICE @@ -0,0 +1,105 @@ + Smack + + An open-source XMPP library + maintained by Florian Schmaus + + https://igniterealtime.org/projects/smack + + +Authors: + +Abmar Barros +Aditya Borikar +Alexander Tovstonozhenko +Alex Wenckus +Andrew Wright +Andrey Prokopenko +Andrey Sokolov +Andrey Starodubtsev +Andri Khrisharyadi +Andriy Tsykholyas +Anno van Vliet +Bastien Rouiller +Benjamin JALON +Bill Lynch +Boris Grozev +Candy Lohse +Cem Yabansu +Chris Deering +Christoph Fiehe +Craig Hesling +Damian Minkov +Dan Caseley +Daniele Ricci +Daniel Henninger +Daniel Hintze +Daryl E. Herzmann +Dave Cridland +Dave Stanley +David Black +Derek DeMoro +Dmitry Deshevoy +Eng ChongMeng +Fernando Martinez Herrera +Fernando Ramirez +Florian Kimmann +Florian Schmaus +Francisco Vives +Frank Matheron +Gaston Dombiak +Georg Lukas +Gilles Cornu +Gligor Selimovic +Greg Thomas +Grigory Fedorov +Günther Niess +Guus der Kinderen +Henning Staib +Holger Bergunde +Hugues Bruant +Ingo Bauersachs +Ishan Khanna +Jae Jang +Jared DiCioccio +Jason Sipula +Jay Kline +Jeff Williams +Jesus Fuentes +John Haubrich +Jonathan Lennox +Júlio Cesar Bueno Cotta +Lars Noschinski +Luca Stucchi +Luke Granger-Brown +Marcel Heckel +Marilyn Daum +Matteo Campana +Matthew Wild +Matt Tucker +Michael Will +Miguel Hincapie +Mohsen Hariri +Oliver Mihatsch +Paul Schaub +Pete Matern +Piotr Nosek +Rajat Kumar Gupta +Robin Collier +Simon Abykov +Simon Schuster +Son Goku +Tairs Rzajevs +Thiago Camargo +Thibaut Le Guilly +Thomas Pocreau +Tim Jentz +Timothy Pitt +Tomáš Havlas +Tomas Nosek +Vadim Fite +Vaibhav Ranglani +V Lau +Vyacheslav Blinov +Wolf Posdorfer +Xiaowei YAN +Yash Thakkar diff --git a/README.md b/README.md index c93556197..edcc71740 100644 --- a/README.md +++ b/README.md @@ -1,75 +1,99 @@ Smack ===== -[![Build Status](https://travis-ci.org/igniterealtime/Smack.svg?branch=master)](https://travis-ci.org/igniterealtime/Smack) [![Project Stats](https://www.openhub.net/p/smackxmpp/widgets/project_thin_badge.gif)](https://www.openhub.net/p/smackxmpp) [![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/thing/3480125) +[![Build Status](https://github.com/igniterealtime/Smack/workflows/CI/badge.svg)](https://github.com/igniterealtime/Smack/actions?query=workflow%3A%22CI%22) [![Coverage Status](https://coveralls.io/repos/igniterealtime/Smack/badge.svg)](https://coveralls.io/r/igniterealtime/Smack) [![Project Stats](https://www.openhub.net/p/smack/widgets/project_thin_badge.gif)](https://www.openhub.net/p/smack) [![Link to XMPP chat smack@conference.igniterealtime.org](https://search.jabber.network/api/1.0/badge?address=smack@conference.igniterealtime.org)](https://inverse.chat/#converse/room?jid=smack@conference.igniterealtime.org) About ----- -[Smack] is an Open Source, cross-platform, easy to use Java XMPP -client library. +[Smack] is an open-source, highly modular, easy to use, XMPP client library written in Java for Java SE compatible JVMs and Android. -[Smack] is an Open Source [XMPP (Jabber)] client library for instant -messaging and presence. A pure Java library, it can be embedded into -your applications to create anything from a full XMPP client to simple -XMPP integrations such as sending notification messages and -presence-enabling devices. +Being a pure Java library, it can be embedded into your applications to create anything from a full XMPP instant messaging client to simple XMPP integrations such as sending notification messages and presence-enabling devices. +Smack and XMPP allow you to easily exchange data in various ways e.g., fire-and-forget, publish-subscribe, between human and non-human endpoints (M2M, IoT, …). -Confused? Have a look at the [Overview](documentation/overview.md). +More information is provided by the [Overview](documentation/overview.md). -[Smack] - an [Ignite Realtime] community project. +Getting started +--------------- + +Start with having a look at the **[Documentation]** and the **[Javadoc]**. + +Instructions on how to use Smack in your Java or Android project are provided in the [Smack Readme and Upgrade Guide](https://igniterealtime.org/projects/smack/readme). + +License +------- + +Most of Smack is governed by the Apache License 2.0 (SPDX License Identifier: Apache 2.0). This license requires that the contents of a NOTICE text file are shown "…within a display generated by the Derivative Works, if and wherever such third-party notices normally appear.". + +Smack comes which such a NOTICE file. Moreover, since `smack-core` is licensed under the Apache License 2.0, the conditions apply to every project using Smack. The content of Smack's NOTICE file can conveniently be retrieved using `Smack.getNoticeStream()`. + +Some subprojects of Smack are governed by other licenses. Please refer to the individual subprojects. + +Professional Services +--------------------- + +Smack is a collaborative effort of many people. +Some are paid, e.g., by their employer or a third party, for their contributions. +But many contribute in their spare time for free. +While we try to provide the best possible XMPP library for Android and Java SE-compatible execution environments by following state-of-the-art software engineering practices, the API may not always perfectly fit your requirements. +Hence welcome contributions and encourage discussion about how Smack can be further improved. +We also provide **paid services** ranging from **XMPP/Smack related consulting** to **designing and developing features** to accommodate your needs. +Please contact [Florian Schmaus](mailto:flo@geekplace.eu) for further information. Bug Reporting ------------- -Only a few users have access for for filling bugs in the tracker. New +Only a few users have access for filling bugs in the tracker. New users should: -1. [Create a forums account](https://community.igniterealtime.org/login!input.jspa?registerOnly=true) (only e-mail is a requirement, you can skip all the other fields). -2. Login to the forum account -3. Press New in your toolbar and choose Discussion -4. Choose the [Smack Developers Forum] of Smack and add the tag 'bug_report' to your new post +1. Read ["How to ask for help or report an issue"](https://github.com/igniterealtime/Smack/wiki/How-to-ask-for-help,-report-an-issue-and-possible-solve-the-problem-yourself) +2. [Create a discourse account](https://discourse.igniterealtime.org/signup) (you can also sign up with your Google account). +3. Login to the forum account +4. Press "New Topic" in your toolbar and choose the 'Smack Support' sub-category. Please search for your issues in the bug tracker before reporting. Contact ------- -The developers hang around in `#smack` (freenode, IRC) and `open_chat@conference.igniterealtime.org` (XMPP MUC room). +The developers hang around in [smack@conference.igniterealtime.org](xmpp:smack@conference.igniterealtime.org?join). You may use [this link](https://inverse.chat/badge.svg?room=smack@conference.igniterealtime.org) to join the room via [inverse.chat](https://inverse.chat). Remember that it may take some time (~hours) to get a response. -You can also reach us via the [Smack Users Forum] if you have questions or need support, or the [Smack Developers Forum] if you want to discuss Smack development. +You can also reach us via the [Smack Support Forum] if you have questions or need support, or the [Smack Developers Forum] if you want to discuss Smack development. + +Contributing +------------ + +If you want to start developing for Smack and eventually contribute code back, then please have a look at the [Guidelines for Smack Developers and Contributors](https://github.com/igniterealtime/Smack/wiki/Guidelines-for-Smack-Developers-and-Contributors). +The guidelines also contain development quickstart instructions. Resources --------- -- Bug Tracker: http://issues.igniterealtime.org/browse/SMACK -- Nightly Builds: http://www.igniterealtime.org/downloads/nightly_smack.jsp +- Current Readme: https://igniterealtime.org/projects/smack/readme +- Bug Tracker: https://issues.igniterealtime.org/browse/SMACK +- JaCoCo Coverage Reports: https://www.igniterealtime.org/builds/smack/dailybuilds/jacoco/html/ - Nightly Javadoc: http://www.igniterealtime.org/builds/smack/dailybuilds/javadoc/ - Nightly Documentation: http://www.igniterealtime.org/builds/smack/dailybuilds/documentation/ -- User Forum: http://community.igniterealtime.org/community/support/smack_users -- Dev Forum: http://community.igniterealtime.org/community/developers/smack +- User Forum: https://discourse.igniterealtime.org/c/smack/smack-support +- Dev Forum: https://discourse.igniterealtime.org/c/smack/smack-dev - Maven Releases: https://oss.sonatype.org/content/repositories/releases/org/igniterealtime/smack/ - Maven Snapshots: https://oss.sonatype.org/content/repositories/snapshots/org/igniterealtime/smack/ - -Donate ------- - -If you find Smack useful and feel like donating, then you can use one of the following systems: - -- [Donate via Flattr](https://flattr.com/thing/3480125) -- Donate via Bitcoin: 1D4k11bsPxRB6rS51fxDty8QYfRVUt5JMB +- Nightly Unique Maven Snapshots: https://www.igniterealtime.org/archiva/repository/maven/ Ignite Realtime =============== -[Ignite Realtime] is an Open Source community composed of end-users and developers around the world who -are interested in applying innovative, open-standards-based Real Time Collaboration to their businesses and organizations. +[Ignite Realtime] is an Open Source community composed of end-users and developers around the world who are interested in applying innovative, open-standards-based RealTime Collaboration to their businesses and organizations. We're aimed at disrupting proprietary, non-open standards-based systems and invite you to participate in what's already one of the biggest and most active Open Source communities. -[Smack]: http://www.igniterealtime.org/projects/smack/index.jsp -[Ignite Realtime]: http://www.igniterealtime.org -[XMPP (Jabber)]: http://xmpp.org/ -[Smack Developers Forum]: http://community.igniterealtime.org/community/developers/smack -[Smack Users Forum]: https://community.igniterealtime.org/community/support/smack_users +[Smack] - an [Ignite Realtime] community project. + +[Smack]: https://www.igniterealtime.org/projects/smack/index.jsp +[Ignite Realtime]: https://www.igniterealtime.org +[XMPP (Jabber)]: https://xmpp.org/ +[Smack Developers Forum]: https://discourse.igniterealtime.org/c/smack/smack-dev +[Smack Support Forum]: https://discourse.igniterealtime.org/c/smack/smack-support +[Documentation]: https://download.igniterealtime.org/smack/docs/latest/documentation/ +[Javadoc]: https://download.igniterealtime.org/smack/docs/latest/javadoc/ diff --git a/build-logic/build.gradle b/build-logic/build.gradle new file mode 100644 index 000000000..7b02d03a7 --- /dev/null +++ b/build-logic/build.gradle @@ -0,0 +1,14 @@ +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 new file mode 100644 index 000000000..d082ce7e0 --- /dev/null +++ b/build-logic/settings.gradle @@ -0,0 +1 @@ +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 new file mode 100644 index 000000000..c14cb3199 --- /dev/null +++ b/build-logic/src/main/groovy/org.igniterealtime.smack.android-boot-classpath-conventions.gradle @@ -0,0 +1,6 @@ +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 new file mode 100644 index 000000000..94beb432c --- /dev/null +++ b/build-logic/src/main/groovy/org.igniterealtime.smack.android-conventions.gradle @@ -0,0 +1,10 @@ +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 new file mode 100644 index 000000000..fa4c7011e --- /dev/null +++ b/build-logic/src/main/groovy/org.igniterealtime.smack.application-conventions.gradle @@ -0,0 +1,12 @@ +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 new file mode 100644 index 000000000..5bd92c7ee --- /dev/null +++ b/build-logic/src/main/groovy/org.igniterealtime.smack.global-conventions.gradle @@ -0,0 +1,37 @@ +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 new file mode 100644 index 000000000..598fdfa67 --- /dev/null +++ b/build-logic/src/main/groovy/org.igniterealtime.smack.java-common-conventions.gradle @@ -0,0 +1,367 @@ +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 new file mode 100644 index 000000000..61cb8f3c6 --- /dev/null +++ b/build-logic/src/main/groovy/org.igniterealtime.smack.javadoc-conventions.gradle @@ -0,0 +1,30 @@ +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 a229f0e04..13f9b12d7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,336 +1,103 @@ -import org.gradle.plugins.signing.Sign +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 'http://dl.bintray.com/content/aalmiray/kordamp' } - } - dependencies { - classpath 'org.kordamp:markdown-gradle-plugin:1.0.0' - classpath 'org.kordamp.gradle:clirr-gradle-plugin:0.2.0' - } -} -apply plugin: 'org.kordamp.gradle.markdown' - -apply from: 'version.gradle' - -allprojects { - apply plugin: 'java' - apply plugin: 'eclipse' - - ext { - gitCommit = getGitCommit() - javadocAllDir = new File(buildDir, 'javadoc') - documentationDir = new File(buildDir, 'documentation') - releasedocsDir = new File(buildDir, 'releasedocs') - rootConfigDir = new File(rootDir, 'config') - sonatypeCredentialsAvailable = project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword') - isReleaseVersion = !isSnapshot - signingRequired = isReleaseVersion - 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' - androidProjects = [ - ':smack-tcp', - ':smack-bosh', - ':smack-core', - ':smack-im', - ':smack-resolver-minidns', - ':smack-sasl-provided', - ':smack-extensions', - ':smack-experimental', - ].collect{ project(it) } - androidBootClasspath = getAndroidRuntimeJar() - androidJavadocOffline = getAndroidJavadocOffline() - } - group = 'org.igniterealtime.smack' - sourceCompatibility = 1.7 - targetCompatibility = sourceCompatibility - version = shortVersion - if (isSnapshot) { - version += '-SNAPSHOT' - } - - ext.sharedManifest = manifest { - attributes('Implementation-Version': version, - 'Implementation-GitRevision': ext.gitCommit, - // According to OSGi core 5.0 section 3.2.5 the qualifier (the fourth - // version element) must begin with a dot. So we replace only the - // first occurence of an dash with a dot. - // For example 4.0.0-rc1 becomes 4.0.0.rc1, but - // 4.0.0-SNAPSHOT-2014-05-01 becomes 4.0.0.SNAPSHOT-2014-05-01 - 'Bundle-Version': version.replaceFirst("-", "."), - '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 { - // Add OSS Sonatype Snapshot repository - maven { - url 'https://oss.sonatype.org/content/repositories/snapshots' - } - } - - compileJava { - // 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" - } - - if (JavaVersion.current().isJava8Compatible()) { - tasks.withType(Javadoc) { - options.addStringOption('Xdoclint:none', '-quiet') - } - } + id 'org.igniterealtime.smack.javadoc-conventions' } -gradle.taskGraph.whenReady { taskGraph -> - if (signingRequired - && taskGraph.allTasks.any { it instanceof Sign }) { - // Use Java 6's console to read from the console (no good for a CI environment) - Console console = System.console() - console.printf '\n\nWe have to sign some things in this build.\n\nPlease enter your signing details.\n\n' - def password = console.readPassword('GnuPG Private Key Password: ') - - allprojects { ext.'signing.password' = password } - - console.printf '\nThanks.\n\n' - } +ext { + javadocAllDir = new File(buildDir, 'javadoc') + integrationTestProjects = [ + ':smack-integration-test', + ':smack-omemo-signal-integration-test', + ].collect{ project(it) } + javadocAllProjects = subprojects - integrationTestProjects } +evaluationDependsOnChildren() task javadocAll(type: Javadoc) { - source subprojects.collect {project -> - project.sourceSets.main.allJava } + source javadocAllProjects.collect {project -> + project.sourceSets.main.allJava.findAll { + // Filter out symbolic links to avoid + // "warning: a package-info.java file has already been seen for package" + // javadoc warnings. + !java.nio.file.Files.isSymbolicLink(it.toPath()) + } + } destinationDir = javadocAllDir // Might need a classpath classpath = files(subprojects.collect {project -> project.sourceSets.main.compileClasspath}) - options.linkSource = true - options.use = true - options.links = ["http://docs.oracle.com/javase/$sourceCompatibility/docs/api/"] as String[] -} - -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()]) -} - -markdownToHtml { - sourceDir = new File(projectDir, "/documentation") - outputDir documentationDir - configuration = [tables: true, fencedCodeBlocks: true] -} - -task distributionZip(type: Zip, dependsOn: [javadocAll, prepareReleasedocs, markdownToHtml]) { - 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. - if (isSnapshot) return - 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}.""" - -evaluationDependsOnChildren() -subprojects { - apply plugin: 'maven' - apply plugin: 'osgi' - apply plugin: 'signing' - apply plugin: 'checkstyle' - apply plugin: 'org.kordamp.gradle.clirr' - - checkstyle { - configFile = new File(rootConfigDir, 'checkstyle.xml') - } - repositories { - mavenLocal() - mavenCentral() - } - task sourcesJar(type: Jar, dependsOn: classes) { - classifier = 'sources' - from sourceSets.main.allSource - } - task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir - } - task testJar(type: Jar) { - classifier = 'tests' - from sourceSets.test.output - } - artifacts { - archives sourcesJar - archives javadocJar - archives testJar + classpath += files(androidBootClasspath) + def staticJxmppVersion = getResolvedVersion('org.jxmpp:jxmpp-core') + def staticMiniDnsVersion = getResolvedVersion('org.minidns:minidns-core') + options { + linkSource = true + use = true + links = [ + "https://docs.oracle.com/en/java/javase/${javaMajor}/docs/api/", + "https://jxmpp.org/releases/${staticJxmppVersion}/javadoc/", + "https://minidns.org/releases/${staticMiniDnsVersion}/javadoc/", + ] as String[] + overview = "$projectDir/resources/javadoc-overview.html" } - uploadArchives { - repositories { - mavenDeployer { - if (signingRequired) { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - } - repository(url: project.sonatypeStagingUrl) { - if (sonatypeCredentialsAvailable) { - authentication(userName: sonatypeUsername, password: sonatypePassword) - } - } - snapshotRepository(url: project.sonatypeSnapshotUrl) { - if (sonatypeCredentialsAvailable) { - authentication(userName: sonatypeUsername, password: sonatypePassword) - } - } - - pom.project { - 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' - } - - distributionManagement { - snapshotRepository { - id 'smack.snapshot' - url project.sonatypeSnapshotUrl - } - } - - 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 { - 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' - } - } + // Finally copy the javadoc doc-files from the subprojects, which + // are potentially generated, to the javadocAll directory. Note + // that we use a copy *method* and not a *task* because the inputs + // of copy tasks is determined within the configuration phase. And + // since some of the inputs are generated, they will not get + // picked up if we used a copy method. See also + // https://stackoverflow.com/a/40518516/194894 + doLast { + copy { + javadocAllProjects.each { + from ("${it.projectDir}/src/javadoc") { + include '**/doc-files/*.*' } } + + into javadocAllDir } } - rootProject.distributionZip { - dependsOn build - from(buildDir) { - include "$libsDirName/*${version}.jar" - include "$libsDirName/*${version}-javadoc.jar" - include "$libsDirName/*${version}-sources.jar" +} + +task integrationTest { + description 'Verify correct functionality of Smack by running some integration tests.' + dependsOn project(':smack-integration-test').tasks.run +} + +task omemoSignalIntTest { + description 'Run integration tests of the smack-omemo module in combination with smack-omemo-signal.' + dependsOn 'smack-omemo-signal-integration-test:run' +} + +task sinttestAll { + description 'Run all of Smack\'s integration tests.' + dependsOn {[ + integrationTest, + omemoSignalIntTest, + ]} +} + +def getResolvedVersion(queriedProject = 'smack-core', component) { + def configuration = project(queriedProject) + .configurations + .compileClasspath + + def artifact = configuration + .resolvedConfiguration + .resolvedArtifacts + .findAll { + // 'it' is of type ResolvedArtifact, 'id' of + // Component*Artifact*Identifier, and we check the + // ComponentIdentifier. + it.id.getComponentIdentifier() instanceof org.gradle.api.artifacts.component.ModuleComponentIdentifier + } + .find { + it.id.getComponentIdentifier().toString().startsWith(component + ':') } - } - signing { - required { signingRequired } - sign configurations.archives - } - clirr { - semver false - } -} - -subprojects*.jar { - manifest { - from sharedManifest - } -} - -// 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) -} - -def getGitCommit() { - def dotGit = new File("$projectDir/.git") - if (!dotGit.isDirectory()) return 'non-git build' - - def cmd = 'git describe --always --tags --dirty=+' - def proc = cmd.execute() - def gitCommit = proc.text.trim() - assert !gitCommit.isEmpty() - gitCommit -} - -def getAndroidRuntimeJar() { - def androidHome = getAndroidHome() - 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 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 + artifact.getModuleVersion().getId().getVersion() } diff --git a/config/checkstyle.xml b/config/checkstyle.xml deleted file mode 100644 index ba33c807c..000000000 --- a/config/checkstyle.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml new file mode 100644 index 000000000..ce6b4200d --- /dev/null +++ b/config/checkstyle/checkstyle.xml @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/header.txt b/config/checkstyle/header.txt similarity index 100% rename from config/header.txt rename to config/checkstyle/header.txt diff --git a/config/checkstyle/smack-examples-gplv3-license-header.txt b/config/checkstyle/smack-examples-gplv3-license-header.txt new file mode 100644 index 000000000..3d9d392c4 --- /dev/null +++ b/config/checkstyle/smack-examples-gplv3-license-header.txt @@ -0,0 +1,20 @@ +/** + * + * 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/config/checkstyle/smack-omemo-signal-gplv3-license-header.txt b/config/checkstyle/smack-omemo-signal-gplv3-license-header.txt new file mode 100644 index 000000000..e2ecef5d1 --- /dev/null +++ b/config/checkstyle/smack-omemo-signal-gplv3-license-header.txt @@ -0,0 +1,20 @@ +/** + * + * Copyright 20XX John Doe + * + * This file is part of smack-omemo-signal. + * + * smack-omemo-signal 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/config/checkstyle/smack-omemo-signal-integration-test-gplv3-license-header.txt b/config/checkstyle/smack-omemo-signal-integration-test-gplv3-license-header.txt new file mode 100644 index 000000000..b77cfaf36 --- /dev/null +++ b/config/checkstyle/smack-omemo-signal-integration-test-gplv3-license-header.txt @@ -0,0 +1,20 @@ +/** + * + * Copyright 20XX John Doe + * + * This file is part of smack-omemo-signal-integration-test. + * + * smack-omemo-signal-integration-test 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/config/checkstyle/smack-repl-gplv3-license-header.txt b/config/checkstyle/smack-repl-gplv3-license-header.txt new file mode 100644 index 000000000..1799ffa34 --- /dev/null +++ b/config/checkstyle/smack-repl-gplv3-license-header.txt @@ -0,0 +1,20 @@ +/** + * + * Copyright 20XX John Doe + * + * This file is part of smack-repl. + * + * 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. + * + * 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/config/suppressions.xml b/config/checkstyle/suppressions.xml similarity index 76% rename from config/suppressions.xml rename to config/checkstyle/suppressions.xml index 4eaa0b979..2a22f2881 100644 --- a/config/suppressions.xml +++ b/config/checkstyle/suppressions.xml @@ -3,11 +3,11 @@ "-//Puppy Crawl//DTD Suppressions 1.1//EN" "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd"> - + + diff --git a/config/scalaStyle.xml b/config/scalaStyle.xml new file mode 100644 index 000000000..fd1914857 --- /dev/null +++ b/config/scalaStyle.xml @@ -0,0 +1,144 @@ + + Scalastyle standard configuration + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documentation/README.md b/documentation/README.md deleted file mode 120000 index dd0ea36c8..000000000 --- a/documentation/README.md +++ /dev/null @@ -1 +0,0 @@ -index.md \ No newline at end of file diff --git a/documentation/connections.md b/documentation/connections.md deleted file mode 100644 index c53ba16b7..000000000 --- a/documentation/connections.md +++ /dev/null @@ -1,60 +0,0 @@ -Smack: XMPPConnection Management -================================ - -[Back](index.md) - -Creating a Connection ---------------------- - -The `org.jivesoftware.smack.XMPPConnection` class manages your connection to -an XMPP server. The default implementation is the -`org.jivesoftware.smack.XMPPTCPConnection` class. Two constructors are mainly -used. The first, `XMPPTCPConnection(String)` takes the server name you'd like -to connect to as an argument. All default connection settings will be used: - - * A DNS SRV lookup will be performed to find the exact address and port (typically 5222) that the server resides at. - * The maximum security possible will be negotiated with the server, including TLS encryption, but the connection will fall back to lower security settings if necessary. - * The XMPP resource name "Smack" will be used for the connection. -Alternatively, you can use the `XMPPTCPConnection(ConnectionConfiguration)` -constructor to specify advanced connection settings. Some of these settings -include: - - * Manually specify the server address and port of the server rather than using a DNS SRV lookup. - * Enable connection compression. - * Customize security settings, such as flagging the connection to require TLS encryption in order to connect. - * Specify a custom connection resource name such as "Work" or "Home". Every connection by a user to a server must have a unique resource name. For the user "jsmith@example.com", the full address with resource might be "jsmith@example.com/Smack". With unique resource names, a user can be logged into the server from multiple locations at once, or using multiple devices. The presence priority value used with each resource will determine which particular connection receives messages to the bare address ("jsmith@example.com" in our example). - -Connect and Disconnect ----------------------- - -``` -// Create the configuration for this new connection -XMPPTCPConnectionConfiguration.Builder configBuilder = XMPPTCPConnectionConfiguration.builder(); -configBuilder.setUsernameAndPassword("username", "password"); -configBuilder.setResource("SomeResource"); -configBuilder.setServiceName("jabber.org"); - -AbstractXMPPConnection connection = new XMPPTCPConnection(configBuilder.build()); -// Connect to the server -connection.connect(); -// Log into the server -connection.login(); - -... - -// Disconnect from the server -connection.disconnect(); -``` - -By default Smack will try to reconnect the connection in case it was abruptly -disconnected. Use _ConnectionConfiguration#setReconnectionAllowed(boolean) to -turn on/off this feature. The reconnection manager will try to immediately -reconnect to the server and increase the delay between attempts as successive -reconnections keep failing._ - -In case you want to force a reconnection while the reconnetion manager is -waiting for the next reconnection, you can just use _AbstractXMPPConnection#connect()_ -and a new attempt will be made. If the manual attempt also failed then the -reconnection manager will still continue the reconnection job. - -Copyright (C) Jive Software 2002-2008 diff --git a/documentation/debugging.md b/documentation/debugging.md deleted file mode 100644 index 41f236172..000000000 --- a/documentation/debugging.md +++ /dev/null @@ -1,62 +0,0 @@ -Debugging with Smack -==================== - -[Back](index.md) - -Smack includes two built-in debugging consoles that will let you track -all XML traffic between the client and server. A lite debugger and an -enhanced debugger contained in `smack-debug.jar`, and a console debugger in `smack-core.jar`. - -Debugging mode can be enabled in two different ways: - - 1. Add the following line of code **before** creating new connections: - -`SmackConfiguration.DEBUG = true;` - - 2. Set the Java system property `smack.debugEnabled` to true. The system property can be set on the command line such as: - -`java -Dsmack.debugEnabled=true SomeApp ` - -If you wish to explicitly disable debug mode in your application, including -using the command-line parameter, add the following line to your application -before opening new connections: - -`SmackConfiguration.DEBUG = false;` - -Smack uses the following logic to decide the debugger console to use: - - 1. It will first try use the debugger class specified in the Java system property `smack.debuggerClass`. If you need to develop your own debugger, implement the `SmackDebugger` interface and then set the system property on the command line such as: - -`java -Dsmack.debuggerClass=my.company.com.MyDebugger SomeApp ` - - 2. If step 1 fails then Smack will try to use the enhanced debugger. The file `smackx-debug.jar` contains the enhanced debugger. Therefore you will need to place the jar file in the classpath. For situations where space is an issue you may want to only deploy `smack-core.jar` in which case the enhanced and lite debugger won't be available, but only the console debugger. - - 3. The last option if the previous two steps fail is to use the console debugger. The console debugger is a very good option for situations where you need to have low memory footprint. - -Enhanced Debugger ------------------ - -![Full Debug Window](images/enhanceddebugger.png) When debugging mode is -enabled, a debug window will appear containing tabs for each new created -connection. The window will contain the following information: - - * XMPPConnection tabs -- each tab shows debugging information related to the connection. - * Smack info tab -- shows information about Smack (e.g. Smack version, installed components, etc.). The connection tab will contain the following information: - * All Stanzas -- shows sent and received packets information parsed by Smack. - * Raw Sent Stanzas -- raw XML traffic generated by Smack and sent to the server. - * Raw Received Stanzas -- raw XML traffic sent by the server to the client. - * Ad-hoc message -- allows to send ad-hoc packets of any type. - * Information -- shows connection state and statistics. - -Lite Debugger -------------- - -![Lite Debug Window](images/debugwindow.gif) When debugging mode is enabled, a -debug window will appear when each new connection is created. The window will -contain the following information: - - * Client Traffic (red text) -- raw XML traffic generated by Smack and sent to the server. - * Server Traffic (blue text) -- raw XML traffic sent by the server to the client. - * Interpreted Stanzas (green text) -- shows XML packets from the server as parsed by Smack. Right click on any of the panes to bring up a menu with the choices to copy of the contents to the system clipboard or to clear the contents of the pane. - -Copyright (C) Jive Software 2002-2008 diff --git a/documentation/developer/provider.md b/documentation/developer/provider.md deleted file mode 100644 index cd5255af5..000000000 --- a/documentation/developer/provider.md +++ /dev/null @@ -1,72 +0,0 @@ -Smack Providers -=============== - -Providers are responsible for parsing the XMPP XML stream into new Java objects. - -Provider Design ---------------- - -Assume you want to parse the following stanza extension element - -```xml - - Foo is greater then Bar - - -``` - -then the related provider would look like this - -```java -public MyExtension parse(XmlPullParser parser, int initialDepth) { - MyElement myElement = null; - MyInfo myInfo = null; - String attrFoo = parser.getAttributeValue("", "attrFoo"); - - // Main parsing loop, use a loop label instead of "boolean done" - outerloop: while(true) { - // Make sure to have already parse all attributes of the outermost element, - // i.e. 'attrFoo' of 'myExtension' in this example. Then advance the parser - int event = parser.next(); - - // Use switch/case of int instead of a if/else-if cascade - switch (event) { - case XmlPullParser.START_TAG: - // Determine the name of the element which start tag we are seeing - String name = parser.getName(); - // We can use switch/case of Strings since Java7, make use of its advantages - // and collect the values of the sub elements. If the sub elements are more - // complex then those of this example, consider creating extra *private static* - // parsing methods for them. - switch(name) { - case "myElement": - // You should only use XmlPullParser.nextText() when the element is - // required to have a text. - myElement = new MyElement(parser.nextText()); - break; - case "myInfo"; - // Use ParserUtils to parse Java primitives - boolenan alpha = ParserUtils.getBooleanAttribute(parser, "alpha"); - int delta = ParserUtils.getIntegerAttribute(parser, "delta"); - myInfo = new MyInfo(alpha, delta); - break; - } - break; - case XmlPullParser.END_TAG: - // The abort condition with the break labeled loop statement - if (parser.getDepth() == initialDepth) { - break outerloop; - } - break; - } - } - - // Create the actual class at the very end, design the classes as immutable as possible - return new MyExtension(attrFoo, myElement, myInfo); -} -``` - -Common Pitfalls ---------------- - -Use a `long` instead of `int` when the XML schema says `xs:unsignedInt`, because Java's `int` range is to small for this XML numeric data type. diff --git a/documentation/developer/stanzas.md b/documentation/developer/stanzas.md deleted file mode 100644 index 15883256f..000000000 --- a/documentation/developer/stanzas.md +++ /dev/null @@ -1,17 +0,0 @@ -PacketExtension -=============== - -The static `from(Stanza)` Method --------------------------------- - -Every PacketExtension class must have a static `from()` method that retrieves that extension for a given Stanza (if any). - -Sample Code - -```java -public static RSMSet from(Stanza) { - return packet.getExtension(ELEMENT, NAMESPACE); -} -``` - -Sometimes certain PacketExtension's are only found in one stanza type, in that case, specify the parameter type. For example `public static CarbonExtension getFrom(Message)`. diff --git a/documentation/extensions/caps.md b/documentation/extensions/caps.md deleted file mode 100644 index 1ab734dea..000000000 --- a/documentation/extensions/caps.md +++ /dev/null @@ -1,47 +0,0 @@ -Entity Capabilities -=================== - -This section details the usage of Smacks implementation of Entity -Capabilities. - -**XEP related:** [XEP-0115: Entity Capabilities](http://xmpp.org/extensions/xep-0115.html) - -**Description** - -Entity Capabilities is an XMPP Protocol extension, which, in order to minimize -network impact, caches the capabilities of XMPP entities. Those capabilities -are determined with the help of the Service Discovery Protocol -([XEP-0030](http://xmpp.org/extensions/xep-0030.html)). - -**Usage** - -Entity Capabilities work silenty in background when enabled. If the remote -XMPP entity does not support XEP-0115 but XEP-0030 then XEP-0030 mechanisms -are transparently used. You can enable or disable Entity Capabilities by using -_**EntityCapsManager**_. - -The cache used by Smack for Entity Capabilities is non-persistent as default. -That is, the cache only uses memory. But it is also possible to set a -persistent Entity Capabilities cache, which is recommended. - -**Examples** - -Enable Entity Capabilities - -``` -// Get an instance of entity caps manager for the specified connection -EntityCapsManager mgr = EntityCapsManager.getInstanceFor(connection); -// Enable entity capabilities -mgr.enableEntityCaps(); -``` - -Configure a persistent cache for Entity Capabilities - -``` -// Get an instance of entity caps manager for the specified connection -EntityCapsManager mgr = EntityCapsManager.getInstanceFor(connection); -// Create an cache, see smackx.entitycaps.cache for pre-defined cache implementations -EntityCapsPersistentCache cache = new SimpleDirectoryPersistentCache(new File("/foo/cachedir")); -// Set the cache -mgr.setPersistentCache(cache); -``` diff --git a/documentation/extensions/dataforms.md b/documentation/extensions/dataforms.md deleted file mode 100644 index 0b49e1850..000000000 --- a/documentation/extensions/dataforms.md +++ /dev/null @@ -1,127 +0,0 @@ -Data Forms -========== - -Allows to exchange structured data between users and applications for common -tasks such as registration and searching using Forms. - - * Create a Form to fill out - * Answer a Form - -**XEP related:** [XEP-4](http://www.xmpp.org/extensions/xep-0004.html) - -Create a Form to fill out -------------------------- - -**Description** - -An XMPP entity may need to gather data from another XMPP entity. Therefore, -the data-gathering entity will need to create a new Form, specify the fields -that will conform the Form and finally send the Form to the data-providing -entity. - -**Usage** - -In order to create a Form to fill out use the _**Form**_'s constructor passing -the constant **DataForm.type.form** as the parameter. The next step is to create -the form fields and add them to the form. In order to create and customize a -_**FormField**_ use the _**FormField**_'s constructor specifying the variable -name of the field as the parameter. Then use **setType(String type)** to set -the field's type (e.g. FormField.type.hidden, FormField.type.text_single). -Once we have the _**Form**_ instance and the _**FormFields**_ the last step is -to send **addField(FormField field)** for each field that we want to add to -the form. - -Once the form to fill out is finished we will want to send it in a message. -Send **getDataFormToSend()** to the form and add the answer as an extension to -the message to send. - -**Examples** - -In this example we can see how to create and send a form to fill out: - -``` -// Create a new form to gather data -Form formToSend = new Form(DataForm.type.form); -formToSend.setInstructions(Fill out this form to report your case.\nThe case will be created automatically."); -formToSend.setTitle("Case configurations"); -// Add a hidden variable to the form -FormField field = new FormField("hidden_var"); -field.setType(FormField.type.hidden); -field.addValue("Some value for the hidden variable"); -formToSend.addField(field); -// Add a fixed variable to the form -field = new FormField(); -field.addValue("Section 1: Case description"); -formToSend.addField(field); -// Add a text-single variable to the form -field = new FormField("name"); -field.setLabel("Enter a name for the case"); -field.setType(FormField.type.text_single); -formToSend.addField(field); -// Add a text-multi variable to the form -field = new FormField("description"); -field.setLabel("Enter a description"); -field.setType(FormField.type.text_multi); -formToSend.addField(field); -// Create a chat with "user2@host.com" -Chat chat = conn1.createChat("user2@host.com" ); -Message msg = chat.createMessage(); -msg.setBody("To enter a case please fill out this form and send it back"); -// Add the form to fill out to the message to send -msg.addExtension(formToSend.getDataFormToSend()); -// Send the message with the form to fill out -chat.sendMessage(msg); -``` - -Answer a Form -------------- - -**Description** - -Under many situations an XMPP entity could receive a form to fill out. For -example, some hosts may require to fill out a form in order to register new -users. Smack lets the data-providing entity to complete the form in an easy -way and send it back to the data-gathering entity. - -**Usage** - -The form to fill out contains useful information that could be used for -rendering the form. But it cannot be used to actually complete it. Instead -it's necessary to create a new form based on the original form whose purpose -is to hold all the answers. - -In order to create a new _**Form**_ to complete based on the original -_**Form**_ just send **createAnswerForm()** to the original _**Form**_. Once -you have a valid form that could be actually completed all you have to do is -send **setAnswer(String variable, String value)** to the form where variable -is the variable of the _**FormField**_ that you want to answer and value is -the String representation of the answer. If the answer consist of several -values you could then use **setAnswer(String variable, List values)** where -values is a List of Strings. - -Once the form has been completed we will want to send it back in a message. -Send **getDataFormToSend()** to the form and add the answer as an extension to -the message to send back. - -**Examples** - -In this example we can see how to retrieve a form to fill out, complete the -form and send it back: - -``` -// Get the message with the form to fill out -Message msg2 = chat2.nextMessage(); -// Retrieve the form to fill out from the message -Form formToRespond = Form.getFormFrom(msg2); -// Obtain the form to send with the replies -Form completedForm = formToRespond.createAnswerForm(); -// Add the answers to the form -completedForm.setAnswer("name", "Credit card number invalid"); -completedForm.setAnswer("description", "The ATM says that my credit card number is invalid"); -msg2 = chat2.createMessage(); -msg2.setBody("To enter a case please fill out this form and send it back"): -// Add the completed form to the message to send back -msg2.addExtension(completedForm.getDataFormToSend()); -// Send the message with the completed form -chat2.sendMessage(msg2); -``` diff --git a/documentation/extensions/disco.md b/documentation/extensions/disco.md deleted file mode 100644 index 7a3c40a66..000000000 --- a/documentation/extensions/disco.md +++ /dev/null @@ -1,224 +0,0 @@ -Service Discovery -================= - -The service discovery extension allows to discover items and information about -XMPP entities. Follow these links to learn how to use this extension. - - * Manage XMPP entity features - * Provide node information - * Discover items associated with an XMPP entity - * Discover information about an XMPP entity - * Publish publicly available items - -**XEP related:** [XEP-30](http://www.xmpp.org/extensions/xep-0030.html) - -Manage XMPP entity features ---------------------------- - -**Description** - -Any XMPP entity may receive a discovery request and must answer with its -associated items or information. Therefore, your Smack client may receive a -discovery request that must respond to (i.e., if your client supports XHTML- -IM). This extension automatically responds to a discovery request with the -information that you previously configured. - -**Usage** - -In order to configure the supported features by your client you should first -obtain the ServiceDiscoveryManager associated with your XMPPConnection. To get -your ServiceDiscoveryManager send **getInstanceFor(connection)** to the class -_**ServiceDiscoveryManager**_ where connection is your XMPPConnection. - -Once you have your ServiceDiscoveryManager you will be able to manage the -supported features. To register a new feature send **addFeature(feature)** to -your _**ServiceDiscoveryManager**_ where feature is a String that represents -the supported feature. To remove a supported feature send -**removeFeature(feature)** to your _**ServiceDiscoveryManager**_ where feature -is a String that represents the feature to remove. - -**Examples** - -In this example we can see how to add and remove supported features: - -``` -// Obtain the ServiceDiscoveryManager associated with my XMPP connection -ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); -// Register that a new feature is supported by this XMPP entity -discoManager.addFeature(namespace1); -// Remove the specified feature from the supported features -discoManager.removeFeature(namespace2); -``` - -Provide node information ------------------------- - -**Description** - -Your XMPP entity may receive a discovery request for items non-addressable as -a JID such as the MUC rooms where you are joined. In order to answer the -correct information it is necessary to configure the information providers -associated to the items/nodes within the Smack client. - -**Usage** - -In order to configure the associated nodes within the Smack client you will -need to create a NodeInformationProvider and register it with the -_**ServiceDiscoveryManager**_. To get your ServiceDiscoveryManager send -**getInstanceFor(connection)** to the class _**ServiceDiscoveryManager**_ -where connection is your XMPPConnection. - -Once you have your ServiceDiscoveryManager you will be able to register -information providers for the XMPP entity's nodes. To register a new node -information provider send **setNodeInformationProvider(String node, -NodeInformationProvider listener)** to your _**ServiceDiscoveryManager**_ -where node is the item non-addressable as a JID and listener is the -_**NodeInformationProvider**_ to register. To unregister a -_**NodeInformationProvider**_ send **removeNodeInformationProvider(String -node)** to your _**ServiceDiscoveryManager**_ where node is the item non- -addressable as a JID whose information provider we want to unregister. - -**Examples** - -In this example we can see how to register a NodeInformationProvider with a -ServiceDiscoveryManager that will provide information concerning a node named -"http://jabber.org/protocol/muc#rooms": - -``` -// Set the NodeInformationProvider that will provide information about the -// joined rooms whenever a disco request is received -ServiceDiscoveryManager.getInstanceFor(connection).setNodeInformationProvider( - "http://jabber.org/protocol/muc#rooms", - new NodeInformationProvider() { - public List getNodeItems() { - ArrayList answer = new ArrayList(); - Iterator rooms = MultiUserChat.getJoinedRooms(connection); - while (rooms.hasNext()) { - answer.add(new DiscoverItems.Item((String)rooms.next())); - } - return answer; - } -}); -``` - -Discover items associated with an XMPP entity ---------------------------------------------- - -**Description** - -In order to obtain information about a specific item you have to first -discover the items available in an XMPP entity. - -**Usage** - -Once you have your ServiceDiscoveryManager you will be able to discover items -associated with an XMPP entity. To discover the items of a given XMPP entity -send **discoverItems(entityID)** to your _**ServiceDiscoveryManager**_ where -entityID is the ID of the entity. The message **discoverItems(entityID)** will -answer an instance of _**DiscoverItems**_ that contains the discovered items. - -**Examples** - -In this example we can see how to discover the items associated with an online -catalog service: - -``` -// Obtain the ServiceDiscoveryManager associated with my XMPPConnection -ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); -// Get the items of a given XMPP entity -// This example gets the items associated with online catalog service -DiscoverItems discoItems = discoManager.discoverItems("plays.shakespeare.lit"); -// Get the discovered items of the queried XMPP entity -Iterator it = discoItems.getItems(); -// Display the items of the remote XMPP entity -while (it.hasNext()) { - DiscoverItems.Item item = (DiscoverItems.Item) it.next(); - System.out.println(item.getEntityID()); - System.out.println(item.getNode()); - System.out.println(item.getName()); -} -``` - -Discover information about an XMPP entity ------------------------------------------ - -**Description** - -Once you have discovered the entity ID and name of an item, you may want to -find out more about the item. The information desired generally is of two -kinds: 1) The item's identity and 2) The features offered by the item. - -This information helps you determine what actions are possible with regard to -this item (registration, search, join, etc.) as well as specific feature types -of interest, if any (e.g., for the purpose of feature negotiation). - -**Usage** - -Once you have your ServiceDiscoveryManager you will be able to discover -information associated with an XMPP entity. To discover the information of a -given XMPP entity send **discoverInfo(entityID)** to your -_**ServiceDiscoveryManager**_ where entityID is the ID of the entity. The -message **discoverInfo(entityID)** will answer an instance of -_**DiscoverInfo**_ that contains the discovered information. - -**Examples** - -In this example we can see how to discover the information of a conference -room: - -``` -// Obtain the ServiceDiscoveryManager associated with my XMPPConnection -ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); -// Get the information of a given XMPP entity -// This example gets the information of a conference room -DiscoverInfo discoInfo = discoManager.discoverInfo("balconyscene@plays.shakespeare.lit"); -// Get the discovered identities of the remote XMPP entity -Iterator it = discoInfo.getIdentities(); -// Display the identities of the remote XMPP entity -while (it.hasNext()) { - DiscoverInfo.Identity identity = (DiscoverInfo.Identity) it.next(); - System.out.println(identity.getName()); - System.out.println(identity.getType()); - System.out.println(identity.getCategory()); -} -// Check if room is password protected -discoInfo.containsFeature("muc_passwordprotected"); -``` - -Publish publicly available items --------------------------------- - -**Description** - -Publish your entity items to some kind of persistent storage. This enables -other entities to query that entity using the disco#items namespace and -receive a result even when the entity being queried is not online (or -available). - -**Usage** - -Once you have your ServiceDiscoveryManager you will be able to publish items -to some kind of persistent storage. To publish the items of a given XMPP -entity you have to first create an instance of _**DiscoverItems**_ and -configure it with the items to publish. Then you will have to send -**publishItems(String entityID, DiscoverItems discoverItems)** to your -_**ServiceDiscoveryManager**_ where entityID is the address of the XMPP entity -that will persist the items and discoverItems contains the items to publish. - -**Examples** - -In this example we can see how to publish new items: - -``` -// Obtain the ServiceDiscoveryManager associated with my XMPPConnection -ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); -// Create a DiscoverItems with the items to publish -DiscoverItems itemsToPublish = new DiscoverItems(); -DiscoverItems.Item itemToPublish = new DiscoverItems.Item("pubsub.shakespeare.lit"); -itemToPublish.setName("Avatar"); -itemToPublish.setNode("romeo/avatar"); -itemToPublish.setAction(DiscoverItems.Item.UPDATE_ACTION); -itemsToPublish.addItem(itemToPublish); -// Publish the new items by sending them to the server -discoManager.publishItems("host", itemsToPublish); -``` diff --git a/documentation/extensions/filetransfer.md b/documentation/extensions/filetransfer.md deleted file mode 100644 index 172be71bb..000000000 --- a/documentation/extensions/filetransfer.md +++ /dev/null @@ -1,147 +0,0 @@ -File Transfer -============= - -The file transfer extension allows the user to transmit and receive files. - - * Send a file to another user - * Recieving a file from another user - * Monitoring the progress of a file transfer - -**XEP related:** [XEP-95](http://www.xmpp.org/extensions/xep-0095.html) [XEP-96](http://www.xmpp.org/extensions/xep-0096.html) [XEP-65](http://www.xmpp.org/extensions/xep-0065.html) [XEP-47](http://www.xmpp.org/extensions/xep-0047.html) - -Send a file to another user ---------------------------- - -**Description** - -A user may wish to send a file to another user. The other user has the option -of acception, rejecting, or ignoring the users request. Smack provides a -simple interface in order to enable the user to easily send a file. **Usage** - -In order to send a file you must first construct an instance of the -**_FileTransferManager_** class. In order to instantiate the manager -you should call _FileTransferManager.getInstanceFor(connection)_ - -Once you have your **_FileTransferManager_** you will need to create an -outgoing file transfer to send a file. The method to use on the -**_FileTransferManager_** is the **createOutgoingFileTransfer(userID)** -method. The userID you provide to this method is the fully-qualified jabber ID -of the user you wish to send the file to. A fully-qualified jabber ID consists -of a node, a domain, and a resource, the user must be connected to the -resource in order to be able to recieve the file transfer. - -Now that you have your **_OutgoingFileTransfer_** instance you will want to -send the file. The method to send a file is **sendFile(file, description)**. -The file you provide to this method should be a readable file on the local -file system, and the description is a short description of the file to help -the user decide whether or not they would like to recieve the file. - -For information on monitoring the progress of a file transfer see the -monitoring progress section of this document. - -Other means to send a file are also provided as part of the -**_OutgoingFileTransfer_**. Please consult the Javadoc for more information. -**Examples** - -In this example we can see how to send a file: - -``` -// Create the file transfer manager -FileTransferManager manager = FileTransferManager.getInstanceFor(connection); -// Create the outgoing file transfer -OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer("romeo@montague.net"); -// Send the file -transfer.sendFile(new File("shakespeare_complete_works.txt"), "You won't believe this!"); -``` - -Recieving a file from another user ----------------------------------- - -**Description** - -The user may wish to recieve files from another user. The process of recieving -a file is event driven, new file transfer requests are recieved from other -users via a listener registered with the file transfer manager. - -**Usage** - -In order to recieve a file you must first construct an instance of the -**_FileTransferManager_** class. This class has one constructor with one -parameter which is your XMPPConnection. In order to instantiate the manager -you should call _FileTransferManager.getInstanceFor(connection)_ - -Once you have your **_FileTransferManager_** you will need to register a -listener with it. The FileTransferListner interface has one method, -**fileTransferRequest(request)**. When a request is recieved through this -method, you can either accept or reject the request. To help you make your -decision there are several methods in the **_FileTransferRequest_** class that -return information about the transfer request. - -To accept the file transfer, call the **accept()**, this method will create an -**_IncomingFileTransfer_**. After you have the file transfer you may start to -transfer the file by calling the **recieveFile(file)** method. The file -provided to this method will be where the data from thefile transfer is saved. - -Finally, to reject the file transfer the only method you need to call is -**reject()** on the **_IncomingFileTransfer_**. - -For information on monitoring the progress of a file transfer see the -monitoring progress section of this document. - -Other means to recieve a file are also provided as part of the -**_IncomingFileTransfer_**. Please consult the Javadoc for more information. -**Examples** - -In this example we can see how to approve or reject a file transfer request: - -``` -// Create the file transfer manager -final FileTransferManager manager = FileTransferManager.getInstanceFor(connection); -// Create the listener -manager.addFileTransferListener(new FileTransferListener() { - public void fileTransferRequest(FileTransferRequest request) { - // Check to see if the request should be accepted - if(shouldAccept(request)) { - // Accept it - IncomingFileTransfer transfer = request.accept(); - transfer.recieveFile(new File("shakespeare_complete_works.txt")); - } else { - // Reject it - request.reject(); - } -} -}); -``` - -Monitoring the progress of a file transfer ------------------------------------------- - -**Description** - -While a file transfer is in progress you may wish to monitor the progress of a -file transfer. - -**Usage** - -Both the **_IncomingFileTransfer_** and the **_OutgoingFileTransfer_** extend -the **_FileTransfer_** class which provides several methods to monitor how a -file transfer is progressing: - - * **getStatus()** - The file transfer can be in several states, negotiating, rejected, canceled, in progress, error, and complete. This method will return which state the file transfer is currently in. - * **getProgress()** - if the status of the file transfer is in progress this method will return a number between 0 and 1, 0 being the transfer has not yet started and 1 being the transfer is complete. It may also return a -1 if the transfer is not in progress. - * **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 occured. **Examples** - -In this example we can see how to monitor a file transfer: - -``` -while(!transfer.isDone()) { - if(transfer.getStatus().equals(Status.ERROR)) { - System.out.println("ERROR!!! " + transfer.getError()); - } else { - System.out.println(transfer.getStatus()); - System.out.println(transfer.getProgress()); - } - sleep(1000); -} -``` diff --git a/documentation/extensions/hoxt.md b/documentation/extensions/hoxt.md deleted file mode 100644 index 55bb17f3a..000000000 --- a/documentation/extensions/hoxt.md +++ /dev/null @@ -1,108 +0,0 @@ -HTTP over XMPP transport -======================== - -Allows to transport HTTP communication over XMPP peer-to-peer networks. - - * Discover HOXT support - * IQ exchange - - -Discover HOXT support ---------------------- - -**Description** - -Before using this extension you must ensure that your counterpart supports it -also. - -**Usage** - -Once you have your _**ServiceDiscoveryManager**_ you will be able to discover -information associated with an XMPP entity. To discover the information of a -given XMPP entity send **discoverInfo(entityID)** to your -_**ServiceDiscoveryManager**_ where entityID is the ID of the entity. The -message **discoverInfo(entityID)** will answer an instance of -_**DiscoverInfo**_ that contains the discovered information. - -**Examples** - -In this example we can see how to check if the counterpart supports HOXT: - -``` -// Obtain the ServiceDiscoveryManager associated with my XMPPConnection -ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); -// Get the information of a given XMPP entity -DiscoverInfo discoInfo = discoManager.discoverInfo("juliet@capulet.com"); -// Check if room is HOXT is supported -discoInfo.containsFeature("urn:xmpp:http"); -``` -IQ exchange ------------ - -**Description** - -You can use IQ's to perform HTTP requests and responses. This is applicable to -relatively short requests and responses (due to limitation of XMPP message -size). - -**Usage** - -First you need to register a _**PacketListener**_ to be able to handle -intended IQs. - -For the HTTP client you: - - * You create and send _**HttpOverXmppReq**_ request. - * Then you handle the _**HttpOverXmppResp**_ response in your _**PacketListener**_. -For the HTTP server you: - - * You handle the _**HttpOverXmppReq**_ requests in your _**PacketListener**_. - * And create and send _**HttpOverXmppResp**_ responses. - -**Examples** - -In this example we are HTTP client, so we send request (POST) and handle the -response: - -``` -// create a request body -String urlEncodedMessage = "I_love_you"; - -// create request -HttpOverXmppReq req = new HttpOverXmppReq(HttpMethod.POST, "/mailbox"); -req.setVersion("1.1"); - -// prepare headers -Set
set = new HashSet
(); -set.add(new Header("Host", "juliet.capulet.com")); -set.add(new Header("Content-Type", "application/x-www-form- urlencoded")); -set.add(new Header("Content-Length", Integer.toString(urlEncodedMessage.length()))); -req.setHeaders(new HeadersExtension(set)); - -// provide body or request (not mandatory, - empty body is used for GET) -AbstractHttpOverXmpp.Text child = new AbstractHttpOverXmpp.Text(urlEncodedMessage); -AbstractHttpOverXmpp.Data data = new AbstractHttpOverXmpp.Data(child); -req.setData(data); - -// add to -req.setTo("juliet@capulet.com/balcony"); - -// send it -connection.sendIqWithResponseCallback(req, new PacketListener() { - public void processPacket(Stanza packet) { - HttpOverXmppResp resp = (HttpOverXmppResp) iq; - // check HTTP response code - if (resp.getStatusCode() == 200) { - // get content of the response - NamedElement child = resp.getData().getChild(); - // check which type of content of the response arrived - if (child instanceof AbstractHttpOverXmpp.Xml) { - // print the message and anxiously read if from console ;) - System.out.println(((AbstractHttpOverXmpp.Xml) child).getText()); - } else { - // process other AbstractHttpOverXmpp.DataChild subtypes - } - } - } -}); -``` diff --git a/documentation/extensions/index.md b/documentation/extensions/index.md deleted file mode 100644 index 49c4cefc9..000000000 --- a/documentation/extensions/index.md +++ /dev/null @@ -1,86 +0,0 @@ -Smack Extensions User Manual -============================ - -The XMPP protocol includes a base protocol and many optional extensions -typically documented as "XEP's". Smack provides the org.jivesoftware.smack -package for the core XMPP protocol, and the org.jivesoftware.smackx package -for many of the protocol extensions. - -This manual provides details about each of the "smackx" extensions, including -what it is, how to use it, and some simple example code. - -Currently supported XEPs of smack-tcp -------------------------------------- - -| Name | XEP | Description | -|---------------------------------------------|----------------------------------------------------------|----------------------------------------------------------------------------------------------------------| -| [Stream Management](streammanagement.md) | [XEP-0198](http://xmpp.org/extensions/xep-0198.html) | Allows active management of an XML Stream between two XMPP entities (stanza acknowledgement, stream resumption). | - - -Smack Extensions and currently supported XEPs by Smack (smack-extensions) -------------------------------------------------------------------------- - -| Name | XEP | Description | -|---------------------------------------------|----------------------------------------------------------|----------------------------------------------------------------------------------------------------------| -| [Data Forms](dataforms.md) | [XEP-0004](http://xmpp.org/extensions/xep-0004.html) | Allows to gather data using Forms. | -| Last Activity | [XEP-0012](http://xmpp.org/extensions/xep-0012.html) | Communicating information about the last activity associated with an XMPP entity. | -| Flexible Offline Message Retrieval | [XEP-0013](http://xmpp.org/extensions/xep-0013.html) | Extension for flexible, POP3-like handling of offline messages. | -| [Privacy Lists](privacy.md) | [XEP-0016](http://xmpp.org/extensions/xep-0016.html) | Enabling or disabling communication with other entities. | -| [Service Discovery](disco.md) | [XEP-0030](http://xmpp.org/extensions/xep-0030.html) | Allows to discover services in XMPP entities. | -| Extended Stanza Addressing | [XEP-0033](http://xmpp.org/extensions/xep-0033.html) | Allows to include headers in stanzas in order to specifiy multiple recipients or sub-addresses. | -| [Multi User Chat](muc.md) | [XEP-0045](http://xmpp.org/extensions/xep-0045.html) | Allows configuration of, participation in, and administration of individual text-based conference rooms. | -| In-Band Bytestreams | [XEP-0047](http://xmpp.org/extensions/xep-0047.html) | Enables any two entities to establish a one-to-one bytestream between themselves using plain XMPP. | -| Bookmarks | [XEP-0048](http://xmpp.org/extensions/xep-0048.html) | Bookmarks, for e.g. MUC and web pages. | -| [Private Data](privatedata.md) | [XEP-0049](http://xmpp.org/extensions/xep-0049.html) | Manages private data. | -| Ad-Hoc Commands | [XEP-0050](http://xmpp.org/extensions/xep-0050.html) | Advertising and executing application-specific commands. | -| vcard-temp | [XEP-0054](http://xmpp.org/extensions/xep-0054.html) | The vCard-XML format currently in use. | -| Jabber Search | [XEP-0055](http://xmpp.org/extensions/xep-0055.html) | Search information repositories on the XMPP network. | -| Result Set Management | [XEP-0059](http://xmpp.org/extensions/xep-0059.html) | Page through and otherwise manage the receipt of large result sets | -| [PubSub](pubsub.md) | [XEP-0060](http://xmpp.org/extensions/xep-0060.html) | Generic publish and subscribe functionality. | -| SOCKS5 Bytestrams | [XEP-0065](http://xmpp.org/extensions/xep-0065.html) | Out-of-band bytestream between any two XMPP entities. | -| [XHTML-IM](xhtml.md) | [XEP-0071](http://xmpp.org/extensions/xep-0071.html) | Allows send and receiving formatted messages using XHTML. | -| In-Band Registration | [XEP-0077](http://xmpp.org/extensions/xep-0077.html) | In-band registration with XMPP services. | -| Advanced Message Processing | [XEP-0079](http://xmpp.org/extensions/xep-0079.html) | Enables entities to request, and servers to perform, advanced processing of XMPP message stanzas. | -| XMPP Date Time Profiles | [XEP-0082](http://xmpp.org/extensions/xep-0082.html) | Standardization of Date and Time representation in XMPP. | -| Chat State Notifications | [XEP-0085](http://xmpp.org/extensions/xep-0085.html) | Communicating the status of a user in a chat session. | -| [Time Exchange](time.md) | [XEP-0090](http://xmpp.org/extensions/xep-0090.html) | Allows local time information to be shared between users. | -| Software Version | [XEP-0092](http://xmpp.org/extensions/xep-0092.html) | Retrieve and announce the software application of an XMPP entity. | -| Stream Initation | [XEP-0095](http://xmpp.org/extensions/xep-0095.html) | Initiating a data stream between any two XMPP entities. | -| [SI File Transfer](filetransfer.md) | [XEP-0096](http://xmpp.org/extensions/xep-0096.html) | Transfer files between two users over XMPP. | -| [Entity Capabilities](caps.md) | [XEP-0115](http://xmpp.org/extensions/xep-0115.html) | Broadcasting and dynamic discovery of entity capabilities. | -| Data Forms Validation | [XEP-0122](http://xmpp.org/extensions/xep-0122.html) | Enables an application to specify additional validation guidelines . | -| Stream Compression | [XEP-0138](http://xmpp.org/extensions/xep-0138.html) | Support for optional compression of the XMPP stream. -| Data Forms Layout | [XEP-0141](http://xmpp.org/extensions/xep-0141.html) | Enables an application to specify form layouts. | -| Personal Eventing Protocol | [XEP-0163](http://xmpp.org/extensions/xep-0163.html) | Using the XMPP publish-subscribe protocol to broadcast state change events associated with an XMPP account. | -| Message Delivery Receipts | [XEP-0184](http://xmpp.org/extensions/xep-0184.html) | Extension for message delivery receipts. The sender can request notification that the message has been delivered. | -| XMPP Ping | [XEP-0199](http://xmpp.org/extensions/xep-0199.html) | Sending application-level pings over XML streams. -| Entity Time | [XEP-0202](http://xmpp.org/extensions/xep-0202.html) | Allows entities to communicate their local time | -| Delayed Delivery | [XEP-0203](http://xmpp.org/extensions/xep-0203.html) | Extension for communicating the fact that an XML stanza has been delivered with a delay. | -| XMPP Over BOSH | [XEP-0206](http://xmpp.org/extensions/xep-0206.html) | Use Bidirectional-streams Over Synchronous HTTP (BOSH) to transport XMPP stanzas. | -| Attention | [XEP-0224](http://xmpp.org/extensions/xep-0224.html) | Getting attention of another user. | -| [Group Chat Invitations](invitation.md) | n/a | Send invitations to other users to join a group chat room. | -| [Jive Properties](properties.md) | n/a | TODO | - - -Experimental Smack Extensions and currently supported XEPs by Smack (smack-experimental) ----------------------------------------------------------------------------------------- - -| Name | XEP | Description | -|---------------------------------------------|----------------------------------------------------------|----------------------------------------------------------------------------------------------------------| -| Message Carbons | [XEP-0280](http://xmpp.org/extensions/xep-0280.html) | Keep all IM clients for a user engaged in a conversation, by carbon-copy outbound messages to all interested resources. -| [HTTP over XMPP transport](hoxt.md) | [XEP-0332](http://xmpp.org/extensions/xep-0332.html) | Allows to transport HTTP communication over XMPP peer-to-peer networks. | -| JSON Containers | [XEP-0335](http://xmpp.org/extensions/xep-0335.html) | Encapsulation of JSON data within XMPP Stanzas. | -| Google GCM JSON payload | n/a | Semantically the same as XEP-0335: JSON Containers | -| Client State Indication | [XEP-0352](http://xmpp.org/extensions/xep-0352.html) | A way for the client to indicate its active/inactive state. | - - -Legacy Smack Extensions and currently supported XEPs by Smack (smack-legacy) ----------------------------------------------------------------------------- - -If a XEP becomes 'Deprecated' or 'Obsolete' the code will be moved to the *smack-legacy* subproject. - -| Name | XEP | Description | -|---------------------------------------------|----------------------------------------------------------|----------------------------------------------------------------------------------------------------------| -| [Message Events](messageevents.md) | [XEP-0022](http://xmpp.org/extensions/xep-0022.html) | Requests and responds to message events. | - -| [Roster Item Exchange](rosterexchange.md) | [XEP-0093](http://xmpp.org/extensions/xep-0093.html) | Allows roster data to be shared between users. | diff --git a/documentation/extensions/intro.md b/documentation/extensions/intro.md deleted file mode 100644 index fa7393a75..000000000 --- a/documentation/extensions/intro.md +++ /dev/null @@ -1,99 +0,0 @@ -Smack Extensions Manual - -Current Extensions - -**Name** -**XEP #** -**Description** - -[Private Data](privatedata.md) - -[XEP-0049](http://www.xmpp.org/extensions/xep-0049.html) - -Manages private data. - -[XHTML Messages](xhtml.md) - -[XEP-0071](http://www.xmpp.org/extensions/xep-0071.html) - -Allows send and receiving formatted messages using XHTML. - -[Message Events](messageevents.md) - -[XEP-0022](http://www.xmpp.org/extensions/xep-0022.html) - -Requests and responds to message events. - -[Data Forms](dataforms.md) - -[XEP-0004](http://www.xmpp.org/extensions/xep-0004.html) - -Allows to gather data using Forms. - -[Multi User Chat](muc.md) - -[XEP-0045](http://www.xmpp.org/extensions/xep-0045.html) - -Allows configuration of, participation in, and administration of individual -text-based conference rooms. - -[Roster Item Exchange](rosterexchange.md) - -[XEP-0093](http://www.xmpp.org/extensions/xep-0093.html) - -Allows roster data to be shared between users. - -[Time Exchange](time.md) - -[XEP-0090](http://www.xmpp.org/extensions/xep-0090.html) - -Allows local time information to be shared between users. - -[Group Chat Invitations](invitation.md) - -N/A - -Send invitations to other users to join a group chat room. - -[Service Discovery](disco.md) - -[XEP-0030](http://www.xmpp.org/extensions/xep-0030.html) - -Allows to discover services in XMPP entities. - -[File Transfer](filetransfer.md) - -[XEP-0096](http://www.xmpp.org/extensions/xep-0096.html) - -Transfer files between two users over XMPP. - -[PubSub](pubsub.md) - -[XEP-0060](http://www.xmpp.org/extensions/xep-0060.html) - -Generic publish and subscribe functionality. - -[Entity Capabilities](caps.md) - -[XEP-0115](http://www.xmpp.org/extensions/xep-0115.html) - -Broadcasting and dynamic discovery of entity capabilities. - -[Privacy Lists](privacy.md) - -[XEP-0016](http://www.xmpp.org/extensions/xep-0016.html) - -Enabling or disabling communication with other entities. - -[HTTP over XMPP transport](hoxt.md) - -[XEP-0332](http://www.xmpp.org/extensions/xep-0332.html) - -Allows to transport HTTP communication over XMPP peer-to-peer networks. - -[Jive Properties](properties.md) - -N/A - -TODO - diff --git a/documentation/extensions/invitation.md b/documentation/extensions/invitation.md deleted file mode 100644 index 222494503..000000000 --- a/documentation/extensions/invitation.md +++ /dev/null @@ -1,42 +0,0 @@ -Group Chat Invitations -====================== - -The group chat invitation extension is used to invite other users to a -group chat room. - - * Inviting Other Users - * Listen for Invitations - -**XEP related:** N/A -- this protocol is outdated now that the Multi-User Chat (MUC) XEP is available ([XEP-45](http://www.xmpp.org/extensions/xep-0045.html)). However, most existing clients still use this older protocol. Once MUC support becomes more widespread, this API may be deprecated. - -Inviting Other Users --------------------- - -To use the GroupChatInvitation packet extension to invite another 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: - -``` -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); -``` - -The XML generated for the invitation portion of the code above would be: - -``` - -``` - -Listening for Invitations -------------------------- - -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: - -``` -StanzaFilter filter = new StanzaExtensionFilter("x", "jabber:x:conference"); -// Create a packet collector or packet listeners using the filter... -``` diff --git a/documentation/extensions/muc.md b/documentation/extensions/muc.md deleted file mode 100644 index 0eb02d388..000000000 --- a/documentation/extensions/muc.md +++ /dev/null @@ -1,652 +0,0 @@ -Multi User Chat -=============== - -Allows configuration of, participation in, and administration of individual -text-based conference rooms. - - * Create a new Room - * Join a room - * Manage room invitations - * Discover MUC support - * Discover joined rooms - * Discover room information - * Start a private chat - * Manage changes on room subject - * Manage role modifications - * Manage affiliation modifications - -**XEP related:** [XEP-45](http://www.xmpp.org/extensions/xep-0045.html) - -Create a new Room ------------------ - -**Description** - -Allowed users may create new rooms. There are two types of rooms that you can -create. **Instant rooms** which are available for immediate access and are -automatically created based on some default configuration and **Reserved -rooms** which are manually configured by the room creator before anyone is -allowed to enter. - -**Usage** - -In order to create a room you will need to first create an instance of -_**MultiUserChat**_. -In order to do so, get a instance of `MultiUserChatManager` and call `getMultiUserChat(String)` to retrieve a `MultiUserChat` instance. -The next step is to send **create(String nickname)** to -the _**MultiUserChat**_ instance where nickname is the nickname to use when -joining the room. - -Depending on the type of room that you want to create you will have to use -different configuration forms. In order to create an Instant room just send -**sendConfigurationForm(Form form)** where form is an empty form. But if you -want to create a Reserved room then you should first get the room's -configuration form, complete the form and finally send it back to the server. - -**Examples** - -In this example we can see how to create an instant room: - -```java -// Get the MultiUserChatManager -MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection); - -// Get a MultiUserChat using MultiUserChatManager -MultiUserChat muc = manager.getMultiUserChat("myroom@conference.jabber.org"); - -// Create the room -muc.create("testbot"); - -// Send an empty room configuration form which indicates that we want -// an instant room -muc.sendConfigurationForm(new Form(DataForm.Type.submit)); -``` - -In this example we can see how to create a reserved room. The form is -completed with default values: - -```java -// Get the MultiUserChatManager -MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection); - -// Create a MultiUserChat using an XMPPConnection for a room -MultiUserChat muc = = manager.getMultiUserChat("myroom@conference.jabber.org"); - -// Create the room -muc.create("testbot"); - -// Get the the room's configuration form -Form form = muc.getConfigurationForm(); -// Create a new form to submit based on the original form -Form submitForm = form.createAnswerForm(); -// Add default answers to the form to submit -for (Iterator fields = form.getFields(); fields.hasNext();) { - FormField field = (FormField) fields.next(); - if (!FormField.type.hidden.equals(field.getType()) && field.getVariable() != null) { - // Sets the default value as the answer - submitForm.setDefaultAnswer(field.getVariable()); -} -} -// Sets the new owner of the room -List owners = new ArrayList(); -owners.add("johndoe@jabber.org"); -submitForm.setAnswer("muc#roomconfig_roomowners", owners); -// Send the completed form (with default values) to the server to configure the room -muc.sendConfigurationForm(submitForm); -``` - -Join a room ------------ - -**Description** - -Your usual first step in order to send messages to a room is to join the room. -Multi User Chat allows to specify several parameter while joining a room. -Basically you can control the amount of history to receive after joining the -room as well as provide your nickname within the room and a password if the -room is password protected. - -**Usage** - -In order to join a room you will need to first get an instance of -_**MultiUserChat**_. -In order to do so, get a instance of `MultiUserChatManager` and call `getMultiUserChat(String)` to retrieve a `MultiUserChat` instance. -The next step is to send **join(...)** to the -_**MultiUserChat**_ instance. But first you will have to decide which join -message to send. If you want to just join the room without a password and -without specifying the amount of history to receive then you could use -**join(String nickname)** where nickname if your nickname in the room. In case -the room requires a password in order to join you could then use **join(String -nickname, String password)**. And finally, the most complete way to join a -room is to send **join(String nickname, String password, DiscussionHistory -history, long timeout)** where nickname is your nickname in the room, , -password is your password to join the room, history is an object that -specifies the amount of history to receive and timeout is the milliseconds to -wait for a response from the server. - -**Examples** - -In this example we can see how to join a room with a given nickname: - -```java -// Get the MultiUserChatManager -MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection); - -// Create a MultiUserChat using an XMPPConnection for a room -MultiUserChat muc2 = manager.getMultiUserChat("myroom@conference.jabber.org"); - -// User2 joins the new room -// The room service will decide the amount of history to send -muc2.join("testbot2"); -``` - -In this example we can see how to join a room with a given nickname and -password: - -```java -// Get the MultiUserChatManager -MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection); - -// Create a MultiUserChat using an XMPPConnection for a room -MultiUserChat muc2 = manager.getMultiUserChat("myroom@conference.jabber.org"); - -// User2 joins the new room using a password -// The room service will decide the amount of history to send -muc2.join("testbot2", "password"); -``` - -In this example we can see how to join a room with a given nickname specifying -the amount of history to receive: - -```java -// Get the MultiUserChatManager -MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection); - -// Create a MultiUserChat using an XMPPConnection for a room -MultiUserChat muc2 = manager.getMultiUserChat("myroom@conference.jabber.org"); - -// User2 joins the new room using a password and specifying -// the amount of history to receive. In this example we are requesting the last 5 messages. -DiscussionHistory history = new DiscussionHistory(); -history.setMaxStanzas(5); -muc2.join("testbot2", "password", history, conn1.getPacketReplyTimeout()); -``` - -Manage room invitations ------------------------ - -**Description** - -It can be useful to invite another user to a room in which one is an occupant. -Depending on the room's type the invitee could receive a password to use to -join the room and/or be added to the member list if the room is of type -members-only. Smack allows to send room invitations and let potential invitees -to listening for room invitations and inviters to listen for invitees' -rejections. - -**Usage** - -In order to invite another user to a room you must be already joined to the -room. Once you are joined just send **invite(String participant, String -reason)** to the _**MultiUserChat**_ where participant is the user to invite -to the room (e.g. hecate@shakespeare.lit) and reason is the reason why the -user is being invited. - -If potential invitees want to listen for room invitations then the invitee -must add an _**InvitationListener**_ to the _**MultiUserChatManager**_ class. Since -the _**InvitationListener**_ is an _interface_, it is necessary to create a -class that implements this _interface_. If an inviter wants to listen for room -invitation rejections, just add an _**InvitationRejectionListener**_ to the -_**MultiUserChat**_. _**InvitationRejectionListener**_ is also an interface so -you will need to create a class that implements this interface. - -**Examples** - -In this example we can see how to invite another user to the room and lister -for possible rejections: - -```java -// Get the MultiUserChatManager -MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection); - -// Create a MultiUserChat using an XMPPConnection for a room -MultiUserChat muc2 = manager.getMultiUserChat("myroom@conference.jabber.org"); - -muc2.join("testbot2"); -// User2 listens for invitation rejections -muc2.addInvitationRejectionListener(new InvitationRejectionListener() { - public void invitationDeclined(String invitee, String reason) { - // Do whatever you need here... - } -}); -// User2 invites user3 to join to the room -muc2.invite("user3@host.org/Smack", "Meet me in this excellent room"); -``` - -In this example we can see how to listen for room invitations and decline -invitations: - -```java -// User3 listens for MUC invitations -MultiUserChatManager.getInstanceFor(connection).addInvitationListener(new InvitationListener() { - public void invitationReceived(XMPPConnection conn, String room, String inviter, String reason, String password) { - // Reject the invitation - MultiUserChat.decline(conn, room, inviter, "I'm busy right now"); - } -}); -``` - -Discover MUC support --------------------- - -**Description** - -A user may want to discover if one of the user's contacts supports the Multi- -User Chat protocol. - -**Usage** - -In order to discover if one of the user's contacts supports MUC just send -**isServiceEnabled(String user)** to the -_**MultiUserChatManager**_ class where user is a fully qualified XMPP ID, e.g. -jdoe@example.com. You will receive a boolean indicating whether the user -supports MUC or not. - -**Examples** - -In this example we can see how to discover support of MUC: - -```java -// Discover whether user3@host.org supports MUC or not -boolean supports = MultiUserChatManager.getInstanceFor(connection).isServiceEnabled("user3@host.org/Smack"); -``` - -Discover joined rooms ---------------------- - -**Description** - -A user may also want to query a contact regarding which rooms the contact is -in. - -**Usage** - -In order to get the rooms where a user is in just send -**getJoinedRooms(String user)** to the -_**MultiUserChatManager**_ class where user is a fully qualified XMPP ID, e.g. -jdoe@example.com. You will get an Iterator of Strings as an answer where each -String represents a room name. - -**Examples** - -In this example we can see how to get the rooms where a user is in: - -```java -// Get the MultiUserChatManager -MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection); - -// Get the rooms where user3@host.org has joined -List joinedRooms = manager.getJoinedRooms("user3@host.org/Smack"); -``` - -Discover room information -------------------------- - -**Description** - -A user may need to discover information about a room without having to -actually join the room. The server will provide information only for public -rooms. - -**Usage** - -In order to discover information about a room just send -**getRoomInfo(String room)** to the -_**MultiUserChatManager**_ class where room is the XMPP ID of the room, e.g. -roomName@conference.myserver. You will get a RoomInfo object that contains the -discovered room information. - -**Examples** - -In this example we can see how to discover information about a room: - -```java -// Get the MultiUserChatManager -MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection); - -// Discover information about the room roomName@conference.myserver -RoomInfo info = manager.getRoomInfo("roomName@conference.myserver"); -System.out.println("Number of occupants:" + info.getOccupantsCount()); -System.out.println("Room Subject:" + info.getSubject()); -``` - -Start a private chat --------------------- - -**Description** - -A room occupant may want to start a private chat with another room occupant -even though they don't know the fully qualified XMPP ID (e.g. -jdoe@example.com) of each other. - -**Usage** - -To create a private chat with another room occupant just send -**createPrivateChat(String participant)** to the _**MultiUserChat**_ that you -used to join the room. The parameter participant is the occupant unique room -JID (e.g. 'darkcave@macbeth.shakespeare.lit/Paul'). You will receive a regular -_**Chat**_ object that you can use to chat with the other room occupant. - -**Examples** - -In this example we can see how to start a private chat with another room -occupant: - -``` -// Start a private chat with another participant -Chat chat = muc2.createPrivateChat("myroom@conference.jabber.org/johndoe"); -chat.sendMessage("Hello there"); -``` - -Manage changes on room subject ------------------------------- - -**Description** - -A common feature of multi-user chat rooms is the ability to change the subject -within the room. As a default, only users with a role of "moderator" are -allowed to change the subject in a room. Although some rooms may be configured -to allow a mere participant or even a visitor to change the subject. - -Every time the room's subject is changed you may want to be notified of the -modification. The new subject could be used to display an in-room message. - -**Usage** - -In order to modify the room's subject just send **changeSubject(String -subject)** to the _**MultiUserChat**_ that you used to join the room where -subject is the new room's subject. On the other hand, if you want to be -notified whenever the room's subject is modified you should add a -_**SubjectUpdatedListener**_ to the _**MultiUserChat**_ by sending -**addSubjectUpdatedListener(SubjectUpdatedListener listener)** to the -_**MultiUserChat**_. Since the _**SubjectUpdatedListener**_ is an _interface_, -it is necessary to create a class that implements this _interface_. - -**Examples** - -In this example we can see how to change the room's subject and react whenever -the room's subject is modified: - -``` -// An occupant wants to be notified every time the room's subject is changed -muc3.addSubjectUpdatedListener(new SubjectUpdatedListener() { - public void subjectUpdated(String subject, String from) { - .... - } -}); -// A room's owner changes the room's subject -muc2.changeSubject("New Subject"); -``` - -Manage role modifications -------------------------- - -**Description** - -There are four defined roles that an occupant can have: - - 1. Moderator - 2. Participant - 3. Visitor - 4. None (the absence of a role) - -These roles are temporary in that they do not persist across a user's visits -to the room and can change during the course of an occupant's visit to the -room. - -A moderator is the most powerful occupant within the context of the room, and -can to some extent manage other occupants' roles in the room. A participant -has fewer privileges than a moderator, although he or she always has the right -to speak. A visitor is a more restricted role within the context of a -moderated room, since visitors are not allowed to send messages to all -occupants. - -Roles are granted, revoked, and maintained based on the occupant's room -nickname or full JID. Whenever an occupant's role is changed Smack will -trigger specific events. - -**Usage** - -In order to grant voice (i.e. make someone a _participant_) just send the -message **grantVoice(String nickname)** to _**MultiUserChat**_. Use -**revokeVoice(String nickname)** to revoke the occupant's voice (i.e. make the -occupant a _visitor_). - -In order to grant moderator privileges to a participant or visitor just send -the message **grantModerator(String nickname)** to _**MultiUserChat**_. Use -**revokeModerator(String nickname)** to revoke the moderator privilege from -the occupant thus making the occupant a participant. - -Smack allows you to listen for role modification events. If you are interested -in listening role modification events of any occupant then use the listener -**_ParticipantStatusListener_**. But if you are interested in listening for -your own role modification events, use the listener **_UserStatusListener_**. -Both listeners should be added to the _**MultiUserChat**_ by using -**addParticipantStatusListener(ParticipantStatusListener listener)** or -**addUserStatusListener(UserStatusListener listener)** respectively. These -listeners include several notification events but you may be interested in -just a few of them. Smack provides default implementations for these listeners -avoiding you to implement all the interfaces' methods. The default -implementations are **_DefaultUserStatusListener_** and -**_DefaultParticipantStatusListener_**. Below you will find the sent messages -to the listeners whenever an occupant's role has changed. - -These are the triggered events when the role has been upgraded: - -| Old | New | Events | -|-----|-----|--------| -| None | Visitor | -- | -| Visitor | Participant | voiceGranted | -| Participant | Moderator | moderatorGranted | -| None | Participant | voiceGranted | -| None | Moderator | voiceGranted + moderatorGranted | -| Visitor | Moderator | voiceGranted + moderatorGranted | - -These are the triggered events when the role has been downgraded: - -| Old | New | Events | -|-----|-----|--------| -| Moderator | Participant | moderatorRevoked | -| Participant | Visitor | voiceRevoked | -| Visitor | None | kicked | -| Moderator | Visitor | voiceRevoked + moderatorRevoked | -| Moderator | None | kicked | -| Participant | None | kicked | - -**Examples** - -In this example we can see how to grant voice to a visitor and listen for the -notification events: - -```java -// User1 creates a room -muc = manager.getMultiUserChat("myroom@conference.jabber.org"); -muc.create("testbot"); -// User1 (which is the room owner) configures the room as a moderated room -Form form = muc.getConfigurationForm(); -Form answerForm = form.createAnswerForm(); -answerForm.setAnswer("muc#roomconfig_moderatedroom", "1"); -muc.sendConfigurationForm(answerForm); - -// User2 joins the new room (as a visitor) -MultiUserChat muc2 = manager2.getMultiUserChat("myroom@conference.jabber.org"); -muc2.join("testbot2"); -// User2 will listen for his own "voice" notification events -muc2.addUserStatusListener(new DefaultUserStatusListener() { - public void voiceGranted() { - super.voiceGranted(); - ... - } - public void voiceRevoked() { - super.voiceRevoked(); - ... - } -}); - -// User3 joins the new room (as a visitor) -MultiUserChat muc3 = manager3.getMultiUserChat("myroom@conference.jabber.org"); -muc3.join("testbot3"); -// User3 will lister for other occupants "voice" notification events -muc3.addParticipantStatusListener(new DefaultParticipantStatusListener() { - public void voiceGranted(String participant) { - super.voiceGranted(participant); - ... - } - public void voiceRevoked(String participant) { - super.voiceRevoked(participant); - ... - } -}); - -// The room's owner grants voice to user2 -muc.grantVoice("testbot2"); -``` - -Manage affiliation modifications --------------------------------- - -**Description** - -There are five defined affiliations that a user can have in relation to a -room: - - 1. Owner - 2. Admin - 3. Member - 4. Outcast - 5. None (the absence of an affiliation) - -These affiliations are semi-permanent 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. - -If a user without a defined affiliation enters a room, the user's affiliation -is defined as "none"; however, this affiliation does not persist across -visits. - -Owners and admins are by definition immune from certain actions. Specifically, -an owner or admin cannot be kicked from a room and cannot be banned from a -room. An admin must first lose his or her affiliation (i.e., have an -affiliation of "none" or "member") before such actions could be performed on -them. - -The member affiliation provides a way for a room owner or admin to specify a -"whitelist" of users who are allowed to enter a members-only room. When a -member enters a members-only room, his or her affiliation does not change, no -matter what his or her role is. The member affiliation also provides a way for -users to effectively register with an open room and thus be permanently -associated with that room in some way (one result may be that the user's -nickname is reserved in the room). - -An outcast is a user who has been banned from a room and who is not allowed to -enter the room. Whenever a user's affiliation is changed Smack will trigger -specific events. - -**Usage** - -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. - -In order to ban a user from the room just send the message **banUser(String -jid, String reason)** to _**MultiUserChat**_. - -Smack allows you to listen for affiliation modification events. If you are -interested in listening affiliation modification events of any user then use -the listener **_ParticipantStatusListener_**. But if you are interested in -listening for your own affiliation modification events, use the listener -**_UserStatusListener_**. Both listeners should be added to the -_**MultiUserChat**_ by using -**addParticipantStatusListener(ParticipantStatusListener listener)** or -**addUserStatusListener(UserStatusListener listener)** respectively. These -listeners include several notification events but you may be interested in -just a few of them. Smack provides default implementations for these listeners -avoiding you to implement all the interfaces' methods. The default -implementations are **_DefaultUserStatusListener_** and -**_DefaultParticipantStatusListener_**. Below you will find the sent messages -to the listeners whenever a user's affiliation has changed. - -These are the triggered events when the affiliation has been upgraded: - -| Old | New | Events | -|-----|-----|--------| -| None | Member | membershipGranted | -| Member | Admin | membershipRevoked + adminGranted | -| Admin | Owner | adminRevoked + ownershipGranted | -| None | Admin | adminGranted | -| None | Owner | ownershipGranted | -| Member | Owner | membershipRevoked + ownershipGranted | - -These are the triggered events when the affiliation has been downgraded: - -| Old | New | Events | -|-----|-----|--------| -| Owner | Admin | ownershipRevoked + adminGranted | -| Admin | Member | adminRevoked + membershipGranted | -| Member | None | membershipRevoked | -| Owner | Member | ownershipRevoked + membershipGranted | -| Owner | None | ownershipRevoked | -| Admin | None | adminRevoked | -| _Anyone_ | Outcast | banned | - -**Examples** - -In this example we can see how to grant admin privileges to a user and listen -for the notification events: - -```java -// User1 creates a room -muc = manager.getMultiUserChat("myroom@conference.jabber.org"); -muc.create("testbot"); -// User1 (which is the room owner) configures the room as a moderated room -Form form = muc.getConfigurationForm(); -Form answerForm = form.createAnswerForm(); -answerForm.setAnswer("muc#roomconfig_moderatedroom", "1"); -muc.sendConfigurationForm(answerForm); - -// User2 joins the new room (as a visitor) -MultiUserChat muc2 = manager2.getMultiUserChat("myroom@conference.jabber.org"); -muc2.join("testbot2"); -// User2 will listen for his own admin privileges -muc2.addUserStatusListener(new DefaultUserStatusListener() { - public void membershipRevoked() { - super.membershipRevoked(); - ... - } - public void adminGranted() { - super.adminGranted(); - ... - } -}); - -// User3 joins the new room (as a visitor) -MultiUserChat muc3 = manager3.getMultiUserChat("myroom@conference.jabber.org"); -muc3.join("testbot3"); -// User3 will lister for other users admin privileges -muc3.addParticipantStatusListener(new DefaultParticipantStatusListener() { - public void membershipRevoked(String participant) { - super.membershipRevoked(participant); - ... - } - public void adminGranted(String participant) { - super.adminGranted(participant); - ... - } -}); -// The room's owner grants admin privileges to user2 -muc.grantAdmin("user2@jabber.org"); -``` diff --git a/documentation/extensions/privacy.md b/documentation/extensions/privacy.md deleted file mode 100644 index f309ea27d..000000000 --- a/documentation/extensions/privacy.md +++ /dev/null @@ -1,139 +0,0 @@ -Privacy Lists -============ - -[XEP-0016: Privacy Lists](http://xmpp.org/extensions/xep-0016.html) - -What is? --------- - -`Privacy` is a method for users to block communications from particular other -users. In XMPP this is done by managing one's privacy lists. - -Server-side privacy lists enable successful completion of the following use -cases: - - * Retrieving one's privacy lists. - * Adding, removing, and editing one's privacy lists. - * Setting, changing, or declining active lists. - * Setting, changing, or declining the default list (i.e., the list that is active by default). - * Allowing or blocking messages based on JID, group, or subscription type (or globally). - * Allowing or blocking inbound presence notifications based on JID, group, or subscription type (or globally). - * Allowing or blocking outbound presence notifications based on JID, group, or subscription type (or globally). - * Allowing or blocking IQ stanzas based on JID, group, or subscription type (or globally). - * Allowing or blocking all communications based on JID, group, or subscription type (or globally). - -How can I use it? ------------------ - -The API implementation releases three main public classes: - - * `PrivacyListManager`: this is the main API class to retrieve and handle server privacy lists. - * `PrivacyList`: witch represents one privacy list, with a name, a set of privacy items. For example, the list with visible or invisible. - * `PrivacyItem`: block or allow one aspect of privacy. For example, to allow my friend to see my presence. - -1. Right from the start, a client MAY **get his/her privacy list** that is stored in the server: - -``` -// Create a privacy manager for the current connection._ -PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); -// Retrieve server privacy lists_ -PrivacyList[] lists = privacyManager.getPrivacyLists(); -``` - -Now the client is able to show every `PrivacyItem` of the server and also for -every list if it is active, default or none of them. The client is a listener -of privacy changes. - - - -2. In order to **add a new list in the server**, the client MAY implement something like: - -``` -// Set the name of the list_ -String listName = "newList"; - -// Create the list of PrivacyItem that will allow or deny some privacy aspect_ -String user = "tybalt@example.com"; -String groupName = "enemies"; -ArrayList privacyItems = new ArrayList(); - -PrivacyItem item = new PrivacyItem(PrivacyItem.Type.jid, user, true, 1); -privacyItems.add(item); - -item = new PrivacyItem(PrivacyItem.Type.subscription, PrivacyItem.SUBSCRIPTION_BOTH, true, 2); -privacyItems.add(item); - -item = new PrivacyItem(PrivacyItem.Type.group, groupName, false, 3); -item.setFilterMessage(true); -privacyItems.add(item); - -// Get the privacy manager for the current connection._ -PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); -// Create the new list._ -privacyManager.createPrivacyList(listName, privacyItems); -``` - -3. To **modify an existent list**, the client code MAY be like: - -``` -// Set the name of the list_ -String listName = "existingList"; -// Get the privacy manager for the current connection._ -PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); -// Sent the new list to the server._ -privacyManager.updatePrivacyList(listName, items); -``` - -Notice `items` was defined at the example 2 and MUST contain all the elements -in the list (not the "delta"). - -4. In order to **delete an existing list**, the client MAY perform something like: - -``` -// Set the name of the list_ -String listName = "existingList"; -// Get the privacy manager for the current connection._ -PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); -// Remove the list._ -privacyManager.deletePrivacyList(listName); -``` - -5. In order to **decline the use of an active list**, the client MAY perform something like: - -``` -// Get the privacy manager for the current connection._ -PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); -// Decline the use of the active list._ -privacyManager.declineActiveList(); -``` - -6. In order to **decline the use of a default list**, the client MAY perform something like: - -``` -// Get the privacy manager for the current connection._ -PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); -// Decline the use of the default list._ -privacyManager.declineDefaultList(); -``` - -Listening for Privacy Changes - -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 -listerners that will be notified when a list has been changed. Listeners -should implement the `PrivacyListListener` interface. - -The most important notification is `updatedPrivacyList` that is performed when -a privacy list changes its privacy items. - -The listener becomes notified after performing: - -``` -// Get the privacy manager for the current connection._ -PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); -// Add the listener (this) to get notified_ -privacyManager.addListener(this); -``` -Copyright (C) Jive Software 2002-2008 diff --git a/documentation/extensions/privatedata.md b/documentation/extensions/privatedata.md deleted file mode 100644 index 5e107510d..000000000 --- a/documentation/extensions/privatedata.md +++ /dev/null @@ -1,17 +0,0 @@ -Private Data -============ - -Manages private data, which is a mechanism to allow users to store arbitrary -XML data on an XMPP server. Each private data chunk is defined by a element -name and XML namespace. Example private data: - -``` - - blue - puce - -``` - -**XEP related:** [XEP-49](http://www.xmpp.org/extensions/xep-0049.html) - -_More coming soon._ diff --git a/documentation/extensions/properties.md b/documentation/extensions/properties.md deleted file mode 100644 index b4a54e281..000000000 --- a/documentation/extensions/properties.md +++ /dev/null @@ -1,83 +0,0 @@ -Stanza Properties -================= - -Smack provides an easy mechanism for attaching arbitrary properties to -packets. Each property has a String name, and a value that is a Java primitive -(int, long, float, double, boolean) or any Serializable object (a Java object -is Serializable when it implements the Serializable interface). - -Using the API -------------- - -All major objects have property support, such as Message objects. The -following code demonstrates how to set properties: - -``` -Message message = chat.createMessage(); -JivePropertiesExtension jpe = new JivePropertiesExtension(); -// Add a Color object as a property._ -jpe.setProperty("favoriteColor", new Color(0, 0, 255)); -// Add an int as a property._ -jpe.setProperty("favoriteNumber", 4); -// Add the JivePropertiesExtension to the message packet_ -message.addStanzaExtension(jpe); -chat.sendMessage(message); -``` - -Getting those same properties would use the following code: - -``` -Message message = chat.nextMessage(); -// Get the JivePropertiesExtension_ -JivePropertiesExtension jpe = message.getExtension(JivePropertiesExtension.NAMESPACE); -// Get a Color object property._ -Color favoriteColor = (Color)jpe.getProperty("favoriteColor"); -// Get an int property. Note that properties are always returned as -// Objects, so we must cast the value to an Integer, then convert -// it to an int._ -int favoriteNumber = ((Integer)jpe.getProperty("favoriteNumber")).intValue(); -``` - -For convenience `JivePropertiesManager` contains two helper methods namely -`addProperty(Stanza packet, String name, Object value)` and -`getProperty(Stanza packet, String name)`. - -Objects as Properties ---------------------- - -Using objects as property values is a very powerful and easy way to exchange -data. However, you should keep the following in mind: - - * 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 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. - -XML Format ----------- - -The current XML format used to send property data is not a standard, so will -likely not be recognized by clients not using Smack. The XML looks like the -following (comments added for clarity): - - - - - - - - prop1 - 123 - - - - blah2 - adf612fna9nab - - - - -The currently supported types are: `integer`, `long`, `float`, `double`, -`boolean`, `string`, and `java-object`. - -Copyright (C) Jive Software 2002-2008 diff --git a/documentation/extensions/pubsub.md b/documentation/extensions/pubsub.md deleted file mode 100644 index 788f63d18..000000000 --- a/documentation/extensions/pubsub.md +++ /dev/null @@ -1,402 +0,0 @@ -Pubsub -====== - -This section details the usage of an API designed for accessing an XMPP based -implementation of a [publish and -subscribe](http://en.wikipedia.org/wiki/Publish/subscribe) based messaging -system. It has functionality for creation, configuration of, subscription and -publishing to pubsub nodes. - - * Node creation and configuration - * Publishing to a node - * Receiving pubsub messages - * Retrieving persisted pubsub messages - * Discover pubsub information - -**XEP related:** [XEP-0060](http://xmpp.org/extensions/xep-0060.html) - -Node creation and configuration -------------------------------- - -### Description - -Allowed users may create and configure pubsub nodes. There are two types of -nodes that can be created, leaf nodes and collection nodes. - -* Leaf Nodes - contains only messages -* Collection Nodes - contains only nodes (both Leaf and Collection are allowed), but no messages -The current version of this API only supports Leaf Nodes. There are many -configuration options available for nodes, but the two main options are -whether the node is **persistent** or not and whether it will deliver payload -or not. - -### Usage - -In order to create a node you will need to first create an instance of -_**PubSubManager**_. There are several options for node creation which range -from creating an instant node, default configuration, or a fully configured -node. - -### Examples - -Create an instant node: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Create the node -LeafNode leaf = mgr.createNode(); -``` - -Create a node with default configuration and then configure it: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Create the node -LeafNode leaf = mgr.createNode("testNode"); -ConfigureForm form = new ConfigureForm(FormType.submit); -form.setAccessModel(AccessModel.open); -form.setDeliverPayloads(false); -form.setNotifyRetract(true); -form.setPersistentItems(true); -form.setPublishModel(PublishModel.open); - -leaf.sendConfigurationForm(form); -``` - -Create and configure a node: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Create the node -ConfigureForm form = new ConfigureForm(FormType.submit); -form.setAccessModel(AccessModel.open); -form.setDeliverPayloads(false); -form.setNotifyRetract(true); -form.setPersistentItems(true); -form.setPublishModel(PublishModel.open); -LeafNode leaf = mgr.createNode("testNode", form); -``` - -Publishing to a node --------------------- - -**Description** - -This section deals with the **publish** portion of pubsub. Usage of a node -typically involves either sending or receiving data, referred to as items. -Depending on the context of the nodes usage, the item being sent to it can -have different properties. It can contain application data known as payload, -or the publisher may choose to supply meaningful unique id's. Determination of -an items acceptable properties is defined by a combination of node -configuration and its purpose. - -**Usage** - -To publish to a node, you will have to either create or retrieve an existing -node and then create and send items to that node. The ability for any given -person to publish to the node will be dependent on its configuration. - -**Examples** - -In this example we publish an item to a node that does not take payload: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Get the node -LeafNode node = mgr.getNode("testNode"); - -// Publish an Item, let service set the id -node.send(new Item()); - -// Publish an Item with the specified id -node.send(new Item("123abc")); -``` - -In this example we publish an item to a node that does take payload: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Get the node -LeafNode node = mgr.getNode("testNode"); - -// Publish an Item with payload -node.send(new PayloadItem("test" + System.currentTimeMillis(), -new SimplePayload("book", "pubsub:test:book", "Two Towers"))); -``` - -Receiving pubsub messages -------------------------- - -**Description** - -This section deals with the **subscribe** portion of pubsub. As mentioned in -the last section, usage of a node typically involves either sending or -receiving items. Subscribers are interested in being notified when items are -published to the pubsub node. These items may or may not have application -specific data (payload), as that is dependent on the context in which the node -is being used. - -**Usage** - -To get messages asynchronously when items are published to a node, you will -have to - -* Get a node. -* Create and register a listener. -* Subscribe to the node. - -Please note that you should register the listener before subscribing so that -all messages sent after subscribing are received. If done in the reverse -order, messages that are sent after subscribing but before registering a -listener may not be processed as expected. - -**Examples** - -In this example we can see how to create a listener and register it and then -subscribe for messages. - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Get the node -LeafNode node = mgr.getNode("testNode"); - -node.addItemEventListener(new ItemEventCoordinator<Item;>()); -node.subscribe(myJid); -``` - -Where the listener is defined like so: - -``` -class ItemEventCoordinator implements ItemEventListener { - @Override - public void handlePublishedItems(ItemPublishEvent items) { - System.out.println("Item count: " + System.out.println(items); - } -} -``` - -In addition to receiving published items, there are notifications for several -other events that occur on a node as well. - -* Deleting items or purging all items from a node -* Changing the node configuration - -In this example we can see how to create a listener, register it and then -subscribe for item deletion messages. - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Get the node -LeafNode node = mgr.getNode("testNode"); - -node.addItemDeleteListener(new ItemDeleteCoordinator<Item;>()); -node.subscribe(myJid); -node.deleteItem("id_one"); -``` - -Where the handler is defined like so: - -``` -class ItemDeleteCoordinator implements ItemDeleteListener { - @Override - public void handleDeletedItems(ItemDeleteEvent items) { - System.out.println("Item count: " + items.getItemIds().size()); - System.out.println(items); - } - - @Override - public void handlePurge() { - System.out.println("All items have been deleted from node"); - } -} -``` - -In this example we can see how to create a listener, register it and then -subscribe for node configuration messages. - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Get the node -Node node = mgr.getNode("testNode"); - -node.addConfigurationListener(new NodeConfigCoordinator()); -node.subscribe(myJid); - -ConfigureForm form = new ConfigureForm(FormType.submit); -form.setAccessModel(AccessModel.open); -form.setDeliverPayloads(false); -form.setNotifyRetract(true); -form.setPersistentItems(true); -form.setPublishModel(PublishModel.open); - -node.sendConfigurationForm(form); -``` - -Where the handler is defined like so: - -``` -class NodeConfigCoordinator implements NodeConfigListener { - @Override - public void handleNodeConfiguration(ConfigurationEvent config) { - System.out.println("New configuration"); - System.out.println(config.getConfiguration()); - } -} -``` - -Retrieving persisted pubsub messages ------------------------------------- - -**Description** - -When persistent nodes are used, the subscription and registration methods -described in the last section will not enable the retrieval of items that -already exist in the node. This section deals with the specific methods for -retrieving these items. There are several means of retrieving existing items. -You can retrieve all items at once, the last N items, or the items specified -by a collection of id's. Please note that the service may, according to the -pubsub specification, reply with a list of items that contains only the item -id's (no payload) to save on bandwidth. This will not occur when the id's are -specified since this is the means of guaranteeing retrieval of payload. - -**Usage** - -To synchronously retrieve existing items from a persistent node, you will have -to get an instance of a _**LeafNode**_ and call one of the retrieve methods. - -**Examples** - -In this example we can see how to retrieve the existing items from a node: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Get the node -LeafNode node = mgr.getNode("testNode"); - -Collection items = node.getItems(); -``` - -In this example we can see how to retrieve the last N existing items: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Get the node -LeafNode node = mgr.getNode("testNode"); - -List items = node.getItems(100); -``` - -In this example we can see how to retrieve the specified existing items: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Get the node -LeafNode node = mgr.getNode("testNode"); -Collection<String;> ids = new ArrayList<String;>(3); -ids.add("1"); -ids.add("3"); -ids.add("4"); - -List items = node.getItems(ids); -``` - -Discover pubsub information ---------------------------- - -**Description** - -A user may want to query a server or node for a variety of pubsub related -information. - -**Usage** - -To retrieve information, a user will simply use either the _**PubSubManager**_ -or _**Node**_ classes depending on what type of information is required. - -**Examples** - -In this example we can see how to get pubsub capabilities: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Get the pubsub features that are supported -DiscoverInfo supportedFeatures = mgr.getSupportedFeatures(); -``` - -In this example we can see how to get pubsub subscriptions for all nodes: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Get all the subscriptions in the pubsub service -List<Subscription;> subscriptions = mgr.getSubscriptions(); -``` - -In this example we can see how to get all affiliations for the users bare JID -on the pubsub service: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); - -// Get the affiliations for the users bare JID -List<Affiliation;> affiliations = mgr.getAffiliations(); -``` - -In this example we can see how to get information about the node: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); -Node node = mgr.getNode("testNode"); - -// Get the node information -DiscoverInfo nodeInfo = node.discoverInfo(); -``` - -In this example we can see how to discover the node items: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); -Node node = mgr.getNode("testNode"); - -// Discover the node items -DiscoverItems nodeItems = node.discoverItems(); -``` - -In this example we can see how to get node subscriptions: - -``` -// Create a pubsub manager using an existing XMPPConnection -PubSubManager mgr = new PubSubManager(con); -Node node = mgr.getNode("testNode"); - -// Discover the node subscriptions -List<Subscription;> subscriptions = node.getSubscriptions(); -``` diff --git a/documentation/extensions/rosterexchange.md b/documentation/extensions/rosterexchange.md deleted file mode 100644 index 9526aa1a1..000000000 --- a/documentation/extensions/rosterexchange.md +++ /dev/null @@ -1,160 +0,0 @@ -Roster Item Exchange -==================== - -This extension is used to send rosters, roster groups and roster entries from -one XMPP Entity to another. It also provides an easy way to hook up custom -logic when entries are received from other XMPP clients. - -Follow these links to learn how to send and receive roster items: - - * Send a complete roster - * Send a roster's group - * Send a roster's entry - * Receive roster entries - -**XEP related:** [XEP-93](http://www.xmpp.org/extensions/xep-0093.html) - -Send a entire roster -------------------- - -**Description** - -Sometimes it is useful to send a whole roster to another user. Smack provides -a very easy way to send a complete roster to another XMPP client. - -**Usage** - -Create an instance of _**RosterExchangeManager**_ and use the **#send(Roster, -String)** message to send a roster to a given user. The first parameter is the -roster to send and the second parameter is the id of the user that will -receive the roster entries. - -**Example** - -In this example we can see how user1 sends his roster to user2. - -``` -XMPPConnection conn1 = … - -// Create a new roster exchange manager on conn1 -RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1); -// Send user1's roster to user2 -rosterExchangeManager.send(Roster.getInstanceFor(conn1), user2); -``` - -Send a roster group -------------------- - -**Description** - -It is also possible to send a roster group to another XMPP client. A roster -group groups a set of roster entries under a name. - -**Usage** - -Create an instance of _**RosterExchangeManager**_ and use the -**#send(RosterGroup, String)** message to send a roster group to a given user. -The first parameter is the roster group to send and the second parameter is -the id of the user that will receive the roster entries. - -**Example** - -In this example we can see how user1 sends his roster groups to user2. - -``` -XMPPConnection conn1 = … - -// Create a new roster exchange manager on conn1 -RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1); -// Send user1's RosterGroups to user2 -for (Iterator it = Roster.getInstanceFor(conn1).getGroups(); it.hasNext(); ) -rosterExchangeManager.send((RosterGroup)it.next(), user2); -``` - -Send a roster entry -------------------- - -**Description** - -Sometimes you may need to send a single roster entry to another XMPP client. -Smack also lets you send items at this granularity level. - -**Usage** - -Create an instance of _**RosterExchangeManager**_ and use the -**#send(RosterEntry, String)** message to send a roster entry to a given user. -The first parameter is the roster entry to send and the second parameter is -the id of the user that will receive the roster entries. - -**Example** - -In this example we can see how user1 sends a roster entry to user2. - -``` -XMPPConnection conn1 = … - -// Create a new roster exchange manager on conn1 -RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1); -// Send a roster entry (any) to user2 -rosterExchangeManager1.send((RosterEntry)Roster.getInstanceFor(conn1).getEntries().next(), user2); -``` - -Receive roster entries ----------------------- - -**Description** - -Since roster items are sent between XMPP clients, it is necessary to listen to -possible roster entries receptions. Smack provides a mechanism that you can -use to execute custom logic when roster entries are received. - -**Usage** - - 1. Create a class that implements the _**RosterExchangeListener**_ interface. - 2. Implement the method **entriesReceived(String, Iterator)** that will be called when new entries are received with custom logic. - 3. Add the listener to the _RosterExchangeManager_ that works on the desired _XMPPConnection_. - -**Example** - -In this example we can see how user1 sends a roster entry to user2 and user2 -adds the received entries to his roster. - -``` -// Connect to the server and log in the users -XMPPConnection conn1 = … -XMPPConnection conn2 = … - -final Roster user2_roster = Roster.getInstanceFor(conn2); - -// Create a RosterExchangeManager that will help user2 to listen and accept -the entries received -RosterExchangeManager rosterExchangeManager2 = new RosterExchangeManager(conn2); -// Create a RosterExchangeListener that will iterate over the received roster entries -RosterExchangeListener rosterExchangeListener = new RosterExchangeListener() { -public void entriesReceived(String from, Iterator remoteRosterEntries) { -while (remoteRosterEntries.hasNext()) { -try { -// Get the received entry -RemoteRosterEntry remoteRosterEntry = (RemoteRosterEntry) remoteRosterEntries.next(); -// Display the remote entry on the console -System.out.println(remoteRosterEntry); -// Add the entry to the user2's roster -user2_roster.createEntry( -remoteRosterEntry.getUser(), -remoteRosterEntry.getName(), -remoteRosterEntry.getGroupArrayNames()); -} -catch (XMPPException e) { -e.printStackTrace(); -} -} -} -}; -// Add the RosterExchangeListener to the RosterExchangeManager that user2 is using -rosterExchangeManager2.addRosterListener(rosterExchangeListener); - -// Create a RosterExchangeManager that will help user1 to send his roster -RosterExchangeManager rosterExchangeManager1 = new RosterExchangeManager(conn1); -// Send user1's roster to user2 -rosterExchangeManager1.send(Roster.getInstanceFor(conn1), user2); -``` diff --git a/documentation/extensions/streammanagement.md b/documentation/extensions/streammanagement.md deleted file mode 100644 index 6f084f028..000000000 --- a/documentation/extensions/streammanagement.md +++ /dev/null @@ -1,37 +0,0 @@ -Stream Management -================= - -XMPPTCPConnection comes with support for Stream Management (SM). - -**XEP related:** [XEP-0198](http://xmpp.org/extensions/xep-0198.html) - -Known interoperability issues ------------------------------ - -- SM resumption failes on prosody when compression in sync flush mode is used with prosody. See [Prosody issue #433](https://code.google.com/p/lxmppd/issues/detail?id=433). - -Enabling stream management ------------------------- - -TODO - -Getting notifications about acknowledges stanzas ------------------------------------------------- - -TODO - -Requisting stanza acknowledgements from the server --------------------------------------------------- - -### By using predicates - -TODO - -### Manually - -TODO - -Enable stream resumption ------------------------- - -TODO diff --git a/documentation/extensions/time.md b/documentation/extensions/time.md deleted file mode 100644 index 812412139..000000000 --- a/documentation/extensions/time.md +++ /dev/null @@ -1,10 +0,0 @@ -Entity Time Exchange -==================== - -Supports a protocol that XMPP clients use to exchange their respective local -times and time zones. - -**XEP related:** [XEP-90](http://www.xmpp.org/extensions/xep-0090.html) - -_More coming soon._ - diff --git a/documentation/extensions/xhtml.md b/documentation/extensions/xhtml.md deleted file mode 100644 index d98fd5063..000000000 --- a/documentation/extensions/xhtml.md +++ /dev/null @@ -1,202 +0,0 @@ -XHTML Messages -============== - -Provides the ability to send and receive formatted messages using XHTML. - -Follow these links to learn how to compose, send, receive and discover support -for XHTML messages: - - * Compose an XHTML Message - * Send an XHTML Message - * Receive an XHTML Message - * Discover support for XHTML Messages - -**XEP related:** [XEP-71](http://www.xmpp.org/extensions/xep-0071.html) - -Compose an XHTML Message ------------------------- - -**Description** - -The first step in order to send an XHTML message is to compose it. Smack -provides a special class that helps to build valid XHTML messages hiding any -low level complexity. For special situations, advanced users may decide not to -use the helper class and generate the XHTML by themselves. Even for these -situations Smack provides a well defined entry point in order to add the -generated XHTML content to a given message. - -Note: not all clients are able to view XHTML formatted messages. Therefore, -it's recommended that you include a normal body in that message that is either -an unformatted version of the text or a note that XHTML support is required to -view the message contents. - -**Usage** - -Create an instance of _**XHTMLText**_ specifying the style and language of the -body. You can add several XHTML bodies to the message but each body should be -for a different language. Once you have an XHTMLText you can start to append -tags and text to it. In order to append tags there are several messages that -you can use. For each XHTML defined tag there is a message that you can send. -In order to add text you can send the message **#append(String -textToAppend)**. - -After you have configured the XHTML text, the last step you have to do is to -add the XHTML text to the message you want to send. If you decided to create -the XHTML text by yourself, you will have to follow this last step too. In -order to add the XHTML text to the message send the message **#addBody(Message -message, String body)** to the _**XHTMLManager**_ class where _message_ is the -message that will receive the XHTML body and _body_ is the string to add as an -XHTML body to the message.** - -**Example** - -In this example we can see how to compose the following XHTML message: - -``` - -

Hey John, this is my new - green - !!!! -

- -``` - -``` -// Create a message to send -Message msg = chat.createMessage(); -msg.setSubject("Any subject you want"); -msg.setBody("Hey John, this is my new green!!!!"); - -// Create an XHTMLText to send with the message -XHTMLText xhtmlText = new XHTMLText(null, null); -xhtmlText.appendOpenParagraphTag("font-size:large"); -xhtmlText.append("Hey John, this is my new "); -xhtmlText.appendOpenSpanTag("color:green"); -xhtmlText.append("green"); -xhtmlText.appendCloseSpanTag(); -xhtmlText.appendOpenEmTag(); -xhtmlText.append("!!!!"); -xhtmlText.appendCloseEmTag(); -xhtmlText.appendCloseParagraphTag(); -xhtmlText.appendCloseBodyTag(); - -// Add the XHTML text to the message -XHTMLManager.addBody(msg, xhtmlText); -``` - -Send an XHTML Message ---------------------- - -**Description** - -After you have composed an XHTML message you will want to send it. Once you -have added the XHTML content to the message you want to send you are almost -done. The last step is to send the message as you do with any other message. - -**Usage** - -An XHTML message is like any regular message, therefore to send the message -you can follow the usual steps you do in order to send a message. For example, -to send a message as part of a chat just use the message **#send(Message)** of -_**Chat**_ or you can use the message **#send(Stanza)** of -_**XMPPConnection**_. - -**Example** - -In this example we can see how to send a message with XHTML content as part of -a chat. - -``` -// Create a message to send -Message msg = chat.createMessage(); -// Obtain the XHTML text to send from somewhere -XHTMLText xhtmlBody = getXHTMLTextToSend(); - -// Add the XHTML text to the message -XHTMLManager.addBody(msg, xhtmlBody); - -// Send the message that contains the XHTML -chat.sendMessage(msg); -``` - -Receive an XHTML Message ------------------------- - -**Description** - -It is also possible to obtain the XHTML content from a received message. -Remember that the specification defines that a message may contain several -XHTML bodies where each body should be for a different language. - -**Usage** - -To get the XHTML bodies of a given message just send the message -**#getBodies(Message)** to the class _**XHTMLManager**_. The answer of this -message will be an _**List**_ with the different XHTML bodies of the -message or null if none. - -**Example** - -In this example we can see how to create a PacketListener that obtains the -XHTML bodies of any received message. - -``` -// Create a listener for the chat and display any XHTML content -PacketListener packetListener = new PacketListener() { -public void processPacket(Stanza packet) { - Message message = (Message) packet; - // Obtain the XHTML bodies of the message - List bodies = XHTMLManager.getBodies(message); - if (bodies != null) { - // Display the bodies on the console - for (CharSequence body : bodies) { - System.out.println(body); - } - } -}; -chat.addMessageListener(packetListener); -``` - -Discover support for XHTML Messages ------------------------------------ - -**Description** - -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 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. - -**Usage** - -In order to discover if a remote user supports XHTML messages send -**#isServiceEnabled(XMPPConnection connection, String userID)** to the class -_**XHTMLManager**_ where connection is the connection to use to perform the -service discovery and userID is the user to check (A fully qualified xmpp ID, -e.g. jdoe@example.com). This message will return true if the specified user -handles XHTML messages. - -**Example** - -In this example we can see how to discover if a remote user supports XHTML -Messages. - -``` -Message msg = chat.createMessage(); -// Include a normal body in the message -msg.setBody(getTextToSend()); -// Check if the other user supports XHTML messages -if (XHTMLManager.isServiceEnabled(connection, chat.getParticipant())) { - // Obtain the XHTML text to send from somewhere - String xhtmlBody = getXHTMLTextToSend(); - // Include an XHTML body in the message - qHTMLManager.addBody(msg, xhtmlBody); -} - -// Send the message -chat.sendMessage(msg); -``` diff --git a/documentation/gettingstarted.md b/documentation/gettingstarted.md deleted file mode 100644 index d0050fbb2..000000000 --- a/documentation/gettingstarted.md +++ /dev/null @@ -1,114 +0,0 @@ -Smack: Getting Started -====================== - -[Back](index.md) - -This document will introduce you to the Smack API and provide an overview of -important classes and concepts. - -JAR Files and Requirements --------------------------- - -Smack is meant to be easily embedded into any existing Java application. The -library ships as several JAR files to provide more flexibility over which -features applications require: - - * `smack-core.jar` -- provides core XMPP functionality. All XMPP features that are part of the XMPP RFCs are included. - * `smack-tcp.jar` -- support for XMPP over TCP. Includes XMPPTCPConnection class, which you usually want to use - * `smack-extensions.jar` -- support for many of the extensions (XEPs) defined by the XMPP Standards Foundation, including multi-user chat, file transfer, user search, etc. The extensions are documented in the [extensions manual](extensions/index.md). - * `smack-experimental.jar` -- support for experimental extensions (XEPs) defined by the XMPP Standards Foundation. The API and functionality of those extensions should be considered as unstable. - * `smack-legacy.jar` -- support for legacy extensions (XEPs) defined by the XMPP Standards Foundation. - * `smack-bosh.jar` -- support for BOSH (XEP-0124). This code should be considered as beta. - * `smack-jingle.jar` -- support for Jingle. This code is old and currenlty unmaintained. - * `smack-resolver-dnsjava.jar` -- support for resolving DNS SRV records with the help of dnsjava. Ideal for platforms that do not support the javax.naming API. - * `smack-resolver-javax.jar` -- support for resolving DNS SRV records with the javax namespace API. - * `smack-debug.jar` -- an enhanced GUI debugger for protocol traffic. It will automatically be used when found in the classpath and when [debugging](debugging.md) is enabled. - -Configuration -------------- - -Smack has an initialization process that involves 2 phases. - - * Initializing system properties - Initializing all the system properties accessible through the class **SmackConfiguration**. These properties are retrieve by the _getXXX_ methods on that class. - * Initializing startup classes - Initializing any classes meant to be active at startup by instantiating the class, and then calling the _initialize_ method on that class if it extends **SmackInitializer**. If it does not extend this interface, then initialization will have to take place in a static block of code which is automatically executed when the class is loaded. - -Initialization is accomplished via a configuration file. By default, Smack -will load the one embedded in the Smack jar at _org.jivesoftware.smack/smack- -config.xml_. This particular configuration contains a list of initializer -classes to load. All manager type classes that need to be initialized are -contained in this list of initializers. - -Establishing a Connection -------------------------- - -The `XMPPTCPConnection` class is used to create a connection to an XMPP -server. Below are code examples for making a connection: - -``` -// Create a connection to the jabber.org server. -AbstractXMPPConnection conn1 = **new** XMPPTCPConnection("username", "password" "jabber.org"); -conn1.connect(); - -// Create a connection to the jabber.org server on a specific port. -XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() - .setUsernameAndPassword("username", "password") - .setServiceName("jabber.org") - .setHost("earl.jabber.org") - .setPort("8222") - .build(); - -AbstractXMPPConnection conn2 = **new** XMPPTCPConnection(config); -conn2.connect(); -``` - -Note that maximum security will be used when connecting to the server by -default (and when possible), including use of TLS encryption. The -ConnectionConfiguration class provides advanced control over the connection -created, such as the ability to disable or require encryption. See -[XMPPConnection Management](connections.md) for full details. - -Once you've created a connection, you should login with the -`XMPPConnection.login()` method. Once you've logged in, you can being -chatting with other users by creating new `Chat` or `GroupChat` -objects. - -Working with the Roster ----------------------- - -The roster lets you keep track of the availability (presence) of other users. -Users can be organized into groups such as "Friends" and "Co-workers", and -then you discover whether each user is online or offline. - -Retrieve the roster using the `Roster.getInstanceFor(XMPPConnection)` method. The roster -class allows you to find all the roster entries, the groups they belong to, -and the current presence status of each entry. - -Reading and Writing Stanzas - -Each message to the XMPP server from a client is called a packet and is sent -as XML. The `org.jivesoftware.smack.packet` package contains classes that -encapsulate the three different basic packet types allowed by XMPP (message, -presence, and IQ). Classes such as `Chat` and `GroupChat` provide higher-level -constructs that manage creating and sending packets automatically, but you can -also create and send packets directly. Below is a code example for changing -your presence to let people know you're unavailable and "out fishing": - -``` -// Create a new presence. Pass in false to indicate we're unavailable._ -Presence presence = new Presence(Presence.Type.unavailable); -presence.setStatus("Gone fishing"); -// Send the packet (assume we have an XMPPConnection instance called "con"). -con.sendStanza(presence); -``` - -Smack provides two ways to read incoming packets: `PacketListener`, and -`PacketCollector`. Both use `StanzaFilter` instances to determine which -packets should be processed. A packet listener is used for event style -programming, while a packet collector has a result queue of packets that you -can do polling and blocking operations on. So, a packet listener is useful -when you want to take some action whenever a packet happens to come in, while -a packet collector is useful when you want to wait for a specific packet to -arrive. Packet collectors and listeners can be created using an Connection -instance. - -Copyright (C) Jive Software 2002-2008 diff --git a/documentation/index.md b/documentation/index.md deleted file mode 100644 index 00e98e92e..000000000 --- a/documentation/index.md +++ /dev/null @@ -1,14 +0,0 @@ -**Smack Documentation** - -**Contents:** - - * [Overview](overview.md) - * [Getting Started Guide](gettingstarted.md) - * [Managing Connections](connections.md) - * [Messaging Basics](messaging.md) - * [Roster and Presence](roster.md) - * [Processing Incoming Stanzas](processing.md) - * [Provider Architecture](providers.md) - * [Debugging with Smack](debugging.md) - - * [Smack Extensions Manual](extensions/index.md) diff --git a/documentation/legacy/index.html b/documentation/legacy/index.html deleted file mode 100644 index d564b2416..000000000 --- a/documentation/legacy/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - -Smack Legacy User Manual - - - - - - - - -<H2>Smack Legacy User Manual</H2> - -<a href="toc.html">Smack Extensions User Manual</a> diff --git a/documentation/legacy/intro.html b/documentation/legacy/intro.html deleted file mode 100644 index bcc3b42ab..000000000 --- a/documentation/legacy/intro.html +++ /dev/null @@ -1,26 +0,0 @@ - - -Smack Extensions User Manual - - - - -
Smack Legacy Manual
-

The XMPP protocol includes a base protocol and many optional extensions - typically documented as "XEP's". Smack provides the smack-legacy artifcate, with - implementations of now obsolete XEPs. You should no longer use this code!

- -
Legacy Extensions

- - - - - - - - - - -
NameXEP #Description
Message EventsXEP-0022Requests and responds to message events.
- - diff --git a/documentation/legacy/messageevents.html b/documentation/legacy/messageevents.html deleted file mode 100644 index 4f03c7a6b..000000000 --- a/documentation/legacy/messageevents.html +++ /dev/null @@ -1,244 +0,0 @@ - - - Message Events - - - - - -

Message Events

- -This extension is used to request and respond to events relating to the delivery, -display, and composition of messages. There are three stages in this extension:

    -
  1. Request for event notifications, -
  2. Receive the event notification requests and send event notifications, and -
  3. Receive the event notifications.
-

For more information on each stage please follow these links:

- -XEP related: XEP-22 -
-

-Description

- -In order to receive event notifications for a given message you first have to specify -which events are you interested in. Each message that you send has to request its own event -notifications. Therefore, every message that you send as part of a chat should request its own event -notifications.

- -Usage

- -The class MessageEventManager provides an easy way for requesting event notifications. All you have to do is specify -the message that requires the event notifications and the events that you are interested in. -

Use the static method MessageEventManager.addNotificationsRequests(Message message, boolean offline, boolean -delivered, boolean displayed, boolean composing) for requesting event notifications. -

- -Example

-Below you can find an example that logs in a user to the server, creates a message, adds the requests -for notifications and sends the message. -

-
      // Connect to the server and log in
-      conn1 = new XMPPConnection(host);
-      conn1.login(server_user1, pass1);
-    
-      // Create a chat with user2
-      Chat chat1 = conn1.createChat(user2);
-    
-      // Create a message to send
-      Message msg = chat1.createMessage();
-      msg.setSubject("Any subject you want");
-      msg.setBody("An interesting body comes here...");
-      // Add to the message all the notifications requests (offline, delivered, displayed,
-      // composing)
-      MessageEventManager.addNotificationsRequests(msg, true, true, true, true);
-    
-      // Send the message that contains the notifications request
-      chat1.sendMessage(msg);
-
-
- -
- -

- -Description

- -You can receive notification requests for the following events: delivered, displayed, composing and offline. You -must listen for these requests and react accordingly.

- -Usage

- -The general idea is to create a new DefaultMessageEventRequestListener that will listen to the event notifications -requests and react with custom logic. Then you will have to add the listener to the -MessageEventManager that works on -the desired XMPPConnection. -

Note that DefaultMessageEventRequestListener is a default implementation of the -MessageEventRequestListener interface. -The class DefaultMessageEventRequestListener automatically sends a delivered notification to the sender of the message -if the sender has requested to be notified when the message is delivered. If you decide to create a new class that -implements the MessageEventRequestListener interface, please remember to send the delivered notification.

-
    -
  • To create a new MessageEventManager use the MessageEventManager(XMPPConnection) constructor. -
  • -
  • To create an event notification requests listener create a subclass of DefaultMessageEventRequestListener or - create a class that implements the MessageEventRequestListener interface. -
  • -
  • To add a listener to the messageEventManager use the MessageEventManager's message -addMessageEventRequestListener(MessageEventRequestListener).
  • -

- -Example

- -Below you can find an example that connects two users to the server. One user will create a message, add the requests -for notifications and will send the message to the other user. The other user will add a -DefaultMessageEventRequestListener -to a MessageEventManager that will listen and react to the event notification requested by the other user. -

-
      // Connect to the server and log in the users
-      conn1 = new XMPPTCPConnection(host);
-      conn1.login(server_user1, pass1);
-      conn2 = new XMPPTCPConnection(host);
-      conn2.login(server_user2, pass2);
-  
-      // User2 creates a MessageEventManager
-      MessageEventManager messageEventManager = new MessageEventManager(conn2);
-      // User2 adds the listener that will react to the event notifications requests
-      messageEventManager.addMessageEventRequestListener(new DefaultMessageEventRequestListener() {
-          public void deliveredNotificationRequested(
-              String from,
-              String packetID,
-              MessageEventManager messageEventManager) {
-              super.deliveredNotificationRequested(from, packetID, messageEventManager);
-              // DefaultMessageEventRequestListener automatically responds that the message was delivered when receives this request
-              System.out.println("Delivered Notification Requested (" + from + ", " + packetID + ")");
-          }
-
-          public void displayedNotificationRequested(
-              String from,
-              String packetID,
-              MessageEventManager messageEventManager) {
-              super.displayedNotificationRequested(from, packetID, messageEventManager);
-              // Send to the message's sender that the message was displayed
-              messageEventManager.sendDisplayedNotification(from, packetID);
-          }
-
-          public void composingNotificationRequested(
-              String from,
-              String packetID,
-              MessageEventManager messageEventManager) {
-              super.composingNotificationRequested(from, packetID, messageEventManager);
-              // Send to the message's sender that the message's receiver is composing a reply
-              messageEventManager.sendComposingNotification(from, packetID);
-          }
-
-          public void offlineNotificationRequested(
-              String from,
-              String packetID,
-              MessageEventManager messageEventManager) {
-              super.offlineNotificationRequested(from, packetID, messageEventManager);
-              // The XMPP server should take care of this request. Do nothing.
-              System.out.println("Offline Notification Requested (" + from + ", " + packetID + ")");
-          }
-      });
-
-      // User1 creates a chat with user2
-      Chat chat1 = conn1.createChat(user2);
-    
-      // User1 creates a message to send to user2
-      Message msg = chat1.createMessage();
-      msg.setSubject("Any subject you want");
-      msg.setBody("An interesting body comes here...");
-      // User1 adds to the message all the notifications requests (offline, delivered, displayed,
-      // composing)
-      MessageEventManager.addNotificationsRequests(msg, true, true, true, true);
-    
-      // User1 sends the message that contains the notifications request
-      chat1.sendMessage(msg);
-      Thread.sleep(500);
-      // User2 sends to the message's sender that the message's receiver cancelled composing a reply
-      messageEventManager.sendCancelledNotification(user1, msg.getPacketID());
-
-
- -
- -

- -Description

- -Once you have requested for event notifications you will start to receive notifications of events. You can -receive notifications of the following events: delivered, displayed, composing, offline and cancelled. You -will probably want to react to some or all of these events.

- -Usage

- -The general idea is to create a new MessageEventNotificationListener that will listen to the event notifications -and react with custom logic. Then you will have to add the listener to the MessageEventManager that works on -the desired XMPPConnection. -

    -
  • To create a new MessageEventManager use the MessageEventManager(XMPPConnection) constructor. -
  • -
  • To create an event notifications listener create a class that implements the MessageEventNotificationListener - interface. -
  • -
  • To add a listener to the messageEventManager use the MessageEventManager's message -addMessageEventNotificationListener(MessageEventNotificationListener).
  • -

- -Example

-Below you can find an example that logs in a user to the server, adds a MessageEventNotificationListener -to a MessageEventManager that will listen and react to the event notifications, creates a message, adds -the requests for notifications and sends the message. -

-
      // Connect to the server and log in
-      conn1 = new XMPPTCPConnection(host);
-      conn1.login(server_user1, pass1);
-  
-      // Create a MessageEventManager
-      MessageEventManager messageEventManager = new MessageEventManager(conn1);
-      // Add the listener that will react to the event notifications
-      messageEventManager.addMessageEventNotificationListener(new MessageEventNotificationListener() {
-          public void deliveredNotification(String from, String packetID) {
-              System.out.println("The message has been delivered (" + from + ", " + packetID + ")");
-          }
-    
-          public void displayedNotification(String from, String packetID) {
-              System.out.println("The message has been displayed (" + from + ", " + packetID + ")");
-          }
-    
-          public void composingNotification(String from, String packetID) {
-              System.out.println("The message's receiver is composing a reply (" + from + ", " + packetID + ")");
-          }
-    
-          public void offlineNotification(String from, String packetID) {
-              System.out.println("The message's receiver is offline (" + from + ", " + packetID + ")");
-          }
-    
-          public void cancelledNotification(String from, String packetID) {
-              System.out.println("The message's receiver cancelled composing a reply (" + from + ", " + packetID + ")");
-          }
-      });
-
-      // Create a chat with user2
-      Chat chat1 = conn1.createChat(user2);
-    
-      // Create a message to send
-      Message msg = chat1.createMessage();
-      msg.setSubject("Any subject you want");
-      msg.setBody("An interesting body comes here...");
-      // Add to the message all the notifications requests (offline, delivered, displayed,
-      // composing)
-      MessageEventManager.addNotificationsRequests(msg, true, true, true, true);
-    
-      // Send the message that contains the notifications request
-      chat1.sendMessage(msg);
-
-
- - - - diff --git a/documentation/legacy/toc.html b/documentation/legacy/toc.html deleted file mode 100644 index 6ee245e50..000000000 --- a/documentation/legacy/toc.html +++ /dev/null @@ -1,19 +0,0 @@ - - -Smack Legacy User Manual - - - - - - -Introduction

- -

Smack Legacy Extensions

- -

-Message Events
-

- - - diff --git a/documentation/messaging.md b/documentation/messaging.md deleted file mode 100644 index 3aa595dae..000000000 --- a/documentation/messaging.md +++ /dev/null @@ -1,95 +0,0 @@ -Messaging using Chats -===================== - -[Back](index.md) - -Sending messages back and forth is at the core of instant messaging. Although -individual messages can be sent and received as packets, it's generally easier -to treat the string of messages as a chat using the -`org.jivesoftware.smack.Chat` class. - -Chat ----- - -A chat creates a new thread of messages (using a thread ID) between two users. -The following code snippet demonstrates how to create a new Chat with a user -and then send them a text message: - -``` -// Assume we've created an XMPPConnection name "connection"._ -ChatManager chatmanager = ChatManager.getInstanceFor(connection); -Chat newChat = chatmanager.createChat("jsmith@jivesoftware.com", new MessageListener() { - public void processMessage(Chat chat, Message message) { - System.out.println("Received message: " + message); - } -}); - -try { - newChat.sendMessage("Howdy!"); -} -catch (XMPPException e) { - System.out.println("Error Delivering block"); -} -``` - -The `Chat.sendMessage(String)` method is a convenience method that creates a -Message object, sets the body using the String parameter, then sends the -message. In the case that you wish to set additional values on a Message -before sending it, use the `Chat.createMessage()` and -`Chat.sendMessage(Message)` methods, as in the following code snippet: - -``` -Message newMessage = new Message(); -newMessage.setBody("Howdy!"); -message.setProperty("favoriteColor", "red"); -newChat.sendMessage(newMessage); -``` - -You'll also notice in the example above that we specified a MessageListener -when creating a chat. The listener is notified any time a new message arrives -from the other user in the chat. The following code snippet uses the listener -as a parrot-bot -- it echoes back everything the other user types. - -``` -// Assume a MessageListener we've setup with a chat._ - -public void processMessage(Chat chat, Message message) { - // Send back the same text the other user sent us._ - chat.sendMessage(message.getBody()); -} -``` - -Incoming Chat -------------- - -When chats are prompted by another user, the setup is slightly different since -you are receiving a chat message first. Instead of explicitly creating a chat -to send messages, you need to register to handle newly created Chat instances -when the ChatManager creates them. The ChatManager will already find a -matching chat (by thread id) and if none exists, then it will create a new one -that does match. To get this new chat, you have to register to be notified -when it happens. You can register a message listener to receive all future -messages as part of this handler. - -``` -// Assume we've created an XMPPConnection name "connection"._ -ChatManager chatManager = ChatManager.getInstanceFor(connection); -chatManager.addChatListener( - new ChatManagerListener() { - @Override - public void chatCreated(Chat chat, boolean createdLocally) - { - if (!createdLocally) - chat.addMessageListener(new MyNewMessageListener());; - } - }); -``` - -In addition to thread based chat messages, there are some clients that do not -send a thread id as part of the chat. To handle this scenario, Smack will -attempt match the incoming messages to the best fit existing chat, based on -the JID. It will attempt to find a chat with the same full JID, failing that, -it will try the base JID. If no existing chat to the user can found, then a -new one is created. - -Copyright (C) Jive Software 2002-2008 diff --git a/documentation/overview.md b/documentation/overview.md deleted file mode 100644 index 9c9d00334..000000000 --- a/documentation/overview.md +++ /dev/null @@ -1,48 +0,0 @@ -Smack Overview -============== - -[Back](index.md) - -Smack is a library for communicating with XMPP servers to perform real-time -communications, including instant messaging and group chat. - -Smack Key Advantages --------------------- - - * Extremely simple to use, yet powerful API. Sending a text message to a user can be accomplished in only a few lines of code: - - ```java - AbstractXMPPConnection connection = new XMPPTCPConnection("mtucker", "password", "jabber.org"); - connection.connect().login(); - - Chat chat = ChatManager.getInstanceFor(connection) - .createChat("jsmith@jivesoftware.com", new MessageListener() { - - public void processMessage(Chat chat, Message message) { - System.out.println("Received message: " + message); - } - }); - chat.sendMessage("Howdy!"); - ``` - -* Doesn't force you to code at the packet level, as other libraries do. Smack provides intelligent higher level constructs such as the `Chat` and `Roster` classes, which let you program more efficiently. - * Does not require that you're familiar with the XMPP XML format, or even that you're familiar with XML. - * Provides easy machine to machine communication. Smack lets you set any number of properties on each message, including properties that are Java objects. - * Open Source under the Apache License, which means you can incorporate Smack into your commercial or non-commercial applications. - -About XMPP ----------- - -XMPP (eXtensible Messaging and Presence Protocol) is an open protocol -standardized by the IETF and supported and extended by the XMPP Standards -Foundation (([http://www.xmpp.org](http://www.xmpp.org)). - -How To Use This Documentation ------------------------------ - -This documentation assumes that you're already familiar with the main features -of XMPP instant messaging. It's also highly recommended that you open the -Javadoc API guide and use that as a reference while reading through this -documentation. - -Copyright (C) Jive Software 2002-2008 diff --git a/documentation/processing.md b/documentation/processing.md deleted file mode 100644 index 868b88d4c..000000000 --- a/documentation/processing.md +++ /dev/null @@ -1,58 +0,0 @@ -Processing Incoming Stanzas -=========================== - -[Back](index.md) - -Smack provides a flexible framework for processing incoming packets using two -constructs: - - * `org.jivesoftware.smack.PacketCollector` -- a class that lets you synchronously wait for new packets. - * `org.jivesoftware.smack.PacketListener` -- an interface for asynchronously notifying you of incoming packets. A packet listener is used for event style programming, while a packet collector has a result queue of packets that you can do polling and blocking operations on. So, a packet listener is useful when you want to take some action whenever a packet happens to come in, while a packet collector is useful when you want to wait for a specific packet to arrive. Packet collectors and listeners can be created using an `XMPPConnection` instance. - -The `org.jivesoftware.smack.filter.StanzaFilter` interface determines which -specific packets will be delivered to a `PacketCollector` or `PacketListener`. -Many pre-defined filters can be found in the `org.jivesoftware.smack.filter` -package. - -The following code snippet demonstrates registering both a packet collector -and a packet listener: - -``` -// Create a packet filter to listen for new messages from a particular -// user. We use an AndFilter to combine two other filters._ -StanzaFilter filter = new AndFilter(new StanzaTypeFilter(Message.class), - new FromContainsFilter("mary@jivesoftware.com")); -// Assume we've created an XMPPConnection name "connection". - -// First, register a packet collector using the filter we created. -PacketCollector myCollector = connection.createPacketCollector(filter); -// Normally, you'd do something with the collector, like wait for new packets. - -// Next, create a packet listener. We use an anonymous inner class for brevity. -PacketListener myListener = new PacketListener() { - **public** **void** processPacket(Packet packet) { - // Do something with the incoming packet here._ - } - }; -// Register the listener._ -connection.addPacketListener(myListener, filter); -``` - -Standard Stanza Filters ------------------------ - -A rich set of packet filters are included with Smack, or you can create your -own filters by coding to the `StanzaFilter` interface. The default set of -filters includes: - - * `StanzaTypeFilter` -- filters for packets that are a particular Class type. - * `StanzaIdFilter` -- filters for packets with a particular packet ID. - * `ThreadFilter` -- filters for message packets with a particular thread ID. - * `ToContainsFilter` -- filters for packets that are sent to a particular address. - * `FromContainsFilter` -- filters for packets that are sent to a particular address. - * `StanzaExtensionFilter` -- filters for packets that have a particular packet extension. - * `AndFilter` -- implements the logical AND operation over two filters. - * `OrFilter` -- implements the logical OR operation over two filters. - * `NotFilter` -- implements the logical NOT operation on a filter. - -Copyright (C) Jive Software 2002-2008 diff --git a/documentation/providers.md b/documentation/providers.md deleted file mode 100644 index 954fc64e3..000000000 --- a/documentation/providers.md +++ /dev/null @@ -1,345 +0,0 @@ -Provider Architecture: Stanza Extensions and Custom IQ's -======================================================== - -[Back](index.md) - -Introduction ------------- - -The Smack provider architecture is a system for plugging in custom XML parsing -of packet extensions and IQ packets. The standard [Smack -Extensions](extensions/index.md) are built using the provider architecture. -There are two types of providers: - - * `IQProvider` -- parses IQ requests into Java objects. - * `Extension Provider` -- parses XML sub-documents attached to packets into PacketExtension instances. By default, Smack only knows how to process a few standard packets and sub-packets that are in a few namespaces such as: - * jabber:iq:auth - * jabber:iq:roster - * jabber:iq:register There are many more IQ types and extensions that are part of XMPP standards, and of course an endless number that can be added as custom extensions. To support this, an extensible parsing mechanism is provided via Smack and user build providers. - -Whenever a packet extension is found in a packet, parsing will be -passed to the correct provider. Each provider must implement the -PacketExtensionProvider interface. Each extension provider is -responsible for parsing the raw XML stream, via the -[XML Pull Parser](http://www.xmlpull.org/), to contruct an object. - -You can also create an introspection provider -(`provider.IntrospectionProvider.PacketExtensionIntrospectionProvider`). Here, -bean introspection is used to try to automatically set the properties -of the class using the values in the packet extension sub-element. - -When no extension provider is registered for an element name and namespace -combination, Smack will store all top-level elements of the sub-packet in the -DefaultPacketExtension object and then attach it to the packet. - -Management of these providers is accomplished via the [ProviderManager]() -class. There are multiple ways to add providers to the manager. - - * Call addXXProvider methods - You can call the appropriate add methods directly. - -``` -ProviderManager.addIQProvider("element", "namespace", new MyIQProvider()); -ProviderManager.addExtensionProvider("element", "namespace", new MyExtProvider()); -``` - - * Add a loader - You can add a ProviderLoader which will inject a means of loading multiple providers (both types) into the manager. This is the mechanism used by Smack to load from the Smack specific file format (via ProviderFileLoader). Implementers can provide the means to load providers from any source they wish, or simply reuse the ProviderFileLoader to load from their own provider files. - - - ProviderManager.addLoader(new ProviderFileLoader(FileUtils.getStreamForUrl("classpath:com/myco/provider/myco_custom.providers", null))); - - - * VM Argument - You can add a provider file via the VM argument _smack.provider.file_. This will load the file at the specified URL during startup when Smack initializes. This also assumes the default configuration, since it requires that the **VmArgInitializer** was part of the startup configuration. - - -`-Dsmack.provider.file=classpath:com/myco/provider/myco_custom.provider`s - -or - -`-Dsmack.provider.file=file:///c:/myco/provider/myco_custom.providers` - - -IQ Providers ------------- - -The IQ provider class must implement the IQProvider interface. Each -IQProvider is responsible for parsing the raw XML stream to create an -IQ instance. - -You can also create an introspection provider -(`provider.IntrospectionProvider.IQIntrospectionProvider`). Which -uses, bean introspection to try to automatically set properties of the -IQ instance using the values found in the IQ packet XML. For example, -an XMPP time packet resembles the following: - -### Introspection - -_Time Stanza_ - - - - - 20020910T17:58:35 - MDT - Tue Sep 10 12:58:35 2002 - - - - -_Time IQ Class_ - - - class Time extends IQ { - private Date utc; - private TimeZone timeZone; - private String display; - - @Override - public String getChildElementXML() { - return null; - } - - public void setUtc(String utcString) { - try { - utc = StringUtils.parseDate(utcString); - } catch (ParseException e) { - } - } - - public void setTimeZone(String zone) { - timeZone = TimeZone.getTimeZone(zone); - } - - public void setDisplay(String timeDisplay) { - display = timeDisplay; - } - } - -_Time Provider_ - -```java -public class TimeProvider extends IQIntrospectionProvider