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