001/**
002 *
003 * Copyright 2017 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.smackx.jingle.provider;
018
019import java.util.logging.Logger;
020
021import org.jivesoftware.smack.packet.StandardExtensionElement;
022import org.jivesoftware.smack.parsing.StandardExtensionElementProvider;
023import org.jivesoftware.smack.provider.IQProvider;
024import org.jivesoftware.smack.util.ParserUtils;
025
026import org.jivesoftware.smackx.jingle.element.Jingle;
027import org.jivesoftware.smackx.jingle.element.JingleAction;
028import org.jivesoftware.smackx.jingle.element.JingleContent;
029import org.jivesoftware.smackx.jingle.element.JingleContentDescription;
030import org.jivesoftware.smackx.jingle.element.JingleContentTransport;
031import org.jivesoftware.smackx.jingle.element.JingleReason;
032import org.jivesoftware.smackx.jingle.element.JingleReason.Reason;
033import org.jivesoftware.smackx.jingle.element.UnknownJingleContentDescription;
034import org.jivesoftware.smackx.jingle.element.UnknownJingleContentTransport;
035
036import org.jxmpp.jid.FullJid;
037import org.xmlpull.v1.XmlPullParser;
038
039public class JingleProvider extends IQProvider<Jingle> {
040
041    private static final Logger LOGGER = Logger.getLogger(JingleProvider.class.getName());
042
043    @Override
044    public Jingle parse(XmlPullParser parser, int initialDepth) throws Exception {
045        Jingle.Builder builder = Jingle.getBuilder();
046
047        String actionString = parser.getAttributeValue("", Jingle.ACTION_ATTRIBUTE_NAME);
048        if (actionString != null) {
049            JingleAction action = JingleAction.fromString(actionString);
050            builder.setAction(action);
051        }
052
053        FullJid initiator = ParserUtils.getFullJidAttribute(parser, Jingle.INITIATOR_ATTRIBUTE_NAME);
054        builder.setInitiator(initiator);
055
056        FullJid responder = ParserUtils.getFullJidAttribute(parser, Jingle.RESPONDER_ATTRIBUTE_NAME);
057        builder.setResponder(responder);
058
059        String sessionId = parser.getAttributeValue("", Jingle.SESSION_ID_ATTRIBUTE_NAME);
060        builder.setSessionId(sessionId);
061
062
063        outerloop: while (true) {
064            int eventType = parser.next();
065            switch (eventType) {
066            case XmlPullParser.START_TAG:
067                String tagName = parser.getName();
068                switch (tagName) {
069                case JingleContent.ELEMENT:
070                    JingleContent content = parseJingleContent(parser, parser.getDepth());
071                    builder.addJingleContent(content);
072                    break;
073                case JingleReason.ELEMENT:
074                    parser.next();
075                    String reasonString = parser.getName();
076                    JingleReason reason;
077                    if (reasonString.equals("alternative-session")) {
078                        parser.next();
079                        String sid = parser.nextText();
080                        reason = new JingleReason.AlternativeSession(sid);
081                    } else {
082                        reason = new JingleReason(Reason.fromString(reasonString));
083                    }
084                    builder.setReason(reason);
085                    break;
086                default:
087                    LOGGER.severe("Unknown Jingle element: " + tagName);
088                    break;
089                }
090                break;
091            case XmlPullParser.END_TAG:
092                if (parser.getDepth() == initialDepth) {
093                    break outerloop;
094                }
095            }
096        }
097
098        return builder.build();
099    }
100
101    public static JingleContent parseJingleContent(XmlPullParser parser, final int initialDepth)
102                    throws Exception {
103        JingleContent.Builder builder = JingleContent.getBuilder();
104
105        String creatorString = parser.getAttributeValue("", JingleContent.CREATOR_ATTRIBUTE_NAME);
106        JingleContent.Creator creator = JingleContent.Creator.valueOf(creatorString);
107        builder.setCreator(creator);
108
109        String disposition = parser.getAttributeValue("", JingleContent.DISPOSITION_ATTRIBUTE_NAME);
110        builder.setDisposition(disposition);
111
112        String name = parser.getAttributeValue("", JingleContent.NAME_ATTRIBUTE_NAME);
113        builder.setName(name);
114
115        String sendersString = parser.getAttributeValue("", JingleContent.SENDERS_ATTRIBUTE_NAME);
116        if (sendersString != null) {
117            JingleContent.Senders senders = JingleContent.Senders.valueOf(sendersString);
118            builder.setSenders(senders);
119        }
120
121        outerloop: while (true) {
122            int eventType = parser.next();
123            switch (eventType) {
124            case XmlPullParser.START_TAG:
125                String tagName = parser.getName();
126                String namespace = parser.getNamespace();
127                switch (tagName) {
128                case JingleContentDescription.ELEMENT: {
129                    JingleContentDescription description;
130                    JingleContentDescriptionProvider<?> provider = JingleContentProviderManager.getJingleContentDescriptionProvider(namespace);
131                    if (provider == null) {
132                        StandardExtensionElement standardExtensionElement = StandardExtensionElementProvider.INSTANCE.parse(parser);
133                        description = new UnknownJingleContentDescription(standardExtensionElement);
134                    }
135                    else {
136                        description = provider.parse(parser);
137                    }
138                    builder.setDescription(description);
139                    break;
140                }
141                case JingleContentTransport.ELEMENT: {
142                    JingleContentTransport transport;
143                    JingleContentTransportProvider<?> provider = JingleContentProviderManager.getJingleContentTransportProvider(namespace);
144                    if (provider == null) {
145                        StandardExtensionElement standardExtensionElement = StandardExtensionElementProvider.INSTANCE.parse(parser);
146                        transport = new UnknownJingleContentTransport(standardExtensionElement);
147                    }
148                    else {
149                        transport = provider.parse(parser);
150                    }
151                    builder.setTransport(transport);
152                    break;
153                }
154                default:
155                    LOGGER.severe("Unknown Jingle content element: " + tagName);
156                    break;
157                }
158                break;
159            case XmlPullParser.END_TAG:
160                if (parser.getDepth() == initialDepth) {
161                    break outerloop;
162                }
163            }
164        }
165
166        return builder.build();
167    }
168}