/** * * Copyright 2003-2007 Jive Software. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. */ package org.jivesoftware.smack.packet; import java.util.Locale; import org.jivesoftware.smack.util.Objects; import org.jivesoftware.smack.util.XmlStringBuilder; /** * The base IQ (Info/Query) packet. IQ packets are used to get and set information * on the server, including authentication, roster operations, and creating * accounts. Each IQ stanza(/packet) has a specific type that indicates what type of action * is being taken: "get", "set", "result", or "error".
* * IQ packets can contain a single child element that exists in a specific XML * namespace. The combination of the element name and namespace determines what * type of IQ stanza(/packet) it is. Some example IQ subpacket snippets:
* Since the type of an IQ must present, an IllegalArgmentException will be thrown when type is
* null
.
*
* For example to create an IQ with a extra attribute and an additional child element *
** {@code ** the body of the {@code getIQChildElementBuilder} looks like ** * } ** *elementText *
* {@code * // The builder 'xml' will already have the child element and the 'xmlns' attribute added * // So the current builder state is "* If your IQ only contains attributes and no child elements, i.e. it can be represented as empty element, then you * can mark it as such. * * xml.attribute("myAttribute", "myAttributeValue"); * xml.setEmptyElement(); ** If your IQ does not contain any attributes or child elements (besides {@link ExtensionElement}s), consider sub-classing * {@link SimpleIQ} instead. * * @param xml a pre-created builder which already has the child element and the 'xmlns' attribute set. * @return the build to create the IQ child content. */ protected abstract IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml); /** * Convenience method to create a new empty {@link Type#result IQ.Type.result} * IQ based on a {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set} * IQ. The new stanza(/packet) will be initialized with:*
* * @param request the {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set} IQ packet. * @throws IllegalArgumentException if the IQ stanza(/packet) does not have a type of * {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set}. * @return a new {@link Type#result IQ.Type.result} IQ based on the originating IQ. */ public static IQ createResultIQ(final IQ request) { return new EmptyResultIQ(request); } /** * Convenience method to create a new {@link Type#error IQ.Type.error} IQ * based on a {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set} * IQ. The new stanza(/packet) will be initialized with:- The sender set to the recipient of the originating IQ. *
- The recipient set to the sender of the originating IQ. *
- The type set to {@link Type#result IQ.Type.result}. *
- The id set to the id of the originating IQ. *
- No child element of the IQ element. *
*
* * @param request the {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set} IQ packet. * @param error the error to associate with the created IQ packet. * @throws IllegalArgumentException if the IQ stanza(/packet) does not have a type of * {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set}. * @return a new {@link Type#error IQ.Type.error} IQ based on the originating IQ. */ public static ErrorIQ createErrorResponse(final IQ request, final XMPPError.Builder error) { if (!(request.getType() == Type.get || request.getType() == Type.set)) { throw new IllegalArgumentException( "IQ must be of type 'set' or 'get'. Original IQ: " + request.toXML()); } final ErrorIQ result = new ErrorIQ(error); result.setStanzaId(request.getStanzaId()); result.setFrom(request.getTo()); result.setTo(request.getFrom()); error.setStanza(result); return result; } public static ErrorIQ createErrorResponse(final IQ request, final XMPPError.Condition condition) { return createErrorResponse(request, XMPPError.getBuilder(condition)); } /** * Convenience method to create a new {@link Type#error IQ.Type.error} IQ * based on a {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set} * IQ. The new stanza(/packet) will be initialized with:- The sender set to the recipient of the originating IQ. *
- The recipient set to the sender of the originating IQ. *
- The type set to {@link Type#error IQ.Type.error}. *
- The id set to the id of the originating IQ. *
- The child element contained in the associated originating IQ. *
- The provided {@link XMPPError XMPPError}. *
*
* * @param request the {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set} IQ packet. * @param error the error to associate with the created IQ packet. * @throws IllegalArgumentException if the IQ stanza(/packet) does not have a type of * {@link Type#get IQ.Type.get} or {@link Type#set IQ.Type.set}. * @return a new {@link Type#error IQ.Type.error} IQ based on the originating IQ. * @deprecated use {@link #createErrorResponse(IQ, org.jivesoftware.smack.packet.XMPPError.Builder)} instead. */ @Deprecated public static ErrorIQ createErrorResponse(final IQ request, final XMPPError error) { return createErrorResponse(request, XMPPError.getBuilder(error)); } /** * A enum to represent the type of the IQ stanza. */ public enum Type { /** * The IQ stanza requests information, inquires about what data is needed in order to complete further operations, etc. */ get, /** * The IQ stanza provides data that is needed for an operation to be completed, sets new values, replaces existing values, etc. */ set, /** * The IQ stanza is a response to a successful get or set request. */ result, /** * The IQ stanza reports an error that has occurred regarding processing or delivery of a get or set request. */ error, ; /** * Converts a String into the corresponding types. Valid String values * that can be converted to types are: "get", "set", "result", and "error". * * @param string the String value to covert. * @return the corresponding Type. * @throws IllegalArgumentException when not able to parse the string parameter * @throws NullPointerException if the string is null */ public static Type fromString(String string) { return Type.valueOf(string.toLowerCase(Locale.US)); } } public static class IQChildElementXmlStringBuilder extends XmlStringBuilder { private final String element; private boolean isEmptyElement; private IQChildElementXmlStringBuilder(IQ iq) { this(iq.getChildElementName(), iq.getChildElementNamespace()); } public IQChildElementXmlStringBuilder(ExtensionElement pe) { this(pe.getElementName(), pe.getNamespace()); } private IQChildElementXmlStringBuilder(String element, String namespace) { prelude(element, namespace); this.element = element; } public void setEmptyElement() { isEmptyElement = true; } } }- The sender set to the recipient of the originating IQ. *
- The recipient set to the sender of the originating IQ. *
- The type set to {@link Type#error IQ.Type.error}. *
- The id set to the id of the originating IQ. *
- The child element contained in the associated originating IQ. *
- The provided {@link XMPPError XMPPError}. *