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