diff options
Diffstat (limited to 'src/org/jivesoftware/smack/packet/IQ.java')
-rw-r--r-- | src/org/jivesoftware/smack/packet/IQ.java | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/src/org/jivesoftware/smack/packet/IQ.java b/src/org/jivesoftware/smack/packet/IQ.java new file mode 100644 index 0000000..8e1f7d4 --- /dev/null +++ b/src/org/jivesoftware/smack/packet/IQ.java @@ -0,0 +1,244 @@ +/** + * $RCSfile$ + * $Revision$ + * $Date$ + * + * Copyright 2003-2007 Jive Software. + * + * All rights reserved. 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 org.jivesoftware.smack.util.StringUtils; + +/** + * 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 packet has a specific type that indicates what type of action + * is being taken: "get", "set", "result", or "error".<p> + * + * 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 packet it is. Some example IQ subpacket snippets:<ul> + * + * <li><query xmlns="jabber:iq:auth"> -- an authentication IQ. + * <li><query xmlns="jabber:iq:private"> -- a private storage IQ. + * <li><pubsub xmlns="http://jabber.org/protocol/pubsub"> -- a pubsub IQ. + * </ul> + * + * @author Matt Tucker + */ +public abstract class IQ extends Packet { + + private Type type = Type.GET; + + public IQ() { + super(); + } + + public IQ(IQ iq) { + super(iq); + type = iq.getType(); + } + /** + * Returns the type of the IQ packet. + * + * @return the type of the IQ packet. + */ + public Type getType() { + return type; + } + + /** + * Sets the type of the IQ packet. + * + * @param type the type of the IQ packet. + */ + public void setType(Type type) { + if (type == null) { + this.type = Type.GET; + } + else { + this.type = type; + } + } + + public String toXML() { + StringBuilder buf = new StringBuilder(); + buf.append("<iq "); + if (getPacketID() != null) { + buf.append("id=\"" + getPacketID() + "\" "); + } + if (getTo() != null) { + buf.append("to=\"").append(StringUtils.escapeForXML(getTo())).append("\" "); + } + if (getFrom() != null) { + buf.append("from=\"").append(StringUtils.escapeForXML(getFrom())).append("\" "); + } + if (type == null) { + buf.append("type=\"get\">"); + } + else { + buf.append("type=\"").append(getType()).append("\">"); + } + // Add the query section if there is one. + String queryXML = getChildElementXML(); + if (queryXML != null) { + buf.append(queryXML); + } + // Add the error sub-packet, if there is one. + XMPPError error = getError(); + if (error != null) { + buf.append(error.toXML()); + } + buf.append("</iq>"); + return buf.toString(); + } + + /** + * Returns the sub-element XML section of the IQ packet, or <tt>null</tt> if there + * isn't one. Packet extensions <b>must</b> be included, if any are defined.<p> + * + * Extensions of this class must override this method. + * + * @return the child element section of the IQ XML. + */ + public abstract String getChildElementXML(); + + /** + * 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 packet will be initialized with:<ul> + * <li>The sender set to the recipient of the originating IQ. + * <li>The recipient set to the sender of the originating IQ. + * <li>The type set to {@link Type#RESULT IQ.Type.RESULT}. + * <li>The id set to the id of the originating IQ. + * <li>No child element of the IQ element. + * </ul> + * + * @param iq the {@link Type#GET IQ.Type.GET} or {@link Type#SET IQ.Type.SET} IQ packet. + * @throws IllegalArgumentException if the IQ 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) { + 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 IQ result = new IQ() { + public String getChildElementXML() { + return null; + } + }; + result.setType(Type.RESULT); + result.setPacketID(request.getPacketID()); + result.setFrom(request.getTo()); + result.setTo(request.getFrom()); + return result; + } + + /** + * 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 packet will be initialized with:<ul> + * <li>The sender set to the recipient of the originating IQ. + * <li>The recipient set to the sender of the originating IQ. + * <li>The type set to {@link Type#ERROR IQ.Type.ERROR}. + * <li>The id set to the id of the originating IQ. + * <li>The child element contained in the associated originating IQ. + * <li>The provided {@link XMPPError XMPPError}. + * </ul> + * + * @param iq 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 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 IQ createErrorResponse(final IQ request, final XMPPError 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 IQ result = new IQ() { + public String getChildElementXML() { + return request.getChildElementXML(); + } + }; + result.setType(Type.ERROR); + result.setPacketID(request.getPacketID()); + result.setFrom(request.getTo()); + result.setTo(request.getFrom()); + result.setError(error); + return result; + } + + /** + * A class to represent the type of the IQ packet. The types are: + * + * <ul> + * <li>IQ.Type.GET + * <li>IQ.Type.SET + * <li>IQ.Type.RESULT + * <li>IQ.Type.ERROR + * </ul> + */ + public static class Type { + + public static final Type GET = new Type("get"); + public static final Type SET = new Type("set"); + public static final Type RESULT = new Type("result"); + public static final Type ERROR = new Type("error"); + + /** + * Converts a String into the corresponding types. Valid String values + * that can be converted to types are: "get", "set", "result", and "error". + * + * @param type the String value to covert. + * @return the corresponding Type. + */ + public static Type fromString(String type) { + if (type == null) { + return null; + } + type = type.toLowerCase(); + if (GET.toString().equals(type)) { + return GET; + } + else if (SET.toString().equals(type)) { + return SET; + } + else if (ERROR.toString().equals(type)) { + return ERROR; + } + else if (RESULT.toString().equals(type)) { + return RESULT; + } + else { + return null; + } + } + + private String value; + + private Type(String value) { + this.value = value; + } + + public String toString() { + return value; + } + } +} |