001/** 002 * 003 * Copyright 2013-2014 Georg Lukas, 2020-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.forward.provider; 018 019import java.io.IOException; 020import java.text.ParseException; 021import java.util.logging.Logger; 022 023import org.jivesoftware.smack.packet.Message; 024import org.jivesoftware.smack.packet.Stanza; 025import org.jivesoftware.smack.packet.XmlEnvironment; 026import org.jivesoftware.smack.parsing.SmackParsingException; 027import org.jivesoftware.smack.provider.ExtensionElementProvider; 028import org.jivesoftware.smack.util.PacketParserUtils; 029import org.jivesoftware.smack.xml.XmlPullParser; 030import org.jivesoftware.smack.xml.XmlPullParserException; 031 032import org.jivesoftware.smackx.delay.packet.DelayInformation; 033import org.jivesoftware.smackx.delay.provider.DelayInformationProvider; 034import org.jivesoftware.smackx.forward.packet.Forwarded; 035 036/** 037 * This class implements the {@link ExtensionElementProvider} to parse 038 * forwarded messages from a packet. It will return a {@link Forwarded} stanza extension. 039 * 040 * @author Georg Lukas 041 */ 042public class ForwardedProvider extends ExtensionElementProvider<Forwarded<?>> { 043 044 public static final ForwardedProvider INSTANCE = new ForwardedProvider(); 045 046 private static final Logger LOGGER = Logger.getLogger(ForwardedProvider.class.getName()); 047 048 @Override 049 public Forwarded<?> parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment) 050 throws XmlPullParserException, IOException, SmackParsingException, ParseException { 051 DelayInformation di = null; 052 Stanza packet = null; 053 054 outerloop: while (true) { 055 XmlPullParser.Event eventType = parser.next(); 056 switch (eventType) { 057 case START_ELEMENT: 058 String name = parser.getName(); 059 String namespace = parser.getNamespace(); 060 switch (name) { 061 case DelayInformation.ELEMENT: 062 if (DelayInformation.NAMESPACE.equals(namespace)) { 063 di = DelayInformationProvider.INSTANCE.parse(parser, parser.getDepth(), null); 064 } else { 065 LOGGER.warning("Namespace '" + namespace + "' does not match expected namespace '" 066 + DelayInformation.NAMESPACE + "'"); 067 } 068 break; 069 case Message.ELEMENT: 070 packet = PacketParserUtils.parseMessage(parser); 071 break; 072 default: 073 LOGGER.warning("Unsupported forwarded packet type: " + name); 074 } 075 break; 076 case END_ELEMENT: 077 if (parser.getDepth() == initialDepth) { 078 break outerloop; 079 } 080 break; 081 default: 082 // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement. 083 break; 084 } 085 } 086 087 if (packet == null) { 088 // TODO: Should be SmackParseException. 089 throw new IOException("forwarded extension must contain a packet"); 090 } 091 return new Forwarded<>(packet, di); 092 } 093 094 public static Forwarded<Message> parseForwardedMessage(XmlPullParser parser, XmlEnvironment xmlEnvironment) 095 throws XmlPullParserException, IOException, SmackParsingException, ParseException { 096 return parseForwardedMessage(parser, parser.getDepth(), xmlEnvironment); 097 } 098 099 @SuppressWarnings("unchecked") 100 public static Forwarded<Message> parseForwardedMessage(XmlPullParser parser, int initialDepth, 101 XmlEnvironment xmlEnvironment) 102 throws XmlPullParserException, IOException, SmackParsingException, ParseException { 103 Forwarded<?> forwarded = INSTANCE.parse(parser, initialDepth, xmlEnvironment); 104 if (!forwarded.isForwarded(Message.class)) { 105 throw new SmackParsingException("Expecting a forwarded message, but got " + forwarded); 106 } 107 return (Forwarded<Message>) forwarded; 108 } 109}