001/**
002 *
003 * Copyright © 2014-2018 Florian Schmaus
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smack.util;
018
019import java.io.IOException;
020import java.net.URI;
021import java.net.URISyntaxException;
022import java.text.ParseException;
023import java.util.Date;
024import java.util.Locale;
025
026import javax.xml.XMLConstants;
027import javax.xml.namespace.QName;
028
029import org.jivesoftware.smack.SmackException;
030
031import org.jxmpp.jid.EntityBareJid;
032import org.jxmpp.jid.EntityFullJid;
033import org.jxmpp.jid.EntityJid;
034import org.jxmpp.jid.Jid;
035import org.jxmpp.jid.impl.JidCreate;
036import org.jxmpp.jid.parts.Resourcepart;
037import org.jxmpp.stringprep.XmppStringprepException;
038import org.jxmpp.util.XmppDateTime;
039import org.xmlpull.v1.XmlPullParser;
040import org.xmlpull.v1.XmlPullParserException;
041
042public class ParserUtils {
043
044    /**
045     * The constant String "jid".
046     */
047    public static final String JID = "jid";
048
049    public static void assertAtStartTag(XmlPullParser parser) throws XmlPullParserException {
050        assert (parser.getEventType() == XmlPullParser.START_TAG);
051    }
052
053    public static void assertAtStartTag(XmlPullParser parser, String name) throws XmlPullParserException {
054        assertAtStartTag(parser);
055        assert name.equals(parser.getName());
056    }
057
058    public static void assertAtEndTag(XmlPullParser parser) throws XmlPullParserException {
059        assert (parser.getEventType() == XmlPullParser.END_TAG);
060    }
061
062    public static void forwardToEndTagOfDepth(XmlPullParser parser, int depth)
063                    throws XmlPullParserException, IOException {
064        int event = parser.getEventType();
065        while (!(event == XmlPullParser.END_TAG && parser.getDepth() == depth)) {
066            event = parser.next();
067        }
068    }
069
070    public static Jid getJidAttribute(XmlPullParser parser) throws XmppStringprepException {
071        return getJidAttribute(parser, JID);
072    }
073
074    public static Jid getJidAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
075        final String jidString = parser.getAttributeValue("", name);
076        if (jidString == null) {
077            return null;
078        }
079        return JidCreate.from(jidString);
080    }
081
082    public static EntityBareJid getBareJidAttribute(XmlPullParser parser) throws XmppStringprepException {
083        return getBareJidAttribute(parser, JID);
084    }
085
086    public static EntityBareJid getBareJidAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
087        final String jidString = parser.getAttributeValue("", name);
088        if (jidString == null) {
089            return null;
090        }
091        return JidCreate.entityBareFrom(jidString);
092    }
093
094    public static EntityFullJid getFullJidAttribute(XmlPullParser parser) throws XmppStringprepException {
095        return getFullJidAttribute(parser, JID);
096    }
097
098    public static EntityFullJid getFullJidAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
099        final String jidString = parser.getAttributeValue("", name);
100        if (jidString == null) {
101            return null;
102        }
103        return JidCreate.entityFullFrom(jidString);
104    }
105
106    public static EntityJid getEntityJidAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
107        final String jidString = parser.getAttributeValue("", name);
108        if (jidString == null) {
109            return null;
110        }
111        Jid jid = JidCreate.from(jidString);
112
113        if (!jid.hasLocalpart()) return null;
114
115        EntityFullJid fullJid = jid.asEntityFullJidIfPossible();
116        if (fullJid != null) {
117            return fullJid;
118        }
119
120        EntityBareJid bareJid = jid.asEntityBareJidIfPossible();
121        return bareJid;
122    }
123
124    public static Resourcepart getResourcepartAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
125        final String resourcepartString = parser.getAttributeValue("", name);
126        if (resourcepartString == null) {
127            return null;
128        }
129        return Resourcepart.from(resourcepartString);
130    }
131
132    /**
133     * Prase a string to a boolean value as per "xs:boolean". Valid input strings are "true", "1" for true, and "false", "0" for false.
134     *
135     * @param booleanString the input string.
136     * @return the boolean representation of the input string
137     * @throws IllegalArgumentException if the input string is not valid.
138     * @since 4.3.2
139     */
140    public static boolean parseXmlBoolean(String booleanString) {
141        switch (booleanString) {
142        case "true":
143        case "1":
144            return true;
145        case "false":
146        case "0":
147            return false;
148        default:
149            throw new IllegalArgumentException(booleanString + " is not a valid boolean string");
150        }
151    }
152
153    /**
154     * Get the boolean value of an argument.
155     *
156     * @param parser
157     * @param name
158     * @return the boolean value or null of no argument of the given name exists
159     */
160    public static Boolean getBooleanAttribute(XmlPullParser parser, String name) {
161        String valueString = parser.getAttributeValue("", name);
162        if (valueString == null)
163            return null;
164        valueString = valueString.toLowerCase(Locale.US);
165        return parseXmlBoolean(valueString);
166    }
167
168    public static boolean getBooleanAttribute(XmlPullParser parser, String name,
169                    boolean defaultValue) {
170        Boolean bool = getBooleanAttribute(parser, name);
171        if (bool == null) {
172            return defaultValue;
173        }
174        else {
175            return bool;
176        }
177    }
178
179    public static int getIntegerAttributeOrThrow(XmlPullParser parser, String name, String throwMessage) throws SmackException {
180        Integer res = getIntegerAttribute(parser, name);
181        if (res == null) {
182            throw new SmackException(throwMessage);
183        }
184        return res;
185    }
186
187    public static Integer getIntegerAttribute(XmlPullParser parser, String name) {
188        String valueString = parser.getAttributeValue("", name);
189        if (valueString == null)
190            return null;
191        return Integer.valueOf(valueString);
192    }
193
194    public static int getIntegerAttribute(XmlPullParser parser, String name, int defaultValue) {
195        Integer integer = getIntegerAttribute(parser, name);
196        if (integer == null) {
197            return defaultValue;
198        }
199        else {
200            return integer;
201        }
202    }
203
204    public static int getIntegerFromNextText(XmlPullParser parser) throws XmlPullParserException, IOException {
205        String intString = parser.nextText();
206        return Integer.valueOf(intString);
207    }
208
209    public static Long getLongAttribute(XmlPullParser parser, String name) {
210        String valueString = parser.getAttributeValue("", name);
211        if (valueString == null)
212            return null;
213        return Long.valueOf(valueString);
214    }
215
216    public static long getLongAttribute(XmlPullParser parser, String name, long defaultValue) {
217        Long l = getLongAttribute(parser, name);
218        if (l == null) {
219            return defaultValue;
220        }
221        else {
222            return l;
223        }
224    }
225
226    public static double getDoubleFromNextText(XmlPullParser parser) throws XmlPullParserException, IOException {
227        String doubleString = parser.nextText();
228        return Double.valueOf(doubleString);
229    }
230
231    public static Double getDoubleAttribute(XmlPullParser parser, String name) {
232        String valueString = parser.getAttributeValue("", name);
233        if (valueString == null)
234            return null;
235        return Double.valueOf(valueString);
236    }
237
238    public static double getDoubleAttribute(XmlPullParser parser, String name, long defaultValue) {
239        Double d = getDoubleAttribute(parser, name);
240        if (d == null) {
241            return defaultValue;
242        }
243        else {
244            return d;
245        }
246    }
247
248    public static Date getDateFromNextText(XmlPullParser parser) throws XmlPullParserException, IOException, ParseException {
249        String dateString = parser.nextText();
250        return XmppDateTime.parseDate(dateString);
251    }
252
253    public static URI getUriFromNextText(XmlPullParser parser) throws XmlPullParserException, IOException, URISyntaxException  {
254        String uriString = parser.nextText();
255        return new URI(uriString);
256    }
257
258    public static String getRequiredAttribute(XmlPullParser parser, String name) throws IOException {
259        String value = parser.getAttributeValue("", name);
260        if (StringUtils.isNullOrEmpty(value)) {
261            throw new IOException("Attribute " + name + " is null or empty (" + value + ')');
262        }
263        return value;
264    }
265
266    public static String getRequiredNextText(XmlPullParser parser) throws XmlPullParserException, IOException {
267        String text = parser.nextText();
268        if (StringUtils.isNullOrEmpty(text)) {
269            throw new IOException("Next text is null or empty (" + text + ')');
270        }
271        return text;
272    }
273
274    public static String getXmlLang(XmlPullParser parser) {
275        return parser.getAttributeValue("http://www.w3.org/XML/1998/namespace", "lang");
276    }
277
278    public static QName getQName(XmlPullParser parser) {
279        String elementName = parser.getName();
280        String prefix = parser.getPrefix();
281        if (prefix == null) {
282            prefix = XMLConstants.DEFAULT_NS_PREFIX;
283        }
284        String namespace = parser.getNamespace();
285        return new QName(namespace, elementName, prefix);
286    }
287}