ParserUtils.java

  1. /**
  2.  *
  3.  * Copyright © 2014-2024 Florian Schmaus
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smack.util;

  18. import java.io.IOException;
  19. import java.net.URI;
  20. import java.net.URISyntaxException;
  21. import java.text.ParseException;
  22. import java.util.Date;
  23. import java.util.Locale;

  24. import org.jivesoftware.smack.datatypes.UInt16;
  25. import org.jivesoftware.smack.datatypes.UInt32;
  26. import org.jivesoftware.smack.packet.XmlEnvironment;
  27. import org.jivesoftware.smack.parsing.SmackParsingException;
  28. import org.jivesoftware.smack.parsing.SmackParsingException.RequiredAttributeMissingException;
  29. import org.jivesoftware.smack.parsing.SmackParsingException.SmackUriSyntaxParsingException;
  30. import org.jivesoftware.smack.xml.XmlPullParser;
  31. import org.jivesoftware.smack.xml.XmlPullParserException;

  32. import org.jxmpp.jid.EntityBareJid;
  33. import org.jxmpp.jid.EntityFullJid;
  34. import org.jxmpp.jid.EntityJid;
  35. import org.jxmpp.jid.Jid;
  36. import org.jxmpp.jid.impl.JidCreate;
  37. import org.jxmpp.jid.parts.Resourcepart;
  38. import org.jxmpp.stringprep.XmppStringprepException;
  39. import org.jxmpp.util.XmppDateTime;

  40. public class ParserUtils {

  41.     /**
  42.      * The constant String "jid".
  43.      */
  44.     public static final String JID = "jid";

  45.     public static void assertAtStartTag(XmlPullParser parser) throws XmlPullParserException {
  46.         assert parser.getEventType() == XmlPullParser.Event.START_ELEMENT;
  47.     }

  48.     public static void assertAtStartTag(XmlPullParser parser, String name) throws XmlPullParserException {
  49.         assertAtStartTag(parser);
  50.         assert name.equals(parser.getName());
  51.     }

  52.     public static void assertAtEndTag(XmlPullParser parser) throws XmlPullParserException {
  53.         assert parser.getEventType() == XmlPullParser.Event.END_ELEMENT;
  54.     }

  55.     public static void forwardToStartElement(XmlPullParser parser) throws XmlPullParserException, IOException {
  56.          // Wind the parser forward to the first start tag
  57.         XmlPullParser.Event event = parser.getEventType();
  58.         while (event != XmlPullParser.Event.START_ELEMENT) {
  59.             if (event == XmlPullParser.Event.END_DOCUMENT) {
  60.                 throw new IllegalArgumentException("Document contains no start tag");
  61.             }
  62.             event = parser.next();
  63.         }
  64.     }

  65.     public static void forwardToEndTagOfDepth(XmlPullParser parser, int depth)
  66.                     throws XmlPullParserException, IOException {
  67.         XmlPullParser.Event event = parser.getEventType();
  68.         while (!(event == XmlPullParser.Event.END_ELEMENT && parser.getDepth() == depth)) {
  69.             assert event != XmlPullParser.Event.END_DOCUMENT;
  70.             event = parser.next();
  71.         }
  72.     }

  73.     public static Jid getJidAttribute(XmlPullParser parser) throws XmppStringprepException {
  74.         return getJidAttribute(parser, JID);
  75.     }

  76.     public static Jid getJidAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
  77.         final String jidString = parser.getAttributeValue("", name);
  78.         if (jidString == null) {
  79.             return null;
  80.         }
  81.         return JidCreate.from(jidString);
  82.     }

  83.     public static EntityBareJid getBareJidAttribute(XmlPullParser parser) throws XmppStringprepException {
  84.         return getBareJidAttribute(parser, JID);
  85.     }

  86.     public static EntityBareJid getBareJidAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
  87.         final String jidString = parser.getAttributeValue("", name);
  88.         if (jidString == null) {
  89.             return null;
  90.         }
  91.         return JidCreate.entityBareFrom(jidString);
  92.     }

  93.     public static EntityFullJid getFullJidAttribute(XmlPullParser parser) throws XmppStringprepException {
  94.         return getFullJidAttribute(parser, JID);
  95.     }

  96.     public static EntityFullJid getFullJidAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
  97.         final String jidString = parser.getAttributeValue("", name);
  98.         if (jidString == null) {
  99.             return null;
  100.         }
  101.         return JidCreate.entityFullFrom(jidString);
  102.     }

  103.     public static EntityJid getEntityJidAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
  104.         final String jidString = parser.getAttributeValue("", name);
  105.         if (jidString == null) {
  106.             return null;
  107.         }
  108.         Jid jid = JidCreate.from(jidString);

  109.         if (!jid.hasLocalpart()) return null;

  110.         EntityFullJid fullJid = jid.asEntityFullJidIfPossible();
  111.         if (fullJid != null) {
  112.             return fullJid;
  113.         }

  114.         EntityBareJid bareJid = jid.asEntityBareJidIfPossible();
  115.         return bareJid;
  116.     }

  117.     public static Resourcepart getResourcepartAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
  118.         final String resourcepartString = parser.getAttributeValue("", name);
  119.         if (resourcepartString == null) {
  120.             return null;
  121.         }
  122.         return Resourcepart.from(resourcepartString);
  123.     }

  124.     /**
  125.      * Phrase a string to a boolean value as per "xs:boolean". Valid input strings are "true", "1" for true, and "false", "0" for false.
  126.      *
  127.      * @param booleanString the input string.
  128.      * @return the boolean representation of the input string
  129.      * @throws IllegalArgumentException if the input string is not valid.
  130.      * @since 4.3.2
  131.      */
  132.     public static boolean parseXmlBoolean(String booleanString) {
  133.         switch (booleanString) {
  134.         case "true":
  135.         case "1":
  136.             return true;
  137.         case "false":
  138.         case "0":
  139.             return false;
  140.         default:
  141.             throw new IllegalArgumentException(booleanString + " is not a valid boolean string");
  142.         }
  143.     }

  144.     /**
  145.      * Get the boolean value of an argument.
  146.      *
  147.      * @param parser TODO javadoc me please
  148.      * @param name TODO javadoc me please
  149.      * @return the boolean value or null of no argument of the given name exists
  150.      */
  151.     public static Boolean getBooleanAttribute(XmlPullParser parser, String name) {
  152.         String valueString = parser.getAttributeValue("", name);
  153.         if (valueString == null)
  154.             return null;
  155.         valueString = valueString.toLowerCase(Locale.US);
  156.         return parseXmlBoolean(valueString);
  157.     }

  158.     public static boolean getBooleanAttribute(XmlPullParser parser, String name,
  159.                     boolean defaultValue) {
  160.         Boolean bool = getBooleanAttribute(parser, name);
  161.         if (bool == null) {
  162.             return defaultValue;
  163.         }
  164.         else {
  165.             return bool;
  166.         }
  167.     }

  168.     public static Byte getByteAttributeFromNextText(XmlPullParser parser) throws IOException, XmlPullParserException {
  169.         String nextText = parser.nextText();
  170.         return Byte.valueOf(nextText);
  171.     }

  172.     public static int getIntegerAttributeOrThrow(XmlPullParser parser, String name, String throwMessage)
  173.                     throws IOException {
  174.         Integer res = getIntegerAttribute(parser, name);
  175.         if (res == null) {
  176.             // TODO Should be SmackParseException.
  177.             throw new IOException(throwMessage);
  178.         }
  179.         return res;
  180.     }

  181.     public static Integer getIntegerAttribute(XmlPullParser parser, String name) {
  182.         String valueString = parser.getAttributeValue("", name);
  183.         if (valueString == null)
  184.             return null;
  185.         return Integer.valueOf(valueString);
  186.     }

  187.     public static int getIntegerAttribute(XmlPullParser parser, String name, int defaultValue) {
  188.         Integer integer = getIntegerAttribute(parser, name);
  189.         if (integer == null) {
  190.             return defaultValue;
  191.         }
  192.         else {
  193.             return integer;
  194.         }
  195.     }

  196.     public static UInt16 getUInt16Attribute(XmlPullParser parser, String name) {
  197.         Integer integer = getIntegerAttribute(parser, name);
  198.         if (integer == null) {
  199.             return null;
  200.         }
  201.         return UInt16.from(integer);
  202.     }

  203.     public static UInt16 getRequiredUInt16Attribute(XmlPullParser parser, String name) throws RequiredAttributeMissingException {
  204.         UInt16 uint16 = getUInt16Attribute(parser, name);
  205.         if (uint16 == null) {
  206.             throw new SmackParsingException.RequiredAttributeMissingException(name);
  207.         }
  208.         return uint16;
  209.     }

  210.     public static int getIntegerFromNextText(XmlPullParser parser) throws XmlPullParserException, IOException {
  211.         String intString = parser.nextText();
  212.         return Integer.valueOf(intString);
  213.     }

  214.     public static Long getLongAttribute(XmlPullParser parser, String name) {
  215.         String valueString = parser.getAttributeValue("", name);
  216.         if (valueString == null)
  217.             return null;
  218.         return Long.valueOf(valueString);
  219.     }

  220.     public static long getLongAttribute(XmlPullParser parser, String name, long defaultValue) {
  221.         Long l = getLongAttribute(parser, name);
  222.         if (l == null) {
  223.             return defaultValue;
  224.         }
  225.         else {
  226.             return l;
  227.         }
  228.     }

  229.     public static UInt32 getUInt32Attribute(XmlPullParser parser, String name) {
  230.         Long l = getLongAttribute(parser, name);
  231.         if (l == null) {
  232.             return null;
  233.         }
  234.         return UInt32.from(l);
  235.     }

  236.     public static double getDoubleFromNextText(XmlPullParser parser) throws XmlPullParserException, IOException {
  237.         String doubleString = parser.nextText();
  238.         return Double.valueOf(doubleString);
  239.     }

  240.     public static Double getDoubleAttribute(XmlPullParser parser, String name) {
  241.         String valueString = parser.getAttributeValue("", name);
  242.         if (valueString == null)
  243.             return null;
  244.         return Double.valueOf(valueString);
  245.     }

  246.     public static double getDoubleAttribute(XmlPullParser parser, String name, long defaultValue) {
  247.         Double d = getDoubleAttribute(parser, name);
  248.         if (d == null) {
  249.             return defaultValue;
  250.         }
  251.         else {
  252.             return d;
  253.         }
  254.     }

  255.     public static Short getShortAttribute(XmlPullParser parser, String name) {
  256.         String valueString = parser.getAttributeValue("", name);
  257.         if (valueString == null) {
  258.             return null;
  259.         }
  260.         return Short.valueOf(valueString);
  261.     }

  262.     public static short getShortAttribute(XmlPullParser parser, String name, short defaultValue) {
  263.         Short s = getShortAttribute(parser, name);
  264.         if (s == null) {
  265.             return defaultValue;
  266.         }
  267.         return s;
  268.     }

  269.     public static Date getDateFromOptionalXep82String(String dateString) throws ParseException {
  270.         if (dateString == null) {
  271.             return null;
  272.         }
  273.         return getDateFromXep82String(dateString);
  274.     }

  275.     public static Date getDateFromXep82String(String dateString) throws ParseException {
  276.         return XmppDateTime.parseXEP0082Date(dateString);
  277.     }

  278.     public static Date getDateFromString(String dateString) throws ParseException {
  279.         return XmppDateTime.parseDate(dateString);
  280.     }

  281.     public static Date getDateFromNextText(XmlPullParser parser)
  282.                     throws XmlPullParserException, IOException, ParseException {
  283.         String dateString = parser.nextText();
  284.         return getDateFromString(dateString);
  285.     }

  286.     public static URI getUriFromNextText(XmlPullParser parser) throws XmlPullParserException, IOException, SmackUriSyntaxParsingException  {
  287.         String uriString = parser.nextText();
  288.         try {
  289.             return new URI(uriString);
  290.         }
  291.         catch (URISyntaxException e) {
  292.             throw new SmackParsingException.SmackUriSyntaxParsingException(e);
  293.         }
  294.     }

  295.     public static String getRequiredAttribute(XmlPullParser parser, String name) throws IOException {
  296.         String value = parser.getAttributeValue("", name);
  297.         if (StringUtils.isNullOrEmpty(value)) {
  298.             throw new IOException("Attribute " + name + " is null or empty (" + value + ')');
  299.         }
  300.         return value;
  301.     }

  302.     public static String getRequiredNextText(XmlPullParser parser) throws XmlPullParserException, IOException {
  303.         String text = parser.nextText();
  304.         if (StringUtils.isNullOrEmpty(text)) {
  305.             throw new IOException("Next text is null or empty (" + text + ')');
  306.         }
  307.         return text;
  308.     }

  309.     public static String getXmlLang(XmlPullParser parser, XmlEnvironment xmlEnvironment) {
  310.         String currentXmlLang = getXmlLang(parser);
  311.         if (currentXmlLang != null) {
  312.             return currentXmlLang;
  313.         }
  314.         return xmlEnvironment.getEffectiveLanguage();
  315.     }

  316.     public static String getXmlLang(XmlPullParser parser) {
  317.         return parser.getAttributeValue("http://www.w3.org/XML/1998/namespace", "lang");
  318.     }

  319.     public static InternetAddress getInternetAddressIngoringZoneIdAttribute(XmlPullParser parser, String attribute) {
  320.         String inetAddressString = parser.getAttributeValue(attribute);
  321.         if (inetAddressString == null) {
  322.             return null;
  323.         }
  324.         return InternetAddress.fromIgnoringZoneId(inetAddressString);
  325.     }
  326. }