mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-30 02:02:06 +01:00
SMACK-391 Moved all date parsing into StringUtils and made it much more robust in handling multiple valid and invalid formats.
git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@13428 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
parent
2afd3bdfa3
commit
1d36ae8db4
5 changed files with 505 additions and 202 deletions
|
@ -209,7 +209,7 @@ public class Presence extends Packet {
|
||||||
* @return the xml:lang of this Presence, or null if one has not been set.
|
* @return the xml:lang of this Presence, or null if one has not been set.
|
||||||
* @since 3.0.2
|
* @since 3.0.2
|
||||||
*/
|
*/
|
||||||
private String getLanguage() {
|
public String getLanguage() {
|
||||||
return language;
|
return language;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,27 +26,87 @@ import java.security.NoSuchAlgorithmException;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A collection of utility methods for String objects.
|
* A collection of utility methods for String objects.
|
||||||
*/
|
*/
|
||||||
public class StringUtils {
|
public class StringUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Date format as defined in XEP-0082 - XMPP Date and Time Profiles. The time zone is set to
|
* Date format as defined in XEP-0082 - XMPP Date and Time Profiles. The time zone is set to
|
||||||
* UTC.
|
* UTC.
|
||||||
* <p>
|
* <p>
|
||||||
* Date formats are not synchronized. Since multiple threads access the format concurrently, it
|
* Date formats are not synchronized. Since multiple threads access the format concurrently, it
|
||||||
* must be synchronized externally or you can use the convenience methods
|
* must be synchronized externally or you can use the convenience methods
|
||||||
* {@link #parseXEP0082Date(String)} and {@link #formatXEP0082Date(Date)}.
|
* {@link #parseXEP0082Date(String)} and {@link #formatXEP0082Date(Date)}.
|
||||||
|
* @deprecated This public version will be removed in favor of using the methods defined within this class.
|
||||||
*/
|
*/
|
||||||
public static final DateFormat XEP_0082_UTC_FORMAT = new SimpleDateFormat(
|
public static final DateFormat XEP_0082_UTC_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
||||||
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
|
||||||
|
/*
|
||||||
|
* private version to use internally so we don't have to be concerned with thread safety.
|
||||||
|
*/
|
||||||
|
private static final DateFormat dateFormatter = DateFormatType.XEP_0082_DATE_PROFILE.createFormatter();
|
||||||
|
private static final Pattern datePattern = Pattern.compile("^\\d+-\\d+-\\d+$");
|
||||||
|
|
||||||
|
private static final DateFormat timeFormatter = DateFormatType.XEP_0082_TIME_MILLIS_ZONE_PROFILE.createFormatter();
|
||||||
|
private static final Pattern timePattern = Pattern.compile("^(\\d+:){2}\\d+.\\d+(Z|([+-](\\d+:\\d+)))$");
|
||||||
|
private static final DateFormat timeNoZoneFormatter = DateFormatType.XEP_0082_TIME_MILLIS_PROFILE.createFormatter();
|
||||||
|
private static final Pattern timeNoZonePattern = Pattern.compile("^(\\d+:){2}\\d+.\\d+$");
|
||||||
|
|
||||||
|
private static final DateFormat timeNoMillisFormatter = DateFormatType.XEP_0082_TIME_ZONE_PROFILE.createFormatter();
|
||||||
|
private static final Pattern timeNoMillisPattern = Pattern.compile("^(\\d+:){2}\\d+(Z|([+-](\\d+:\\d+)))$");
|
||||||
|
private static final DateFormat timeNoMillisNoZoneFormatter = DateFormatType.XEP_0082_TIME_PROFILE.createFormatter();
|
||||||
|
private static final Pattern timeNoMillisNoZonePattern = Pattern.compile("^(\\d+:){2}\\d+$");
|
||||||
|
|
||||||
|
private static final DateFormat dateTimeFormatter = DateFormatType.XEP_0082_DATETIME_MILLIS_PROFILE.createFormatter();
|
||||||
|
private static final Pattern dateTimePattern = Pattern.compile("^\\d+(-\\d+){2}+T(\\d+:){2}\\d+.\\d+(Z|([+-](\\d+:\\d+)))?$");
|
||||||
|
private static final DateFormat dateTimeNoMillisFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||||
|
private static final Pattern dateTimeNoMillisPattern = Pattern.compile("^\\d+(-\\d+){2}+T(\\d+:){2}\\d+(Z|([+-](\\d+:\\d+)))?$");
|
||||||
|
|
||||||
|
private static final DateFormat xep0091Formatter = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
|
||||||
|
private static final DateFormat xep0091Date6DigitFormatter = new SimpleDateFormat("yyyyMd'T'HH:mm:ss");
|
||||||
|
private static final DateFormat xep0091Date7Digit1MonthFormatter = new SimpleDateFormat("yyyyMdd'T'HH:mm:ss");
|
||||||
|
private static final DateFormat xep0091Date7Digit2MonthFormatter = new SimpleDateFormat("yyyyMMd'T'HH:mm:ss");
|
||||||
|
private static final Pattern xep0091Pattern = Pattern.compile("^\\d+T\\d+:\\d+:\\d+$");
|
||||||
|
|
||||||
|
private static final List<PatternCouplings> couplings = new ArrayList<PatternCouplings>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
XEP_0082_UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
|
TimeZone utc = TimeZone.getTimeZone("UTC");
|
||||||
|
XEP_0082_UTC_FORMAT.setTimeZone(utc);
|
||||||
|
dateFormatter.setTimeZone(utc);
|
||||||
|
timeFormatter.setTimeZone(utc);
|
||||||
|
timeNoZoneFormatter.setTimeZone(utc);
|
||||||
|
timeNoMillisFormatter.setTimeZone(utc);
|
||||||
|
timeNoMillisNoZoneFormatter.setTimeZone(utc);
|
||||||
|
dateTimeFormatter.setTimeZone(utc);
|
||||||
|
dateTimeNoMillisFormatter.setTimeZone(utc);
|
||||||
|
|
||||||
|
xep0091Formatter.setTimeZone(utc);
|
||||||
|
xep0091Date6DigitFormatter.setTimeZone(utc);
|
||||||
|
xep0091Date7Digit1MonthFormatter.setTimeZone(utc);
|
||||||
|
xep0091Date7Digit1MonthFormatter.setLenient(false);
|
||||||
|
xep0091Date7Digit2MonthFormatter.setTimeZone(utc);
|
||||||
|
xep0091Date7Digit2MonthFormatter.setLenient(false);
|
||||||
|
|
||||||
|
couplings.add(new PatternCouplings(datePattern, dateFormatter));
|
||||||
|
couplings.add(new PatternCouplings(dateTimePattern, dateTimeFormatter));
|
||||||
|
couplings.add(new PatternCouplings(dateTimeNoMillisPattern, dateTimeNoMillisFormatter));
|
||||||
|
couplings.add(new PatternCouplings(timePattern, timeFormatter));
|
||||||
|
couplings.add(new PatternCouplings(timeNoZonePattern, timeNoZoneFormatter));
|
||||||
|
couplings.add(new PatternCouplings(timeNoMillisPattern, timeNoMillisFormatter));
|
||||||
|
couplings.add(new PatternCouplings(timeNoMillisNoZonePattern, timeNoMillisNoZoneFormatter));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final char[] QUOTE_ENCODE = """.toCharArray();
|
private static final char[] QUOTE_ENCODE = """.toCharArray();
|
||||||
|
@ -56,18 +116,139 @@ public class StringUtils {
|
||||||
private static final char[] GT_ENCODE = ">".toCharArray();
|
private static final char[] GT_ENCODE = ">".toCharArray();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the given date string in the XEP-0082 - XMPP Date and Time Profiles format.
|
* Parses the given date string in the <a href="http://xmpp.org/extensions/xep-0082.html">XEP-0082 - XMPP Date and Time Profiles</a>.
|
||||||
*
|
*
|
||||||
* @param dateString the date string to parse
|
* @param dateString the date string to parse
|
||||||
* @return the parsed Date
|
* @return the parsed Date
|
||||||
* @throws ParseException if the specified string cannot be parsed
|
* @throws ParseException if the specified string cannot be parsed
|
||||||
|
* @deprecated Use {@link #parseDate(String)} instead.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public static Date parseXEP0082Date(String dateString) throws ParseException {
|
public static Date parseXEP0082Date(String dateString) throws ParseException {
|
||||||
synchronized (XEP_0082_UTC_FORMAT) {
|
return parseDate(dateString);
|
||||||
return XEP_0082_UTC_FORMAT.parse(dateString);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the given date string in either of the three profiles of <a href="http://xmpp.org/extensions/xep-0082.html">XEP-0082 - XMPP Date and Time Profiles</a>
|
||||||
|
* or <a href="http://xmpp.org/extensions/xep-0091.html">XEP-0091 - Legacy Delayed Delivery</a> format.
|
||||||
|
* <p>
|
||||||
|
* This method uses internal date formatters and is thus threadsafe.
|
||||||
|
* @param dateString the date string to parse
|
||||||
|
* @return the parsed Date
|
||||||
|
* @throws ParseException if the specified string cannot be parsed
|
||||||
|
*/
|
||||||
|
public static Date parseDate(String dateString) throws ParseException {
|
||||||
|
Matcher matcher = xep0091Pattern.matcher(dateString);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if date is in XEP-0091 format handle ambiguous dates missing the
|
||||||
|
* leading zero in month and day
|
||||||
|
*/
|
||||||
|
if (matcher.matches()) {
|
||||||
|
int length = dateString.split("T")[0].length();
|
||||||
|
|
||||||
|
if (length < 8) {
|
||||||
|
Date date = handleDateWithMissingLeadingZeros(dateString, length);
|
||||||
|
|
||||||
|
if (date != null)
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
synchronized (xep0091Formatter) {
|
||||||
|
return xep0091Formatter.parse(dateString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (PatternCouplings coupling : couplings) {
|
||||||
|
matcher = coupling.pattern.matcher(dateString);
|
||||||
|
|
||||||
|
if (matcher.matches())
|
||||||
|
{
|
||||||
|
synchronized (coupling.formatter) {
|
||||||
|
return coupling.formatter.parse(dateString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We assume it is the XEP-0082 DateTime profile with no milliseconds at this point. If it isn't, is is just not parseable, then we attempt
|
||||||
|
* to parse it regardless and let it throw the ParseException.
|
||||||
|
*/
|
||||||
|
synchronized (dateTimeNoMillisFormatter) {
|
||||||
|
return dateTimeNoMillisFormatter.parse(dateString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the given date string in different ways and returns the date that
|
||||||
|
* lies in the past and/or is nearest to the current date-time.
|
||||||
|
*
|
||||||
|
* @param stampString date in string representation
|
||||||
|
* @param dateLength
|
||||||
|
* @param noFuture
|
||||||
|
* @return the parsed date
|
||||||
|
* @throws ParseException The date string was of an unknown format
|
||||||
|
*/
|
||||||
|
private static Date handleDateWithMissingLeadingZeros(String stampString, int dateLength) throws ParseException {
|
||||||
|
if (dateLength == 6) {
|
||||||
|
synchronized (xep0091Date6DigitFormatter) {
|
||||||
|
return xep0091Date6DigitFormatter.parse(stampString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Calendar now = Calendar.getInstance();
|
||||||
|
|
||||||
|
Calendar oneDigitMonth = parseXEP91Date(stampString, xep0091Date7Digit1MonthFormatter);
|
||||||
|
Calendar twoDigitMonth = parseXEP91Date(stampString, xep0091Date7Digit2MonthFormatter);
|
||||||
|
|
||||||
|
List<Calendar> dates = filterDatesBefore(now, oneDigitMonth, twoDigitMonth);
|
||||||
|
|
||||||
|
if (!dates.isEmpty()) {
|
||||||
|
return determineNearestDate(now, dates).getTime();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Calendar parseXEP91Date(String stampString, DateFormat dateFormat) {
|
||||||
|
try {
|
||||||
|
synchronized (dateFormat) {
|
||||||
|
dateFormat.parse(stampString);
|
||||||
|
return dateFormat.getCalendar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ParseException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Calendar> filterDatesBefore(Calendar now, Calendar... dates) {
|
||||||
|
List<Calendar> result = new ArrayList<Calendar>();
|
||||||
|
|
||||||
|
for (Calendar calendar : dates) {
|
||||||
|
if (calendar != null && calendar.before(now)) {
|
||||||
|
result.add(calendar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Calendar determineNearestDate(final Calendar now, List<Calendar> dates) {
|
||||||
|
|
||||||
|
Collections.sort(dates, new Comparator<Calendar>() {
|
||||||
|
|
||||||
|
public int compare(Calendar o1, Calendar o2) {
|
||||||
|
Long diff1 = new Long(now.getTimeInMillis() - o1.getTimeInMillis());
|
||||||
|
Long diff2 = new Long(now.getTimeInMillis() - o2.getTimeInMillis());
|
||||||
|
return diff1.compareTo(diff2);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return dates.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a Date into a XEP-0082 - XMPP Date and Time Profiles string.
|
* Formats a Date into a XEP-0082 - XMPP Date and Time Profiles string.
|
||||||
*
|
*
|
||||||
|
@ -75,10 +256,15 @@ public class StringUtils {
|
||||||
* @return the formatted time string in XEP-0082 format
|
* @return the formatted time string in XEP-0082 format
|
||||||
*/
|
*/
|
||||||
public static String formatXEP0082Date(Date date) {
|
public static String formatXEP0082Date(Date date) {
|
||||||
synchronized (XEP_0082_UTC_FORMAT) {
|
synchronized (dateTimeFormatter) {
|
||||||
return XEP_0082_UTC_FORMAT.format(date);
|
return dateTimeFormatter.format(date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String formatDate(Date toFormat, DateFormatType type)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name portion of a XMPP address. For example, for the
|
* Returns the name portion of a XMPP address. For example, for the
|
||||||
|
@ -562,4 +748,15 @@ public class StringUtils {
|
||||||
private StringUtils() {
|
private StringUtils() {
|
||||||
// Not instantiable.
|
// Not instantiable.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class PatternCouplings {
|
||||||
|
Pattern pattern;
|
||||||
|
DateFormat formatter;
|
||||||
|
|
||||||
|
public PatternCouplings(Pattern datePattern, DateFormat dateFormat) {
|
||||||
|
pattern = datePattern;
|
||||||
|
formatter = dateFormat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,19 +20,8 @@
|
||||||
|
|
||||||
package org.jivesoftware.smackx.provider;
|
package org.jivesoftware.smackx.provider;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.PacketExtension;
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
||||||
|
@ -47,82 +36,25 @@ import org.xmlpull.v1.XmlPullParser;
|
||||||
* @author Henning Staib
|
* @author Henning Staib
|
||||||
*/
|
*/
|
||||||
public class DelayInformationProvider implements PacketExtensionProvider {
|
public class DelayInformationProvider implements PacketExtensionProvider {
|
||||||
|
|
||||||
/*
|
|
||||||
* Date format used to parse dates in the XEP-0091 format but missing leading
|
|
||||||
* zeros for month and day.
|
|
||||||
*/
|
|
||||||
private static final SimpleDateFormat XEP_0091_UTC_FALLBACK_FORMAT = new SimpleDateFormat(
|
|
||||||
"yyyyMd'T'HH:mm:ss");
|
|
||||||
static {
|
|
||||||
XEP_0091_UTC_FALLBACK_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Date format used to parse dates in the XEP-0082 format but missing milliseconds.
|
|
||||||
*/
|
|
||||||
private static final SimpleDateFormat XEP_0082_UTC_FORMAT_WITHOUT_MILLIS = new SimpleDateFormat(
|
|
||||||
"yyyy-MM-dd'T'HH:mm:ss'Z'");
|
|
||||||
static {
|
|
||||||
XEP_0082_UTC_FORMAT_WITHOUT_MILLIS.setTimeZone(TimeZone.getTimeZone("UTC"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Maps a regular expression for a date format to the date format parser.
|
|
||||||
*/
|
|
||||||
private static Map<String, DateFormat> formats = new HashMap<String, DateFormat>();
|
|
||||||
static {
|
|
||||||
formats.put("^\\d+T\\d+:\\d+:\\d+$", DelayInformation.XEP_0091_UTC_FORMAT);
|
|
||||||
formats.put("^\\d+-\\d+-\\d+T\\d+:\\d+:\\d+\\.\\d+Z$", StringUtils.XEP_0082_UTC_FORMAT);
|
|
||||||
formats.put("^\\d+-\\d+-\\d+T\\d+:\\d+:\\d+Z$", XEP_0082_UTC_FORMAT_WITHOUT_MILLIS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new DeliveryInformationProvider. ProviderManager requires that
|
|
||||||
* every PacketExtensionProvider has a public, no-argument constructor
|
|
||||||
*/
|
|
||||||
public DelayInformationProvider() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
|
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
|
||||||
String stampString = (parser.getAttributeValue("", "stamp"));
|
String stampString = (parser.getAttributeValue("", "stamp"));
|
||||||
Date stamp = null;
|
Date stamp = null;
|
||||||
DateFormat format = null;
|
|
||||||
|
|
||||||
for (String regexp : formats.keySet()) {
|
try {
|
||||||
if (stampString.matches(regexp)) {
|
stamp = StringUtils.parseDate(stampString);
|
||||||
try {
|
}
|
||||||
format = formats.get(regexp);
|
catch (ParseException parseExc) {
|
||||||
synchronized (format) {
|
/*
|
||||||
stamp = format.parse(stampString);
|
* if date could not be parsed but XML is valid, don't shutdown
|
||||||
}
|
* connection by throwing an exception instead set timestamp to epoch
|
||||||
}
|
* so that it is obviously wrong.
|
||||||
catch (ParseException e) {
|
*/
|
||||||
// do nothing, format is still set
|
if (stamp == null) {
|
||||||
}
|
stamp = new Date(0);
|
||||||
|
|
||||||
// break because only one regexp can match
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* if date is in XEP-0091 format handle ambiguous dates missing the
|
|
||||||
* leading zero in month and day
|
|
||||||
*/
|
|
||||||
if (format == DelayInformation.XEP_0091_UTC_FORMAT
|
|
||||||
&& stampString.split("T")[0].length() < 8) {
|
|
||||||
stamp = handleDateWithMissingLeadingZeros(stampString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* if date could not be parsed but XML is valid, don't shutdown
|
|
||||||
* connection by throwing an exception instead set timestamp to current
|
|
||||||
* time
|
|
||||||
*/
|
|
||||||
if (stamp == null) {
|
|
||||||
stamp = new Date();
|
|
||||||
}
|
|
||||||
|
|
||||||
DelayInformation delayInformation = new DelayInformation(stamp);
|
DelayInformation delayInformation = new DelayInformation(stamp);
|
||||||
delayInformation.setFrom(parser.getAttributeValue("", "from"));
|
delayInformation.setFrom(parser.getAttributeValue("", "from"));
|
||||||
|
@ -133,72 +65,9 @@ public class DelayInformationProvider implements PacketExtensionProvider {
|
||||||
* DelayInformation API specifies that null should be returned in that
|
* DelayInformation API specifies that null should be returned in that
|
||||||
* case.
|
* case.
|
||||||
*/
|
*/
|
||||||
reason = "".equals(reason) ? null : reason;
|
reason = reason.isEmpty() ? null : reason;
|
||||||
delayInformation.setReason(reason);
|
delayInformation.setReason(reason);
|
||||||
|
|
||||||
return delayInformation;
|
return delayInformation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the given date string in different ways and returns the date that
|
|
||||||
* lies in the past and/or is nearest to the current date-time.
|
|
||||||
*
|
|
||||||
* @param stampString date in string representation
|
|
||||||
* @return the parsed date
|
|
||||||
*/
|
|
||||||
private Date handleDateWithMissingLeadingZeros(String stampString) {
|
|
||||||
Calendar now = new GregorianCalendar();
|
|
||||||
Calendar xep91 = null;
|
|
||||||
Calendar xep91Fallback = null;
|
|
||||||
|
|
||||||
xep91 = parseXEP91Date(stampString, DelayInformation.XEP_0091_UTC_FORMAT);
|
|
||||||
xep91Fallback = parseXEP91Date(stampString, XEP_0091_UTC_FALLBACK_FORMAT);
|
|
||||||
|
|
||||||
List<Calendar> dates = filterDatesBefore(now, xep91, xep91Fallback);
|
|
||||||
|
|
||||||
if (!dates.isEmpty()) {
|
|
||||||
return determineNearestDate(now, dates).getTime();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Calendar parseXEP91Date(String stampString, DateFormat dateFormat) {
|
|
||||||
try {
|
|
||||||
synchronized (dateFormat) {
|
|
||||||
dateFormat.parse(stampString);
|
|
||||||
return dateFormat.getCalendar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (ParseException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Calendar> filterDatesBefore(Calendar now, Calendar... dates) {
|
|
||||||
List<Calendar> result = new ArrayList<Calendar>();
|
|
||||||
|
|
||||||
for (Calendar calendar : dates) {
|
|
||||||
if (calendar != null && calendar.before(now)) {
|
|
||||||
result.add(calendar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Calendar determineNearestDate(final Calendar now, List<Calendar> dates) {
|
|
||||||
|
|
||||||
Collections.sort(dates, new Comparator<Calendar>() {
|
|
||||||
|
|
||||||
public int compare(Calendar o1, Calendar o2) {
|
|
||||||
Long diff1 = new Long(now.getTimeInMillis() - o1.getTimeInMillis());
|
|
||||||
Long diff2 = new Long(now.getTimeInMillis() - o2.getTimeInMillis());
|
|
||||||
return diff1.compareTo(diff2);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return dates.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,22 +7,30 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.util;
|
package org.jivesoftware.smack.util;
|
||||||
|
|
||||||
import static junit.framework.Assert.*;
|
import static junit.framework.Assert.assertEquals;
|
||||||
import static org.custommonkey.xmlunit.XMLAssert.*;
|
import static junit.framework.Assert.assertFalse;
|
||||||
|
import static junit.framework.Assert.assertNotNull;
|
||||||
|
import static junit.framework.Assert.assertNull;
|
||||||
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
import static junit.framework.Assert.fail;
|
||||||
|
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
|
||||||
|
import static org.custommonkey.xmlunit.XMLAssert.assertXMLNotEqual;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.util.Calendar;
|
||||||
import java.io.StringReader;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.custommonkey.xmlunit.DetailedDiff;
|
import org.custommonkey.xmlunit.DetailedDiff;
|
||||||
import org.custommonkey.xmlunit.Diff;
|
import org.custommonkey.xmlunit.Diff;
|
||||||
|
import org.jivesoftware.smack.TestUtils;
|
||||||
import org.jivesoftware.smack.packet.Message;
|
import org.jivesoftware.smack.packet.Message;
|
||||||
import org.jivesoftware.smack.packet.Packet;
|
import org.jivesoftware.smack.packet.Packet;
|
||||||
|
import org.jivesoftware.smack.packet.Presence;
|
||||||
|
import org.jivesoftware.smackx.packet.DelayInformation;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.xmlpull.mxp1.MXParser;
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
import com.jamesmurty.utils.XMLBuilder;
|
import com.jamesmurty.utils.XMLBuilder;
|
||||||
|
@ -56,7 +64,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
Message message = (Message) PacketParserUtils
|
Message message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getBody());
|
assertEquals(defaultLanguage, message.getBody());
|
||||||
assertTrue(message.getBodyLanguages().isEmpty());
|
assertTrue(message.getBodyLanguages().isEmpty());
|
||||||
|
@ -75,7 +83,7 @@ public class PacketParserUtilsTest {
|
||||||
.t(otherLanguage)
|
.t(otherLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils.parseMessage(getParser(control));
|
message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(otherLanguage, message.getBody());
|
assertEquals(otherLanguage, message.getBody());
|
||||||
assertTrue(message.getBodyLanguages().isEmpty());
|
assertTrue(message.getBodyLanguages().isEmpty());
|
||||||
|
@ -93,7 +101,7 @@ public class PacketParserUtilsTest {
|
||||||
.t(defaultLanguage)
|
.t(defaultLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils.parseMessage(getParser(control));
|
message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getBody());
|
assertEquals(defaultLanguage, message.getBody());
|
||||||
assertTrue(message.getBodyLanguages().isEmpty());
|
assertTrue(message.getBodyLanguages().isEmpty());
|
||||||
|
@ -112,7 +120,7 @@ public class PacketParserUtilsTest {
|
||||||
.t(defaultLanguage)
|
.t(defaultLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils.parseMessage(getParser(control));
|
message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getBody());
|
assertEquals(defaultLanguage, message.getBody());
|
||||||
assertTrue(message.getBodyLanguages().isEmpty());
|
assertTrue(message.getBodyLanguages().isEmpty());
|
||||||
|
@ -133,7 +141,7 @@ public class PacketParserUtilsTest {
|
||||||
.t(otherLanguage)
|
.t(otherLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils.parseMessage(getParser(control));
|
message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertNull(message.getBody());
|
assertNull(message.getBody());
|
||||||
assertFalse(message.getBodyLanguages().isEmpty());
|
assertFalse(message.getBodyLanguages().isEmpty());
|
||||||
|
@ -154,7 +162,7 @@ public class PacketParserUtilsTest {
|
||||||
.t(otherLanguage)
|
.t(otherLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils.parseMessage(getParser(control));
|
message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertNull(message.getBody());
|
assertNull(message.getBody());
|
||||||
assertFalse(message.getBodyLanguages().isEmpty());
|
assertFalse(message.getBodyLanguages().isEmpty());
|
||||||
|
@ -175,7 +183,7 @@ public class PacketParserUtilsTest {
|
||||||
.t(defaultLanguage)
|
.t(defaultLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils.parseMessage(getParser(control));
|
message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertNull(message.getBody());
|
assertNull(message.getBody());
|
||||||
assertFalse(message.getBodyLanguages().isEmpty());
|
assertFalse(message.getBodyLanguages().isEmpty());
|
||||||
|
@ -205,7 +213,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
Message message = (Message) PacketParserUtils
|
Message message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getSubject());
|
assertEquals(defaultLanguage, message.getSubject());
|
||||||
assertTrue(message.getSubjectLanguages().isEmpty());
|
assertTrue(message.getSubjectLanguages().isEmpty());
|
||||||
|
@ -224,7 +232,7 @@ public class PacketParserUtilsTest {
|
||||||
.t(otherLanguage)
|
.t(otherLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils.parseMessage(getParser(control));
|
message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(otherLanguage, message.getSubject());
|
assertEquals(otherLanguage, message.getSubject());
|
||||||
assertTrue(message.getSubjectLanguages().isEmpty());
|
assertTrue(message.getSubjectLanguages().isEmpty());
|
||||||
|
@ -242,7 +250,7 @@ public class PacketParserUtilsTest {
|
||||||
.t(defaultLanguage)
|
.t(defaultLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils.parseMessage(getParser(control));
|
message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getSubject());
|
assertEquals(defaultLanguage, message.getSubject());
|
||||||
assertTrue(message.getSubjectLanguages().isEmpty());
|
assertTrue(message.getSubjectLanguages().isEmpty());
|
||||||
|
@ -261,7 +269,7 @@ public class PacketParserUtilsTest {
|
||||||
.t(defaultLanguage)
|
.t(defaultLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils.parseMessage(getParser(control));
|
message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getSubject());
|
assertEquals(defaultLanguage, message.getSubject());
|
||||||
assertTrue(message.getSubjectLanguages().isEmpty());
|
assertTrue(message.getSubjectLanguages().isEmpty());
|
||||||
|
@ -282,7 +290,7 @@ public class PacketParserUtilsTest {
|
||||||
.t(otherLanguage)
|
.t(otherLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils.parseMessage(getParser(control));
|
message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertNull(message.getSubject());
|
assertNull(message.getSubject());
|
||||||
assertFalse(message.getSubjectLanguages().isEmpty());
|
assertFalse(message.getSubjectLanguages().isEmpty());
|
||||||
|
@ -303,7 +311,7 @@ public class PacketParserUtilsTest {
|
||||||
.t(otherLanguage)
|
.t(otherLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils.parseMessage(getParser(control));
|
message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertNull(message.getSubject());
|
assertNull(message.getSubject());
|
||||||
assertFalse(message.getSubjectLanguages().isEmpty());
|
assertFalse(message.getSubjectLanguages().isEmpty());
|
||||||
|
@ -324,7 +332,7 @@ public class PacketParserUtilsTest {
|
||||||
.t(defaultLanguage)
|
.t(defaultLanguage)
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils.parseMessage(getParser(control));
|
message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertNull(message.getSubject());
|
assertNull(message.getSubject());
|
||||||
assertFalse(message.getSubjectLanguages().isEmpty());
|
assertFalse(message.getSubjectLanguages().isEmpty());
|
||||||
|
@ -359,7 +367,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils
|
message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getBody());
|
assertEquals(defaultLanguage, message.getBody());
|
||||||
assertEquals(otherLanguage, message.getBody(otherLanguage));
|
assertEquals(otherLanguage, message.getBody(otherLanguage));
|
||||||
|
@ -384,7 +392,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils
|
message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getBody());
|
assertEquals(defaultLanguage, message.getBody());
|
||||||
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
||||||
|
@ -408,7 +416,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils
|
message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(otherLanguage, message.getBody());
|
assertEquals(otherLanguage, message.getBody());
|
||||||
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
||||||
|
@ -432,7 +440,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils
|
message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getBody());
|
assertEquals(defaultLanguage, message.getBody());
|
||||||
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
||||||
|
@ -455,7 +463,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils
|
message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getBody());
|
assertEquals(defaultLanguage, message.getBody());
|
||||||
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
||||||
|
@ -478,7 +486,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils
|
message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getBody());
|
assertEquals(defaultLanguage, message.getBody());
|
||||||
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
assertEquals(defaultLanguage, message.getBody(defaultLanguage));
|
||||||
|
@ -512,7 +520,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils
|
message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getSubject());
|
assertEquals(defaultLanguage, message.getSubject());
|
||||||
assertEquals(otherLanguage, message.getSubject(otherLanguage));
|
assertEquals(otherLanguage, message.getSubject(otherLanguage));
|
||||||
|
@ -537,7 +545,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils
|
message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getSubject());
|
assertEquals(defaultLanguage, message.getSubject());
|
||||||
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
||||||
|
@ -561,7 +569,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils
|
message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(otherLanguage, message.getSubject());
|
assertEquals(otherLanguage, message.getSubject());
|
||||||
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
||||||
|
@ -585,7 +593,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils
|
message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getSubject());
|
assertEquals(defaultLanguage, message.getSubject());
|
||||||
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
||||||
|
@ -608,7 +616,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils
|
message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getSubject());
|
assertEquals(defaultLanguage, message.getSubject());
|
||||||
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
||||||
|
@ -631,7 +639,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
message = (Message) PacketParserUtils
|
message = (Message) PacketParserUtils
|
||||||
.parseMessage(getParser(control));
|
.parseMessage(TestUtils.getMessageParser(control));
|
||||||
|
|
||||||
assertEquals(defaultLanguage, message.getSubject());
|
assertEquals(defaultLanguage, message.getSubject());
|
||||||
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
assertEquals(defaultLanguage, message.getSubject(defaultLanguage));
|
||||||
|
@ -657,7 +665,7 @@ public class PacketParserUtilsTest {
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Message message = (Message) PacketParserUtils.parseMessage(getParser(control));
|
Message message = (Message) PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
String body = "<span style=\"font-weight: bold;\">"
|
String body = "<span style=\"font-weight: bold;\">"
|
||||||
+ "Bad Message Body</span>";
|
+ "Bad Message Body</span>";
|
||||||
assertEquals(body, message.getBody());
|
assertEquals(body, message.getBody());
|
||||||
|
@ -689,7 +697,7 @@ public class PacketParserUtilsTest {
|
||||||
String invalidControl = validControl.replace("Good Message Body", "Bad </span> Body");
|
String invalidControl = validControl.replace("Good Message Body", "Bad </span> Body");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PacketParserUtils.parseMessage(getParser(invalidControl));
|
PacketParserUtils.parseMessage(TestUtils.getMessageParser(invalidControl));
|
||||||
fail("Exception should be thrown");
|
fail("Exception should be thrown");
|
||||||
} catch(XmlPullParserException e) {
|
} catch(XmlPullParserException e) {
|
||||||
assertTrue(e.getMessage().contains("end tag name </span>"));
|
assertTrue(e.getMessage().contains("end tag name </span>"));
|
||||||
|
@ -698,7 +706,7 @@ public class PacketParserUtilsTest {
|
||||||
invalidControl = validControl.replace("Good Message Body", "Bad </body> Body");
|
invalidControl = validControl.replace("Good Message Body", "Bad </body> Body");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PacketParserUtils.parseMessage(getParser(invalidControl));
|
PacketParserUtils.parseMessage(TestUtils.getMessageParser(invalidControl));
|
||||||
fail("Exception should be thrown");
|
fail("Exception should be thrown");
|
||||||
} catch(XmlPullParserException e) {
|
} catch(XmlPullParserException e) {
|
||||||
assertTrue(e.getMessage().contains("end tag name </body>"));
|
assertTrue(e.getMessage().contains("end tag name </body>"));
|
||||||
|
@ -707,7 +715,7 @@ public class PacketParserUtilsTest {
|
||||||
invalidControl = validControl.replace("Good Message Body", "Bad </message> Body");
|
invalidControl = validControl.replace("Good Message Body", "Bad </message> Body");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PacketParserUtils.parseMessage(getParser(invalidControl));
|
PacketParserUtils.parseMessage(TestUtils.getMessageParser(invalidControl));
|
||||||
fail("Exception should be thrown");
|
fail("Exception should be thrown");
|
||||||
} catch(XmlPullParserException e) {
|
} catch(XmlPullParserException e) {
|
||||||
assertTrue(e.getMessage().contains("end tag name </message>"));
|
assertTrue(e.getMessage().contains("end tag name </message>"));
|
||||||
|
@ -736,20 +744,94 @@ public class PacketParserUtilsTest {
|
||||||
.t("This is a test of the emergency broadcast system, 3.")
|
.t("This is a test of the emergency broadcast system, 3.")
|
||||||
.asString(outputProperties);
|
.asString(outputProperties);
|
||||||
|
|
||||||
Packet message = PacketParserUtils.parseMessage(getParser(control));
|
Packet message = PacketParserUtils.parseMessage(TestUtils.getMessageParser(control));
|
||||||
assertXMLEqual(control, message.toXML());
|
assertXMLEqual(control, message.toXML());
|
||||||
}
|
}
|
||||||
|
|
||||||
private XmlPullParser getParser(String control) throws XmlPullParserException, IOException {
|
@Test
|
||||||
XmlPullParser parser = new MXParser();
|
public void validateSimplePresence() throws Exception {
|
||||||
parser.setInput(new StringReader(control));
|
String stanza = "<presence from='juliet@example.com/balcony' to='romeo@example.net'/>";
|
||||||
while(true) {
|
|
||||||
if(parser.next() == XmlPullParser.START_TAG
|
Presence presence = PacketParserUtils.parsePresence(TestUtils.getPresenceParser(stanza));
|
||||||
&& parser.getName().equals("message")) { break; }
|
|
||||||
}
|
assertXMLEqual(stanza, presence.toXML());
|
||||||
return parser;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void validatePresenceProbe() throws Exception {
|
||||||
|
String stanza = "<presence from='mercutio@example.com' id='xv291f38' to='juliet@example.com' type='unsubscribed'/>";
|
||||||
|
|
||||||
|
Presence presence = PacketParserUtils.parsePresence(TestUtils.getPresenceParser(stanza));
|
||||||
|
|
||||||
|
assertXMLEqual(stanza, presence.toXML());
|
||||||
|
assertEquals(Presence.Type.unsubscribed, presence.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void validatePresenceOptionalElements() throws Exception {
|
||||||
|
String stanza = "<presence xml:lang='en' type='unsubscribed'>"
|
||||||
|
+ "<show>dnd</show>"
|
||||||
|
+ "<status>Wooing Juliet</status>"
|
||||||
|
+ "<priority>1</priority>"
|
||||||
|
+ "</presence>";
|
||||||
|
|
||||||
|
Presence presence = PacketParserUtils.parsePresence(TestUtils.getPresenceParser(stanza));
|
||||||
|
assertXMLEqual(stanza, presence.toXML());
|
||||||
|
assertEquals(Presence.Type.unsubscribed, presence.getType());
|
||||||
|
assertEquals("dnd", presence.getMode().name());
|
||||||
|
assertEquals("en", presence.getLanguage());
|
||||||
|
assertEquals("Wooing Juliet", presence.getStatus());
|
||||||
|
assertEquals(1, presence.getPriority());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void validatePresenceWithDelayedDelivery() throws Exception {
|
||||||
|
String stanza = "<presence from='mercutio@example.com' to='juliet@example.com'>"
|
||||||
|
+ "<delay xmlns='urn:xmpp:delay' stamp='2002-09-10T23:41:07Z'/></presence>";
|
||||||
|
|
||||||
|
Presence presence = PacketParserUtils.parsePresence(TestUtils.getPresenceParser(stanza));
|
||||||
|
|
||||||
|
DelayInformation delay = (DelayInformation) presence.getExtension("urn:xmpp:delay");
|
||||||
|
assertNotNull(delay);
|
||||||
|
Date date = StringUtils.parseDate("2002-09-10T23:41:07Z");
|
||||||
|
assertEquals(date, delay.getStamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void validatePresenceWithLegacyDelayed() throws Exception {
|
||||||
|
String stanza = "<presence from='mercutio@example.com' to='juliet@example.com'>"
|
||||||
|
+ "<x xmlns='jabber:x:delay' stamp='20020910T23:41:07'/></presence>";
|
||||||
|
|
||||||
|
Presence presence = PacketParserUtils.parsePresence(TestUtils.getPresenceParser(stanza));
|
||||||
|
|
||||||
|
DelayInformation delay = (DelayInformation) presence.getExtension("jabber:x:delay");
|
||||||
|
assertNotNull(delay);
|
||||||
|
Date date = StringUtils.parseDate("20020910T23:41:07");
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
|
cal.setTime(date);
|
||||||
|
assertEquals(cal.getTime(), delay.getStamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsePresenceWithInvalidDelayedDelivery() throws Exception {
|
||||||
|
String stanza = "<presence from='mercutio@example.com' to='juliet@example.com'>"
|
||||||
|
+ "<delay xmlns='urn:xmpp:delay'/></presence>";
|
||||||
|
|
||||||
|
Presence presence = PacketParserUtils.parsePresence(TestUtils.getPresenceParser(stanza));
|
||||||
|
assertNull(presence.getExtension("urn:xmpp:delay"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsePresenceWithInvalidLegacyDelayed() throws Exception {
|
||||||
|
String stanza = "<presence from='mercutio@example.com' to='juliet@example.com'>"
|
||||||
|
+ "<x xmlns='jabber:x:delay'/></presence>";
|
||||||
|
|
||||||
|
Presence presence = PacketParserUtils.parsePresence(TestUtils.getPresenceParser(stanza));
|
||||||
|
DelayInformation delay = (DelayInformation) presence.getExtension("urn:xmpp:delay");
|
||||||
|
assertNull(delay);
|
||||||
|
}
|
||||||
|
|
||||||
private String determineNonDefaultLanguage() {
|
private String determineNonDefaultLanguage() {
|
||||||
String otherLanguage = "jp";
|
String otherLanguage = "jp";
|
||||||
Locale[] availableLocales = Locale.getAvailableLocales();
|
Locale[] availableLocales = Locale.getAvailableLocales();
|
||||||
|
|
|
@ -52,13 +52,23 @@
|
||||||
|
|
||||||
package org.jivesoftware.smack.util;
|
package org.jivesoftware.smack.util;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A test case for the StringUtils class.
|
* A test case for the StringUtils class.
|
||||||
*/
|
*/
|
||||||
public class StringUtilsTest extends TestCase {
|
public class StringUtilsTest {
|
||||||
|
@Test
|
||||||
public void testEscapeForXML() {
|
public void testEscapeForXML() {
|
||||||
String input = null;
|
String input = null;
|
||||||
|
|
||||||
|
@ -98,6 +108,7 @@ public class StringUtilsTest extends TestCase {
|
||||||
assertEquals("It's a good day today", StringUtils.escapeForXML(input));
|
assertEquals("It's a good day today", StringUtils.escapeForXML(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testHash() {
|
public void testHash() {
|
||||||
// Test null
|
// Test null
|
||||||
// @TODO - should the StringUtils.hash(String) method be fixed to handle null input?
|
// @TODO - should the StringUtils.hash(String) method be fixed to handle null input?
|
||||||
|
@ -148,6 +159,7 @@ public class StringUtilsTest extends TestCase {
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testEncodeHex() {
|
public void testEncodeHex() {
|
||||||
String input = "";
|
String input = "";
|
||||||
String output = "";
|
String output = "";
|
||||||
|
@ -163,6 +175,7 @@ public class StringUtilsTest extends TestCase {
|
||||||
/**
|
/**
|
||||||
* This method tests 2 StringUtil methods - encodeBase64(String) and encodeBase64(byte[]).
|
* This method tests 2 StringUtil methods - encodeBase64(String) and encodeBase64(byte[]).
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testEncodeBase64() {
|
public void testEncodeBase64() {
|
||||||
String input = "";
|
String input = "";
|
||||||
String output = "";
|
String output = "";
|
||||||
|
@ -204,6 +217,7 @@ public class StringUtilsTest extends TestCase {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testRandomString() {
|
public void testRandomString() {
|
||||||
// Boundary test
|
// Boundary test
|
||||||
String result = StringUtils.randomString(-1);
|
String result = StringUtils.randomString(-1);
|
||||||
|
@ -222,6 +236,7 @@ public class StringUtilsTest extends TestCase {
|
||||||
assertTrue(result.length() == 128);
|
assertTrue(result.length() == 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testParsing() {
|
public void testParsing() {
|
||||||
String error = "Error parsing node name";
|
String error = "Error parsing node name";
|
||||||
assertEquals(error, "", StringUtils.parseName("yahoo.myjabber.net"));
|
assertEquals(error, "", StringUtils.parseName("yahoo.myjabber.net"));
|
||||||
|
@ -236,4 +251,144 @@ public class StringUtilsTest extends TestCase {
|
||||||
assertEquals(error, result, StringUtils.parseServer("user@yahoo.myjabber.net/registred"));
|
assertEquals(error, result, StringUtils.parseServer("user@yahoo.myjabber.net/registred"));
|
||||||
assertEquals(error, result, StringUtils.parseServer("user@yahoo.myjabber.net"));
|
assertEquals(error, result, StringUtils.parseServer("user@yahoo.myjabber.net"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseXep0082DateProfile() throws Exception
|
||||||
|
{
|
||||||
|
Date date = StringUtils.parseDate("1971-07-21");
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(date);
|
||||||
|
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
|
assertEquals(1971, cal.get(Calendar.YEAR));
|
||||||
|
assertEquals(6, cal.get(Calendar.MONTH));
|
||||||
|
assertEquals(21, cal.get(Calendar.DAY_OF_MONTH));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseXep0082TimeProfile() throws Exception
|
||||||
|
{
|
||||||
|
Date date = StringUtils.parseDate("02:56:15");
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(date);
|
||||||
|
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
|
assertEquals(2, cal.get(Calendar.HOUR_OF_DAY));
|
||||||
|
assertEquals(56, cal.get(Calendar.MINUTE));
|
||||||
|
assertEquals(15, cal.get(Calendar.SECOND));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseXep0082TimeWithMillisProfile() throws Exception
|
||||||
|
{
|
||||||
|
Date date = StringUtils.parseDate("02:56:15.123");
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(date);
|
||||||
|
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
|
assertEquals(2, cal.get(Calendar.HOUR_OF_DAY));
|
||||||
|
assertEquals(56, cal.get(Calendar.MINUTE));
|
||||||
|
assertEquals(15, cal.get(Calendar.SECOND));
|
||||||
|
assertEquals(123, cal.get(Calendar.MILLISECOND));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseXep0082DateTimeProfile() throws Exception
|
||||||
|
{
|
||||||
|
Date date = StringUtils.parseDate("1971-07-21T02:56:15Z");
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(date);
|
||||||
|
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
|
assertEquals(1971, cal.get(Calendar.YEAR));
|
||||||
|
assertEquals(6, cal.get(Calendar.MONTH));
|
||||||
|
assertEquals(21, cal.get(Calendar.DAY_OF_MONTH));
|
||||||
|
assertEquals(2, cal.get(Calendar.HOUR_OF_DAY));
|
||||||
|
assertEquals(56, cal.get(Calendar.MINUTE));
|
||||||
|
assertEquals(15, cal.get(Calendar.SECOND));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseXep0082DateTimeProfileWithMillis() throws Exception
|
||||||
|
{
|
||||||
|
Date date = StringUtils.parseDate("1971-07-21T02:56:15.123Z");
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(date);
|
||||||
|
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
|
assertEquals(1971, cal.get(Calendar.YEAR));
|
||||||
|
assertEquals(6, cal.get(Calendar.MONTH));
|
||||||
|
assertEquals(21, cal.get(Calendar.DAY_OF_MONTH));
|
||||||
|
assertEquals(2, cal.get(Calendar.HOUR_OF_DAY));
|
||||||
|
assertEquals(56, cal.get(Calendar.MINUTE));
|
||||||
|
assertEquals(15, cal.get(Calendar.SECOND));
|
||||||
|
assertEquals(123, cal.get(Calendar.MILLISECOND));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseXep0091() throws Exception
|
||||||
|
{
|
||||||
|
Date date = StringUtils.parseDate("20020910T23:08:25");
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(date);
|
||||||
|
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
|
assertEquals(2002, cal.get(Calendar.YEAR));
|
||||||
|
assertEquals(8, cal.get(Calendar.MONTH));
|
||||||
|
assertEquals(10, cal.get(Calendar.DAY_OF_MONTH));
|
||||||
|
assertEquals(23, cal.get(Calendar.HOUR_OF_DAY));
|
||||||
|
assertEquals(8, cal.get(Calendar.MINUTE));
|
||||||
|
assertEquals(25, cal.get(Calendar.SECOND));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseXep0091NoLeading0() throws Exception
|
||||||
|
{
|
||||||
|
Date date = StringUtils.parseDate("200291T23:08:25");
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(date);
|
||||||
|
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
|
assertEquals(2002, cal.get(Calendar.YEAR));
|
||||||
|
assertEquals(8, cal.get(Calendar.MONTH));
|
||||||
|
assertEquals(1, cal.get(Calendar.DAY_OF_MONTH));
|
||||||
|
assertEquals(23, cal.get(Calendar.HOUR_OF_DAY));
|
||||||
|
assertEquals(8, cal.get(Calendar.MINUTE));
|
||||||
|
assertEquals(25, cal.get(Calendar.SECOND));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseXep0091AmbiguousMonthDay() throws Exception
|
||||||
|
{
|
||||||
|
Date date = StringUtils.parseDate("2002101T23:08:25");
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(date);
|
||||||
|
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
|
assertEquals(2002, cal.get(Calendar.YEAR));
|
||||||
|
assertEquals(9, cal.get(Calendar.MONTH));
|
||||||
|
assertEquals(1, cal.get(Calendar.DAY_OF_MONTH));
|
||||||
|
assertEquals(23, cal.get(Calendar.HOUR_OF_DAY));
|
||||||
|
assertEquals(8, cal.get(Calendar.MINUTE));
|
||||||
|
assertEquals(25, cal.get(Calendar.SECOND));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseXep0091SingleDigitMonth() throws Exception
|
||||||
|
{
|
||||||
|
Date date = StringUtils.parseDate("2002130T23:08:25");
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(date);
|
||||||
|
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
|
assertEquals(2002, cal.get(Calendar.YEAR));
|
||||||
|
assertEquals(0, cal.get(Calendar.MONTH));
|
||||||
|
assertEquals(30, cal.get(Calendar.DAY_OF_MONTH));
|
||||||
|
assertEquals(23, cal.get(Calendar.HOUR_OF_DAY));
|
||||||
|
assertEquals(8, cal.get(Calendar.MINUTE));
|
||||||
|
assertEquals(25, cal.get(Calendar.SECOND));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test (expected=ParseException.class)
|
||||||
|
public void parseNoMonthDay() throws Exception
|
||||||
|
{
|
||||||
|
StringUtils.parseDate("2002T23:08:25");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test (expected=ParseException.class)
|
||||||
|
public void parseNoYear() throws Exception
|
||||||
|
{
|
||||||
|
StringUtils.parseDate("130T23:08:25");
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue