Try to escape _ in markdown

This commit is contained in:
steckbrief 2025-01-06 16:41:03 +01:00
parent 34d3918770
commit 0459210dc3
93 changed files with 5022 additions and 86 deletions

View file

@ -1,23 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="lib" path="libs/3rdParty/smack/smack-core-4.2.1.jar" sourcepath="/smack-core/src"/>
<classpathentry kind="lib" path="libs/3rdParty/smack/smack-extensions-4.2.1.jar"/>
<classpathentry kind="lib" path="libs/3rdParty/jxmpp-core-0.5.0.jar"/>
<classpathentry kind="lib" path="libs/3rdParty/jxmpp-jid-0.5.0.jar"/>
<classpathentry kind="lib" path="libs/3rdParty/xmlpull-1.1.3.1.jar"/>
<classpathentry kind="lib" path="libs/3rdParty/xpp3_min-1.1.4c.jar"/>
<classpathentry kind="lib" path="libs/3rdParty/smack/smack-experimental-4.2.1.jar" sourcepath="/smack-experimental"/>
<classpathentry kind="lib" path="libs/3rdParty/smack/smack-java7-4.2.1.jar"/>
<classpathentry kind="lib" path="libs/3rdParty/smack/smack-resolver-minidns-4.2.1.jar"/>
<classpathentry kind="lib" path="libs/3rdParty/smack/smack-tcp-4.2.1.jar" sourcepath="/smack-tcp"/>
<classpathentry kind="lib" path="libs/3rdParty/minidns-core-0.2.4.jar"/>
<classpathentry kind="lib" path="libs/3rdParty/minidns-hla-0.2.4.jar"/>
<classpathentry kind="lib" path="libs/3rdParty/minidns-iterative-resolver-0.2.4.jar"/>
<classpathentry kind="lib" path="libs/3rdParty/minidns-dnssec-0.2.4.jar"/>
<classpathentry kind="lib" path="libs/3rdParty/jxmpp-util-cache-0.5.0.jar"/>
<classpathentry kind="lib" path="libs/3rdParty/smack/smack-im-4.2.1.jar"/>
<classpathentry kind="lib" path="libs/3rdParty/smack/smack-sasl-javax-4.2.1.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/smack/smack-core-4.4.8.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/smack/smack-extensions-4.4.8.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/smack/smack-streammanagement-4.4.8.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/smack/smack-xmlparser-4.4.8.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/smack/smack-xmlparser-xpp3-4.4.8.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/xmlpull-1.1.3.1.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/xpp3_min-1.1.4c.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/smack/smack-experimental-4.4.8.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/smack/smack-java8-4.4.8.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/smack/smack-resolver-javax-4.4.8.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/smack/smack-tcp-4.4.8.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/minidns-core-1.1.0.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/jxmpp-core-1.1.0.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/jxmpp-repl-1.1.0.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/jxmpp-stringprep-libidn-1.1.0.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/jxmpp-util-cache-1.1.0.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/smack/smack-im-4.4.8.jar"/>
<classpathentry kind="lib" path="c:/Users/tzur/development/MamLoader/MamHistoryLoader/libs/3rdParty/smack/smack-sasl-javax-4.4.8.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

Binary file not shown.

View file

@ -0,0 +1,2 @@
#Fri Jan 03 15:30:29 CET 2025
gradle.version=8.8

Binary file not shown.

BIN
.gradle/file-system.probe Normal file

Binary file not shown.

View file

View file

@ -14,4 +14,15 @@
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
<filteredResources>
<filter>
<id>1735908922007</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

33
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,33 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Current File",
"request": "launch",
"mainClass": "${file}"
},
{
"type": "java",
"name": "MamLoader",
"request": "launch",
"mainClass": "de.thedevstack.xmpp.mamloader.MamLoader",
"projectName": "MamHistoryLoader",
"args": "tristan@jabber.mail-zur.de lookshe@jabber.thehappy.de -limit 10"
},
{
"type": "java",
"name": "MamLoader oldest message",
"request": "launch",
"mainClass": "de.thedevstack.xmpp.mamloader.MamLoader",
"projectName": "MamHistoryLoader",
"args": "tristan@jabber.mail-zur.de lookshe@jabber.thehappy.de -limit -1"
}
]
}

View file

@ -1,9 +1,9 @@
# MamHistoryLoader
## Build
Build using ant with the target "create__run__jar"
Build using ant with the target "create\_run\_jar"
## Run
```
java -jar <YOUR-JID> <CONTACT-JID> [-debug] [-start dd.MM.yyyy] [-end dd.MM.yyyy] [-limit <MAX-MESSAGE-COUNT>]
java -jar MamHistoryLoader.jar <YOUR-JID> <CONTACT-JID> [-debug] [-from dd.MM.yyyy] [-to dd.MM.yyyy] [-limit <MAX-MESSAGE-COUNT>]
```
The options -start and -limit cannot be used together.
The options -from and -limit cannot be used together.

26
build.gradle Normal file
View file

@ -0,0 +1,26 @@
plugins {
id 'application'
}
repositories {
mavenCentral()
}
apply plugin: 'application'
application {
mainClass = 'de.thedevstack.xmpp.mamloader.MamLoader'
}
dependencies {
implementation "org.jxmpp:jxmpp-core:1.1.0"
implementation "org.igniterealtime.smack:smack-java8:4.4.8"
// Optional for XMPPTCPConnection
implementation "org.igniterealtime.smack:smack-tcp:4.4.8"
// Optional for XMPP-IM (RFC 6121) support (Roster, Threaded Chats, )
implementation "org.igniterealtime.smack:smack-im:4.4.8"
// Optional for XMPP extensions support
implementation "org.igniterealtime.smack:smack-extensions:4.4.8"
// Optional for XMPP extensions support
implementation "org.igniterealtime.smack:smack-experimental:4.4.8"
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,248 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://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.
#
##############################################################################
#
# MamHistoryLoader start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh MamHistoryLoader
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and MAM_HISTORY_LOADER_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}.." > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/lib/MamHistoryLoader.jar:$APP_HOME/lib/smack-java8-4.4.8.jar:$APP_HOME/lib/smack-tcp-4.4.8.jar:$APP_HOME/lib/smack-experimental-4.4.8.jar:$APP_HOME/lib/smack-extensions-4.4.8.jar:$APP_HOME/lib/smack-im-4.4.8.jar:$APP_HOME/lib/smack-resolver-javax-4.4.8.jar:$APP_HOME/lib/smack-sasl-javax-4.4.8.jar:$APP_HOME/lib/smack-streammanagement-4.4.8.jar:$APP_HOME/lib/smack-core-4.4.8.jar:$APP_HOME/lib/jxmpp-jid-1.0.3.jar:$APP_HOME/lib/jxmpp-core-1.1.0.jar:$APP_HOME/lib/jxmpp-util-cache-1.1.0.jar:$APP_HOME/lib/smack-xmlparser-stax-4.4.8.jar:$APP_HOME/lib/hsluv-0.2.jar:$APP_HOME/lib/smack-xmlparser-4.4.8.jar:$APP_HOME/lib/minidns-core-1.0.5.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and MAM_HISTORY_LOADER_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and MAM_HISTORY_LOADER_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
-classpath "$CLASSPATH" \
de.thedevstack.xmpp.mamloader.MamLoader \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $MAM_HISTORY_LOADER_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

View file

@ -0,0 +1,92 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem MamHistoryLoader startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%..
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and MAM_HISTORY_LOADER_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\lib\MamHistoryLoader.jar;%APP_HOME%\lib\smack-java8-4.4.8.jar;%APP_HOME%\lib\smack-tcp-4.4.8.jar;%APP_HOME%\lib\smack-experimental-4.4.8.jar;%APP_HOME%\lib\smack-extensions-4.4.8.jar;%APP_HOME%\lib\smack-im-4.4.8.jar;%APP_HOME%\lib\smack-resolver-javax-4.4.8.jar;%APP_HOME%\lib\smack-sasl-javax-4.4.8.jar;%APP_HOME%\lib\smack-streammanagement-4.4.8.jar;%APP_HOME%\lib\smack-core-4.4.8.jar;%APP_HOME%\lib\jxmpp-jid-1.0.3.jar;%APP_HOME%\lib\jxmpp-core-1.1.0.jar;%APP_HOME%\lib\jxmpp-util-cache-1.1.0.jar;%APP_HOME%\lib\smack-xmlparser-stax-4.4.8.jar;%APP_HOME%\lib\hsluv-0.2.jar;%APP_HOME%\lib\smack-xmlparser-4.4.8.jar;%APP_HOME%\lib\minidns-core-1.0.5.jar
@rem Execute MamHistoryLoader
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %MAM_HISTORY_LOADER_OPTS% -classpath "%CLASSPATH%" de.thedevstack.xmpp.mamloader.MamLoader %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable MAM_HISTORY_LOADER_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%MAM_HISTORY_LOADER_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

Binary file not shown.

View file

@ -0,0 +1,2 @@
Manifest-Version: 1.0

1
gradle.properties Normal file
View file

@ -0,0 +1 @@
org.gradle.java.home=c:\\Program Files\\Microsoft\\jdk-21.0.5.11-hotspot\\

Binary file not shown.

BIN
libs/3rdParty/jxmpp-core-1.1.0.jar vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
libs/3rdParty/jxmpp-jid-1.1.0.jar vendored Normal file

Binary file not shown.

BIN
libs/3rdParty/jxmpp-repl-1.1.0.jar vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
libs/3rdParty/jxmpp-util-cache-1.1.0.jar vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
libs/3rdParty/minidns-core-1.1.0.jar vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
libs/3rdParty/smack/smack-core-4.4.8.jar vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
libs/3rdParty/smack/smack-im-4.4.8.jar vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
libs/3rdParty/smack/smack-tcp-4.4.8.jar vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -20,7 +20,9 @@ import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jivesoftware.smackx.forward.packet.Forwarded;
import org.jivesoftware.smackx.mam.MamManager;
import org.jivesoftware.smackx.mam.MamManager.MamQueryResult;
import org.jivesoftware.smackx.mam.MamManager.MamQuery;
import org.jivesoftware.smackx.mam.MamManager.MamQueryArgs;
import org.jivesoftware.smackx.mam.element.MamElements.MamResultExtension;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.impl.JidCreate;
@ -42,15 +44,16 @@ public class MamLoadClient {
}
private void connectAndLogin(String username, String password, String host) throws SmackException, IOException, XMPPException, InterruptedException {
XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
XMPPTCPConnectionConfiguration.Builder configBuilder = XMPPTCPConnectionConfiguration.builder()
.setUsernameAndPassword(username, password)
.setXmppDomain(host)
.setHost(host)
.setDebuggerEnabled(this.debug)
//.setCustomSSLContext(SSLHelper.createNaiveSSLContext())
.setResource("MAMLoader_" + UUID.randomUUID())
.setSendPresence(false)
.build();
.setSendPresence(false);
if (this.debug) {
configBuilder.enableDefaultDebugger();
}
XMPPTCPConnectionConfiguration config = configBuilder.build();
connection = new XMPPTCPConnection(config);
connection.connect();
connection.login();
@ -59,61 +62,64 @@ public class MamLoadClient {
}
public void disconnect() {
if (null != this.connection) {
this.connection.disconnect();
}
}
public List<Forwarded> loadHistory(String jid) throws XmppStringprepException, NoResponseException, XMPPErrorException, NotConnectedException, NotLoggedInException, InterruptedException {
public List<MamMessage> loadHistory(String jid) throws XmppStringprepException, NoResponseException, XMPPErrorException, NotConnectedException, NotLoggedInException, InterruptedException {
return this.loadHistory(jid, null, null);
}
public List<Forwarded> loadHistory(String jid, Date start) throws XmppStringprepException, NoResponseException, XMPPErrorException, NotConnectedException, NotLoggedInException, InterruptedException {
public List<MamMessage> loadHistory(String jid, Date start) throws XmppStringprepException, NoResponseException, XMPPErrorException, NotConnectedException, NotLoggedInException, InterruptedException {
return this.loadHistory(jid, start, null);
}
public List<Forwarded> loadHistory(String jid, Date start, Date end) throws XmppStringprepException, NoResponseException, XMPPErrorException, NotConnectedException, NotLoggedInException, InterruptedException {
List<Forwarded> allMessages = new ArrayList<>();
public List<MamMessage> loadHistory(String jid, Date start, Date end) throws XmppStringprepException, NoResponseException, XMPPErrorException, NotConnectedException, NotLoggedInException, InterruptedException {
List<MamMessage> allMessages = new ArrayList<>();
if (mamManager.isSupported()) {
Jid withJid = JidCreate.bareFrom(jid);
MamQueryResult archive = mamManager.queryArchive(null, start, end, withJid, null);
allMessages.addAll(archive.forwardedMessages);
while (!archive.mamFin.isComplete()) {
archive = mamManager.pageNext(archive, LIMIT_PER_REQUEST);
allMessages.addAll(archive.forwardedMessages);
}
allMessages = this.filterAndSort(allMessages);
MamQueryArgs mamQueryArgs = MamQueryArgs.builder()
.limitResultsToJid(withJid)
.limitResultsSince(start)
.limitResultsBefore(end)
.build();
MamQuery archive = mamManager.queryArchive(mamQueryArgs);
allMessages = this.convertResult(archive);
} else {
throw new RuntimeException("MAM not supported");
}
return allMessages;
}
public List<Forwarded> loadHistory(String jid, int limit) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, NotLoggedInException, XmppStringprepException {
List<Forwarded> allMessages = new ArrayList<>();
public List<MamMessage> loadHistory(String jid, int limit) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, NotLoggedInException, XmppStringprepException {
List<MamMessage> allMessages = new ArrayList<>();
if (mamManager.isSupported()) {
Jid withJid = JidCreate.bareFrom(jid);
MamQueryResult archive = mamManager.mostRecentPage(withJid, LIMIT_PER_REQUEST);
MamQuery archive = mamManager.queryMostRecentPage(withJid, limit);
allMessages.addAll(archive.forwardedMessages);
while (!archive.mamFin.isComplete() && limit > allMessages.size()) {
int requestLimit = limit - allMessages.size();
archive = mamManager.pagePrevious(archive, (requestLimit < LIMIT_PER_REQUEST ? requestLimit : LIMIT_PER_REQUEST));
allMessages.addAll(archive.forwardedMessages);
}
allMessages = this.filterAndSort(allMessages);
allMessages = this.convertResult(archive);
} else {
throw new RuntimeException("MAM not supported");
}
return allMessages;
}
private List<Forwarded> filterAndSort(List<Forwarded> messages) {
return messages.stream()
.filter(forwarded -> forwarded.getForwardedStanza() instanceof Message
&& ((Message)forwarded.getForwardedStanza()).getBody() != null)
.sorted(new Comparator<Forwarded>() {
private List<MamMessage> convertResult(MamQuery mamQuery) {
List<MamMessage> allMessages = new ArrayList<>();
for (MamResultExtension mre : mamQuery.getMamResultExtensions()) {
Date date = mre.getForwarded().getDelayInformation().getStamp();
Message message = mre.getForwarded().getForwardedStanza();
allMessages.add(new MamMessage(message, date));
}
return allMessages.stream()
.sorted(new Comparator<MamMessage>() {
@Override
public int compare(Forwarded o1, Forwarded o2) {
return o1.getDelayInformation().getStamp().compareTo(o2.getDelayInformation().getStamp());
public int compare(MamMessage o1, MamMessage o2) {
return o1.getDate().compareTo(o2.getDate());
}
})
.collect(Collectors.toList());

View file

@ -12,8 +12,6 @@ import java.util.List;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smackx.forward.packet.Forwarded;
public class MamLoader {
private static final SimpleDateFormat SDF = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
@ -96,10 +94,11 @@ public class MamLoader {
mlc.connectAndLogin(myjid, password);
// mlc.loadHistory(jid, Date.from(LocalDate.of(2017, 11, 8).atStartOfDay().toInstant(ZoneOffset.UTC)), Date.from(LocalDate.of(2017, 11, 9).atStartOfDay().toInstant(ZoneOffset.UTC)));
// mlc.loadHistory(jid);
List<Forwarded> messages = null;
List<MamMessage> messages = null;
if (start == null && -1 == limit) {
messages = mlc.loadHistory(jid);
//printMessage(messages.get(0), jid, false);
} else if (start == null && -1 < limit) {
messages = mlc.loadHistory(jid, limit);
} else if (start != null && end == null) {
@ -111,10 +110,14 @@ public class MamLoader {
System.out.println(messages.size() + " messages found");
printMessagesWithBody(messages, jid);
} catch(Exception e) {
e.printStackTrace();
} finally {
if (null != mlc) {
mlc.disconnect();
}
}
}
private static Date parseDate(String dateToParse) {
try {
@ -128,26 +131,36 @@ public class MamLoader {
}
}
private static void printMessagesWithBody(List<Forwarded> messages, String withJid) {
for (Forwarded f : messages) {
Stanza stanza = f.getForwardedStanza();
if (stanza instanceof Message) {
StringBuilder sb = new StringBuilder();
Message message = (Message) stanza;
private static void printMessagesWithBody(List<MamMessage> messages, String withJid) {
for (MamMessage mamMessage : messages) {
printMessage(mamMessage, withJid, true);
}
}
if (null != message.getBody()) {
private static void printMessage(MamMessage mamMessage, String withJid, boolean onlyWithBody) {
StringBuilder sb = new StringBuilder();
Message message = mamMessage.getMessage();
if (onlyWithBody && null != message.getBody()) {
if (withJid.equals(message.getFrom().asBareJid().toString())) {
sb.append("<");
} else {
sb.append(">");
}
sb.append(" ");
sb.append(SDF.format(f.getDelayInformation().getStamp()));
sb.append(SDF.format(mamMessage.getDate()));
sb.append(": ");
sb.append(message.getBody());
System.out.println(sb.toString());
} else if (!onlyWithBody) {
if (withJid.equals(message.getFrom().asBareJid().toString())) {
sb.append("<");
} else {
sb.append(">");
}
}
sb.append(" ");
sb.append(SDF.format(mamMessage.getDate()));
System.out.println(sb.toString());
}
}

View file

@ -0,0 +1,23 @@
package de.thedevstack.xmpp.mamloader;
import java.util.Date;
import org.jivesoftware.smack.packet.Message;
public final class MamMessage {
private Message message;
private Date date;
public MamMessage(Message message, Date date) {
this.message = message;
this.date = date;
}
public Message getMessage() {
return this.message;
}
public Date getDate() {
return this.date;
}
}

View file

@ -0,0 +1,34 @@
/**
*
* Copyright © 2015-2016 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid;
/**
* An XMPP address (JID) which has no {@link org.jxmpp.jid.parts.Resourcepart}. Either
* {@link EntityBareJid} or {@link DomainBareJid}.
* <p>
* Examples:
* </p>
* <ul>
* <li><code>localpart@domain.part</code></li>
* <li><code>domain.part</code></li>
* </ul>
*
* @see Jid
*/
public interface BareJid extends Jid {
}

View file

@ -0,0 +1,33 @@
/**
*
* Copyright © 2014-2016 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid;
/**
* An XMPP address (JID) consisting of the domainpart. For example "xmpp.org".
* <p>
* Examples:
* </p>
* <ul>
* <li><code>xmpp.org</code></li>
* <li><code>example.net</code></li>
* </ul>
*
* @see Jid
*/
public interface DomainBareJid extends Jid, BareJid, DomainJid {
}

View file

@ -0,0 +1,34 @@
/**
*
* Copyright © 2014-2016 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid;
/**
* An XMPP address (JID) consisting of a domainpart and a resourcepart. For example
* "xmpp.org/resource".
* <p>
* Examples:
* </p>
* <ul>
* <li><code>domain.part/resource</code></li>
* <li><code>example.net/8c6def89</code></li>
* </ul>
*
* @see Jid
*/
public interface DomainFullJid extends Jid, FullJid, DomainJid {
}

View file

@ -0,0 +1,34 @@
/**
*
* Copyright © 2015-2016 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid;
/**
* An XMPP address (JID) which has no {@link org.jxmpp.jid.parts.Localpart}. Either
* {@link DomainBareJid} or {@link DomainFullJid}.
* <p>
* Examples:
* </p>
* <ul>
* <li><code>domain.part</code></li>
* <li><code>domain.part/resourcepart</code></li>
* </ul>
*
* @see Jid
*/
public interface DomainJid extends Jid {
}

View file

@ -0,0 +1,34 @@
/**
*
* Copyright © 2014-2016 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid;
/**
* An XMPP address (JID) consisting of a localpart and a domainpart. For example
* "user@xmpp.org".
* <p>
* Examples:
* </p>
* <ul>
* <li><code>localpart@domain.part</code></li>
* <li><code>user@example.net</code></li>
* </ul>
*
* @see Jid
*/
public interface EntityBareJid extends Jid, EntityJid, BareJid {
}

View file

@ -0,0 +1,34 @@
/**
*
* Copyright © 2014-2016 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid;
/**
* An XMPP address (JID) consisting of a localpart, domainpart and resourcepart. For example
* "user@xmpp.org/resource".
* <p>
* Examples:
* </p>
* <ul>
* <li><code>localpart@domain.part/resource</code></li>
* <li><code>juliet@xmpp.org/balcony</code></li>
* </ul>
*
* @see Jid
*/
public interface EntityFullJid extends Jid, FullJid, EntityJid {
}

View file

@ -0,0 +1,56 @@
/**
*
* Copyright © 2014-2018 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid;
import org.jxmpp.jid.parts.Localpart;
/**
* An XMPP address (JID) which has a {@link Localpart}. Either {@link EntityBareJid} or {@link EntityFullJid}.
* <p>
* Examples:
* </p>
* <ul>
* <li><code>localpart@domain.part</code></li>
* <li><code>localpart@domain.part/resourcepart</code></li>
* </ul>
*
* @see Jid
*/
public interface EntityJid extends Jid {
/**
* Return the {@link Localpart} of this JID.
*
* @return the localpart.
*/
Localpart getLocalpart();
/**
* Return the bare JID of this entity JID.
*
* @return the bare JID.
*/
EntityBareJid asEntityBareJid();
/**
* Return the bare JID string of this full JID.
*
* @return the bare JID string.
*/
String asEntityBareJidString();
}

View file

@ -0,0 +1,42 @@
/**
*
* Copyright © 2014-2016 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid;
import org.jxmpp.jid.parts.Resourcepart;
/**
* An XMPP address (JID) which has a {@link Resourcepart}. Either {@link EntityFullJid} or {@link DomainFullJid}.
* <p>
* Examples:
* </p>
* <ul>
* <li><code>localpart@domain.part/resourcepart</code></li>
* <li><code>domain.part/resourcepart</code></li>
* </ul>
*
* @see Jid
*/
public interface FullJid extends Jid {
/**
* Return the {@link Resourcepart} of this JID.
*
* @return the resourcepart.
*/
Resourcepart getResourcepart();
}

489
src/org/jxmpp/jid/Jid.java Normal file
View file

@ -0,0 +1,489 @@
/**
*
* Copyright © 2014-2024 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid;
import java.io.Serializable;
import org.jxmpp.jid.parts.Domainpart;
import org.jxmpp.jid.parts.Localpart;
import org.jxmpp.jid.parts.Resourcepart;
/**
* An <b>XMPP address</b>, also known as JID (formerly for "Jabber Identifier"), which acts as globally unique address
* within the XMPP network.
* <p>
* JIDs are created from {@link String} or {@link CharSequence} with the {@link org.jxmpp.jid.impl.JidCreate} utility.
* </p>
*
* <pre>
* Jid jid = JidCreate.from("juliet@capulet.org/balcony");
* EntityBareJid bareJid = JidCreate.entityBareFrom("romeo@montague.net");
* </pre>
* <p>
* This is the super interface for all JID types, which are constructed from two dimensions: Bare/Full and
* Domain/Entity. Every JID consists at least of a {@link Domainpart}. Bare JID types do not come with a
* {@link Resourcepart}, full JID types always have a {@link Resourcepart}. Domain JID types do not possess a
* {@link Localpart}, whereas entity JID types always do.
* </p>
* <p>
* The following table shows a few examples of JID types.
* </p>
* <table>
* <caption>XMPP Address Types</caption>
* <tr>
* <td>Example</td>
* <td>Type</td>
* </tr>
* <tr>
* <td><code>example.org</code></td>
* <td>{@link DomainBareJid}</td>
* </tr>
* <tr>
* <td><code>example.org/resource</code></td>
* <td>{@link DomainFullJid}</td>
* </tr>
* <tr>
* <td><code>user@example.org</code></td>
* <td>{@link EntityBareJid}</td>
* </tr>
* <tr>
* <td><code>user@example.org/resource</code></td>
* <td>{@link EntityFullJid}</td>
* </tr>
* </table>
* <p>
* You can retrieve the escaped String representing the Jid with {@link #toString()} or the unescaped String of the JID
* with {@link #asUnescapedString()}.
* </p>
* <h2>URL Encoded JIDs</h2>
* <p>
* The URL encoded representation of a JID is ideal if a JID should be stored as part of a path name, e.g. as file name.
* You can retrieve this information using {@link #asUrlEncodedString()}. The JidCreate API provides methods to create
* JIDs from URL encoded Strings like {@link org.jxmpp.jid.impl.JidCreate#fromUrlEncoded(CharSequence)}.
* </p>
*
*
* @see <a href="http://xmpp.org/rfcs/rfc6120.html#arch-addresses">RFC 6120 (XMPP: Core) § 2.1 Global Addresses</a>
* @see <a href="http://xmpp.org/rfcs/rfc6122.html#addressing-fundamentals">RFC 6122 (XMPP: Address Format) § 2.1
* Fundamentals</a>
*/
public interface Jid extends Comparable<Jid>, CharSequence, Serializable {
/**
* Get the {@link Domainpart} of this Jid.
*
* @return the domainpart.
*/
Domainpart getDomain();
/**
* Returns the String representation of this JID.
*
* @return the String representation of this JID.
*/
@Override
String toString();
/**
* Return the <b>unescaped</b> String representation of this JID.
* <p>
* Since certain Unicode code points are disallowed in the localpart of a JID by the required stringprep profile,
* those need to get escaped when used in a real JID. The unescaped representation of the JID is only for
* presentation to a human user or for gatewaying to a non-XMPP system.
* </p>
* For example, if the users inputs {@code 'at&t guy@example.com'}, the escaped real JID created with
* {@link org.jxmpp.jid.impl.JidCreate} will be {@code 'at\26t\20guy@example.com'}, which is what
* {@link Jid#toString()} will return. But {@link Jid#asUnescapedString()} will return again
* {@code 'at&t guy@example.com'}.
*
* @return the unescaped String representation of this JID.
*/
String asUnescapedString();
/**
* Get the URL encoded version of this JID.
*
* @return the URL encoded version of this JID.
* @since 0.7.0
*/
String asUrlEncodedString();
/**
* Check if this is a {@link EntityBareJid} or {@link EntityFullJid}.
*
* @return true if this is an instance of BareJid or FullJid.
*/
boolean isEntityJid();
/**
* Check if this is an instance of {@link EntityBareJid}.
*
* @return true if this is an instance of EntityBareJid
*/
boolean isEntityBareJid();
/**
* Check if this is an instance of {@link EntityFullJid}.
*
* @return true if this is an instance of EntityFullJid
*/
boolean isEntityFullJid();
/**
* Check if this is an instance of {@link DomainBareJid}.
*
* @return true if this is an instance of DomainBareJid
*/
boolean isDomainBareJid();
/**
* Check if this is an instance of {@link DomainFullJid}.
*
* @return true if this is an instance of DomainFullJid
*/
boolean isDomainFullJid();
/**
* Check if this is an instance of {@link EntityBareJid} or {@link DomainBareJid}.
*
* @return true if this is an instance of BareJid or DomainBareJid
*/
boolean hasNoResource();
/**
* Check if this is a Jid with a {@link Resourcepart}.
*
* @return true if this Jid has a resourcepart.
*/
boolean hasResource();
/**
* Check if this is a Jid with a {@link Localpart}.
*
* @return true if this Jid has a localpart.
*/
boolean hasLocalpart();
/**
* Return a JID created by removing the Resourcepart from this JID.
*
* @return this Jid without a Resourcepart.
*/
BareJid asBareJid();
/**
* Convert this Jid to a {@link EntityBareJid} if possible.
*
* @return the corresponding {@link EntityBareJid} or null.
*/
EntityBareJid asEntityBareJidIfPossible();
/**
* Convert this Jid to a {@link EntityBareJid} or throw an {@code IllegalStateException} if this is not possible.
*
* @return the corresponding {@link EntityBareJid}.
*/
EntityBareJid asEntityBareJidOrThrow();
/**
* Convert this Jid to a {@link EntityFullJid} if possible.
*
* @return the corresponding {@link EntityFullJid} or null.
*/
EntityFullJid asEntityFullJidIfPossible();
/**
* Convert this Jid to a {@link EntityFullJid} or throw an {@code IllegalStateException} if this is not possible.
*
* @return the corresponding {@link EntityFullJid}.
*/
EntityFullJid asEntityFullJidOrThrow();
/**
* Convert this Jid to a {@link EntityJid} if possible.
*
* @return the corresponding {@link EntityJid} or null.
*/
EntityJid asEntityJidIfPossible();
/**
* Convert this Jid to a {@link EntityJid} or throw an {@code IllegalStateException} if this is not possible.
*
* @return the corresponding {@link EntityJid}.
*/
EntityJid asEntityJidOrThrow();
/**
* Convert this Jid to a {@link FullJid} if possible.
*
* @return the corresponding {@link FullJid} or null.
*/
FullJid asFullJidIfPossible();
/**
* Convert this Jid to a {@link FullJid} or throw an {@code IllegalStateException} if this is not possible.
*
* @return the corresponding {@link FullJid}.
*/
EntityFullJid asFullJidOrThrow();
/**
* Convert this Jid to a {@link DomainBareJid}.
* <p>
* Note that it is always possible to convert a Jid to a DomainBareJid, since every Jid has a domain part.
* </p>
*
* @return the corresponding DomainBareJid.
*/
DomainBareJid asDomainBareJid();
/**
* Convert this Jid to a {@link DomainFullJid} if possible.
*
* @return the corresponding DomainFullJid or null.
*/
DomainFullJid asDomainFullJidIfPossible();
/**
* Convert this Jid to a {@link DomainFullJid} or throw an {@code IllegalStateException} if this is not possible.
*
* @return the corresponding {@link DomainFullJid}.
*/
DomainFullJid asDomainFullJidOrThrow();
/**
* Get the resourcepart of this JID or null.
* <p>
* If the JID is of form {@code <localpart@domain.example/resource>} then this method returns 'resource'. If the JID no
* resourcepart, then <code>null</code> is returned.
* </p>
*
* @return the resource of this JID or null.
*/
Resourcepart getResourceOrNull();
/**
* Get the resourcepart of this JID or return the empty resourcepart.
* <p>
* If the JID is of form {@code <localpart@domain.example/resource>} then this method returns 'resource'. If the JID no
* resourcepart, then {@link org.jxmpp.jid.parts.Resourcepart#EMPTY} is returned.
* </p>
*
* @return the resource of this JID or the empty resourcepart.
*/
Resourcepart getResourceOrEmpty();
/**
* Get the resourcepart of this JID or throw an {@code IllegalStateException}.
* <p>
* If the JID is of form {@code <localpart@domain.example/resource>} then this method returns 'resource'. If the JID no
* resourcepart, then an {@code IllegalStateException} is thrown.
* </p>
*
* @return the resource of this JID.
*/
Resourcepart getResourceOrThrow();
/**
* Get the localpart of this JID or null.
* <p>
* If the JID is of form {@code <localpart@domain.example>} then this method returns 'localpart'. If the JID has no
* localpart, then <code>null</code> is returned.
* </p>
*
* @return the localpart of this JID or null.
*/
Localpart getLocalpartOrNull();
/**
* Get the localpart of this JID or throw an {@code IllegalStateException}.
* <p>
* If the JID is of form {@code <localpart@domain.example>} then this method returns 'localpart'. If the JID has no
* localpart, then <code>null</code> is returned.
* </p>
*
* @return the localpart of this JID.
*/
Localpart getLocalpartOrThrow();
/**
* Check if this JID is the parent of another JID. The <b>parent of</b> relation is defined, under the
* precondition that the JID parts (localpart, domainpart and resourcepart) are equal, as follows:
* <pre>
* | this JID (parentOf) | other JID | result |
* |---------------------+---------------------+--------|
* | dom.example | dom.example | true |
* | dom.example | dom.example/res | true |
* | dom.example | loc@dom.example | true |
* | dom.example | loc@dom.example/res | true |
* | dom.example/res | dom.exmple | false |
* | dom.example/res | dom.example/res | true |
* | dom.example/res | loc@dom.example | false |
* | dom.example/res | loc@dom.example/res | false |
* | loc@dom.example | dom.example | false |
* | loc@dom.example | dom.example/res | false |
* | loc@dom.example | loc@dom.example | true |
* | loc@dom.example | loc@dom.example/res | true |
* | loc@dom.example/res | dom.example | false |
* | loc@dom.example/res | dom.example/res | false |
* | loc@dom.example/res | loc@dom.example | false |
* | loc@dom.example/res | loc@dom.example/res | true |
* </pre>
*
* @param jid
* the other JID to compare with
* @return true if this JID is a parent of the given JID.
*/
boolean isParentOf(Jid jid);
/**
* See {@link #isParentOf(Jid)}.
*
* @param bareJid the bare JID.
* @return true if this JID is a parent of the given JID.
*/
boolean isParentOf(EntityBareJid bareJid);
/**
* See {@link #isParentOf(Jid)}.
*
* @param fullJid the full JID.
* @return true if this JID is a parent of the given JID.
*/
boolean isParentOf(EntityFullJid fullJid);
/**
* See {@link #isParentOf(Jid)}.
*
* @param domainBareJid the domain bare JID.
* @return true if this JID is a parent of the given JID.
*/
boolean isParentOf(DomainBareJid domainBareJid);
/**
* See {@link #isParentOf(Jid)}.
*
* @param domainFullJid the domain full JID.
* @return true if this JID is a parent of the given JID.
*/
boolean isParentOf(DomainFullJid domainFullJid);
/**
* Check if this JID is the strict parent of another JID. In other words, all parts of this JID must
* exist on the other JID, and match this JID's values. Furthermore, and this is what makes this
* method different from {@link #isParentOf(Jid)}, the other JID must have one additional part,
* that this JID does not have. The <b>parent of</b> relation is defined, under the
* precondition that the JID parts (localpart, domainpart and resourcepart) are equal, as follows:
* <pre>
* | this JID | other JID | result |
* |---------------------+---------------------+--------|
* | dom.example | dom.example | false | (different from isParentOf)
* | dom.example | dom.example/res | true |
* | dom.example | loc@dom.example | true |
* | dom.example | loc@dom.example/res | true |
* | dom.example/res | dom.exmple | false |
* | dom.example/res | dom.example/res | false | (different from isParentOf)
* | dom.example/res | loc@dom.example | false |
* | dom.example/res | loc@dom.example/res | false |
* | loc@dom.example | dom.example | false |
* | loc@dom.example | dom.example/res | false |
* | loc@dom.example | loc@dom.example | false | (different from isParentOf)
* | loc@dom.example | loc@dom.example/res | true |
* | loc@dom.example/res | dom.example | false |
* | loc@dom.example/res | dom.example/res | false |
* | loc@dom.example/res | loc@dom.example | false |
* | loc@dom.example/res | loc@dom.example/res | false | (different from isParentOf)
* </pre>
*
* @param jid
* the other JID to compare with
* @return true if this JID is a parent of the given JID.
*/
boolean isStrictParentOf(Jid jid);
/**
* See {@link #isParentOf(Jid)}.
*
* @param bareJid the bare JID.
* @return true if this JID is a parent of the given JID.
*/
boolean isStrictParentOf(EntityBareJid bareJid);
/**
* See {@link #isStrictParentOf(Jid)}.
*
* @param fullJid the full JID.
* @return true if this JID is a parent of the given JID.
*/
boolean isStrictParentOf(EntityFullJid fullJid);
/**
* See {@link #isStrictParentOf(Jid)}.
*
* @param domainBareJid the domain bare JID.
* @return true if this JID is a parent of the given JID.
*/
boolean isStrictParentOf(DomainBareJid domainBareJid);
/**
* See {@link #isStrictParentOf(Jid)}.
*
* @param domainFullJid the domain full JID.
* @return true if this JID is a parent of the given JID.
*/
boolean isStrictParentOf(DomainFullJid domainFullJid);
/**
* Return the downcasted instance of this Jid. This method is unsafe, make sure to check that this is actually of the type of are casting to.
*
* @param jidClass the class of JID to downcast too.
* @param <T> the Jid type to downcast to.
* @return the downcasted instanced of this
* @throws ClassCastException if this JID is not assignable to the type T.
*/
<T extends Jid> T downcast(Class<T> jidClass) throws ClassCastException;
/**
* Compares the given CharSequence with this JID. Returns true if {@code equals(charSequence.toString()} would
* return true.
*
* @param charSequence the CharSequence to compare this JID with.
* @return true if if {@code equals(charSequence.toString()} would return true.
* @see #equals(String)
*/
@SuppressWarnings("NonOverridingEquals")
boolean equals(CharSequence charSequence);
/**
* Compares the given String wit this JID.
* <p>
* Returns true if {@code toString().equals(string)}, that is if the String representation of this JID matches the given string.
* </p>
*
* @param string the String to compare this JID with.
* @return true if {@code toString().equals(string)}.
*/
@SuppressWarnings("NonOverridingEquals")
boolean equals(String string);
/**
* Returns the canonical String representation of this JID. See {@link String#intern} for details.
*
* @return the canonical String representation.
*/
String intern();
}

View file

@ -0,0 +1,282 @@
/**
*
* Copyright © 2014-2024 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid.impl;
import org.jxmpp.jid.EntityBareJid;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.DomainFullJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.EntityJid;
import org.jxmpp.jid.FullJid;
import org.jxmpp.jid.parts.Localpart;
import org.jxmpp.jid.parts.Resourcepart;
public abstract class AbstractJid implements Jid {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* Cache for the String representation of this JID.
*/
protected String cache;
@Override
public final boolean isEntityJid() {
return isEntityBareJid() || isEntityFullJid();
}
@Override
public final boolean isEntityBareJid() {
return this instanceof EntityBareJid;
}
@Override
public final boolean isEntityFullJid() {
return this instanceof EntityFullJid;
}
@Override
public final boolean isDomainBareJid() {
return this instanceof DomainBareJid;
}
@Override
public final boolean isDomainFullJid() {
return this instanceof DomainFullJid;
}
@Override
public abstract boolean hasNoResource();
@Override
public final boolean hasResource() {
return this instanceof FullJid;
}
@Override
public final boolean hasLocalpart() {
return this instanceof EntityJid;
}
@Override
public final <T extends Jid> T downcast(Class<T> jidClass) {
return jidClass.cast(this);
}
@Override
public int length() {
return toString().length();
}
@Override
public char charAt(int index) {
return toString().charAt(index);
}
@Override
public CharSequence subSequence(int start, int end) {
return toString().subSequence(start, end);
}
@Override
public final EntityBareJid asEntityBareJidOrThrow() {
EntityBareJid entityBareJid = asEntityBareJidIfPossible();
if (entityBareJid == null) throwIse("can not be converted to EntityBareJid");
return entityBareJid;
}
@Override
public EntityFullJid asEntityFullJidOrThrow() {
EntityFullJid entityFullJid = asEntityFullJidIfPossible();
if (entityFullJid == null) throwIse("can not be converted to EntityFullJid");
return entityFullJid;
}
@Override
public EntityJid asEntityJidOrThrow() {
EntityJid entityJid = asEntityJidIfPossible();
if (entityJid == null) throwIse("can not be converted to EntityJid");
return entityJid;
}
@Override
public EntityFullJid asFullJidOrThrow() {
EntityFullJid entityFullJid = asEntityFullJidIfPossible();
if (entityFullJid == null) throwIse("can not be converted to EntityBareJid");
return entityFullJid;
}
@Override
public DomainFullJid asDomainFullJidOrThrow() {
DomainFullJid domainFullJid = asDomainFullJidIfPossible();
if (domainFullJid == null) throwIse("can not be converted to DomainFullJid");
return domainFullJid;
}
@Override
public abstract Resourcepart getResourceOrNull();
@Override
public final Resourcepart getResourceOrEmpty() {
Resourcepart resourcepart = getResourceOrNull();
if (resourcepart == null) return Resourcepart.EMPTY;
return resourcepart;
}
@Override
public final Resourcepart getResourceOrThrow() {
Resourcepart resourcepart = getResourceOrNull();
if (resourcepart == null) throwIse("has no resourcepart");
return resourcepart;
}
@Override
public abstract Localpart getLocalpartOrNull();
@Override
public final Localpart getLocalpartOrThrow() {
Localpart localpart = getLocalpartOrNull();
if (localpart == null) throwIse("has no localpart");
return localpart;
}
@Override
public final boolean isParentOf(Jid jid) {
EntityFullJid fullJid = jid.asEntityFullJidIfPossible();
if (fullJid != null) {
return isParentOf(fullJid);
}
EntityBareJid bareJid = jid.asEntityBareJidIfPossible();
if (bareJid != null) {
return isParentOf(bareJid);
}
DomainFullJid domainFullJid = jid.asDomainFullJidIfPossible();
if (domainFullJid != null) {
return isParentOf(domainFullJid);
}
return isParentOf(jid.asDomainBareJid());
}
@Override
public final boolean isStrictParentOf(Jid jid) {
EntityFullJid fullJid = jid.asEntityFullJidIfPossible();
if (fullJid != null) {
return isStrictParentOf(fullJid);
}
EntityBareJid bareJid = jid.asEntityBareJidIfPossible();
if (bareJid != null) {
return isStrictParentOf(bareJid);
}
DomainFullJid domainFullJid = jid.asDomainFullJidIfPossible();
if (domainFullJid != null) {
return isStrictParentOf(domainFullJid);
}
return isStrictParentOf(jid.asDomainBareJid());
}
@Override
public final int hashCode() {
return toString().hashCode();
}
@Override
public final boolean equals(Object other) {
if (other == null) {
return false;
}
if (this == other) {
return true;
}
if (other instanceof CharSequence) {
return equals((CharSequence) other);
}
return false;
}
@SuppressWarnings("NonOverridingEquals")
@Override
public final boolean equals(CharSequence charSequence) {
if (charSequence == null) {
return false;
}
return equals(charSequence.toString());
}
@SuppressWarnings("NonOverridingEquals")
@Override
public final boolean equals(String string) {
return toString().equals(string);
}
@Override
public final int compareTo(Jid other) {
String otherString = other.toString();
String myString = toString();
return myString.compareTo(otherString);
}
/**
* The cache holding the internalized value of this part. This needs to be transient so that the
* cache is recreated once the data was de-serialized.
*/
private transient String internalizedCache;
@Override
public final String intern() {
if (internalizedCache == null) {
cache = internalizedCache = toString().intern();
}
return internalizedCache;
}
private transient String urlEncodedCache;
@Override
public final String asUrlEncodedString() {
if (urlEncodedCache == null) {
String string = toString();
try {
urlEncodedCache = URLEncoder.encode(string, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
}
return urlEncodedCache;
}
private void throwIse(String message) {
String exceptionMessage = "The JID '" + this + "' " + message;
throw new IllegalStateException(exceptionMessage);
}
static <O> O requireNonNull(O object, String message) {
if (object != null) {
return object;
}
throw new IllegalArgumentException(message);
}
}

View file

@ -0,0 +1,173 @@
/**
*
* Copyright © 2014-2024 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid.impl;
import org.jxmpp.JxmppContext;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.DomainFullJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.EntityJid;
import org.jxmpp.jid.FullJid;
import org.jxmpp.jid.parts.Domainpart;
import org.jxmpp.jid.parts.Localpart;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;
/**
* RFC6122 2.4 allows JIDs with only a domain and resource part.
* <p>
* Note that this implementation does not require an cache for the unescaped
* string, compared to {@link LocalDomainAndResourcepartJid}.
* </p>
*
*/
public final class DomainAndResourcepartJid extends AbstractJid implements DomainFullJid {
/**
*
*/
private static final long serialVersionUID = 1L;
private final DomainBareJid domainBareJid;
private final Resourcepart resource;
DomainAndResourcepartJid(String domain, String resource, JxmppContext context) throws XmppStringprepException {
this(new DomainpartJid(domain, context), Resourcepart.from(resource, context));
}
DomainAndResourcepartJid(DomainBareJid domainBareJid, Resourcepart resource) {
this.domainBareJid = requireNonNull(domainBareJid, "The DomainBareJid must not be null");
this.resource = requireNonNull(resource, "The Resource must not be null");
}
@Override
public String toString() {
if (cache != null) {
return cache;
}
cache = domainBareJid.toString() + '/' + resource;
return cache;
}
@Override
public DomainBareJid asDomainBareJid() {
return domainBareJid;
}
@Override
public boolean hasNoResource() {
return false;
}
@Override
public EntityBareJid asEntityBareJidIfPossible() {
return null;
}
@Override
public EntityFullJid asEntityFullJidIfPossible() {
return null;
}
@Override
public DomainFullJid asDomainFullJidIfPossible() {
return this;
}
@Override
public Resourcepart getResourceOrNull() {
return getResourcepart();
}
@Override
public boolean isParentOf(EntityBareJid bareJid) {
return false;
}
@Override
public boolean isParentOf(EntityFullJid fullJid) {
return false;
}
@Override
public boolean isParentOf(DomainBareJid domainBareJid) {
return false;
}
@Override
public boolean isParentOf(DomainFullJid domainFullJid) {
return domainBareJid.equals(domainFullJid.getDomain()) && resource.equals(domainFullJid.getResourcepart());
}
@Override
public boolean isStrictParentOf(EntityBareJid bareJid) {
return false;
}
@Override
public boolean isStrictParentOf(EntityFullJid fullJid) {
return false;
}
@Override
public boolean isStrictParentOf(DomainBareJid domainBareJid) {
return false;
}
@Override
public boolean isStrictParentOf(DomainFullJid domainFullJid) {
// A DomainFullJid can never be the strict parent of another DomainFullJid.
return false;
}
@Override
public Resourcepart getResourcepart() {
return resource;
}
@Override
public BareJid asBareJid() {
return asDomainBareJid();
}
@Override
public Domainpart getDomain() {
return domainBareJid.getDomain();
}
@Override
public String asUnescapedString() {
return toString();
}
@Override
public EntityJid asEntityJidIfPossible() {
return null;
}
@Override
public FullJid asFullJidIfPossible() {
return this;
}
@Override
public Localpart getLocalpartOrNull() {
return null;
}
}

View file

@ -0,0 +1,162 @@
/**
*
* Copyright © 2014-2024 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid.impl;
import org.jxmpp.JxmppContext;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.DomainFullJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.EntityJid;
import org.jxmpp.jid.FullJid;
import org.jxmpp.jid.parts.Domainpart;
import org.jxmpp.jid.parts.Localpart;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;
public final class DomainpartJid extends AbstractJid implements DomainBareJid {
/**
*
*/
private static final long serialVersionUID = 1L;
final Domainpart domain;
DomainpartJid(String domain, JxmppContext context) throws XmppStringprepException {
this(Domainpart.from(domain, context));
}
DomainpartJid(Domainpart domain) {
this.domain = requireNonNull(domain, "The Domainpart must not be null");
}
@Override
public Domainpart getDomain() {
return domain;
}
@Override
public String toString() {
// Prefer the cached version over the domain.toString() one, since the cached version may
// also be the internalized representation of the String. Which, e.g. provides benefits when
// comparing JIDs.
if (cache != null) {
return cache;
}
cache = domain.toString();
return cache;
}
@Override
public String asUnescapedString() {
// No un-escaping necessary for DomainpartJid
return toString();
}
@Override
public DomainBareJid asDomainBareJid() {
return this;
}
@Override
public boolean hasNoResource() {
return true;
}
@Override
public EntityBareJid asEntityBareJidIfPossible() {
return null;
}
@Override
public EntityFullJid asEntityFullJidIfPossible() {
return null;
}
@Override
public DomainFullJid asDomainFullJidIfPossible() {
return null;
}
@Override
public boolean isParentOf(EntityBareJid bareJid) {
return domain.equals(bareJid.getDomain());
}
@Override
public boolean isParentOf(EntityFullJid fullJid) {
return domain.equals(fullJid.getDomain());
}
@Override
public boolean isParentOf(DomainBareJid domainBareJid) {
return domain.equals(domainBareJid.getDomain());
}
@Override
public boolean isParentOf(DomainFullJid domainFullJid) {
return domain.equals(domainFullJid.getDomain());
}
@Override
public boolean isStrictParentOf(EntityBareJid bareJid) {
return isParentOf(bareJid);
}
@Override
public boolean isStrictParentOf(EntityFullJid fullJid) {
return isParentOf(fullJid);
}
@Override
public boolean isStrictParentOf(DomainBareJid domainBareJid) {
return false;
}
@Override
public boolean isStrictParentOf(DomainFullJid domainFullJid) {
return isParentOf(domainFullJid);
}
@Override
public BareJid asBareJid() {
return this;
}
@Override
public EntityJid asEntityJidIfPossible() {
return null;
}
@Override
public FullJid asFullJidIfPossible() {
return null;
}
@Override
public Resourcepart getResourceOrNull() {
return null;
}
@Override
public Localpart getLocalpartOrNull() {
return null;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,182 @@
/**
*
* Copyright © 2014-2024 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid.impl;
import org.jxmpp.JxmppContext;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.DomainFullJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.EntityJid;
import org.jxmpp.jid.FullJid;
import org.jxmpp.jid.parts.Domainpart;
import org.jxmpp.jid.parts.Localpart;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;
public final class LocalAndDomainpartJid extends AbstractJid implements EntityBareJid {
/**
*
*/
private static final long serialVersionUID = 1L;
private final DomainBareJid domainBareJid;
private final Localpart localpart;
private transient String unescapedCache;
LocalAndDomainpartJid(String localpart, String domain, JxmppContext context) throws XmppStringprepException {
domainBareJid = new DomainpartJid(domain, context);
this.localpart = Localpart.from(localpart, context);
}
LocalAndDomainpartJid(Localpart localpart, Domainpart domain) {
this.localpart = requireNonNull(localpart, "The Localpart must not be null");
this.domainBareJid = new DomainpartJid(domain);
}
@Override
public Localpart getLocalpart() {
return localpart;
}
@Override
public String toString() {
if (cache != null) {
return cache;
}
cache = getLocalpart().toString() + '@' + domainBareJid.toString();
return cache;
}
@Override
public String asUnescapedString() {
if (unescapedCache != null) {
return unescapedCache;
}
unescapedCache = getLocalpart().asUnescapedString() + '@' + domainBareJid.toString();
return unescapedCache;
}
@Override
public EntityBareJid asEntityBareJidIfPossible() {
return this;
}
@Override
public EntityFullJid asEntityFullJidIfPossible() {
return null;
}
@Override
public DomainFullJid asDomainFullJidIfPossible() {
return null;
}
@Override
public boolean isParentOf(EntityBareJid bareJid) {
return domainBareJid.equals(bareJid.getDomain()) && localpart.equals(bareJid.getLocalpart());
}
@Override
public boolean isParentOf(EntityFullJid fullJid) {
return isParentOf(fullJid.asBareJid());
}
@Override
public boolean isParentOf(DomainBareJid domainBareJid) {
return false;
}
@Override
public boolean isParentOf(DomainFullJid domainFullJid) {
return false;
}
@Override
public boolean isStrictParentOf(EntityBareJid bareJid) {
return false;
}
@Override
public boolean isStrictParentOf(EntityFullJid fullJid) {
return isParentOf(fullJid);
}
@Override
public boolean isStrictParentOf(DomainBareJid domainBareJid) {
return false;
}
@Override
public boolean isStrictParentOf(DomainFullJid domainFullJid) {
return false;
}
@Override
public DomainBareJid asDomainBareJid() {
return domainBareJid;
}
@Override
public Domainpart getDomain() {
return domainBareJid.getDomain();
}
@Override
public BareJid asBareJid() {
return this;
}
@Override
public boolean hasNoResource() {
return true;
}
@Override
public EntityJid asEntityJidIfPossible() {
return this;
}
@Override
public FullJid asFullJidIfPossible() {
return null;
}
@Override
public EntityBareJid asEntityBareJid() {
return this;
}
@Override
public Resourcepart getResourceOrNull() {
return null;
}
@Override
public Localpart getLocalpartOrNull() {
return getLocalpart();
}
@Override
public String asEntityBareJidString() {
return toString();
}
}

View file

@ -0,0 +1,185 @@
/**
*
* Copyright © 2014-2024 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid.impl;
import org.jxmpp.JxmppContext;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.DomainFullJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.EntityJid;
import org.jxmpp.jid.FullJid;
import org.jxmpp.jid.parts.Domainpart;
import org.jxmpp.jid.parts.Localpart;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;
public final class LocalDomainAndResourcepartJid extends AbstractJid implements EntityFullJid {
/**
*
*/
private static final long serialVersionUID = 1L;
private final EntityBareJid bareJid;
private final Resourcepart resource;
private String unescapedCache;
LocalDomainAndResourcepartJid(String localpart, String domain, String resource, JxmppContext context) throws XmppStringprepException {
this(new LocalAndDomainpartJid(localpart, domain, context), Resourcepart.from(resource, context));
}
LocalDomainAndResourcepartJid(EntityBareJid bareJid, Resourcepart resource) {
this.bareJid = requireNonNull(bareJid, "The EntityBareJid must not be null");
this.resource = requireNonNull(resource, "The Resourcepart must not be null");
}
@Override
public String toString() {
if (cache != null) {
return cache;
}
cache = bareJid.toString() + '/' + resource;
return cache;
}
@Override
public String asUnescapedString() {
if (unescapedCache != null) {
return unescapedCache;
}
unescapedCache = bareJid.asUnescapedString() + '/' + resource;
return unescapedCache;
}
@Override
public EntityBareJid asEntityBareJid() {
return bareJid;
}
@Override
public String asEntityBareJidString() {
return asEntityBareJid().toString();
}
@Override
public boolean hasNoResource() {
return false;
}
@Override
public EntityBareJid asEntityBareJidIfPossible() {
return asEntityBareJid();
}
@Override
public EntityFullJid asEntityFullJidIfPossible() {
return this;
}
@Override
public DomainFullJid asDomainFullJidIfPossible() {
return null;
}
@Override
public Localpart getLocalpartOrNull() {
return bareJid.getLocalpart();
}
@Override
public Resourcepart getResourceOrNull() {
return getResourcepart();
}
@Override
public boolean isParentOf(EntityBareJid bareJid) {
return false;
}
@Override
public boolean isParentOf(EntityFullJid fullJid) {
return this.equals(fullJid);
}
@Override
public boolean isParentOf(DomainBareJid domainBareJid) {
return false;
}
@Override
public boolean isParentOf(DomainFullJid domainFullJid) {
return false;
}
@Override
public boolean isStrictParentOf(EntityBareJid bareJid) {
return false;
}
@Override
public boolean isStrictParentOf(EntityFullJid fullJid) {
return false;
}
@Override
public boolean isStrictParentOf(DomainBareJid domainBareJid) {
return false;
}
@Override
public boolean isStrictParentOf(DomainFullJid domainFullJid) {
return false;
}
@Override
public DomainBareJid asDomainBareJid() {
return bareJid.asDomainBareJid();
}
@Override
public Resourcepart getResourcepart() {
return resource;
}
@Override
public BareJid asBareJid() {
return asEntityBareJid();
}
@Override
public Domainpart getDomain() {
return bareJid.getDomain();
}
@Override
public Localpart getLocalpart() {
return bareJid.getLocalpart();
}
@Override
public EntityJid asEntityJidIfPossible() {
return this;
}
@Override
public FullJid asFullJidIfPossible() {
return this;
}
}

View file

@ -0,0 +1,21 @@
/**
*
* Copyright 2015 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.
*/
/**
* JXMPP's implementation of {@link org.jxmpp.jid.Jid} and it's subtypes.
*/
package org.jxmpp.jid.impl;

View file

@ -0,0 +1,21 @@
/**
*
* Copyright 2015 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.
*/
/**
* Interfaces and classes for XMPP Addresses (JIDs).
*/
package org.jxmpp.jid;

View file

@ -0,0 +1,108 @@
/**
*
* Copyright © 2014-2018 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid.parts;
import org.jxmpp.JxmppContext;
import org.jxmpp.stringprep.XmppStringPrepUtil;
import org.jxmpp.stringprep.XmppStringprepException;
/**
* A <i>domainpart</i> of an XMPP address (JID).
* <p>
* You can create instances of this class from Strings using {@link #from(String)}.
* </p>
*
* @see <a href="http://xmpp.org/rfcs/rfc6122.html#addressing-domain">RFC 6122 § 2.2. Domainpart</a>
*/
public class Domainpart extends Part {
/**
*
*/
private static final long serialVersionUID = 1L;
private Domainpart(String domain) {
super(domain);
}
/**
* Get a {@link Domainpart} from a given {@link CharSequence} or {@code null} if the input is not a valid domainpart.
*
* @param cs the input CharSequence
* @return a Domainpart or {@code null}
*/
public static Domainpart fromOrNull(CharSequence cs) {
try {
return from(cs.toString());
} catch (XmppStringprepException e) {
return null;
}
}
/**
* Like {@link #from(String)} but does throw an unchecked {@link IllegalArgumentException} instead of a
* {@link XmppStringprepException}.
*
* @param cs the character sequence which should be transformed to a {@link Domainpart}
* @return the {@link Domainpart} if no exception occurs
* @throws IllegalArgumentException if the given input is not a valid {@link Domainpart}
* @see #from(String)
* @since 0.6.2
*/
public static Domainpart fromOrThrowUnchecked(CharSequence cs) {
try {
return from(cs.toString());
} catch (XmppStringprepException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Get the {@link Domainpart} representing the input String.
*
* @param domain the input String.
* @return the domainpart.
* @throws XmppStringprepException if an error occurs.
*/
public static Domainpart from(String domain) throws XmppStringprepException {
return from(domain, JxmppContext.getDefaultContext());
}
/**
* Get the {@link Domainpart} representing the input String.
*
* @param domain the input String.
* @param context the JXMPP context.
* @return the domainpart.
* @throws XmppStringprepException if an error occurs.
*/
public static Domainpart from(String domain, JxmppContext context) throws XmppStringprepException {
if (domain == null) {
throw new XmppStringprepException(domain, "Input 'domain' must not be null");
}
// TODO cache
// RFC 6122 § 2.2 "If the domainpart includes a final character considered to be a label
// separator (dot) by [IDNA2003] or [DNS], this character MUST be stripped "
if (domain.length() > 0 && domain.charAt(domain.length() - 1) == '.') {
domain = domain.substring(0, domain.length() - 1);
}
domain = XmppStringPrepUtil.domainprep(domain, context);
// First prep the String, then assure the limits of the *result*
assertNotLongerThan1023BytesOrEmpty(domain);
return new Domainpart(domain);
}
}

View file

@ -0,0 +1,183 @@
/**
*
* Copyright © 2014-2018 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid.parts;
import org.jxmpp.JxmppContext;
import org.jxmpp.stringprep.XmppStringPrepUtil;
import org.jxmpp.stringprep.XmppStringprepException;
import org.jxmpp.util.XmppStringUtils;
/**
* A <i>localpart</i> of an XMPP address (JID). The localpart is the part before the
* first @ sign in an XMPP address and usually identifies the user (or the XMPP
* entity) within an XMPP service. It is also often referred to as "username",
* but note that the actual username used to login may be different from the
* resulting localpart of the user's JID.
* <p>
* You can create instances of this class from Strings using {@link #from(String)}.
* </p>
*
* @see <a href="http://xmpp.org/rfcs/rfc6122.html#addressing-localpart">RFC
* 6122 § 2.3. Localpart</a>
*/
public class Localpart extends Part {
/**
*
*/
private static final long serialVersionUID = 1L;
private transient String unescapedCache;
private Localpart(String localpart) {
super(localpart);
}
/**
* Return the <b>unescaped</b> String representation of this Localpart.
* <p>
* Since certain Unicode code points are disallowed in the localpart of a JID by the required stringprep profile,
* those need to get escaped when used in a real JID. The unescaped representation of the JID is only for
* presentation to a human user or for gatewaying to a non-XMPP system.
* </p>
*
* @return the unescaped String representation of this JID.
* @see org.jxmpp.jid.Jid#asUnescapedString()
* @since 0.6.1
*/
public String asUnescapedString() {
if (unescapedCache != null) {
return unescapedCache;
}
unescapedCache = XmppStringUtils.unescapeLocalpart(toString());
return unescapedCache;
}
/**
* Like {@link #from(String)} but does throw an unchecked {@link IllegalArgumentException} instead of a
* {@link XmppStringprepException}.
*
* @param cs the character sequence which should be transformed to a {@link Localpart}
* @return the {@link Localpart} if no exception occurs
* @throws IllegalArgumentException if the given input is not a valid {@link Localpart}
* @see #from(String)
* @since 0.6.2
*/
public static Localpart fromOrThrowUnchecked(CharSequence cs) {
try {
return from(cs.toString());
} catch (XmppStringprepException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Like {@link #fromUnescaped(String)} but does throw an unchecked {@link IllegalArgumentException} instead of a
* {@link XmppStringprepException}.
*
* @param cs the character sequence which should be transformed to a {@link Localpart}
* @return the {@link Localpart} if no exception occurs
* @see #from(String)
* @since 0.6.2
*/
public static Localpart fromUnescapedOrThrowUnchecked(CharSequence cs) {
try {
return fromUnescaped(cs.toString());
} catch (XmppStringprepException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Get a {@link Localpart} from a given {@link CharSequence} or {@code null} if the input is not a valid localpart.
*
* @param cs the input CharSequence
* @return a Localpart or {@code null}
*/
public static Localpart formUnescapedOrNull(CharSequence cs) {
try {
return fromUnescaped(cs);
} catch (XmppStringprepException e) {
return null;
}
}
/**
* Get a {@link Localpart} from an unescaped String.
*
* @param unescapedLocalpart an unescaped String representing a Localpart.
* @return a Localpart
* @throws XmppStringprepException if an error occurs.
* @since 0.6.2
*/
public static Localpart fromUnescaped(String unescapedLocalpart) throws XmppStringprepException {
String escapedLocalpartString = XmppStringUtils.escapeLocalpart(unescapedLocalpart);
return from(escapedLocalpartString);
}
/**
* Get a {@link Localpart} from an unescaped CharSequence.
*
* @param unescapedLocalpart an unescaped CharSequence representing a Localpart.
* @return a Localpart
* @throws XmppStringprepException if an error occurs.
* @since 0.6.2
*/
public static Localpart fromUnescaped(CharSequence unescapedLocalpart) throws XmppStringprepException {
return fromUnescaped(unescapedLocalpart.toString());
}
/**
* Get a {@link Localpart} from a given {@link CharSequence} or {@code null} if the input is not a valid localpart.
*
* @param cs the input CharSequence
* @return a Localpart or {@code null}
*/
public static Localpart fromOrNull(CharSequence cs) {
try {
return from(cs.toString());
} catch (XmppStringprepException e) {
return null;
}
}
/**
* Get the {@link Localpart} representing the input String.
*
* @param localpart the input String.
* @return the localpart.
* @throws XmppStringprepException if an error occurs.
*/
public static Localpart from(String localpart) throws XmppStringprepException {
return from(localpart, JxmppContext.getDefaultContext());
}
/**
* Get the {@link Localpart} representing the input String.
*
* @param localpart the input String.
* @param context the JXMPP context.
* @return the localpart.
* @throws XmppStringprepException if an error occurs.
*/
public static Localpart from(String localpart, JxmppContext context) throws XmppStringprepException {
localpart = XmppStringPrepUtil.localprep(localpart, context);
// First prep the String, then assure the limits of the *result*
assertNotLongerThan1023BytesOrEmpty(localpart);
return new Localpart(localpart);
}
}

View file

@ -0,0 +1,102 @@
/**
*
* Copyright © 2014-2019 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid.parts;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import org.jxmpp.stringprep.XmppStringprepException;
public abstract class Part implements CharSequence, Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private final String part;
protected Part(String part) {
this.part = part;
}
@Override
public final int length() {
return part.length();
}
@Override
public final char charAt(int index) {
return part.charAt(index);
}
@Override
public final CharSequence subSequence(int start, int end) {
return part.subSequence(start, end);
}
@Override
public final String toString() {
return part;
}
@Override
public final boolean equals(Object other) {
if (this == other) {
return true;
}
if (other == null) {
return false;
}
return part.equals(other.toString());
}
@Override
public final int hashCode() {
return part.hashCode();
}
protected static void assertNotLongerThan1023BytesOrEmpty(String string) throws XmppStringprepException {
byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
// Better throw XmppStringprepException instead of IllegalArgumentException here, because users don't expect an
// IAE and it also makes the error handling for users easier.
if (bytes.length > 1023) {
throw new XmppStringprepException(string, "Given string is longer then 1023 bytes");
} else if (bytes.length == 0) {
throw new XmppStringprepException(string, "Argument can't be the empty string");
}
}
/**
* The cache holding the internalized value of this part. This needs to be transient so that the
* cache is recreated once the data was de-serialized.
*/
private transient String internalizedCache;
/**
* Returns the canonical String representation of this Part. See {@link String#intern} for details.
*
* @return the canonical String representation.
*/
public final String intern() {
if (internalizedCache == null) {
internalizedCache = toString().intern();
}
return internalizedCache;
}
}

View file

@ -0,0 +1,119 @@
/**
*
* Copyright © 2014-2024 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid.parts;
import org.jxmpp.JxmppContext;
import org.jxmpp.stringprep.XmppStringPrepUtil;
import org.jxmpp.stringprep.XmppStringprepException;
/**
* A <i>resourcepart</i> of an XMPP address (JID).
* <p>
* You can create instances of this class from Strings using {@link #from(String)}.
* </p>
*
* @see <a href="http://xmpp.org/rfcs/rfc6122.html#addressing-resource">RFC 6122 § 2.4. Resourcepart</a>
*/
public class Resourcepart extends Part {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* The empty resource part.
* <p>
* This empty resource part is the part that is represented by the empty String. This is useful in cases where you
* have a collection of Resourceparts that does not allow <code>null</code> values, but you want to deal with the
* "no resource" case.
* </p>
*/
public static final Resourcepart EMPTY = new Resourcepart("");
private Resourcepart(String resource) {
super(resource);
}
/**
* Get a {@link Resourcepart} from a given {@link CharSequence} or {@code null} if the input is not a valid resourcepart.
*
* @param cs the input CharSequence
* @return a Resourcepart or {@code null}
*/
public static Resourcepart fromOrNull(CharSequence cs) {
try {
return from(cs.toString());
} catch (XmppStringprepException e) {
return null;
}
}
/**
* Like {@link #from(String)} but does throw an unchecked {@link IllegalArgumentException} instead of a
* {@link XmppStringprepException}.
*
* @param cs the character sequence which should be transformed to a {@link Resourcepart}
* @return the {@link Resourcepart} if no exception occurs
* @throws IllegalArgumentException if the given input is not a valid {@link Resourcepart}
* @see #from(String)
* @since 0.6.2
*/
public static Resourcepart fromOrThrowUnchecked(CharSequence cs) {
try {
return from(cs.toString());
} catch (XmppStringprepException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Get the {@link Resourcepart} representing the input String.
*
* @param resource the input String.
* @return the resource part.
* @throws XmppStringprepException if an error occurs.
*/
public static Resourcepart from(String resource) throws XmppStringprepException {
return from(resource, JxmppContext.getDefaultContext());
}
/**
* Get the {@link Resourcepart} representing the input String.
*
* @param resource the input String.
* @return the resource part.
* @throws XmppStringprepException if an error occurs.
*/
public static Resourcepart from(CharSequence resource) throws XmppStringprepException {
return from(resource.toString());
}
/**
* Get the {@link Resourcepart} representing the input String.
*
* @param resource the input String.
* @param context the JXMPP context.
* @return the resource part.
* @throws XmppStringprepException if an error occurs.
*/
public static Resourcepart from(String resource, JxmppContext context) throws XmppStringprepException {
resource = XmppStringPrepUtil.resourceprep(resource, context);
// First prep the String, then assure the limits of the *result*
assertNotLongerThan1023BytesOrEmpty(resource);
return new Resourcepart(resource);
}}

View file

@ -0,0 +1,21 @@
/**
*
* Copyright 2015 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.
*/
/**
* Classes representing JID parts (Local-, Resource- and Domainpart).
*/
package org.jxmpp.jid.parts;

View file

@ -0,0 +1,424 @@
/**
*
* Copyright © 2014-2024 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jxmpp.jid.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.DomainFullJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.stringprep.XmppStringprepException;
import org.jxmpp.util.XmppStringUtils;
public class JidUtil {
/**
* Check if the given CharSequence represents a typical and valid entity bare JID. This method does perform the same
* check as {@link #isValidEntityBareJid(CharSequence)} and additionally verifies that the domainpart of the JID
* contains at least one dot ('.') character.
* <p>
* For more information about the different verification methods see {@link #validateEntityBareJid(CharSequence)}.
* </p>
*
* @param jid the CharSequence to check.
* @return true if {@code jid} represents a valid entity bare JID, false otherwise
* @see #isValidEntityBareJid(CharSequence)
* @see EntityBareJid
*/
public static boolean isTypicalValidEntityBareJid(CharSequence jid) {
try {
validateTypicalEntityBareJid(jid);
} catch (NotAEntityBareJidStringException | XmppStringprepException e) {
return false;
}
return true;
}
/**
* Check if the given CharSequence is a typical and valid entity bare JID. This method does perform the same
* check as {@link #isValidEntityBareJid(CharSequence)} and additionally verifies that the domainpart of the JID
* contains at least one dot ('.') character.
* <p>
* The <code>TypicalValidEntityBareJid(CharSequence)</code> methods are useful if you expect your users to always
* enter a FQDN as domainpart. Whereas <code>isValidEntityBareJid(CharSequence)</code> and
* <code>validateEntityBareJid</code> accept also inputs like "foo@example", the "is typical JID" methods require
* the domainpart to contain a dot, e.g. "foo@example.org".
* </p>
*
* @param jidcs the JID CharSequence
* @return a BareJid instance representing the given JID CharSequence
* @throws NotAEntityBareJidStringException if the given CharSequence is not a bare JID.
* @throws XmppStringprepException if an error happens.
*/
public static EntityBareJid validateTypicalEntityBareJid(CharSequence jidcs) throws NotAEntityBareJidStringException, XmppStringprepException {
EntityBareJid jid = validateEntityBareJid(jidcs);
if (jid.getDomain().toString().indexOf('.') == -1) {
throw new NotAEntityBareJidStringException("Domainpart does not include a dot ('.') character");
}
return jid;
}
/**
* Check if the given CharSequence represents a valid entity bare JID. That
* is, it must consists exactly of a local- and a domainpart
* (&lt;localpart@domainpart&gt;).
* <p>
* This method is meant to validate user input and give fast feedback (e.g.
* with a red or green light) about if the user entered CharSequence
* represents a bare JID.
* </p>
*
* @param jid
* the CharSequence to check.
* @return true if {@code jid} represents a valid entity bare JID, false otherwise
* @see EntityBareJid
*/
public static boolean isValidEntityBareJid(CharSequence jid) {
try {
validateEntityBareJid(jid);
} catch (NotAEntityBareJidStringException | XmppStringprepException e) {
return false;
}
return true;
}
/**
* Check if the given CharSequence is a valid entity bare JID. That
* is, it must consists exactly of a local- and a domainpart
* (&lt;localpart@domainpart&gt;).
* <p>
* This is a convenience method meant to validate user entered bare JIDs. If
* the given {@code jid} is not a valid bare JID, then this method will
* throw either {@link NotAEntityBareJidStringException} or
* {@link XmppStringprepException}. The NotABareJidStringException will
* contain a meaningful message explaining why the given CharSequence is not a
* valid bare JID (e.g. "does not contain a '@' character").
* </p>
*
* @param jidcs the JID CharSequence
* @return a BareJid instance representing the given JID CharSequence
* @throws NotAEntityBareJidStringException if the given CharSequence is not a bare JID.
* @throws XmppStringprepException if an error happens.
*/
public static EntityBareJid validateEntityBareJid(CharSequence jidcs) throws NotAEntityBareJidStringException, XmppStringprepException {
String jid = jidcs.toString();
final int atIndex = jid.indexOf('@');
if (atIndex == -1) {
throw new NotAEntityBareJidStringException("'" + jid + "' does not contain a '@' character");
} else if (jid.indexOf('@', atIndex + 1) != -1) {
throw new NotAEntityBareJidStringException("'" + jid + "' contains multiple '@' characters");
}
final String localpart = XmppStringUtils.parseLocalpart(jid);
if (localpart == null || localpart.length() == 0) {
throw new NotAEntityBareJidStringException("'" + jid + "' has empty localpart");
}
final String domainpart = XmppStringUtils.parseDomain(jid);
if (domainpart == null || domainpart.length() == 0) {
throw new NotAEntityBareJidStringException("'" + jid + "' has empty domainpart");
}
return JidCreate.entityBareFromUnescaped(jid);
}
public static class NotAEntityBareJidStringException extends Exception {
/**
*
*/
private static final long serialVersionUID = -1710386661031655082L;
/**
* Construct a new "not a entity bare JID" exception.
*
* @param message the message of the exception.
*/
public NotAEntityBareJidStringException(String message) {
super(message);
}
}
/**
* Filter all entity bare JIDs.
*
* @param in the input collection.
* @param out the collection where the filtered JIDs are added to.
*/
public static void filterEntityBareJid(Collection<? extends Jid> in, Collection<? super EntityBareJid> out) {
for (Jid jid : in) {
EntityBareJid bareJid = jid.asEntityBareJidIfPossible();
if (bareJid != null) {
out.add(bareJid);
}
}
}
/**
* Filter all entity bare JIDs.
*
* @param input the input collection.
* @return a set containing all bare JIDs of the input collection.
*/
public static Set<EntityBareJid> filterEntityBareJidSet(Collection<? extends Jid> input) {
Set<EntityBareJid> res = new HashSet<EntityBareJid>(input.size());
filterEntityBareJid(input, res);
return res;
}
/**
* Filter all entity bare JIDs.
*
* @param input the input collection.
* @return a list containing all bare JIDs of the input collection.
*/
public static List<EntityBareJid> filterEntityBareJidList(Collection<? extends Jid> input) {
List<EntityBareJid> res = new ArrayList<EntityBareJid>(input.size());
filterEntityBareJid(input, res);
return res;
}
/**
* Filter all entity full JIDs.
*
* @param in the input collection.
* @param out the collection where the filtered JIDs are added to.
*/
public static void filterEntityFullJid(Collection<? extends Jid> in, Collection<? super EntityFullJid> out) {
for (Jid jid : in) {
EntityFullJid fullJid = jid.asEntityFullJidIfPossible();
if (fullJid != null) {
out.add(fullJid);
}
}
}
/**
* Filter all full JIDs.
*
* @param input the input collection.
* @return a set containing all full JIDs of the input collection.
*/
public static Set<EntityFullJid> filterEntityFullJidSet(Collection<? extends Jid> input) {
Set<EntityFullJid> res = new HashSet<EntityFullJid>(input.size());
filterEntityFullJid(input, res);
return res;
}
/**
* Filter all full JIDs.
*
* @param input the input collection.
* @return a list containing all full JIDs of the input collection.
*/
public static List<EntityFullJid> filterEntityFullJidList(Collection<? extends Jid> input) {
List<EntityFullJid> res = new ArrayList<EntityFullJid>(input.size());
filterEntityFullJid(input, res);
return res;
}
/**
* Filter all domain full JIDs.
*
* @param in the input collection.
* @param out the collection where the filtered JIDs are added to.
*/
public static void filterDomainFullJid(Collection<? extends Jid> in, Collection<? super DomainFullJid> out) {
for (Jid jid : in) {
DomainFullJid domainFullJid = jid.asDomainFullJidIfPossible();
if (domainFullJid != null) {
out.add(domainFullJid);
}
}
}
/**
* Filter all domain full JIDs.
*
* @param input the input collection.
* @return a set containing all domain full JIDs of the input collection.
*/
public static Set<DomainFullJid> filterDomainFullJidSet(Collection<? extends Jid> input) {
Set<DomainFullJid> res = new HashSet<DomainFullJid>(input.size());
filterDomainFullJid(input, res);
return res;
}
/**
* Filter all domain full JIDs.
*
* @param input the input collection.
* @return a list containing all domain full JIDs of the input collection.
*/
public static List<DomainFullJid> filterDomainFullJidList(Collection<? extends Jid> input) {
List<DomainFullJid> res = new ArrayList<DomainFullJid>(input.size());
filterDomainFullJid(input, res);
return res;
}
/**
* Convert the given collection of CharSequences to bare JIDs.
*
* @param jidStrings the collection of CharSequences.
* @return a set of bare JIDs.
*/
public static Set<EntityBareJid> entityBareJidSetFrom(Collection<? extends CharSequence> jidStrings) {
Set<EntityBareJid> res = new HashSet<EntityBareJid>(jidStrings.size());
entityBareJidsFrom(jidStrings, res, null);
return res;
}
/**
* Convert a collection of Strings to a Set of {@link EntityBareJid}'s.
* <p>
* If the optional argument <code>exceptions</code> is given, then all {@link XmppStringprepException} thrown while
* converting will be added to the list. Otherwise, if an XmppStringprepExceptions is thrown, it will be wrapped in
* a AssertionError Exception and throw.
* </p>
*
* @param jidStrings
* the strings that are going to get converted
* @param output
* the collection where the BareJid's will be added to
* @param exceptions the list of exceptions thrown while converting.
*/
public static void entityBareJidsFrom(Collection<? extends CharSequence> jidStrings, Collection<? super EntityBareJid> output,
List<XmppStringprepException> exceptions) {
for (CharSequence jid : jidStrings) {
try {
EntityBareJid bareJid = JidCreate.entityBareFrom(jid);
output.add(bareJid);
} catch (XmppStringprepException e) {
if (exceptions != null) {
exceptions.add(e);
} else {
throw new AssertionError(e);
}
}
}
}
/**
* Convert the given array of Strings to JIDs.
* <p>
* Note that errors while converting the Strings will be silently ignored.
* </p>
*
* @param jids a array of JID Strings.
* @return a set of JIDs.
*/
public static Set<Jid> jidSetFrom(String[] jids) {
return jidSetFrom(Arrays.asList(jids));
}
/**
* Convert the given collection of CharSequences to JIDs.
*
* @param jidStrings the collection of CharSequences.
* @return a set of JIDs.
*/
public static Set<Jid> jidSetFrom(Collection<? extends CharSequence> jidStrings) {
Set<Jid> res = new HashSet<Jid>(jidStrings.size());
jidsFrom(jidStrings, res, null);
return res;
}
/**
* Convert a collection of Strings to a Set of {@link Jid}'s.
* <p>
* If the optional argument <code>exceptions</code> is given, then all {@link XmppStringprepException} thrown while
* converting will be added to the list. Otherwise, if an XmppStringprepExceptions is thrown, it will be wrapped in
* a AssertionError Exception and throw.
* </p>
*
* @param jidStrings
* the strings that are going to get converted
* @param output
* the collection where the Jid's will be added to
* @param exceptions the list of exceptions thrown while converting.
*/
public static void jidsFrom(Collection<? extends CharSequence> jidStrings, Collection<? super Jid> output,
List<XmppStringprepException> exceptions) {
for (CharSequence jidString : jidStrings) {
try {
Jid jid = JidCreate.from(jidString);
output.add(jid);
} catch (XmppStringprepException e) {
if (exceptions != null) {
exceptions.add(e);
} else {
throw new AssertionError(e);
}
}
}
}
/**
* Convert a collection of JIDs to a list of Strings representing those JIDs.
*
* @param jids a collection of JIDs.
* @return a list of Strings.
*/
public static List<String> toStringList(Collection<? extends Jid> jids) {
List<String> res = new ArrayList<String>(jids.size());
toStrings(jids, res);
return res;
}
/**
* convert a collection of JIDs to a set of Strings representing those JIDs.
*
* @param jids a collection of JIDs.
* @return a set of String.
*/
public static Set<String> toStringSet(Collection<? extends Jid> jids) {
Set<String> res = new HashSet<String>(jids.size());
toStrings(jids, res);
return res;
}
/**
* Convert a collection of JIDs to a Collection of Strings.
*
* @param jids the collection of Strings to convert.
* @param jidStrings the collection of Strings to append to.
*/
public static void toStrings(Collection<? extends Jid> jids, Collection<? super String> jidStrings) {
for (Jid jid : jids) {
jidStrings.add(jid.toString());
}
}
/**
* Check if two JIDs are equals. Takes <code>null</code> values into consideration. Which means that this method will return <code>true</code> if both JIDs are <code>null</code>.
*
* @param jidOne The first JID to compare.
* @param jidTwo The second JID to compare.
* @return <code>true</code> if both JIDs are equals.
* @since 0.7.0
*/
public static boolean equals(Jid jidOne, Jid jidTwo) {
if (jidOne != null) {
return jidOne.equals(jidTwo);
}
return jidTwo == null;
}
}

View file

@ -0,0 +1,21 @@
/**
*
* Copyright 2015 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.
*/
/**
* Utility classes for JIDs.
*/
package org.jxmpp.jid.util;