diff --git a/documentation/extensions/hoxt.md b/documentation/extensions/hoxt.md index 9a83a3834..b89f5a7d2 100644 --- a/documentation/extensions/hoxt.md +++ b/documentation/extensions/hoxt.md @@ -65,13 +65,11 @@ In this example we are HTTP client, so we send request (POST) and handle the response: ``` -// register listener for IQ packets -connection.addPacketListener(new IqPacketListener(), new PacketTypeFilter(IQ.class)); // create a request body String urlEncodedMessage = "I_love_you"; // create request -HttpOverXmppReq.Req req = new HttpOverXmppReq.Req(HttpMethod.POST, "/mailbox"); +HttpOverXmppReq req = new HttpOverXmppReq(HttpMethod.POST, "/mailbox"); req.setVersion("1.1"); // prepare headers @@ -86,52 +84,25 @@ AbstractHttpOverXmpp.Text child = new AbstractHttpOverXmpp.Text(urlEncodedMessag AbstractHttpOverXmpp.Data data = new AbstractHttpOverXmpp.Data(child); req.setData(data); -// create IQ packet -HttpOverXmppReq packet = new HttpOverXmppReq(); -packet.setReq(req); -packet.setTo("juliet@capulet.com/balcony"); -packet.setType(IQ.Type.SET); -packet.setPacketID("42"); +// add to +req.setTo("juliet@capulet.com/balcony"); // send it -connection.sendPacket(packet); - - -// then in your PacketListener -private class IqPacketListener implements PacketListener { - - @Override - public void processPacket(Packet packet) { - IQ iq = (IQ) packet; - - // verify from and packed ID - if (iq.getFrom().equals("juliet@capulet.com/balcony") && (iq.getPacketID().equals("42"))) { - - // ensure it's not ERROR - if (iq.getType().equals(IQ.Type.RESULT)) { - - // check if correct IQ implementation arrived - if (iq instanceof HttpOverXmppResp) { - HttpOverXmppResp resp = (HttpOverXmppResp) iq; - - // check HTTP response code - if (resp.getResp().getStatusCode() == 200) { - - // get content of the response - AbstractHttpOverXmpp.DataChild child = resp.getResp().getData().getChild(); - - // check which type of content of the response arrived - if (child instanceof AbstractHttpOverXmpp.Xml) { - - // print the message and anxiously read if from console ;) - System.out.println(((AbstractHttpOverXmpp.Xml) child).getText()); - } else { - // process other AbstractHttpOverXmpp.DataChild subtypes - } - } +connection.sendIqWithResponseCallback(req, new PacketListener() { + public void processPacket(Packet packet) { + HttpOverXmppResp resp = (HttpOverXmppResp) iq; + // check HTTP response code + if (resp.getStatusCode() == 200) { + // get content of the response + NamedElement child = resp.getData().getChild(); + // check which type of content of the response arrived + if (child instanceof AbstractHttpOverXmpp.Xml) { + // print the message and anxiously read if from console ;) + System.out.println(((AbstractHttpOverXmpp.Xml) child).getText()); + } else { + // process other AbstractHttpOverXmpp.DataChild subtypes } } } -} -} +}); ``` diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Bind.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Bind.java index ef5cc4232..df59cc5f6 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Bind.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Bind.java @@ -17,8 +17,6 @@ package org.jivesoftware.smack.packet; -import org.jivesoftware.smack.util.XmlStringBuilder; - /** * IQ packet used by Smack to bind a resource and to obtain the jid assigned by the server. * There are two ways to bind a resource. One is simply sending an empty Bind packet where the @@ -39,6 +37,7 @@ public class Bind extends IQ { private final String jid; public Bind(String resource, String jid) { + super(ELEMENT, NAMESPACE); this.resource = resource; this.jid = jid; } @@ -62,12 +61,10 @@ public class Bind extends IQ { } @Override - public XmlStringBuilder getChildElementXML() { - XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).rightAngleBracket(); + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { + xml.rightAngleBracket(); xml.optElement("resource", resource); xml.optElement("jid", jid); - xml.closeElement(ELEMENT); return xml; } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/EmptyResultIQ.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/EmptyResultIQ.java new file mode 100644 index 000000000..0af904bc8 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/EmptyResultIQ.java @@ -0,0 +1,42 @@ +/** + * + * Copyright © 2014 Florian Schmaus + * + * 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; + +public class EmptyResultIQ extends IQ { + + public EmptyResultIQ() { + super(null, null); + type = IQ.Type.result; + } + + public EmptyResultIQ(IQ request) { + this(); + if (!(request.getType() == Type.get || request.getType() == Type.set)) { + throw new IllegalArgumentException( + "IQ must be of type 'set' or 'get'. Original IQ: " + request.toXML()); + } + setPacketID(request.getPacketID()); + setFrom(request.getTo()); + setTo(request.getFrom()); + } + + @Override + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { + // Empty result IQs don't have an child elements + return null; + } +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/ErrorIQ.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/ErrorIQ.java new file mode 100644 index 000000000..18a3eca3a --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/ErrorIQ.java @@ -0,0 +1,38 @@ +/** + * + * Copyright © 2014 Florian Schmaus + * + * 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; + +public class ErrorIQ extends SimpleIQ { + + public static final String ELEMENT = XMPPError.ERROR; + + /** + * Constructs a new error IQ. + *
+ * According to RFC 6120 § 8.3.1 "4. An error stanza MUST contain an
- * - * Extensions of this class must override this method. + * Returns the sub-element XML section of the IQ packet, or the empty String if there + * isn't one. * * @return the child element section of the IQ XML. */ - public abstract CharSequence getChildElementXML(); + public final XmlStringBuilder getChildElementXML() { + XmlStringBuilder xml = new XmlStringBuilder(); + if (type == Type.error) { + // Add the error sub-packet, if there is one. + appendErrorIfExists(xml); + } + else if (childElementName != null) { + // Add the query section if there is one. + IQChildElementXmlStringBuilder iqChildElement = getIQChildElementBuilder(new IQChildElementXmlStringBuilder(this)); + if (iqChildElement != null) { + xml.append(iqChildElement); + XmlStringBuilder extensionsXml = getExtensionsXML(); + if (iqChildElement.isEmptyElement) { + if (extensionsXml.length() == 0) { + xml.closeEmptyElement(); + return xml; + } else { + xml.rightAngleBracket(); + } + } + xml.append(extensionsXml); + xml.closeElement(iqChildElement.element); + } + } + return xml; + } + + /** + * This method must be overwritten by IQ subclasses to create their child content. It is important that the builder + * does not include the final end element. This will be done automatically by IQChildelementXmlStringBuilder + * after eventual existing packet extensions have been added. + *
+ * 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 "* */ - public String getChildElementXML() { - StringBuilder buf = new StringBuilder(); - buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append("\">"); - buf.append("+ * 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 packet extensions), 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} @@ -126,20 +203,7 @@ public abstract class IQ extends Packet { * @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; + return new EmptyResultIQ(request); } /** @@ -165,17 +229,10 @@ public abstract class IQ extends Packet { throw new IllegalArgumentException( "IQ must be of type 'set' or 'get'. Original IQ: " + request.toXML()); } - final IQ result = new IQ() { - @Override - public CharSequence getChildElementXML() { - return request.getChildElementXML(); - } - }; - result.setType(Type.error); + final IQ result = new ErrorIQ(error); result.setPacketID(request.getPacketID()); result.setFrom(request.getTo()); result.setTo(request.getFrom()); - result.setError(error); return result; } @@ -209,4 +266,27 @@ public abstract class IQ extends Packet { 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(PacketExtension pe) { + this(pe.getElementName(), pe.getNamespace()); + } + + private IQChildElementXmlStringBuilder(String element, String namespace) { + prelude(element, namespace); + this.element = element; + } + + public void setEmptyElement() { + isEmptyElement = true; + } + } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java index f5ac6030d..6a81e4e21 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Message.java @@ -430,10 +430,7 @@ public final class Message extends Packet { buf.optElement("thread", thread); // Append the error subpacket if the message type is an error. if (type == Type.error) { - XMPPError error = getError(); - if (error != null) { - buf.append(error.toXML()); - } + appendErrorIfExists(buf); } // Add packet extensions, if any are defined. buf.append(getExtensionsXML()); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Packet.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Packet.java index 0fbd14a32..c33f9299e 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Packet.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Packet.java @@ -383,9 +383,21 @@ public abstract class Packet extends TopLevelStreamElement { * @param xml */ protected void addCommonAttributes(XmlStringBuilder xml) { - xml.optAttribute("id", getPacketID()); xml.optAttribute("to", getTo()); xml.optAttribute("from", getFrom()); + xml.optAttribute("id", getPacketID()); xml.xmllangAttribute(getLanguage()); } + + /** + * Append an XMPPError is this packet has one set. + * + * @param xml the XmlStringBuilder to append the error to. + */ + protected void appendErrorIfExists(XmlStringBuilder xml) { + XMPPError error = getError(); + if (error != null) { + xml.append(error.toXML()); + } + } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java index 56d042eba..1f84755aa 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Presence.java @@ -223,10 +223,8 @@ public final class Presence extends Packet { buf.append(getExtensionsXML()); // Add the error sub-packet, if there is one. - XMPPError error = getError(); - if (error != null) { - buf.append(error.toXML()); - } + appendErrorIfExists(buf); + buf.closeElement(ELEMENT); return buf; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/RosterPacket.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/RosterPacket.java index d1b92ac1d..470b603e7 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/RosterPacket.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/RosterPacket.java @@ -40,6 +40,10 @@ public class RosterPacket extends IQ { private final List- rosterItems = new ArrayList
- (); private String rosterVersion; + public RosterPacket() { + super(ELEMENT, NAMESPACE); + } + /** * Adds a roster item to the packet. * @@ -74,10 +78,7 @@ public class RosterPacket extends IQ { } @Override - public XmlStringBuilder getChildElementXML() { - XmlStringBuilder buf = new XmlStringBuilder(); - buf.halfOpenElement(ELEMENT); - buf.xmlnsAttribute(NAMESPACE); + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder buf) { buf.optAttribute("ver", rosterVersion); buf.rightAngleBracket(); @@ -86,7 +87,6 @@ public class RosterPacket extends IQ { buf.append(entry.toXML()); } } - buf.closeElement(ELEMENT); return buf; } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java index 8f6ed5ea9..2b2ac49ed 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java @@ -30,7 +30,7 @@ package org.jivesoftware.smack.packet; * * @author Gaston Dombiak */ -public class Session extends IQ { +public class Session extends SimpleIQ { public static final String ELEMENT = "session"; public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-session"; @@ -38,14 +38,10 @@ public class Session extends IQ { private static final String SESSION = '<' + ELEMENT + " xmlns='" + NAMESPACE + "'/>"; public Session() { + super(ELEMENT, NAMESPACE); setType(IQ.Type.set); } - @Override - public String getChildElementXML() { - return SESSION; - } - public static class Feature implements PacketExtension { public static final Session.Feature INSTANCE = new Feature(); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/SimpleIQ.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/SimpleIQ.java new file mode 100644 index 000000000..cd20108d8 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/SimpleIQ.java @@ -0,0 +1,38 @@ +/** + * + * Copyright © 2014 Florian Schmaus + * + * 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; + +/** + * A simple IQ. + *
+ * Simple IQs child elements do not contain further attributes besides 'xmlns'. They may contain additional packet + * extensions. + *
+ */ +public abstract class SimpleIQ extends IQ { + + protected SimpleIQ(String childElementName, String childElementNamespace) { + super(childElementName, childElementNamespace); + } + + @Override + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { + xml.setEmptyElement(); + return xml; + } + +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java index 6a843bfc9..a56a81289 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java @@ -32,6 +32,8 @@ import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.compress.packet.Compress; import org.jivesoftware.smack.packet.DefaultPacketExtension; +import org.jivesoftware.smack.packet.EmptyResultIQ; +import org.jivesoftware.smack.packet.ErrorIQ; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; @@ -634,10 +636,12 @@ public class PacketParserUtils { } // Only handle unknown IQs of type result. Types of 'get' and 'set' which are not understood // have to be answered with an IQ error response. See the code a few lines below + // Note that if we reach this code, it is guranteed that the result IQ contained a child element + // (RFC 6120 § 8.2.3 6) because otherwhise we would have reached the END_TAG first. else if (IQ.Type.result == type){ // No Provider found for the IQ stanza, parse it to an UnparsedIQ instance // so that the content of the IQ can be examined later on - iqPacket = new UnparsedResultIQ(parseElement(parser)); + iqPacket = new UnparsedResultIQ(elementName, namespace, parseElement(parser)); } } break; @@ -652,32 +656,28 @@ public class PacketParserUtils { } // Decide what to do when an IQ packet was not understood if (iqPacket == null) { - if (connection != null && (IQ.Type.get == type || IQ.Type.set == type)) { + switch (type) { + case get: + case set: + if (connection == null) { + return null; + } // If the IQ stanza is of type "get" or "set" containing a child element qualified // by a namespace with no registered Smack provider, then answer an IQ of type // "error" with code 501 ("feature-not-implemented") - iqPacket = new IQ() { - @Override - public String getChildElementXML() { - return null; - } - }; + iqPacket = new ErrorIQ(new XMPPError(XMPPError.Condition.feature_not_implemented)); iqPacket.setPacketID(id); iqPacket.setTo(from); iqPacket.setFrom(to); - iqPacket.setType(IQ.Type.error); - iqPacket.setError(new XMPPError(XMPPError.Condition.feature_not_implemented)); connection.sendPacket(iqPacket); return null; - } - else { - // If an IQ packet wasn't created above, create an empty IQ packet. - iqPacket = new IQ() { - @Override - public String getChildElementXML() { - return null; - } - }; + case error: + // If an IQ packet wasn't created above, create an empty error IQ packet. + iqPacket = new ErrorIQ(error); + break; + case result: + iqPacket = new EmptyResultIQ(); + break; } } @@ -1077,15 +1077,20 @@ public class PacketParserUtils { * */ public static class UnparsedResultIQ extends IQ { - public UnparsedResultIQ(CharSequence content) { + private UnparsedResultIQ(String element, String namespace, CharSequence content) { + super(element, namespace); this.content = content; } private final CharSequence content; + public CharSequence getContent() { + return content; + } + @Override - public CharSequence getChildElementXML() { - return this.content; + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { + throw new UnsupportedOperationException(); } } } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java b/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java index 0400b98cc..5d6e80fc9 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java @@ -39,8 +39,15 @@ public class XmlStringBuilder implements Appendable, CharSequence { halfOpenElement(e.getElementName()); } + public XmlStringBuilder escapedElement(String name, String escapedContent) { + assert escapedContent != null; + openElement(name); + append(escapedContent); + closeElement(name); + return this; + } + /** - * Does nothing if content is null. * * @param name * @param content @@ -94,6 +101,7 @@ public class XmlStringBuilder implements Appendable, CharSequence { } public XmlStringBuilder halfOpenElement(String name) { + assert(StringUtils.isNotEmpty(name)); sb.append('<').append(name); return this; } @@ -235,8 +243,12 @@ public class XmlStringBuilder implements Appendable, CharSequence { } public XmlStringBuilder prelude(PacketExtension pe) { - halfOpenElement(pe.getElementName()); - xmlnsAttribute(pe.getNamespace()); + return prelude(pe.getElementName(), pe.getNamespace()); + } + + public XmlStringBuilder prelude(String elementName, String namespace) { + halfOpenElement(elementName); + xmlnsAttribute(namespace); return this; } @@ -247,6 +259,13 @@ public class XmlStringBuilder implements Appendable, CharSequence { return this; } + public XmlStringBuilder optAppend(Element element) { + if (element != null) { + append(element.toXML()); + } + return this; + } + public XmlStringBuilder append(XmlStringBuilder xsb) { assert xsb != null; sb.append(xsb.sb); diff --git a/smack-core/src/test/java/org/jivesoftware/smack/RosterTest.java b/smack-core/src/test/java/org/jivesoftware/smack/RosterTest.java index a7a4a78a1..faebc25ab 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/RosterTest.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/RosterTest.java @@ -655,14 +655,7 @@ public class RosterTest { connection.processPacket(rosterPush); // Create and process the IQ response - final IQ response = new IQ() { - public String getChildElementXML() { - return null; - } - }; - response.setPacketID(rosterRequest.getPacketID()); - response.setType(Type.result); - response.setTo(connection.getUser()); + final IQ response = IQ.createResultIQ(rosterRequest); connection.processPacket(response); // Verify the roster update request diff --git a/smack-core/src/test/java/org/jivesoftware/smack/StanzaIdTest.java b/smack-core/src/test/java/org/jivesoftware/smack/StanzaIdTest.java index 49f06a503..083ec6908 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/StanzaIdTest.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/StanzaIdTest.java @@ -1,6 +1,6 @@ /** * - * Copyright © Florian Schmaus + * Copyright © 2014 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.TestIQ; import org.jivesoftware.smack.util.StringUtils; import org.junit.Test; @@ -27,26 +28,15 @@ public class StanzaIdTest { @Test public void testIqId() { - IQ iq1 = new TestIqId(); + IQ iq1 = new TestIQ(); String iq1Id = iq1.getPacketID(); assertTrue(StringUtils.isNotEmpty(iq1Id)); - IQ iq2 = new TestIqId(); + IQ iq2 = new TestIQ(); String iq2Id = iq2.getPacketID(); assertTrue(StringUtils.isNotEmpty(iq2Id)); assertFalse(iq1Id.equals(iq2Id)); } - private static class TestIqId extends IQ { - - public TestIqId() { - setType(Type.set); - } - - @Override - public CharSequence getChildElementXML() { - return ""; - } - } } diff --git a/smack-core/src/test/java/org/jivesoftware/smack/packet/IQResponseTest.java b/smack-core/src/test/java/org/jivesoftware/smack/packet/IQResponseTest.java index df3845b4e..9aea18595 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/packet/IQResponseTest.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/packet/IQResponseTest.java @@ -19,7 +19,6 @@ package org.jivesoftware.smack.packet; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import org.junit.Test; @@ -32,18 +31,15 @@ import org.junit.Test; */ public class IQResponseTest { - final static private String childElement = " "; + private static final String ELEMENT = "child"; + private static final String NAMESPACE = "http://igniterealtime.org/protocol/test"; /** * Test creating a simple and empty IQ response. */ @Test public void testGeneratingSimpleResponse() { - final IQ request = new IQ() { - public String getChildElementXML() { - return childElement; - } - }; + final IQ request = new TestIQ(ELEMENT, NAMESPACE); request.setFrom("sender@test/Smack"); request.setTo("receiver@test/Smack"); @@ -54,7 +50,7 @@ public class IQResponseTest { assertEquals(request.getPacketID(), result.getPacketID()); assertEquals(request.getFrom(), result.getTo()); assertEquals(request.getTo(), result.getFrom()); - assertNull(result.getChildElementXML()); + assertEquals("", result.getChildElementXML().toString()); } /** @@ -63,11 +59,8 @@ public class IQResponseTest { @Test public void testGeneratingValidErrorResponse() { final XMPPError error = new XMPPError(XMPPError.Condition.bad_request); - final IQ request = new IQ() { - public String getChildElementXML() { - return childElement; - } - }; + final IQ request = new TestIQ(ELEMENT, NAMESPACE); + request.setType(IQ.Type.set); request.setFrom("sender@test/Smack"); request.setTo("receiver@test/Smack"); @@ -79,7 +72,8 @@ public class IQResponseTest { assertEquals(request.getPacketID(), result.getPacketID()); assertEquals(request.getFrom(), result.getTo()); assertEquals(error, result.getError()); - assertEquals(childElement, result.getChildElementXML()); + // TODO this test was never valid + // assertEquals(CHILD_ELEMENT, result.getChildElementXML()); } /** @@ -88,11 +82,8 @@ public class IQResponseTest { */ @Test public void testGeneratingResponseBasedOnResult() { - final IQ request = new IQ() { - public String getChildElementXML() { - return childElement; - } - }; + final IQ request = new TestIQ(ELEMENT, NAMESPACE); + request.setType(IQ.Type.result); request.setFrom("sender@test/Smack"); request.setTo("receiver@test/Smack"); @@ -114,11 +105,8 @@ public class IQResponseTest { @Test public void testGeneratingErrorBasedOnError() { final XMPPError error = new XMPPError(XMPPError.Condition.bad_request); - final IQ request = new IQ() { - public String getChildElementXML() { - return childElement; - } - }; + final IQ request = new TestIQ(ELEMENT, NAMESPACE); + request.setType(IQ.Type.error); request.setFrom("sender@test/Smack"); request.setTo("receiver@test/Smack"); diff --git a/smack-core/src/test/java/org/jivesoftware/smack/packet/TestIQ.java b/smack-core/src/test/java/org/jivesoftware/smack/packet/TestIQ.java new file mode 100644 index 000000000..a9f203632 --- /dev/null +++ b/smack-core/src/test/java/org/jivesoftware/smack/packet/TestIQ.java @@ -0,0 +1,35 @@ +/** + * + * Copyright © 2014 Florian Schmaus + * + * 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; + +public class TestIQ extends SimpleIQ { + + public TestIQ() { + this(null, null); + } + + public TestIQ(String element, String namespace) { + super(element, namespace); + } + + @Override + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { + if (getChildElementName() == null) + return null; + return super.getIQChildElementBuilder(xml); + } +} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/carbons/packet/Carbon.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/carbons/packet/Carbon.java index 9dbd21990..ce521caa6 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/carbons/packet/Carbon.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/carbons/packet/Carbon.java @@ -16,7 +16,7 @@ */ package org.jivesoftware.smackx.carbons.packet; -import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.SimpleIQ; /** * Carbon IQs @@ -24,29 +24,23 @@ import org.jivesoftware.smack.packet.IQ; public class Carbon { public static final String NAMESPACE = "urn:xmpp:carbons:2"; - public static class Enable extends IQ { + public static class Enable extends SimpleIQ { public static final String ELEMENT = "enable"; public Enable() { + super(ELEMENT, NAMESPACE); setType(Type.set); } - @Override - public String getChildElementXML() { - return "<" + ELEMENT + " xmlns='" + NAMESPACE + "'/>"; - } } - public static class Disable extends IQ { + public static class Disable extends SimpleIQ { public static final String ELEMENT = "disable"; public Disable() { + super(ELEMENT, NAMESPACE); setType(Type.set); } - @Override - public String getChildElementXML() { - return "<" + ELEMENT + " xmlns='" + NAMESPACE + "'/>"; - } } } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/HOXTManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/HOXTManager.java index fd24deeee..20b1b4aec 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/HOXTManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/HOXTManager.java @@ -23,6 +23,7 @@ import org.jivesoftware.smack.XMPPConnectionRegistry; import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; +import org.jivesoftware.smackx.hoxt.packet.AbstractHttpOverXmpp; /** * Manager for HTTP ove XMPP transport (XEP-0332) extension. @@ -35,7 +36,7 @@ public class HOXTManager { /** * Namespace for this extension. */ - public static final String NAMESPACE = "urn:xmpp:http"; + public static final String NAMESPACE = AbstractHttpOverXmpp.NAMESPACE; static { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/packet/AbstractHttpOverXmpp.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/packet/AbstractHttpOverXmpp.java index 9c326b1c6..ac4a5fc6d 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/packet/AbstractHttpOverXmpp.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/packet/AbstractHttpOverXmpp.java @@ -17,6 +17,8 @@ package org.jivesoftware.smackx.hoxt.packet; import org.jivesoftware.smack.packet.IQ; +import org.jivesoftware.smack.packet.NamedElement; +import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smackx.shim.packet.HeadersExtension; /** @@ -27,97 +29,84 @@ import org.jivesoftware.smackx.shim.packet.HeadersExtension; */ public abstract class AbstractHttpOverXmpp extends IQ { + public static final String NAMESPACE = "urn:xmpp:http"; + + protected AbstractHttpOverXmpp(String element) { + super(element, NAMESPACE); + } + + private HeadersExtension headers; + private Data data; + + protected String version; + + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { + IQChildElementXmlStringBuilder builder = getIQHoxtChildElementBuilder(xml); + builder.append(headers.toXML()); + builder.append(data.toXML()); + + return builder; + } + /** - * Abstract representation of parent of Req and Resp elements. + * Returns start tag. + * + * @return start tag */ - public static abstract class AbstractBody { + protected abstract IQChildElementXmlStringBuilder getIQHoxtChildElementBuilder(IQChildElementXmlStringBuilder xml); - private HeadersExtension headers; - private Data data; + /** + * Returns version attribute. + * + * @return version attribute + */ + public String getVersion() { + return version; + } - protected String version; + /** + * Sets version attribute. + * + * @param version version attribute + */ + public void setVersion(String version) { + this.version = version; + } - /** - * Returns string containing xml representation of this object. - * - * @return xml representation of this object - */ - public String toXML() { - StringBuilder builder = new StringBuilder(); - builder.append(getStartTag()); - builder.append(headers.toXML()); - builder.append(data.toXML()); - builder.append(getEndTag()); - return builder.toString(); - } + /** + * Returns Headers element. + * + * @return Headers element + */ + public HeadersExtension getHeaders() { + return headers; + } - /** - * Returns start tag. - * - * @return start tag - */ - protected abstract String getStartTag(); + /** + * Sets Headers element. + * + * @param headers Headers element + */ + public void setHeaders(HeadersExtension headers) { + this.headers = headers; + } - /** - * Returns end tag. - * - * @return end tag - */ - protected abstract String getEndTag(); + /** + * Returns Data element. + * + * @return Data element + */ + public Data getData() { + return data; + } - /** - * Returns version attribute. - * - * @return version attribute - */ - public String getVersion() { - return version; - } - - /** - * Sets version attribute. - * - * @param version version attribute - */ - public void setVersion(String version) { - this.version = version; - } - - /** - * Returns Headers element. - * - * @return Headers element - */ - public HeadersExtension getHeaders() { - return headers; - } - - /** - * Sets Headers element. - * - * @param headers Headers element - */ - public void setHeaders(HeadersExtension headers) { - this.headers = headers; - } - - /** - * Returns Data element. - * - * @return Data element - */ - public Data getData() { - return data; - } - - /** - * Sets Data element. - * - * @param data Headers element - */ - public void setData(Data data) { - this.data = data; - } + /** + * Sets Data element. + * + * @param data Headers element + */ + public void setData(Data data) { + this.data = data; } /** @@ -126,14 +115,14 @@ public abstract class AbstractHttpOverXmpp extends IQ { */ public static class Data { - private final DataChild child; + private final NamedElement child; /** * Creates Data element. * * @param child element nested by Data */ - public Data(DataChild child) { + public Data(NamedElement child) { this.child = child; } @@ -155,29 +144,18 @@ public abstract class AbstractHttpOverXmpp extends IQ { * * @return element nested by Data */ - public DataChild getChild() { + public NamedElement getChild() { return child; } } - /** - * Interface for child elements of Data element. - */ - public static interface DataChild { - - /** - * Returns string containing xml representation of this object. - * - * @return xml representation of this object - */ - public String toXML(); - } - /** * Representation of Text element. * This class is immutable. */ - public static class Text implements DataChild { + public static class Text implements NamedElement { + + public static final String ELEMENT = "text"; private final String text; @@ -191,14 +169,12 @@ public abstract class AbstractHttpOverXmpp extends IQ { } @Override - public String toXML() { - StringBuilder builder = new StringBuilder(); - builder.append("
"); - if (text != null) { - builder.append(text); - } - builder.append(" "); - return builder.toString(); + public XmlStringBuilder toXML() { + XmlStringBuilder xml = new XmlStringBuilder(this); + xml.rightAngleBracket(); + xml.optAppend(text); + xml.closeElement(this); + return xml; } /** @@ -209,13 +185,20 @@ public abstract class AbstractHttpOverXmpp extends IQ { public String getText() { return text; } + + @Override + public String getElementName() { + return ELEMENT; + } } /** * Representation of Base64 element.* This class is immutable. */ - public static class Base64 implements DataChild { + public static class Base64 implements NamedElement { + + public static final String ELEMENT = "base64"; private final String text; @@ -229,14 +212,12 @@ public abstract class AbstractHttpOverXmpp extends IQ { } @Override - public String toXML() { - StringBuilder builder = new StringBuilder(); - builder.append("
"); - if (text != null) { - builder.append(text); - } - builder.append(" "); - return builder.toString(); + public XmlStringBuilder toXML() { + XmlStringBuilder xml = new XmlStringBuilder(this); + xml.rightAngleBracket(); + xml.optAppend(text); + xml.closeElement(this); + return xml; } /** @@ -247,18 +228,25 @@ public abstract class AbstractHttpOverXmpp extends IQ { public String getText() { return text; } + + @Override + public String getElementName() { + return ELEMENT; + } } /** * Representation of Xml element.* This class is immutable. */ - public static class Xml implements DataChild { + public static class Xml implements NamedElement { + + public static final String ELEMENT = "xml"; private final String text; /** - * Creates this element. + * Creates this element.builder.toString(); * * @param text value of text */ @@ -267,14 +255,12 @@ public abstract class AbstractHttpOverXmpp extends IQ { } @Override - public String toXML() { - StringBuilder builder = new StringBuilder(); - builder.append("
"); - if (text != null) { - builder.append(text); - } - builder.append(" "); - return builder.toString(); + public XmlStringBuilder toXML() { + XmlStringBuilder xml = new XmlStringBuilder(this); + xml.rightAngleBracket(); + xml.optAppend(text); + xml.closeElement(this); + return xml; } /** @@ -285,13 +271,20 @@ public abstract class AbstractHttpOverXmpp extends IQ { public String getText() { return text; } + + @Override + public String getElementName() { + return ELEMENT; + } } /** * Representation of ChunkedBase64 element.* This class is immutable. */ - public static class ChunkedBase64 implements DataChild { + public static class ChunkedBase64 implements NamedElement { + + public static final String ELEMENT = "chunkedBase64"; private final String streamId; @@ -305,12 +298,11 @@ public abstract class AbstractHttpOverXmpp extends IQ { } @Override - public String toXML() { - StringBuilder builder = new StringBuilder(); - builder.append("
"); - return builder.toString(); + public XmlStringBuilder toXML() { + XmlStringBuilder xml = new XmlStringBuilder(this); + xml.attribute("streamId", streamId); + xml.closeEmptyElement(); + return xml; } /** @@ -321,13 +313,20 @@ public abstract class AbstractHttpOverXmpp extends IQ { public String getStreamId() { return streamId; } + + @Override + public String getElementName() { + return ELEMENT; + } } /** * Representation of Ibb element. * This class is immutable. */ - public static class Ibb implements DataChild { + public static class Ibb implements NamedElement { + + public static final String ELEMENT = "ibb"; private final String sid; @@ -341,12 +340,11 @@ public abstract class AbstractHttpOverXmpp extends IQ { } @Override - public String toXML() { - StringBuilder builder = new StringBuilder(); - builder.append("
"); - return builder.toString(); + public XmlStringBuilder toXML() { + XmlStringBuilder xml = new XmlStringBuilder(this); + xml.attribute("sid", sid); + xml.closeEmptyElement(); + return xml; } /** @@ -357,5 +355,10 @@ public abstract class AbstractHttpOverXmpp extends IQ { public String getSid() { return sid; } + + @Override + public String getElementName() { + return ELEMENT; + } } } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/packet/HttpOverXmppReq.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/packet/HttpOverXmppReq.java index c0b6b4104..13bdd8f00 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/packet/HttpOverXmppReq.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/packet/HttpOverXmppReq.java @@ -17,7 +17,6 @@ package org.jivesoftware.smackx.hoxt.packet; import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.hoxt.HOXTManager; /** * Represents Req IQ packet. @@ -27,177 +26,136 @@ import org.jivesoftware.smackx.hoxt.HOXTManager; */ public class HttpOverXmppReq extends AbstractHttpOverXmpp { - private Req req; + public static final String ELEMENT = "req"; + + + public HttpOverXmppReq(HttpMethod method, String resource) { + super(ELEMENT); + this.method = method; + this.resource = resource; + type = Type.set; + } + + private HttpMethod method; + private String resource; + + // TODO: validate: xs:minInclusive value='256' xs:maxInclusive value='65536' + private int maxChunkSize = 0; // 0 means not set + + private boolean sipub = true; + + private boolean ibb = true; + private boolean jingle = true; @Override - public String getChildElementXML() { - return req.toXML(); + protected IQChildElementXmlStringBuilder getIQHoxtChildElementBuilder(IQChildElementXmlStringBuilder builder) { + builder.append(" "); + builder.append("method='").append(method.toString()).append("'"); + builder.append(" "); + builder.append("resource='").append(StringUtils.escapeForXML(resource)).append("'"); + builder.append(" "); + builder.append("version='").append(StringUtils.escapeForXML(version)).append("'"); + if (maxChunkSize != 0) { + builder.append(" "); + builder.append("maxChunkSize='").append(Integer.toString(maxChunkSize)).append("'"); + } + builder.append(" "); + builder.append("sipub='").append(Boolean.toString(sipub)).append("'"); + builder.append(" "); + builder.append("ibb='").append(Boolean.toString(ibb)).append("'"); + builder.append(" "); + builder.append("jingle='").append(Boolean.toString(jingle)).append("'"); + builder.append(">"); + return builder; } /** - * Returns Req element. + * Returns method attribute. * - * @return Req element + * @return method attribute */ - public Req getReq() { - return req; + public HttpMethod getMethod() { + return method; } /** - * Sets Req element. + * Returns resource attribute. * - * @param req Req element + * @return resource attribute */ - public void setReq(Req req) { - this.req = req; + public String getResource() { + return resource; } /** - * Represents Req element. + * Returns maxChunkSize attribute. + * + * @return maxChunkSize attribute */ - public static class Req extends AbstractBody { + public int getMaxChunkSize() { + return maxChunkSize; + } - private HttpMethod method; - private String resource; + /** + * Sets maxChunkSize attribute. + * + * @param maxChunkSize maxChunkSize attribute + */ + public void setMaxChunkSize(int maxChunkSize) { + this.maxChunkSize = maxChunkSize; + } - // TODO: validate: xs:minInclusive value='256' xs:maxInclusive value='65536' - private int maxChunkSize = 0; // 0 means not set + /** + * Returns sipub attribute. + * + * @return sipub attribute + */ + public boolean isSipub() { + return sipub; + } - private boolean sipub = true; + /** + * Sets sipub attribute. + * + * @param sipub sipub attribute + */ + public void setSipub(boolean sipub) { + this.sipub = sipub; + } - private boolean ibb = true; - private boolean jingle = true; + /** + * Returns ibb attribute. + * + * @return ibb attribute + */ + public boolean isIbb() { + return ibb; + } - /** - * Creates this object. - * - * @param method method attribute - * @param resource resource attribute - */ - public Req(HttpMethod method, String resource) { - this.method = method; - this.resource = resource; - } + /** + * Sets ibb attribute. + * + * @param ibb ibb attribute + */ + public void setIbb(boolean ibb) { + this.ibb = ibb; + } - @Override - protected String getStartTag() { - StringBuilder builder = new StringBuilder(); - builder.append(" "); - return builder.toString(); - } + /** + * Returns jingle attribute. + * + * @return jingle attribute + */ + public boolean isJingle() { + return jingle; + } - @Override - protected String getEndTag() { - return " "; - } - - /** - * Returns method attribute. - * - * @return method attribute - */ - public HttpMethod getMethod() { - return method; - } - - /** - * Returns resource attribute. - * - * @return resource attribute - */ - public String getResource() { - return resource; - } - - /** - * Returns maxChunkSize attribute. - * - * @return maxChunkSize attribute - */ - public int getMaxChunkSize() { - return maxChunkSize; - } - - /** - * Sets maxChunkSize attribute. - * - * @param maxChunkSize maxChunkSize attribute - */ - public void setMaxChunkSize(int maxChunkSize) { - this.maxChunkSize = maxChunkSize; - } - - /** - * Returns sipub attribute. - * - * @return sipub attribute - */ - public boolean isSipub() { - return sipub; - } - - /** - * Sets sipub attribute. - * - * @param sipub sipub attribute - */ - public void setSipub(boolean sipub) { - this.sipub = sipub; - } - - /** - * Returns ibb attribute. - * - * @return ibb attribute - */ - public boolean isIbb() { - return ibb; - } - - /** - * Sets ibb attribute. - * - * @param ibb ibb attribute - */ - public void setIbb(boolean ibb) { - this.ibb = ibb; - } - - /** - * Returns jingle attribute. - * - * @return jingle attribute - */ - public boolean isJingle() { - return jingle; - } - - /** - * Sets jingle attribute. - * - * @param jingle jingle attribute - */ - public void setJingle(boolean jingle) { - this.jingle = jingle; - } + /** + * Sets jingle attribute. + * + * @param jingle jingle attribute + */ + public void setJingle(boolean jingle) { + this.jingle = jingle; } } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/packet/HttpOverXmppResp.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/packet/HttpOverXmppResp.java index 3979a224b..4e134f0d6 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/packet/HttpOverXmppResp.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/packet/HttpOverXmppResp.java @@ -17,7 +17,6 @@ package org.jivesoftware.smackx.hoxt.packet; import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.hoxt.HOXTManager; /** * Represents Resp IQ packet. @@ -27,96 +26,63 @@ import org.jivesoftware.smackx.hoxt.HOXTManager; */ public class HttpOverXmppResp extends AbstractHttpOverXmpp { - private Resp resp; + public static final String ELEMENT = "resp"; + + + public HttpOverXmppResp() { + super(ELEMENT); + } + + private int statusCode; + private String statusMessage = null; @Override - public String getChildElementXML() { - return resp.toXML(); + protected IQChildElementXmlStringBuilder getIQHoxtChildElementBuilder(IQChildElementXmlStringBuilder builder) { + builder.append(" "); + builder.append("version='").append(StringUtils.escapeForXML(version)).append("'"); + builder.append(" "); + builder.append("statusCode='").append(Integer.toString(statusCode)).append("'"); + if (statusMessage != null) { + builder.append(" "); + builder.append("statusMessage='").append(StringUtils.escapeForXML(statusMessage)).append("'"); + } + builder.append(">"); + return builder; } /** - * Returns Resp element. + * Returns statusCode attribute. * - * @return Resp element + * @return statusCode attribute */ - public Resp getResp() { - return resp; + public int getStatusCode() { + return statusCode; } /** - * Sets Resp element. + * Sets statusCode attribute. * - * @param resp Resp element + * @param statusCode statusCode attribute */ - public void setResp(Resp resp) { - this.resp = resp; + public void setStatusCode(int statusCode) { + this.statusCode = statusCode; } /** - * Represents Resp element. + * Returns statusMessage attribute. + * + * @return statusMessage attribute */ - public static class Resp extends AbstractBody { + public String getStatusMessage() { + return statusMessage; + } - private int statusCode; - private String statusMessage = null; - - @Override - protected String getStartTag() { - StringBuilder builder = new StringBuilder(); - builder.append(""); - return builder.toString(); - } - - @Override - protected String getEndTag() { - return " "; - } - - /** - * Returns statusCode attribute. - * - * @return statusCode attribute - */ - public int getStatusCode() { - return statusCode; - } - - /** - * Sets statusCode attribute. - * - * @param statusCode statusCode attribute - */ - public void setStatusCode(int statusCode) { - this.statusCode = statusCode; - } - - /** - * Returns statusMessage attribute. - * - * @return statusMessage attribute - */ - public String getStatusMessage() { - return statusMessage; - } - - /** - * Sets statusMessage attribute. - * - * @param statusMessage statusMessage attribute - */ - public void setStatusMessage(String statusMessage) { - this.statusMessage = statusMessage; - } + /** + * Sets statusMessage attribute. + * + * @param statusMessage statusMessage attribute + */ + public void setStatusMessage(String statusMessage) { + this.statusMessage = statusMessage; } } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/provider/AbstractHttpOverXmppProvider.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/provider/AbstractHttpOverXmppProvider.java index 01d188d7a..fcfcac495 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/provider/AbstractHttpOverXmppProvider.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/hoxt/provider/AbstractHttpOverXmppProvider.java @@ -17,6 +17,7 @@ package org.jivesoftware.smackx.hoxt.provider; import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.packet.NamedElement; import org.jivesoftware.smack.provider.IQProvider; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.hoxt.packet.AbstractHttpOverXmpp; @@ -63,7 +64,7 @@ public abstract class AbstractHttpOverXmppProvider{ - private static final String ELEMENT_REQ = "req"; - private static final String ATTRIBUTE_METHOD = "method"; private static final String ATTRIBUTE_RESOURCE = "resource"; private static final String ATTRIBUTE_MAX_CHUNK_SIZE = "maxChunkSize"; - /** - * Mandatory no argument constructor. - */ - public HttpOverXmppReqProvider() { - } - @Override public HttpOverXmppReq parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException, SmackException { @@ -53,7 +45,7 @@ public class HttpOverXmppReqProvider extends AbstractHttpOverXmppProvider { - private static final String ELEMENT_RESP = "resp"; - private static final String ATTRIBUTE_STATUS_MESSAGE = "statusMessage"; private static final String ATTRIBUTE_STATUS_CODE = "statusCode"; @@ -44,15 +42,12 @@ public class HttpOverXmppRespProvider extends AbstractHttpOverXmppProvider expectedHeaders) { diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/hoxt/provider/HttpOverXmppReqProviderTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/hoxt/provider/HttpOverXmppReqProviderTest.java index 48e666279..e317ea026 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/hoxt/provider/HttpOverXmppReqProviderTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/hoxt/provider/HttpOverXmppReqProviderTest.java @@ -31,7 +31,7 @@ public class HttpOverXmppReqProviderTest { @Test public void areAllReqAttributesCorrectlyParsed() throws Exception { String string = " "; - HttpOverXmppReq.Req req = parseReq(string); + HttpOverXmppReq req = parseReq(string); assertEquals(req.getVersion(), "1.1"); assertEquals(req.getMethod(), HttpMethod.OPTIONS); assertEquals(req.getResource(), "*"); @@ -40,7 +40,7 @@ public class HttpOverXmppReqProviderTest { @Test public void areGetRequestAttributesCorrectlyParsed() throws Exception { String string = " "; - HttpOverXmppReq.Req req = parseReq(string); + HttpOverXmppReq req = parseReq(string); assertEquals(req.getVersion(), "1.1"); assertEquals(req.getMethod(), HttpMethod.GET); assertEquals(req.getResource(), "/rdf/xep"); @@ -49,7 +49,7 @@ public class HttpOverXmppReqProviderTest { @Test public void getReqOptionAttributesCorrectlyParsed() throws Exception { String string = " "; - HttpOverXmppReq.Req req = parseReq(string); + HttpOverXmppReq req = parseReq(string); assertEquals(req.getMaxChunkSize(), 256); assertEquals(req.isSipub(), false); assertEquals(req.isIbb(), true); @@ -59,18 +59,18 @@ public class HttpOverXmppReqProviderTest { @Test public void getReqOptionalAttributesDefaultValues() throws Exception { String string = " "; - HttpOverXmppReq.Req req = parseReq(string); + HttpOverXmppReq req = parseReq(string); assertEquals(req.isSipub(), true); assertEquals(req.isIbb(), true); assertEquals(req.isJingle(), true); } - private HttpOverXmppReq.Req parseReq(String string) throws Exception { + private HttpOverXmppReq parseReq(String string) throws Exception { HttpOverXmppReqProvider provider = new HttpOverXmppReqProvider(); XmlPullParser parser = PacketParserUtils.getParserFor(string); IQ iq = provider.parse(parser); assertTrue(iq instanceof HttpOverXmppReq); HttpOverXmppReq castedIq = (HttpOverXmppReq) iq; - return castedIq.getReq(); + return castedIq; } } diff --git a/smack-experimental/src/test/java/org/jivesoftware/smackx/hoxt/provider/HttpOverXmppRespProviderTest.java b/smack-experimental/src/test/java/org/jivesoftware/smackx/hoxt/provider/HttpOverXmppRespProviderTest.java index 867b51a6c..6da0887a3 100644 --- a/smack-experimental/src/test/java/org/jivesoftware/smackx/hoxt/provider/HttpOverXmppRespProviderTest.java +++ b/smack-experimental/src/test/java/org/jivesoftware/smackx/hoxt/provider/HttpOverXmppRespProviderTest.java @@ -39,8 +39,7 @@ public class HttpOverXmppRespProviderTest { IQ iq = provider.parse(parser); assertTrue(iq instanceof HttpOverXmppResp); - HttpOverXmppResp castedIq = (HttpOverXmppResp) iq; - HttpOverXmppResp.Resp resp = castedIq.getResp(); + HttpOverXmppResp resp = (HttpOverXmppResp) iq; assertEquals(resp.getVersion(), "1.1"); assertEquals(resp.getStatusCode(), 200); @@ -55,8 +54,7 @@ public class HttpOverXmppRespProviderTest { IQ iq = provider.parse(parser); assertTrue(iq instanceof HttpOverXmppResp); - HttpOverXmppResp castedIq = (HttpOverXmppResp) iq; - HttpOverXmppResp.Resp resp = castedIq.getResp(); + HttpOverXmppResp resp = (HttpOverXmppResp) iq; assertEquals(resp.getVersion(), "1.1"); assertEquals(resp.getStatusCode(), 200); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java index 0db995261..6771dda13 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/InBandBytestreamSession.java @@ -33,7 +33,6 @@ import org.jivesoftware.smack.filter.PacketTypeFilter; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; -import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.packet.XMPPError; import org.jivesoftware.smack.util.stringencoder.Base64; import org.jivesoftware.smackx.bytestreams.BytestreamSession; @@ -450,9 +449,7 @@ public class InBandBytestreamSession implements BytestreamSession { public void processPacket(Packet packet) throws NotConnectedException { // get data packet extension - DataPacketExtension data = (DataPacketExtension) packet.getExtension( - DataPacketExtension.ELEMENT, - DataPacketExtension.NAMESPACE); + DataPacketExtension data = ((Data) packet).getDataPacketExtension(); /* * check if sequence was not used already (see XEP-0047 Section 2.2) @@ -562,15 +559,20 @@ public class InBandBytestreamSession implements BytestreamSession { return false; } - // stanza contains data packet extension - PacketExtension packetExtension = packet.getExtension(DataPacketExtension.ELEMENT, - DataPacketExtension.NAMESPACE); - if (packetExtension == null || !(packetExtension instanceof DataPacketExtension)) { - return false; + DataPacketExtension data; + if (packet instanceof Data) { + data = ((Data) packet).getDataPacketExtension(); + } else { + // stanza contains data packet extension + data = packet.getExtension( + DataPacketExtension.ELEMENT, + DataPacketExtension.NAMESPACE); + if (data == null) { + return false; + } } // session ID equals this session ID - DataPacketExtension data = (DataPacketExtension) packetExtension; if (!data.getSessionID().equals(byteStreamRequest.getSessionID())) { return false; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Close.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Close.java index 9b6412eba..40d295169 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Close.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Close.java @@ -17,7 +17,6 @@ package org.jivesoftware.smackx.bytestreams.ibb.packet; import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.util.XmlStringBuilder; /** * Represents a request to close an In-Band Bytestream. @@ -27,6 +26,7 @@ import org.jivesoftware.smack.util.XmlStringBuilder; public class Close extends IQ { public static final String ELEMENT = "close"; + public static final String NAMESPACE = DataPacketExtension.NAMESPACE; /* unique session ID identifying this In-Band Bytestream */ private final String sessionID; @@ -37,6 +37,7 @@ public class Close extends IQ { * @param sessionID unique session ID identifying this In-Band Bytestream */ public Close(String sessionID) { + super(ELEMENT, NAMESPACE); if (sessionID == null || "".equals(sessionID)) { throw new IllegalArgumentException("Session ID must not be null or empty"); } @@ -54,12 +55,9 @@ public class Close extends IQ { } @Override - public XmlStringBuilder getChildElementXML() { - XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement(ELEMENT); - xml.xmlnsAttribute(DataPacketExtension.NAMESPACE); + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { xml.attribute("sid", sessionID); - xml.closeEmptyElement(); + xml.setEmptyElement(); return xml; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Data.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Data.java index 7c950771e..25000231a 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Data.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Data.java @@ -17,7 +17,6 @@ package org.jivesoftware.smackx.bytestreams.ibb.packet; import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.util.XmlStringBuilder; /** * Represents a chunk of data sent over an In-Band Bytestream encapsulated in an @@ -36,24 +35,17 @@ public class Data extends IQ { * @param data data packet extension containing the encoded data */ public Data(DataPacketExtension data) { + super(DataPacketExtension.ELEMENT, DataPacketExtension.NAMESPACE); if (data == null) { throw new IllegalArgumentException("Data must not be null"); } this.dataPacketExtension = data; - /* - * also set as packet extension so that data packet extension can be - * retrieved from IQ stanza and message stanza in the same way - */ - addExtension(data); setType(IQ.Type.set); } /** * Returns the data packet extension. - * - * Convenience method for
packet.getExtension("data", - * "http://jabber.org/protocol/ibb")
. * * @return the data packet extension */ @@ -62,8 +54,8 @@ public class Data extends IQ { } @Override - public XmlStringBuilder getChildElementXML() { - return dataPacketExtension.toXML(); + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { + return dataPacketExtension.getIQChildElementBuilder(xml); } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/DataPacketExtension.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/DataPacketExtension.java index eea083def..71534f8c9 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/DataPacketExtension.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/DataPacketExtension.java @@ -17,6 +17,7 @@ package org.jivesoftware.smackx.bytestreams.ibb.packet; import org.jivesoftware.smack.packet.PacketExtension; +import org.jivesoftware.smack.packet.IQ.IQChildElementXmlStringBuilder; import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smack.util.stringencoder.Base64; @@ -135,13 +136,16 @@ public class DataPacketExtension implements PacketExtension { @Override public XmlStringBuilder toXML() { - XmlStringBuilder xml = new XmlStringBuilder(this); - xml.attribute("seq", Long.toString(seq)); - xml.attribute("sid", sessionID); - xml.rightAngleBracket(); - xml.append(data); + XmlStringBuilder xml = getIQChildElementBuilder(new IQChildElementXmlStringBuilder(this)); xml.closeElement(this); return xml; } + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { + xml.attribute("seq", Long.toString(seq)); + xml.attribute("sid", sessionID); + xml.rightAngleBracket(); + xml.append(data); + return xml; + } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Open.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Open.java index 3f1f915bc..7613c36d2 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Open.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/ibb/packet/Open.java @@ -19,7 +19,7 @@ package org.jivesoftware.smackx.bytestreams.ibb.packet; import java.util.Locale; import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.util.XmlStringBuilder; +import org.jivesoftware.smack.packet.IQ.IQChildElementXmlStringBuilder; import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager.StanzaType; /** @@ -30,6 +30,7 @@ import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager.StanzaTyp public class Open extends IQ { public static final String ELEMENT = "open"; + public static final String NAMESPACE = DataPacketExtension.NAMESPACE; /* unique session ID identifying this In-Band Bytestream */ private final String sessionID; @@ -54,6 +55,7 @@ public class Open extends IQ { * @param stanza stanza type used to encapsulate the data */ public Open(String sessionID, int blockSize, StanzaType stanza) { + super(ELEMENT, NAMESPACE); if (sessionID == null || "".equals(sessionID)) { throw new IllegalArgumentException("Session ID must not be null or empty"); } @@ -111,14 +113,11 @@ public class Open extends IQ { } @Override - public XmlStringBuilder getChildElementXML() { - XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement(ELEMENT); - xml.xmlnsAttribute(DataPacketExtension.NAMESPACE); + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { xml.attribute("block-size", Integer.toString(blockSize)); xml.attribute("sid", sessionID); xml.attribute("stanza", stanza.toString().toLowerCase(Locale.US)); - xml.closeEmptyElement(); + xml.setEmptyElement(); return xml; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/packet/Bytestream.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/packet/Bytestream.java index b6febddd4..2b29ef024 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/packet/Bytestream.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/bytestreams/socks5/packet/Bytestream.java @@ -49,6 +49,7 @@ public class Bytestream extends IQ { * The default constructor */ public Bytestream() { + super(QUERY_ELEMENT, NAMESPACE); } /** @@ -58,6 +59,7 @@ public class Bytestream extends IQ { * @see #setSessionID(String) */ public Bytestream(final String SID) { + this(); setSessionID(SID); } @@ -215,11 +217,7 @@ public class Bytestream extends IQ { } @Override - public XmlStringBuilder getChildElementXML() { - XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement(QUERY_ELEMENT); - xml.xmlnsAttribute(NAMESPACE); - + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { switch(getType()) { case set: xml.optAttribute("sid", getSessionID()); @@ -236,25 +234,20 @@ public class Bytestream extends IQ { break; case result: xml.rightAngleBracket(); - if (getUsedHost() != null) { - xml.append(getUsedHost().toXML()); - } + xml.optAppend(getUsedHost()); + // TODO Bytestream can include either used host *or* streamHosts. Never both. This should be ensured by the + // constructions mechanisms of Bytestream // A result from the server can also contain stream hosts - else if (countStreamHosts() > 0) { - for (StreamHost host : streamHosts) { - xml.append(host.toXML()); - } + for (StreamHost host : streamHosts) { + xml.append(host.toXML()); } break; case get: - xml.closeEmptyElement(); - // Return here so that we don't run into the - // closeElement(QUERY_ELEMNT) section - return xml; + xml.setEmptyElement(); + break; default: throw new IllegalStateException(); } - xml.closeElement(QUERY_ELEMENT); return xml; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandData.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandData.java index 332625f47..fc58c8088 100755 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandData.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/commands/packet/AdHocCommandData.java @@ -19,7 +19,6 @@ package org.jivesoftware.smackx.commands.packet; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.PacketExtension; -import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smackx.commands.AdHocCommand; import org.jivesoftware.smackx.commands.AdHocCommand.Action; import org.jivesoftware.smackx.commands.AdHocCommand.SpecificErrorCondition; @@ -66,12 +65,11 @@ public class AdHocCommandData extends IQ { private AdHocCommand.Action executeAction; public AdHocCommandData() { + super(ELEMENT, NAMESPACE); } @Override - public XmlStringBuilder getChildElementXML() { - XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE); + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { xml.attribute("node", node); xml.optAttribute("sessionid", sessionID); xml.optAttribute("status", status); @@ -108,7 +106,6 @@ public class AdHocCommandData extends IQ { // buf.append(getError().toXML()); // } - xml.closeElement(ELEMENT); return xml; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java index 7e5d70f77..9b7e97159 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java @@ -40,6 +40,7 @@ import java.util.Set; */ public class DiscoverInfo extends IQ implements Cloneable { + public static final String ELEMENT = QUERY_ELEMENT; public static final String NAMESPACE = "http://jabber.org/protocol/disco#info"; private final Listfeatures = new LinkedList (); @@ -50,7 +51,7 @@ public class DiscoverInfo extends IQ implements Cloneable { private boolean containsDuplicateFeatures; public DiscoverInfo() { - super(); + super(ELEMENT, NAMESPACE); } /** @@ -212,10 +213,7 @@ public class DiscoverInfo extends IQ implements Cloneable { } @Override - public CharSequence getChildElementXML() { - XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement("query"); - xml.xmlnsAttribute(NAMESPACE); + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { xml.optAttribute("node", getNode()); xml.rightAngleBracket(); for (Identity identity : identities) { @@ -224,9 +222,7 @@ public class DiscoverInfo extends IQ implements Cloneable { for (Feature feature : features) { xml.append(feature.toXML()); } - // Add packet extensions, if any are defined. - xml.append(getExtensionsXML()); - xml.closeElement("query"); + return xml; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverItems.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverItems.java index 7f295d88a..50636e616 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverItems.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverItems.java @@ -35,11 +35,16 @@ import java.util.List; */ public class DiscoverItems extends IQ { + public static final String ELEMENT = QUERY_ELEMENT; public static final String NAMESPACE = "http://jabber.org/protocol/disco#items"; private final List - items = new LinkedList
- (); private String node; + public DiscoverItems() { + super(ELEMENT, NAMESPACE); + } + /** * Adds a new item to the discovered information. * @@ -97,10 +102,8 @@ public class DiscoverItems extends IQ { this.node = node; } - public XmlStringBuilder getChildElementXML() { - XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement("query"); - xml.xmlnsAttribute(NAMESPACE); + @Override + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { xml.optAttribute("node", getNode()); xml.rightAngleBracket(); @@ -108,7 +111,6 @@ public class DiscoverItems extends IQ { xml.append(item.toXML()); } - xml.closeElement("query"); return xml; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqlast/packet/LastActivity.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqlast/packet/LastActivity.java index d05eb8a8b..b4cd6fcd6 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqlast/packet/LastActivity.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqlast/packet/LastActivity.java @@ -22,7 +22,6 @@ import java.io.IOException; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.provider.IQProvider; -import org.jivesoftware.smack.util.XmlStringBuilder; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -37,12 +36,14 @@ import org.xmlpull.v1.XmlPullParserException; */ public class LastActivity extends IQ { + public static final String ELEMENT = QUERY_ELEMENT; public static final String NAMESPACE = "jabber:iq:last"; public long lastActivity = -1; public String message; public LastActivity() { + super(ELEMENT, NAMESPACE); setType(IQ.Type.get); } @@ -52,15 +53,12 @@ public class LastActivity extends IQ { } @Override - public XmlStringBuilder getChildElementXML() { - XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement(IQ.QUERY_ELEMENT); - xml.xmlnsAttribute(NAMESPACE); + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { xml.optLongAttribute("seconds", lastActivity); // We don't support adding the optional message attribute, because it is usually only added // by XMPP servers and not by client entities. - xml.closeEmptyElement(); + xml.setEmptyElement(); return xml; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/PrivateDataManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/PrivateDataManager.java index 54916e6ce..5c7b910b9 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/PrivateDataManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/PrivateDataManager.java @@ -27,6 +27,7 @@ import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.provider.IQProvider; import org.jivesoftware.smackx.iqprivate.packet.DefaultPrivateData; import org.jivesoftware.smackx.iqprivate.packet.PrivateData; +import org.jivesoftware.smackx.iqprivate.packet.PrivateDataIQ; import org.jivesoftware.smackx.iqprivate.provider.PrivateDataProvider; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -156,18 +157,9 @@ public class PrivateDataManager extends Manager { public PrivateData getPrivateData(final String elementName, final String namespace) throws NoResponseException, XMPPErrorException, NotConnectedException { // Create an IQ packet to get the private data. - IQ privateDataGet = new IQ() { - public String getChildElementXML() { - StringBuilder buf = new StringBuilder(); - buf.append("
"); - buf.append("<").append(elementName).append(" xmlns=\"").append(namespace).append("\"/>"); - buf.append(" "); - return buf.toString(); - } - }; - privateDataGet.setType(IQ.Type.get); + IQ privateDataGet = new PrivateDataIQ(elementName, namespace); - PrivateDataResult response = (PrivateDataResult) connection().createPacketCollectorAndSend( + PrivateDataIQ response = connection().createPacketCollectorAndSend( privateDataGet).nextResultOrThrow(); return response.getPrivateData(); } @@ -184,16 +176,7 @@ public class PrivateDataManager extends Manager { */ public void setPrivateData(final PrivateData privateData) throws NoResponseException, XMPPErrorException, NotConnectedException { // Create an IQ packet to set the private data. - IQ privateDataSet = new IQ() { - public String getChildElementXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); - buf.append(privateData.toXML()); - buf.append(" "); - return buf.toString(); - } - }; - privateDataSet.setType(IQ.Type.set); + IQ privateDataSet = new PrivateDataIQ(privateData); connection().createPacketCollectorAndSend(privateDataSet).nextResultOrThrow(); } @@ -214,10 +197,10 @@ public class PrivateDataManager extends Manager { /** * An IQ provider to parse IQ results containing private data. */ - public static class PrivateDataIQProvider extends IQProvider{ + public static class PrivateDataIQProvider extends IQProvider { @Override - public PrivateDataResult parse(XmlPullParser parser, int initialDepth) + public PrivateDataIQ parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException, SmackException { PrivateData privateData = null; boolean done = false; @@ -268,33 +251,7 @@ public class PrivateDataManager extends Manager { } } } - return new PrivateDataResult(privateData); - } - } - - /** - * An IQ packet to hold PrivateData GET results. - */ - private static class PrivateDataResult extends IQ { - - private PrivateData privateData; - - PrivateDataResult(PrivateData privateData) { - this.privateData = privateData; - } - - public PrivateData getPrivateData() { - return privateData; - } - - public String getChildElementXML() { - StringBuilder buf = new StringBuilder(); - buf.append(" "); - if (privateData != null) { - buf.append(privateData.toXML()); - } - buf.append(" "); - return buf.toString(); + return new PrivateDataIQ(privateData); } } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/packet/PrivateDataIQ.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/packet/PrivateDataIQ.java new file mode 100644 index 000000000..6063e040e --- /dev/null +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqprivate/packet/PrivateDataIQ.java @@ -0,0 +1,61 @@ +/** + * + * Copyright © 2014 Florian Schmaus + * + * 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.smackx.iqprivate.packet; + +import org.jivesoftware.smack.packet.IQ; + +public class PrivateDataIQ extends IQ { + + public static final String ELEMENT = QUERY_ELEMENT; + public static final String NAMESPACE = "jabber:iq:private"; + + private final PrivateData privateData; + private final String getElement; + private final String getNamespace; + + public PrivateDataIQ(PrivateData privateData) { + this(privateData, null, null); + setType(Type.set); + } + + public PrivateDataIQ(String element, String namespace) { + this(null, element, namespace); + setType(Type.get); + } + + private PrivateDataIQ(PrivateData privateData, String getElement, String getNamespace) { + super(ELEMENT, NAMESPACE); + this.privateData = privateData; + this.getElement = getElement; + this.getNamespace = getNamespace; + } + + public PrivateData getPrivateData() { + return privateData; + } + + @Override + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { + xml.rightAngleBracket(); + if (privateData != null) { + xml.append(privateData.toXML()); + } else { + xml.halfOpenElement(getElement).xmlnsAttribute(getNamespace).closeEmptyElement(); + } + return xml; + } +} diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/packet/Registration.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/packet/Registration.java index 4cd4a8b9c..fe78b61b8 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/packet/Registration.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/packet/Registration.java @@ -21,7 +21,6 @@ import java.util.Map; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.PacketExtension; -import org.jivesoftware.smack.util.XmlStringBuilder; /** * Represents registration packets. An empty GET query will cause the server to return information @@ -48,6 +47,7 @@ import org.jivesoftware.smack.util.XmlStringBuilder; */ public class Registration extends IQ { + public static final String ELEMENT = QUERY_ELEMENT; public static final String NAMESPACE = "jabber:iq:register"; private final String instructions; @@ -62,6 +62,7 @@ public class Registration extends IQ { } public Registration(String instructions, Mapattributes) { + super(ELEMENT, NAMESPACE); this.instructions = instructions; this.attributes = attributes; } @@ -87,10 +88,7 @@ public class Registration extends IQ { } @Override - public XmlStringBuilder getChildElementXML() { - XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement(QUERY_ELEMENT); - xml.xmlnsAttribute(NAMESPACE); + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { xml.rightAngleBracket(); xml.optElement("instructions", instructions); if (attributes != null && attributes.size() > 0) { @@ -99,9 +97,6 @@ public class Registration extends IQ { xml.element(name, value); } } - // Add packet extensions, if any are defined. - xml.append(getExtensionsXML()); - xml.closeElement(QUERY_ELEMENT); return xml; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqversion/packet/Version.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqversion/packet/Version.java index e87843be5..6ffbcd03b 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqversion/packet/Version.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqversion/packet/Version.java @@ -20,7 +20,6 @@ package org.jivesoftware.smackx.iqversion.packet; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Packet; -import org.jivesoftware.smack.util.XmlStringBuilder; /** * A Version IQ packet, which is used by XMPP clients to discover version information @@ -49,6 +48,7 @@ import org.jivesoftware.smack.util.XmlStringBuilder; * @author Gaston Dombiak */ public class Version extends IQ { + public static final String ELEMENT = QUERY_ELEMENT; public static final String NAMESPACE = "jabber:iq:version"; private final String name; @@ -56,6 +56,7 @@ public class Version extends IQ { private String os; public Version() { + super(ELEMENT, NAMESPACE); name = null; version = null; setType(Type.get); @@ -83,6 +84,7 @@ public class Version extends IQ { * @param os The operating system of the queried entity. This element is OPTIONAL. */ public Version(String name, String version, String os) { + super(ELEMENT, NAMESPACE); if (name == null) { throw new IllegalArgumentException("name must not be null"); @@ -141,15 +143,13 @@ public class Version extends IQ { } @Override - public XmlStringBuilder getChildElementXML() { - XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement(IQ.QUERY_ELEMENT).xmlnsAttribute(NAMESPACE).rightAngleBracket(); + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { + xml.rightAngleBracket(); // Although not really optional elements, 'name' and 'version' are not set when sending a // version request. So we must handle the case that those are 'null' here. xml.optElement("name", name); xml.optElement("version", version); xml.optElement("os", os); - xml.closeElement(IQ.QUERY_ELEMENT); return xml; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/MUCAdmin.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/MUCAdmin.java index ed264288e..33b970213 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/MUCAdmin.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/MUCAdmin.java @@ -21,7 +21,6 @@ import java.util.Collections; import java.util.List; import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.util.XmlStringBuilder; /** * IQ packet that serves for kicking users, granting and revoking voice, banning users, @@ -33,10 +32,15 @@ import org.jivesoftware.smack.util.XmlStringBuilder; */ public class MUCAdmin extends IQ { + public static final String ELEMENT = QUERY_ELEMENT; public static final String NAMESPACE = MUCInitialPresence.NAMESPACE + "#admin"; private final List items = new ArrayList (); + public MUCAdmin() { + super(ELEMENT, NAMESPACE); + } + /** * Returns a List of item childs that holds information about roles, affiliation, * jids and nicks. @@ -62,19 +66,15 @@ public class MUCAdmin extends IQ { } @Override - public XmlStringBuilder getChildElementXML() { - XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement(IQ.QUERY_ELEMENT); - xml.xmlnsAttribute(NAMESPACE); + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { xml.rightAngleBracket(); + synchronized (items) { for (MUCItem item : items) { xml.append(item.toXML()); } } - // Add packet extensions, if any are defined. - xml.append(getExtensionsXML()); - xml.closeElement(IQ.QUERY_ELEMENT); + return xml; } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/MUCOwner.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/MUCOwner.java index 8f9352a14..50f694d99 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/MUCOwner.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/packet/MUCOwner.java @@ -17,7 +17,6 @@ package org.jivesoftware.smackx.muc.packet; import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.util.XmlStringBuilder; import java.util.ArrayList; import java.util.Collections; @@ -32,11 +31,16 @@ import java.util.List; */ public class MUCOwner extends IQ { + public static final String ELEMENT = QUERY_ELEMENT; public static final String NAMESPACE = MUCInitialPresence.NAMESPACE + "#owner"; private final List items = new ArrayList (); private Destroy destroy; + public MUCOwner() { + super(ELEMENT, NAMESPACE); + } + /** * Returns a List of item childs that holds information about affiliation, * jids and nicks. @@ -84,20 +88,16 @@ public class MUCOwner extends IQ { } @Override - public XmlStringBuilder getChildElementXML() { - XmlStringBuilder xml = new XmlStringBuilder(); - xml.halfOpenElement(IQ.QUERY_ELEMENT); - xml.xmlnsAttribute(NAMESPACE); + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { xml.rightAngleBracket(); + synchronized (items) { for (MUCItem item : items) { xml.append(item.toXML()); } } xml.optElement(getDestroy()); - // Add packet extensions, if any are defined. - xml.append(getExtensionsXML()); - xml.closeElement(IQ.QUERY_ELEMENT); + return xml; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/offline/packet/OfflineMessageRequest.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/offline/packet/OfflineMessageRequest.java index ee9bb9829..67f294740 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/offline/packet/OfflineMessageRequest.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/offline/packet/OfflineMessageRequest.java @@ -35,10 +35,17 @@ import java.util.List; */ public class OfflineMessageRequest extends IQ { + public static final String ELEMENT = "offline"; + public static final String NAMESPACE = "http://jabber.org/protocol/offline"; + private List - items = new ArrayList
- (); private boolean purge = false; private boolean fetch = false; + public OfflineMessageRequest() { + super(ELEMENT, NAMESPACE); + } + /** * Returns a List of item childs that holds information about offline messages to * view or delete. @@ -99,9 +106,10 @@ public class OfflineMessageRequest extends IQ { this.fetch = fetch; } - public String getChildElementXML() { - StringBuilder buf = new StringBuilder(); - buf.append("
"); + @Override + protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder buf) { + buf.rightAngleBracket(); + synchronized (items) { for (int i = 0; i < items.size(); i++) { Item item = items.get(i); @@ -114,10 +122,8 @@ public class OfflineMessageRequest extends IQ { if (fetch) { buf.append(" "); - return buf.toString(); + + return buf; } /** diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/pep/packet/PEPPubSub.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/pep/packet/PEPPubSub.java index a2514426d..f3cc4d1bc 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/pep/packet/PEPPubSub.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/pep/packet/PEPPubSub.java @@ -29,39 +29,20 @@ import org.jivesoftware.smack.packet.IQ; */ public class PEPPubSub extends IQ { - PEPItem item; + public static final String ELEMENT = "pubsub"; + public static final String NAMESPACE = "http://jabber.org/protocol/pubsub"; + + private final PEPItem item; /** * Creates a new PubSub. * */ public PEPPubSub(PEPItem item) { - super(); - + super(ELEMENT, NAMESPACE); this.item = item; } - /** - * Returns the XML element name of the extension sub-packet root element. - * Always returns "x" - * - * @return the XML element name of the packet extension. - */ - public String getElementName() { - return "pubsub"; - } - - /** - * Returns the XML namespace of the extension sub-packet root element. - * According the specification the namespace is always "jabber:x:roster" - * (which is not to be confused with the 'jabber:iq:roster' namespace - * - * @return the XML namespace of the packet extension. - */ - public String getNamespace() { - return "http://jabber.org/protocol/pubsub"; - } - /** * Returns the XML representation of a Personal Event Publish according the specification. * @@ -79,14 +60,15 @@ public class PEPPubSub extends IQ { *"); } - // Add packet extensions, if any are defined. - buf.append(getExtensionsXML()); - buf.append("