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