2003-01-13 17:58:47 +01:00
|
|
|
/**
|
|
|
|
*
|
2007-02-12 01:59:05 +01:00
|
|
|
* Copyright 2003-2007 Jive Software.
|
2003-01-13 17:58:47 +01:00
|
|
|
*
|
2014-02-17 18:57:38 +01:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
2004-11-03 00:53:30 +01:00
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2003-01-13 17:58:47 +01:00
|
|
|
*
|
2004-11-03 00:53:30 +01:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2003-01-13 17:58:47 +01:00
|
|
|
*
|
2004-11-03 00:53:30 +01:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
2003-01-13 17:58:47 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
package org.jivesoftware.smack.packet;
|
|
|
|
|
2018-07-17 15:10:39 +02:00
|
|
|
import static org.jivesoftware.smack.util.StringUtils.requireNotNullNorEmpty;
|
2015-02-05 12:29:26 +01:00
|
|
|
|
2017-06-14 17:12:43 +02:00
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Locale;
|
|
|
|
|
2019-06-11 00:10:38 +02:00
|
|
|
import javax.xml.namespace.QName;
|
|
|
|
|
2015-01-19 16:17:03 +01:00
|
|
|
import org.jivesoftware.smack.packet.id.StanzaIdUtil;
|
2015-02-05 11:04:38 +01:00
|
|
|
import org.jivesoftware.smack.util.MultiMap;
|
2014-09-13 11:03:40 +02:00
|
|
|
import org.jivesoftware.smack.util.PacketUtil;
|
2014-03-21 09:51:52 +01:00
|
|
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
2017-06-14 17:12:43 +02:00
|
|
|
|
2015-02-14 17:15:02 +01:00
|
|
|
import org.jxmpp.jid.Jid;
|
|
|
|
import org.jxmpp.jid.impl.JidCreate;
|
|
|
|
import org.jxmpp.stringprep.XmppStringprepException;
|
2003-01-13 17:58:47 +01:00
|
|
|
|
|
|
|
/**
|
2018-04-23 21:06:35 +02:00
|
|
|
* Base class for XMPP Stanzas, which are called Stanza in older versions of Smack (i.e. < 4.1).
|
2014-10-29 14:05:38 +01:00
|
|
|
* <p>
|
2015-02-05 11:17:27 +01:00
|
|
|
* Every stanza has a unique ID (which is automatically generated, but can be overridden). Stanza
|
|
|
|
* IDs are required for IQ stanzas and recommended for presence and message stanzas. Optionally, the
|
|
|
|
* "to" and "from" fields can be set.
|
2014-10-29 14:05:38 +01:00
|
|
|
* </p>
|
|
|
|
* <p>
|
2015-02-05 11:17:27 +01:00
|
|
|
* XMPP Stanzas are {@link Message}, {@link IQ} and {@link Presence}. Which therefore subclass this
|
|
|
|
* class. <b>If you think you need to subclass this class, then you are doing something wrong.</b>
|
2014-10-29 14:05:38 +01:00
|
|
|
* </p>
|
2003-01-13 17:58:47 +01:00
|
|
|
*
|
|
|
|
* @author Matt Tucker
|
2015-02-05 11:17:27 +01:00
|
|
|
* @see <a href="http://xmpp.org/rfcs/rfc6120.html#stanzas">RFC 6120 § 8. XML Stanzas</a>
|
2003-01-13 17:58:47 +01:00
|
|
|
*/
|
2015-02-14 16:21:26 +01:00
|
|
|
public abstract class Stanza implements TopLevelStreamElement {
|
2014-04-26 15:43:58 +02:00
|
|
|
|
2014-07-07 12:29:59 +02:00
|
|
|
public static final String TEXT = "text";
|
|
|
|
public static final String ITEM = "item";
|
|
|
|
|
2007-04-26 08:22:55 +02:00
|
|
|
protected static final String DEFAULT_LANGUAGE =
|
2014-04-03 22:50:13 +02:00
|
|
|
java.util.Locale.getDefault().getLanguage().toLowerCase(Locale.US);
|
2007-04-26 08:22:55 +02:00
|
|
|
|
2019-06-11 00:10:38 +02:00
|
|
|
private final MultiMap<QName, ExtensionElement> extensionElements = new MultiMap<>();
|
2014-10-26 19:32:19 +01:00
|
|
|
|
2015-02-05 11:17:27 +01:00
|
|
|
private String id = null;
|
2015-02-14 17:15:02 +01:00
|
|
|
private Jid to;
|
|
|
|
private Jid from;
|
2018-04-07 21:25:40 +02:00
|
|
|
private StanzaError error = null;
|
2003-01-13 17:58:47 +01:00
|
|
|
|
2014-09-12 11:20:34 +02:00
|
|
|
/**
|
|
|
|
* Optional value of the 'xml:lang' attribute of the outermost element of
|
|
|
|
* the stanza.
|
|
|
|
* <p>
|
|
|
|
* Such an attribute is defined for all stanza types. For IQ, see for
|
|
|
|
* example XEP-50 3.7:
|
|
|
|
* "The requester SHOULD provide its locale information using the "xml:lang
|
2017-12-25 12:51:41 +01:00
|
|
|
* " attribute on either the <iq/> (RECOMMENDED) or <command/> element."
|
2014-09-12 11:20:34 +02:00
|
|
|
* </p>
|
|
|
|
*/
|
|
|
|
protected String language;
|
|
|
|
|
2015-02-23 10:48:43 +01:00
|
|
|
protected Stanza() {
|
2015-01-19 16:17:03 +01:00
|
|
|
this(StanzaIdUtil.newStanzaId());
|
2014-07-06 23:57:06 +02:00
|
|
|
}
|
|
|
|
|
2015-02-23 10:48:43 +01:00
|
|
|
protected Stanza(String stanzaId) {
|
2015-02-05 11:17:27 +01:00
|
|
|
setStanzaId(stanzaId);
|
2013-03-18 09:50:48 +01:00
|
|
|
}
|
|
|
|
|
2015-02-23 10:48:43 +01:00
|
|
|
protected Stanza(Stanza p) {
|
2015-02-05 11:17:27 +01:00
|
|
|
id = p.getStanzaId();
|
2013-03-18 09:50:48 +01:00
|
|
|
to = p.getTo();
|
|
|
|
from = p.getFrom();
|
|
|
|
error = p.error;
|
|
|
|
|
|
|
|
// Copy extensions
|
2015-02-26 18:41:17 +01:00
|
|
|
for (ExtensionElement pe : p.getExtensions()) {
|
2013-03-18 09:50:48 +01:00
|
|
|
addExtension(pe);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-13 17:58:47 +01:00
|
|
|
/**
|
2015-02-05 11:17:27 +01:00
|
|
|
* Returns the unique ID of the stanza. The returned value could be <code>null</code>.
|
2003-01-13 17:58:47 +01:00
|
|
|
*
|
2015-02-05 11:17:27 +01:00
|
|
|
* @return the packet's unique ID or <code>null</code> if the id is not available.
|
2003-01-13 17:58:47 +01:00
|
|
|
*/
|
2015-02-05 11:17:27 +01:00
|
|
|
public String getStanzaId() {
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-03-29 12:15:32 +02:00
|
|
|
* Get the Stanza ID.
|
2015-02-05 11:17:27 +01:00
|
|
|
* @return the stanza id.
|
|
|
|
* @deprecated use {@link #getStanzaId()} instead.
|
|
|
|
*/
|
|
|
|
@Deprecated
|
2003-01-13 17:58:47 +01:00
|
|
|
public String getPacketID() {
|
2015-02-05 11:17:27 +01:00
|
|
|
return getStanzaId();
|
2003-01-13 17:58:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-03-31 14:17:30 +02:00
|
|
|
* Sets the unique ID of the packet. To indicate that a stanza has no id
|
2015-01-19 14:04:05 +01:00
|
|
|
* pass <code>null</code> as the packet's id value.
|
2003-01-13 17:58:47 +01:00
|
|
|
*
|
2015-02-05 11:17:27 +01:00
|
|
|
* @param id the unique ID for the packet.
|
|
|
|
*/
|
|
|
|
public void setStanzaId(String id) {
|
2015-02-08 11:50:07 +01:00
|
|
|
if (id != null) {
|
2018-07-17 15:10:39 +02:00
|
|
|
requireNotNullNorEmpty(id, "id must either be null or not the empty String");
|
2015-02-08 11:50:07 +01:00
|
|
|
}
|
2015-02-05 11:17:27 +01:00
|
|
|
this.id = id;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-03-29 12:15:32 +02:00
|
|
|
* Set the stanza ID.
|
2015-02-05 11:17:27 +01:00
|
|
|
* @param packetID
|
|
|
|
* @deprecated use {@link #setStanzaId(String)} instead.
|
2003-01-13 17:58:47 +01:00
|
|
|
*/
|
2015-02-05 11:17:27 +01:00
|
|
|
@Deprecated
|
2003-01-13 17:58:47 +01:00
|
|
|
public void setPacketID(String packetID) {
|
2015-02-05 11:17:27 +01:00
|
|
|
setStanzaId(packetID);
|
2003-01-13 17:58:47 +01:00
|
|
|
}
|
|
|
|
|
2015-02-08 11:50:07 +01:00
|
|
|
/**
|
|
|
|
* Check if this stanza has an ID set.
|
|
|
|
*
|
|
|
|
* @return true if the stanza ID is set, false otherwise.
|
|
|
|
* @since 4.1
|
|
|
|
*/
|
|
|
|
public boolean hasStanzaIdSet() {
|
|
|
|
// setStanzaId ensures that the id is either null or not empty,
|
|
|
|
// so we can assume that it is set if it's not null.
|
|
|
|
return id != null;
|
|
|
|
}
|
|
|
|
|
2016-07-23 15:45:45 +02:00
|
|
|
/**
|
|
|
|
* Set the stanza id if none is set.
|
2018-05-09 23:06:12 +02:00
|
|
|
*
|
2016-07-23 15:45:45 +02:00
|
|
|
* @return the stanza id.
|
|
|
|
* @since 4.2
|
|
|
|
*/
|
|
|
|
public String setStanzaId() {
|
|
|
|
if (!hasStanzaIdSet()) {
|
|
|
|
setStanzaId(StanzaIdUtil.newStanzaId());
|
|
|
|
}
|
|
|
|
return getStanzaId();
|
|
|
|
}
|
|
|
|
|
2003-01-13 17:58:47 +01:00
|
|
|
/**
|
2018-03-31 14:17:30 +02:00
|
|
|
* Returns who the stanza is being sent "to", or <tt>null</tt> if
|
2003-01-13 17:58:47 +01:00
|
|
|
* the value is not set. The XMPP protocol often makes the "to"
|
2007-04-21 22:14:40 +02:00
|
|
|
* attribute optional, so it does not always need to be set.<p>
|
|
|
|
*
|
2018-03-31 14:17:30 +02:00
|
|
|
* @return who the stanza is being sent to, or <tt>null</tt> if the
|
2003-01-13 17:58:47 +01:00
|
|
|
* value has not been set.
|
|
|
|
*/
|
2015-02-14 17:15:02 +01:00
|
|
|
public Jid getTo() {
|
2006-09-15 22:53:18 +02:00
|
|
|
return to;
|
2003-01-13 17:58:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-03-31 14:17:30 +02:00
|
|
|
* Sets who the stanza is being sent "to". The XMPP protocol often makes
|
2003-01-13 17:58:47 +01:00
|
|
|
* the "to" attribute optional, so it does not always need to be set.
|
|
|
|
*
|
2018-03-31 14:17:30 +02:00
|
|
|
* @param to who the stanza is being sent to.
|
2015-02-14 17:15:02 +01:00
|
|
|
* @throws IllegalArgumentException if to is not a valid JID String.
|
|
|
|
* @deprecated use {@link #setTo(Jid)} instead.
|
2003-01-13 17:58:47 +01:00
|
|
|
*/
|
2015-02-14 17:15:02 +01:00
|
|
|
@Deprecated
|
2003-01-13 17:58:47 +01:00
|
|
|
public void setTo(String to) {
|
2015-02-14 17:15:02 +01:00
|
|
|
Jid jid;
|
|
|
|
try {
|
|
|
|
jid = JidCreate.from(to);
|
|
|
|
}
|
|
|
|
catch (XmppStringprepException e) {
|
|
|
|
throw new IllegalArgumentException(e);
|
|
|
|
}
|
|
|
|
setTo(jid);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets who the packet is being sent "to". The XMPP protocol often makes
|
|
|
|
* the "to" attribute optional, so it does not always need to be set.
|
|
|
|
*
|
|
|
|
* @param to who the packet is being sent to.
|
|
|
|
*/
|
|
|
|
public void setTo(Jid to) {
|
2006-09-16 00:42:06 +02:00
|
|
|
this.to = to;
|
2003-01-13 17:58:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-03-31 14:17:30 +02:00
|
|
|
* Returns who the stanza is being sent "from" or <tt>null</tt> if
|
2003-01-13 17:58:47 +01:00
|
|
|
* the value is not set. The XMPP protocol often makes the "from"
|
2007-04-21 22:14:40 +02:00
|
|
|
* attribute optional, so it does not always need to be set.<p>
|
|
|
|
*
|
2018-03-31 14:17:30 +02:00
|
|
|
* @return who the stanza is being sent from, or <tt>null</tt> if the
|
2007-04-21 22:14:40 +02:00
|
|
|
* value has not been set.
|
2003-01-13 17:58:47 +01:00
|
|
|
*/
|
2015-02-14 17:15:02 +01:00
|
|
|
public Jid getFrom() {
|
2006-09-15 22:53:18 +02:00
|
|
|
return from;
|
2003-01-13 17:58:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-03-31 14:17:30 +02:00
|
|
|
* Sets who the stanza is being sent "from". The XMPP protocol often
|
2003-01-13 17:58:47 +01:00
|
|
|
* makes the "from" attribute optional, so it does not always need to
|
|
|
|
* be set.
|
|
|
|
*
|
2018-03-31 14:17:30 +02:00
|
|
|
* @param from who the stanza is being sent to.
|
2015-02-14 17:15:02 +01:00
|
|
|
* @throws IllegalArgumentException if from is not a valid JID String.
|
|
|
|
* @deprecated use {@link #setFrom(Jid)} instead.
|
2003-01-13 17:58:47 +01:00
|
|
|
*/
|
2015-02-14 17:15:02 +01:00
|
|
|
@Deprecated
|
2003-01-13 17:58:47 +01:00
|
|
|
public void setFrom(String from) {
|
2015-02-14 17:15:02 +01:00
|
|
|
Jid jid;
|
|
|
|
try {
|
|
|
|
jid = JidCreate.from(from);
|
|
|
|
}
|
|
|
|
catch (XmppStringprepException e) {
|
|
|
|
throw new IllegalArgumentException(e);
|
|
|
|
}
|
|
|
|
setFrom(jid);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets who the packet is being sent "from". The XMPP protocol often
|
|
|
|
* makes the "from" attribute optional, so it does not always need to
|
|
|
|
* be set.
|
|
|
|
*
|
|
|
|
* @param from who the packet is being sent to.
|
|
|
|
*/
|
|
|
|
public void setFrom(Jid from) {
|
2006-09-16 00:42:06 +02:00
|
|
|
this.from = from;
|
2003-01-13 17:58:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the error associated with this packet, or <tt>null</tt> if there are
|
|
|
|
* no errors.
|
|
|
|
*
|
|
|
|
* @return the error sub-packet or <tt>null</tt> if there isn't an error.
|
|
|
|
*/
|
2018-04-07 21:25:40 +02:00
|
|
|
public StanzaError getError() {
|
2003-01-13 17:58:47 +01:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the error for this packet.
|
|
|
|
*
|
|
|
|
* @param error the error to associate with this packet.
|
2018-04-07 21:25:40 +02:00
|
|
|
* @deprecated use {@link #setError(org.jivesoftware.smack.packet.StanzaError.Builder)} instead.
|
2003-01-13 17:58:47 +01:00
|
|
|
*/
|
2015-12-08 08:22:50 +01:00
|
|
|
@Deprecated
|
2018-04-07 21:25:40 +02:00
|
|
|
public void setError(StanzaError error) {
|
2003-01-13 17:58:47 +01:00
|
|
|
this.error = error;
|
|
|
|
}
|
|
|
|
|
2015-12-08 08:22:50 +01:00
|
|
|
/**
|
|
|
|
* Sets the error for this stanza.
|
|
|
|
*
|
|
|
|
* @param xmppErrorBuilder the error to associate with this stanza.
|
|
|
|
*/
|
2018-04-07 21:25:40 +02:00
|
|
|
public void setError(StanzaError.Builder xmppErrorBuilder) {
|
2015-12-08 08:22:50 +01:00
|
|
|
if (xmppErrorBuilder == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
xmppErrorBuilder.setStanza(this);
|
|
|
|
error = xmppErrorBuilder.build();
|
|
|
|
}
|
|
|
|
|
2014-09-12 11:20:34 +02:00
|
|
|
/**
|
|
|
|
* Returns the xml:lang of this Stanza, or null if one has not been set.
|
|
|
|
*
|
|
|
|
* @return the xml:lang of this Stanza, or null.
|
|
|
|
*/
|
|
|
|
public String getLanguage() {
|
|
|
|
return language;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the xml:lang of this Stanza.
|
|
|
|
*
|
|
|
|
* @param language the xml:lang of this Stanza.
|
|
|
|
*/
|
|
|
|
public void setLanguage(String language) {
|
|
|
|
this.language = language;
|
|
|
|
}
|
|
|
|
|
2003-05-08 17:55:06 +02:00
|
|
|
/**
|
2015-02-23 10:49:33 +01:00
|
|
|
* Returns a list of all extension elements of this stanza.
|
2003-05-08 17:55:06 +02:00
|
|
|
*
|
2015-02-23 10:49:33 +01:00
|
|
|
* @return a list of all extension elements of this stanza.
|
2003-05-08 17:55:06 +02:00
|
|
|
*/
|
2015-02-26 18:41:17 +01:00
|
|
|
public List<ExtensionElement> getExtensions() {
|
2019-06-11 00:10:38 +02:00
|
|
|
synchronized (extensionElements) {
|
2015-02-23 10:49:33 +01:00
|
|
|
// No need to create a new list, values() will already create a new one for us
|
2019-06-11 00:10:38 +02:00
|
|
|
return extensionElements.values();
|
2003-05-08 17:55:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-05 12:29:26 +01:00
|
|
|
/**
|
2015-10-13 22:31:11 +02:00
|
|
|
* Return a list of all extensions with the given element name <em>and</em> namespace.
|
2015-02-05 12:29:26 +01:00
|
|
|
* <p>
|
2018-03-31 14:17:30 +02:00
|
|
|
* Changes to the returned set will update the stanza extensions, if the returned set is not the empty set.
|
2015-02-05 12:29:26 +01:00
|
|
|
* </p>
|
|
|
|
*
|
|
|
|
* @param elementName the element name, must not be null.
|
|
|
|
* @param namespace the namespace of the element(s), must not be null.
|
|
|
|
* @return a set of all matching extensions.
|
|
|
|
* @since 4.1
|
|
|
|
*/
|
2015-10-13 22:31:11 +02:00
|
|
|
public List<ExtensionElement> getExtensions(String elementName, String namespace) {
|
2018-07-17 15:10:39 +02:00
|
|
|
requireNotNullNorEmpty(elementName, "elementName must not be null nor empty");
|
|
|
|
requireNotNullNorEmpty(namespace, "namespace must not be null nor empty");
|
2019-06-11 00:10:38 +02:00
|
|
|
QName key = new QName(namespace, elementName);
|
|
|
|
return extensionElements.getAll(key);
|
2015-02-05 12:29:26 +01:00
|
|
|
}
|
|
|
|
|
2006-11-23 22:10:59 +01:00
|
|
|
/**
|
2018-03-31 14:17:30 +02:00
|
|
|
* Returns the first extension of this stanza that has the given namespace.
|
2014-10-31 17:12:24 +01:00
|
|
|
* <p>
|
2019-05-17 21:56:46 +02:00
|
|
|
* When possible, use {@link #getExtension(String, String)} instead.
|
2014-10-31 17:12:24 +01:00
|
|
|
* </p>
|
2006-11-23 22:10:59 +01:00
|
|
|
*
|
|
|
|
* @param namespace the namespace of the extension that is desired.
|
2018-03-31 14:17:30 +02:00
|
|
|
* @return the stanza extension with the given namespace.
|
2006-11-23 22:10:59 +01:00
|
|
|
*/
|
2015-02-26 18:41:17 +01:00
|
|
|
public ExtensionElement getExtension(String namespace) {
|
2015-01-19 08:38:41 +01:00
|
|
|
return PacketUtil.extensionElementFrom(getExtensions(), null, namespace);
|
2006-11-23 22:10:59 +01:00
|
|
|
}
|
|
|
|
|
2003-05-08 17:55:06 +02:00
|
|
|
/**
|
2015-02-26 18:41:17 +01:00
|
|
|
* Returns the first extension that matches the specified element name and
|
2014-03-05 08:11:52 +01:00
|
|
|
* namespace, or <tt>null</tt> if it doesn't exist. If the provided elementName is null,
|
2015-02-26 18:41:17 +01:00
|
|
|
* only the namespace is matched. Extensions are
|
2015-10-13 22:31:11 +02:00
|
|
|
* are arbitrary XML elements in standard XMPP stanzas.
|
2003-05-08 17:55:06 +02:00
|
|
|
*
|
2015-02-26 18:41:17 +01:00
|
|
|
* @param elementName the XML element name of the extension. (May be null)
|
|
|
|
* @param namespace the XML element namespace of the extension.
|
2017-12-23 20:21:19 +01:00
|
|
|
* @param <PE> type of the ExtensionElement.
|
2003-05-08 17:55:06 +02:00
|
|
|
* @return the extension, or <tt>null</tt> if it doesn't exist.
|
|
|
|
*/
|
2014-10-26 19:32:19 +01:00
|
|
|
@SuppressWarnings("unchecked")
|
2015-02-26 18:41:17 +01:00
|
|
|
public <PE extends ExtensionElement> PE getExtension(String elementName, String namespace) {
|
2006-11-23 22:10:59 +01:00
|
|
|
if (namespace == null) {
|
2003-05-08 17:55:06 +02:00
|
|
|
return null;
|
|
|
|
}
|
2019-06-11 00:10:38 +02:00
|
|
|
QName key = new QName(namespace, elementName);
|
2015-02-26 18:41:17 +01:00
|
|
|
ExtensionElement packetExtension;
|
2019-06-11 00:10:38 +02:00
|
|
|
synchronized (extensionElements) {
|
|
|
|
packetExtension = extensionElements.getFirst(key);
|
2014-10-26 19:32:19 +01:00
|
|
|
}
|
|
|
|
if (packetExtension == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return (PE) packetExtension;
|
2003-05-08 17:55:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-03-31 14:17:30 +02:00
|
|
|
* Adds a stanza extension to the packet. Does nothing if extension is null.
|
2003-05-08 17:55:06 +02:00
|
|
|
*
|
2018-03-31 14:17:30 +02:00
|
|
|
* @param extension a stanza extension.
|
2003-05-08 17:55:06 +02:00
|
|
|
*/
|
2015-02-26 18:41:17 +01:00
|
|
|
public void addExtension(ExtensionElement extension) {
|
2013-03-18 09:50:48 +01:00
|
|
|
if (extension == null) return;
|
2019-06-11 00:10:38 +02:00
|
|
|
QName key = extension.getQName();
|
|
|
|
synchronized (extensionElements) {
|
|
|
|
extensionElements.put(key, extension);
|
2014-10-26 19:32:19 +01:00
|
|
|
}
|
2003-05-08 17:55:06 +02:00
|
|
|
}
|
|
|
|
|
2015-05-21 22:04:26 +02:00
|
|
|
/**
|
|
|
|
* Add the given extension and override eventually existing extensions with the same name and
|
|
|
|
* namespace.
|
|
|
|
*
|
|
|
|
* @param extension the extension element to add.
|
|
|
|
* @return one of the removed extensions or <code>null</code> if there are none.
|
|
|
|
* @since 4.1.2
|
|
|
|
*/
|
|
|
|
public ExtensionElement overrideExtension(ExtensionElement extension) {
|
|
|
|
if (extension == null) return null;
|
2019-06-11 00:10:38 +02:00
|
|
|
synchronized (extensionElements) {
|
2018-05-10 15:34:24 +02:00
|
|
|
// Note that we need to use removeExtension(String, String) here. If would use
|
|
|
|
// removeExtension(ExtensionElement) then we would remove based on the equality of ExtensionElement, which
|
|
|
|
// is not what we want in this case.
|
|
|
|
ExtensionElement removedExtension = removeExtension(extension.getElementName(), extension.getNamespace());
|
2015-05-21 22:04:26 +02:00
|
|
|
addExtension(extension);
|
|
|
|
return removedExtension;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-18 09:50:48 +01:00
|
|
|
/**
|
2018-03-31 14:17:30 +02:00
|
|
|
* Adds a collection of stanza extensions to the packet. Does nothing if extensions is null.
|
2018-05-09 23:06:12 +02:00
|
|
|
*
|
2018-03-31 14:17:30 +02:00
|
|
|
* @param extensions a collection of stanza extensions
|
2013-03-18 09:50:48 +01:00
|
|
|
*/
|
2015-02-26 18:41:17 +01:00
|
|
|
public void addExtensions(Collection<ExtensionElement> extensions) {
|
2013-03-18 09:50:48 +01:00
|
|
|
if (extensions == null) return;
|
2015-02-26 18:41:17 +01:00
|
|
|
for (ExtensionElement packetExtension : extensions) {
|
2014-10-26 19:32:19 +01:00
|
|
|
addExtension(packetExtension);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-03-31 14:17:30 +02:00
|
|
|
* Check if a stanza extension with the given element and namespace exists.
|
2014-10-26 19:32:19 +01:00
|
|
|
* <p>
|
|
|
|
* The argument <code>elementName</code> may be null.
|
|
|
|
* </p>
|
|
|
|
*
|
|
|
|
* @param elementName
|
|
|
|
* @param namespace
|
2018-03-31 14:17:30 +02:00
|
|
|
* @return true if a stanza extension exists, false otherwise.
|
2014-10-26 19:32:19 +01:00
|
|
|
*/
|
|
|
|
public boolean hasExtension(String elementName, String namespace) {
|
|
|
|
if (elementName == null) {
|
|
|
|
return hasExtension(namespace);
|
|
|
|
}
|
2019-06-11 00:10:38 +02:00
|
|
|
QName key = new QName(namespace, elementName);
|
|
|
|
synchronized (extensionElements) {
|
|
|
|
return extensionElements.containsKey(key);
|
2014-10-26 19:32:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-03-31 14:17:30 +02:00
|
|
|
* Check if a stanza extension with the given namespace exists.
|
2018-05-09 23:06:12 +02:00
|
|
|
*
|
2014-10-26 19:32:19 +01:00
|
|
|
* @param namespace
|
2018-03-31 14:17:30 +02:00
|
|
|
* @return true if a stanza extension exists, false otherwise.
|
2014-10-26 19:32:19 +01:00
|
|
|
*/
|
|
|
|
public boolean hasExtension(String namespace) {
|
2019-06-11 00:10:38 +02:00
|
|
|
synchronized (extensionElements) {
|
|
|
|
for (ExtensionElement packetExtension : extensionElements.values()) {
|
2014-10-26 19:32:19 +01:00
|
|
|
if (packetExtension.getNamespace().equals(namespace)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-03-31 14:17:30 +02:00
|
|
|
* Remove the stanza extension with the given elementName and namespace.
|
2014-10-26 19:32:19 +01:00
|
|
|
*
|
|
|
|
* @param elementName
|
|
|
|
* @param namespace
|
2018-03-31 14:17:30 +02:00
|
|
|
* @return the removed stanza extension or null.
|
2014-10-26 19:32:19 +01:00
|
|
|
*/
|
2015-02-26 18:41:17 +01:00
|
|
|
public ExtensionElement removeExtension(String elementName, String namespace) {
|
2019-06-11 00:10:38 +02:00
|
|
|
QName key = new QName(namespace, elementName);
|
|
|
|
synchronized (extensionElements) {
|
|
|
|
return extensionElements.remove(key);
|
2014-10-26 19:32:19 +01:00
|
|
|
}
|
2013-03-18 09:50:48 +01:00
|
|
|
}
|
|
|
|
|
2003-05-08 17:55:06 +02:00
|
|
|
/**
|
2018-03-31 14:17:30 +02:00
|
|
|
* Removes a stanza extension from the packet.
|
2003-05-08 17:55:06 +02:00
|
|
|
*
|
2018-03-31 14:17:30 +02:00
|
|
|
* @param extension the stanza extension to remove.
|
|
|
|
* @return the removed stanza extension or null.
|
2003-05-08 17:55:06 +02:00
|
|
|
*/
|
2015-02-26 18:41:17 +01:00
|
|
|
public ExtensionElement removeExtension(ExtensionElement extension) {
|
2019-06-11 00:10:38 +02:00
|
|
|
QName key = extension.getQName();
|
|
|
|
synchronized (extensionElements) {
|
|
|
|
List<ExtensionElement> list = extensionElements.getAll(key);
|
2018-05-09 16:53:08 +02:00
|
|
|
boolean removed = list.remove(extension);
|
|
|
|
if (removed) {
|
|
|
|
return extension;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
2003-05-08 17:55:06 +02:00
|
|
|
}
|
|
|
|
|
2016-05-25 22:52:29 +02:00
|
|
|
/**
|
|
|
|
* Returns a short String describing the Stanza. This method is suited for log purposes.
|
|
|
|
*/
|
2014-12-27 21:12:59 +01:00
|
|
|
@Override
|
2016-05-25 22:52:29 +02:00
|
|
|
public abstract String toString();
|
2014-12-27 21:12:59 +01:00
|
|
|
|
2010-08-15 17:13:05 +02:00
|
|
|
/**
|
|
|
|
* Returns the default language used for all messages containing localized content.
|
2018-05-09 23:06:12 +02:00
|
|
|
*
|
2010-08-15 17:13:05 +02:00
|
|
|
* @return the default language
|
|
|
|
*/
|
|
|
|
public static String getDefaultLanguage() {
|
2007-04-26 08:22:55 +02:00
|
|
|
return DEFAULT_LANGUAGE;
|
|
|
|
}
|
|
|
|
|
2014-03-21 09:51:52 +01:00
|
|
|
/**
|
2014-09-12 11:20:34 +02:00
|
|
|
* Add to, from, id and 'xml:lang' attributes
|
2014-03-21 09:51:52 +01:00
|
|
|
*
|
2018-05-09 16:53:08 +02:00
|
|
|
* @param xml the {@link XmlStringBuilder}.
|
2019-02-04 13:27:41 +01:00
|
|
|
* @param enclosingXmlEnvironment the enclosing XML namespace.
|
|
|
|
* @return the XML environment for this stanza.
|
|
|
|
*/
|
|
|
|
protected XmlEnvironment addCommonAttributes(XmlStringBuilder xml, XmlEnvironment enclosingXmlEnvironment) {
|
|
|
|
String language = getLanguage();
|
|
|
|
String namespace = StreamOpen.CLIENT_NAMESPACE;
|
|
|
|
if (enclosingXmlEnvironment != null) {
|
|
|
|
String effectiveEnclosingNamespace = enclosingXmlEnvironment.getEffectiveNamespaceOrUse(namespace);
|
|
|
|
switch (effectiveEnclosingNamespace) {
|
|
|
|
case StreamOpen.CLIENT_NAMESPACE:
|
|
|
|
case StreamOpen.SERVER_NAMESPACE:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
namespace = effectiveEnclosingNamespace;
|
|
|
|
}
|
2018-05-09 16:53:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
xml.xmlnsAttribute(namespace);
|
2014-03-21 09:51:52 +01:00
|
|
|
xml.optAttribute("to", getTo());
|
|
|
|
xml.optAttribute("from", getFrom());
|
2015-02-05 11:17:27 +01:00
|
|
|
xml.optAttribute("id", getStanzaId());
|
2019-02-04 13:27:41 +01:00
|
|
|
xml.xmllangAttribute(language);
|
2018-05-09 16:53:08 +02:00
|
|
|
|
2019-02-04 13:27:41 +01:00
|
|
|
return new XmlEnvironment(namespace, language);
|
2014-02-01 23:22:30 +01:00
|
|
|
}
|
2014-11-07 21:12:01 +01:00
|
|
|
|
2016-05-25 22:52:29 +02:00
|
|
|
protected void logCommonAttributes(StringBuilder sb) {
|
|
|
|
if (getTo() != null) {
|
|
|
|
sb.append("to=").append(to).append(',');
|
|
|
|
}
|
|
|
|
if (getFrom() != null) {
|
|
|
|
sb.append("from=").append(from).append(',');
|
|
|
|
}
|
|
|
|
if (hasStanzaIdSet()) {
|
|
|
|
sb.append("id=").append(id).append(',');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-07 21:12:01 +01:00
|
|
|
/**
|
2018-03-31 14:17:30 +02:00
|
|
|
* Append an XMPPError is this stanza has one set.
|
2014-11-07 21:12:01 +01:00
|
|
|
*
|
|
|
|
* @param xml the XmlStringBuilder to append the error to.
|
|
|
|
*/
|
2019-02-04 13:27:41 +01:00
|
|
|
protected void appendErrorIfExists(XmlStringBuilder xml, XmlEnvironment enclosingXmlEnvironment) {
|
2018-04-07 21:25:40 +02:00
|
|
|
StanzaError error = getError();
|
2014-11-07 21:12:01 +01:00
|
|
|
if (error != null) {
|
2019-02-04 13:27:41 +01:00
|
|
|
xml.append(error.toXML(enclosingXmlEnvironment));
|
2014-11-07 21:12:01 +01:00
|
|
|
}
|
|
|
|
}
|
2013-03-18 09:50:48 +01:00
|
|
|
}
|