aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/thedevstack/conversationsplus/xmpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/xmpp')
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/IqPacketParser.java52
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/BadRequestIqErrorException.java17
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/InternalServerErrorException.java17
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/IqPacketErrorException.java20
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/MissingRequiredContentException.java26
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/MissingRequiredElementException.java26
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/ServiceUnavailableException.java17
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/UndefinedConditionException.java17
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/UnexpectedIqPacketTypeException.java25
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/XmppException.java56
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/FileTransferHttp.java8
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/delete/DeleteSlotPacketParser.java30
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/delete/DeleteSlotRequestPacket.java35
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/delete/FileTransferHttpDeleteSlotRequestPacketGenerator.java39
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/HttpUpload.java9
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/HttpUploadRequestSlotPacketGenerator.java46
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/HttpUploadSlot.java22
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/SlotPacketParser.java31
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/SlotRequestPacket.java53
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/httpuploadim/HttpUploadHint.java12
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacket.java43
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacketGenerator.java46
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacketParser.java30
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/xmpp/utils/ErrorIqPacketExceptionHelper.java45
24 files changed, 716 insertions, 6 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/IqPacketParser.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/IqPacketParser.java
new file mode 100644
index 00000000..eee5b0aa
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/IqPacketParser.java
@@ -0,0 +1,52 @@
+package de.thedevstack.conversationsplus.xmpp;
+
+import de.thedevstack.conversationsplus.xmpp.exceptions.MissingRequiredContentException;
+import de.thedevstack.conversationsplus.xmpp.exceptions.MissingRequiredElementException;
+
+import eu.siacs.conversations.xml.Element;
+
+/**
+ *
+ */
+public abstract class IqPacketParser {
+ public static Element findRequiredChild(Element element, String elementName, String namespace) throws MissingRequiredElementException {
+ Element child = findChild(element, elementName, namespace);
+ if (child == null) {
+ throw new MissingRequiredElementException(elementName, namespace, element);
+ }
+ return child;
+ }
+
+ public static Element findChild(Element element, String elementName, String namespace) {
+ if (null == element) {
+ return null;
+ }
+ return element.findChild(elementName, namespace);
+ }
+
+ public static String findRequiredChildContent(Element element, String elementName) throws MissingRequiredContentException {
+ if (null == element) {
+ return null;
+ }
+ String childContent = element.findChildContent(elementName);
+ if (null == childContent) {
+ throw new MissingRequiredContentException(elementName, element);
+ }
+ return childContent;
+ }
+
+ public static String findRequiredChildContent(Element element, String elementName, String namespace) throws MissingRequiredContentException {
+ String childContent = findChildContent(element, elementName, namespace);
+ if (null == childContent) {
+ throw new MissingRequiredContentException(elementName, namespace, element);
+ }
+ return childContent;
+ }
+
+ public static String findChildContent(Element element, String elementName, String namespace) {
+ if (null == element) {
+ return null;
+ }
+ return element.findChildContent(elementName, namespace);
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/BadRequestIqErrorException.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/BadRequestIqErrorException.java
new file mode 100644
index 00000000..120ef495
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/BadRequestIqErrorException.java
@@ -0,0 +1,17 @@
+package de.thedevstack.conversationsplus.xmpp.exceptions;
+
+import eu.siacs.conversations.xml.Element;
+
+/**
+ * Created by steckbrief on 22.08.2016.
+ */
+public class BadRequestIqErrorException extends IqPacketErrorException {
+ public BadRequestIqErrorException(Element context, String errorMessage) {
+ super(context, errorMessage);
+ }
+
+ @Override
+ public String getMessage() {
+ return "Bad Request: " + super.getMessage();
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/InternalServerErrorException.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/InternalServerErrorException.java
new file mode 100644
index 00000000..1a1cded2
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/InternalServerErrorException.java
@@ -0,0 +1,17 @@
+package de.thedevstack.conversationsplus.xmpp.exceptions;
+
+import eu.siacs.conversations.xml.Element;
+
+/**
+ * Created by steckbrief on 22.08.2016.
+ */
+public class InternalServerErrorException extends IqPacketErrorException {
+ public InternalServerErrorException(Element packet, String errorText) {
+ super(packet, errorText);
+ }
+
+ @Override
+ public String getMessage() {
+ return "Internal Server Error: " + super.getMessage();
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/IqPacketErrorException.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/IqPacketErrorException.java
new file mode 100644
index 00000000..65e02688
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/IqPacketErrorException.java
@@ -0,0 +1,20 @@
+package de.thedevstack.conversationsplus.xmpp.exceptions;
+
+import eu.siacs.conversations.xml.Element;
+
+/**
+ * Created by steckbrief on 22.08.2016.
+ */
+public class IqPacketErrorException extends XmppException {
+ private final String iqErrorText;
+
+ public IqPacketErrorException(Element context, String errorMessage) {
+ super(context);
+ this.iqErrorText = errorMessage;
+ }
+
+ @Override
+ public String getMessage() {
+ return this.iqErrorText + " in context: " + this.getContext();
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/MissingRequiredContentException.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/MissingRequiredContentException.java
new file mode 100644
index 00000000..060bb618
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/MissingRequiredContentException.java
@@ -0,0 +1,26 @@
+package de.thedevstack.conversationsplus.xmpp.exceptions;
+
+import eu.siacs.conversations.xml.Element;
+
+/**
+ *
+ */
+public class MissingRequiredContentException extends XmppException {
+ private String elementName;
+ private String namespace;
+
+ public MissingRequiredContentException(String elementName, Element context) {
+ super(context);
+ this.elementName = elementName;
+ }
+
+ public MissingRequiredContentException(String elementName, String namespace, Element context) {
+ this(elementName, context);
+ this.namespace = namespace;
+ }
+
+ @Override
+ public String getMessage() {
+ return "Missing required element content " + ((namespace != null) ? namespace + ":" : "") + elementName + " in context " + getContext();
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/MissingRequiredElementException.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/MissingRequiredElementException.java
new file mode 100644
index 00000000..de24262f
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/MissingRequiredElementException.java
@@ -0,0 +1,26 @@
+package de.thedevstack.conversationsplus.xmpp.exceptions;
+
+import eu.siacs.conversations.xml.Element;
+
+/**
+ *
+ */
+public class MissingRequiredElementException extends XmppException {
+ private String elementName;
+ private String namespace;
+
+ public MissingRequiredElementException(String elementName, Element context) {
+ super(context);
+ this.elementName = elementName;
+ }
+
+ public MissingRequiredElementException(String elementName, String namespace, Element context) {
+ this(elementName, context);
+ this.namespace = namespace;
+ }
+
+ @Override
+ public String getMessage() {
+ return "Missing required element " + ((namespace != null) ? namespace + ":" : "") + elementName + " in context " + getContext();
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/ServiceUnavailableException.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/ServiceUnavailableException.java
new file mode 100644
index 00000000..88d5389b
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/ServiceUnavailableException.java
@@ -0,0 +1,17 @@
+package de.thedevstack.conversationsplus.xmpp.exceptions;
+
+import eu.siacs.conversations.xml.Element;
+
+/**
+ * Created by steckbrief on 22.08.2016.
+ */
+public class ServiceUnavailableException extends IqPacketErrorException {
+ public ServiceUnavailableException(Element context, String errorMessage) {
+ super(context, errorMessage);
+ }
+
+ @Override
+ public String getMessage() {
+ return "Service unavailable: " + super.getMessage();
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/UndefinedConditionException.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/UndefinedConditionException.java
new file mode 100644
index 00000000..de821873
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/UndefinedConditionException.java
@@ -0,0 +1,17 @@
+package de.thedevstack.conversationsplus.xmpp.exceptions;
+
+import eu.siacs.conversations.xml.Element;
+
+/**
+ * Created by steckbrief on 22.08.2016.
+ */
+public class UndefinedConditionException extends IqPacketErrorException {
+ public UndefinedConditionException(Element packet, String errorText) {
+ super(packet, errorText);
+ }
+
+ @Override
+ public String getMessage() {
+ return "Undefined Condition: " + super.getMessage();
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/UnexpectedIqPacketTypeException.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/UnexpectedIqPacketTypeException.java
new file mode 100644
index 00000000..82f229e8
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/UnexpectedIqPacketTypeException.java
@@ -0,0 +1,25 @@
+package de.thedevstack.conversationsplus.xmpp.exceptions;
+
+import java.util.Arrays;
+
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.stanzas.IqPacket;
+
+/**
+ *
+ */
+public class UnexpectedIqPacketTypeException extends XmppException {
+ private final IqPacket.TYPE current;
+ private final IqPacket.TYPE[] expected;
+
+ public UnexpectedIqPacketTypeException(Element context, IqPacket.TYPE current, IqPacket.TYPE... expected) {
+ super(context);
+ this.expected = expected;
+ this.current = current;
+ }
+
+ @Override
+ public String getMessage() {
+ return "Unexpected IQ packet type '" + this.current + "' retrieved. One of " + Arrays.toString(expected) + " was expected.";
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/XmppException.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/XmppException.java
new file mode 100644
index 00000000..b8c6c89d
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/XmppException.java
@@ -0,0 +1,56 @@
+package de.thedevstack.conversationsplus.xmpp.exceptions;
+
+import eu.siacs.conversations.xml.Element;
+
+/**
+ *
+ */
+public class XmppException extends Exception {
+ private Element context;
+ /**
+ * Constructs a new {@code Exception} that includes the current stack trace.
+ */
+ public XmppException() {
+ }
+
+ /**
+ * Constructs a new {@code Exception} that includes the current stack trace.
+ */
+ public XmppException(Element context) {
+ this.context = context;
+ }
+
+ /**
+ * Constructs a new {@code Exception} with the current stack trace and the
+ * specified cause.
+ *
+ * @param throwable the cause of this exception.
+ */
+ public XmppException(Throwable throwable) {
+ super(throwable);
+ }
+
+ /**
+ * Constructs a new {@code Exception} with the current stack trace and the
+ * specified cause.
+ *
+ * @param throwable the cause of this exception.
+ */
+ public XmppException(Element context, Throwable throwable) {
+ super(throwable);
+ this.context = context;
+ }
+
+ @Override
+ public String getMessage() {
+ if (null != context) {
+ return "Error in XMPP Element. XML element is: " + this.context.toString();
+ } else {
+ return super.getMessage();
+ }
+ }
+
+ public Element getContext() {
+ return context;
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/FileTransferHttp.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/FileTransferHttp.java
new file mode 100644
index 00000000..28f4f870
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/FileTransferHttp.java
@@ -0,0 +1,8 @@
+package de.thedevstack.conversationsplus.xmpp.filetransfer.http;
+
+/**
+ * Created by steckbrief on 21.08.2016.
+ */
+public interface FileTransferHttp {
+ String NAMESPACE = "urn:xmpp:filetransfer:http";
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/delete/DeleteSlotPacketParser.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/delete/DeleteSlotPacketParser.java
new file mode 100644
index 00000000..a6408e9f
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/delete/DeleteSlotPacketParser.java
@@ -0,0 +1,30 @@
+package de.thedevstack.conversationsplus.xmpp.filetransfer.http.delete;
+
+import de.thedevstack.conversationsplus.xmpp.IqPacketParser;
+import de.thedevstack.conversationsplus.xmpp.exceptions.UnexpectedIqPacketTypeException;
+import de.thedevstack.conversationsplus.xmpp.exceptions.XmppException;
+import de.thedevstack.conversationsplus.xmpp.filetransfer.http.FileTransferHttp;
+import de.thedevstack.conversationsplus.xmpp.utils.ErrorIqPacketExceptionHelper;
+
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.stanzas.IqPacket;
+
+/**
+ * Created by steckbrief on 21.08.2016.
+ */
+public class DeleteSlotPacketParser extends IqPacketParser {
+ public static String parseDeleteToken(IqPacket packet) throws XmppException {
+ String deletetoken = null;
+ if (packet.getType() == IqPacket.TYPE.RESULT) {
+ Element slot = findRequiredChild(packet, "slot", FileTransferHttp.NAMESPACE);
+
+ deletetoken = findRequiredChildContent(slot, "deletetoken");
+ } else if (packet.getType() == IqPacket.TYPE.ERROR) {
+ ErrorIqPacketExceptionHelper.throwIqErrorException(packet);
+ } else {
+ throw new UnexpectedIqPacketTypeException(packet, packet.getType(), IqPacket.TYPE.RESULT, IqPacket.TYPE.ERROR);
+ }
+
+ return deletetoken;
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/delete/DeleteSlotRequestPacket.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/delete/DeleteSlotRequestPacket.java
new file mode 100644
index 00000000..67deeb6f
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/delete/DeleteSlotRequestPacket.java
@@ -0,0 +1,35 @@
+package de.thedevstack.conversationsplus.xmpp.filetransfer.http.delete;
+
+import de.thedevstack.conversationsplus.xmpp.filetransfer.http.FileTransferHttp;
+
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.stanzas.IqPacket;
+
+/**
+ * Created by steckbrief on 21.08.2016.
+ */
+public class DeleteSlotRequestPacket extends IqPacket {
+ public static final String ELEMENT_NAME = "request";
+ public static final String FILEURL_ELEMENT_NAME = "fileurl";
+ private Element requestElement;
+ private String fileurl;
+
+ private DeleteSlotRequestPacket() {
+ super(TYPE.GET);
+ this.requestElement = super.addChild(DeleteSlotRequestPacket.ELEMENT_NAME, FileTransferHttp.NAMESPACE);
+ this.requestElement.setAttribute("type", "delete");
+ }
+
+ public DeleteSlotRequestPacket(String fileurl) {
+ this();
+ this.setFileURL(fileurl);
+ }
+
+ public void setFileURL(String fileurl) {
+ if (null == fileurl || fileurl.isEmpty()) {
+ throw new IllegalArgumentException("fileurl must not be null or empty.");
+ }
+ this.fileurl = fileurl;
+ this.requestElement.addChild(FILEURL_ELEMENT_NAME).setContent(fileurl);
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/delete/FileTransferHttpDeleteSlotRequestPacketGenerator.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/delete/FileTransferHttpDeleteSlotRequestPacketGenerator.java
new file mode 100644
index 00000000..fa0f7a34
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/delete/FileTransferHttpDeleteSlotRequestPacketGenerator.java
@@ -0,0 +1,39 @@
+package de.thedevstack.conversationsplus.xmpp.filetransfer.http.delete;
+
+import eu.siacs.conversations.xmpp.jid.Jid;
+import eu.siacs.conversations.xmpp.stanzas.IqPacket;
+
+/**
+ * Created by steckbrief on 21.08.2016.
+ */
+public final class FileTransferHttpDeleteSlotRequestPacketGenerator {
+ /**
+ * Generates the IqPacket to request a slot to delete a file previously uploaded via http upload.
+ * The attributes from and id are not set in here - this is added while sending the packet.
+ * <pre>
+ * <iq from='romeo@montague.tld/garden'
+ * id='step_01'
+ * to='upload.montague.tld'
+ * type='get'>
+ * <request type='delete' xmlns='urn:xmpp:filetransfer:http'>
+ * <fileurl>http://upload.montague.tld/files/1e56ee17-ee4c-4a9c-aedd-cb09cb3984a7/my_juliet.png</fileurl>
+ * </request>
+ * </iq>
+ * </pre>
+ * @param host the jid of the host to request a slot from
+ * @param fileurl the URL of the file to be deleted
+ * @return the IqPacket
+ */
+ public static IqPacket generate(Jid host, String fileurl) {
+ DeleteSlotRequestPacket packet = new DeleteSlotRequestPacket(fileurl);
+ packet.setTo(host);
+ return packet;
+ }
+
+ /**
+ * Utility class - avoid instantiation
+ */
+ private FileTransferHttpDeleteSlotRequestPacketGenerator() {
+ // Helper class - avoid instantiation
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/HttpUpload.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/HttpUpload.java
new file mode 100644
index 00000000..3bcbd219
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/HttpUpload.java
@@ -0,0 +1,9 @@
+package de.thedevstack.conversationsplus.xmpp.filetransfer.http.upload;
+
+/**
+ *
+ */
+public interface HttpUpload {
+ String NAMESPACE = "urn:xmpp:http:upload";
+ String DEFAULT_MIME_TYPE = "application/octet-stream";
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/HttpUploadRequestSlotPacketGenerator.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/HttpUploadRequestSlotPacketGenerator.java
new file mode 100644
index 00000000..915cf9a7
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/HttpUploadRequestSlotPacketGenerator.java
@@ -0,0 +1,46 @@
+package de.thedevstack.conversationsplus.xmpp.filetransfer.http.upload;
+
+import eu.siacs.conversations.xmpp.jid.Jid;
+import eu.siacs.conversations.xmpp.stanzas.IqPacket;
+
+/**
+ * Generates the IQ Packets for requesting a http upload slot
+ * as defined in XEP-0363.
+ * @see <a href="http://xmpp.org/extensions/xep-0363.html">http://xmpp.org/extensions/xep-0363.html</a>
+ */
+public final class HttpUploadRequestSlotPacketGenerator {
+ /**
+ * Generates the IqPacket to request a http upload slot.
+ * The attributes from and id are not set in here - this is added while sending the packet.
+ * <pre>
+ * <iq from='romeo@montague.tld/garden'
+ * id='step_03'
+ * to='upload.montague.tld'
+ * type='get'>
+ * <request xmlns='urn:xmpp:http:upload'>
+ * <filename>my_juliet.png</filename>
+ * <size>23456</size>
+ * <content-type>image/jpeg</content-type>
+ * </request>
+ * </iq>
+ * </pre>
+ * @param host the jid of the host to request a slot from
+ * @param filename the filename of the file which will be transferred
+ * @param filesize the filesize of the file which will be transferred
+ * @param mime the mime type of the file which will be transferred - <code>optional</code> and therefore nullable
+ * @return the IqPacket
+ */
+ public static IqPacket generate(Jid host, String filename, long filesize, String mime) {
+ SlotRequestPacket packet = new SlotRequestPacket(filename, filesize);
+ packet.setTo(host);
+ packet.setMime((mime == null) ? HttpUpload.DEFAULT_MIME_TYPE : mime);
+ return packet;
+ }
+
+ /**
+ * Utility class - avoid instantiation
+ */
+ private HttpUploadRequestSlotPacketGenerator() {
+ // Helper class - avoid instantiation
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/HttpUploadSlot.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/HttpUploadSlot.java
new file mode 100644
index 00000000..1e320afe
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/HttpUploadSlot.java
@@ -0,0 +1,22 @@
+package de.thedevstack.conversationsplus.xmpp.filetransfer.http.upload;
+
+/**
+ *
+ */
+public class HttpUploadSlot {
+ private final String getUrl;
+ private final String putUrl;
+
+ public HttpUploadSlot(String getUrl, String putUrl) {
+ this.getUrl = getUrl;
+ this.putUrl = putUrl;
+ }
+
+ public String getGetUrl() {
+ return this.getUrl;
+ }
+
+ public String getPutUrl() {
+ return this.putUrl;
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/SlotPacketParser.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/SlotPacketParser.java
new file mode 100644
index 00000000..40e7db96
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/SlotPacketParser.java
@@ -0,0 +1,31 @@
+package de.thedevstack.conversationsplus.xmpp.filetransfer.http.upload;
+
+import de.thedevstack.conversationsplus.xmpp.IqPacketParser;
+import de.thedevstack.conversationsplus.xmpp.exceptions.UnexpectedIqPacketTypeException;
+import de.thedevstack.conversationsplus.xmpp.exceptions.XmppException;
+import de.thedevstack.conversationsplus.xmpp.utils.ErrorIqPacketExceptionHelper;
+
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.stanzas.IqPacket;
+
+/**
+ *
+ */
+public final class SlotPacketParser extends IqPacketParser {
+ public static HttpUploadSlot parseGetAndPutUrl(IqPacket packet) throws XmppException {
+ HttpUploadSlot httpUploadSlot = null;
+ if (packet.getType() == IqPacket.TYPE.RESULT) {
+ Element slot = findRequiredChild(packet, "slot", HttpUpload.NAMESPACE);
+
+ String getUrl = findRequiredChildContent(slot, "get");
+ String putUrl = findRequiredChildContent(slot, "put");
+
+ httpUploadSlot = new HttpUploadSlot(getUrl, putUrl);
+ } else if (packet.getType() == IqPacket.TYPE.ERROR) {
+ ErrorIqPacketExceptionHelper.throwIqErrorException(packet);
+ } else {
+ throw new UnexpectedIqPacketTypeException(packet, packet.getType(), IqPacket.TYPE.RESULT, IqPacket.TYPE.ERROR);
+ }
+ return httpUploadSlot;
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/SlotRequestPacket.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/SlotRequestPacket.java
new file mode 100644
index 00000000..30c5db79
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/filetransfer/http/upload/SlotRequestPacket.java
@@ -0,0 +1,53 @@
+package de.thedevstack.conversationsplus.xmpp.filetransfer.http.upload;
+
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.stanzas.IqPacket;
+
+/**
+ *
+ */
+public class SlotRequestPacket extends IqPacket {
+ public static final String ELEMENT_NAME = "request";
+ public static final String FILENAME_ELEMENT_NAME = "filename";
+ public static final String FILESIZE_ELEMENT_NAME = "size";
+ public static final String MIME_ELEMENT_NAME = "content-type";
+ private Element requestElement;
+ private String filename;
+ private long filesize;
+ private String mime;
+
+ private SlotRequestPacket() {
+ super(TYPE.GET);
+ this.requestElement = super.addChild(SlotRequestPacket.ELEMENT_NAME, HttpUpload.NAMESPACE);
+ }
+
+ public SlotRequestPacket(String filename, long filesize) {
+ this();
+ this.setFilename(filename);
+ this.setFilesize(filesize);
+ }
+
+ public void setFilename(String filename) {
+ if (null == filename || filename.isEmpty()) {
+ throw new IllegalArgumentException("filename must not be null or empty.");
+ }
+ this.filename = filename;
+ this.requestElement.addChild(FILENAME_ELEMENT_NAME).setContent(filename);
+ }
+
+ public void setFilesize(long filesize) {
+ if (0 >= filesize) {
+ throw new IllegalArgumentException("filesize must not be null or empty.");
+ }
+ this.filesize = filesize;
+ this.requestElement.addChild(FILESIZE_ELEMENT_NAME).setContent(String.valueOf(filesize));
+ }
+
+ public void setMime(String mime) {
+ if (null == mime || mime.isEmpty()) {
+ throw new IllegalArgumentException("mime type must not be null or empty.");
+ }
+ this.mime = mime;
+ this.requestElement.addChild(MIME_ELEMENT_NAME).setContent(mime);
+ }
+}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/httpuploadim/HttpUploadHint.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/httpuploadim/HttpUploadHint.java
index 7868a2f5..00bd1158 100644
--- a/src/main/java/de/thedevstack/conversationsplus/xmpp/httpuploadim/HttpUploadHint.java
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/httpuploadim/HttpUploadHint.java
@@ -3,10 +3,20 @@ package de.thedevstack.conversationsplus.xmpp.httpuploadim;
import eu.siacs.conversations.xml.Element;
/**
- * Created by steckbrief on 17.04.2016.
+ * Representation of the HttpUploadHint.
+ * <pre>
+ * <httpupload xmlns="urn:xmpp:hints"/>
+ * </pre>
*/
public class HttpUploadHint extends Element {
+ /**
+ * The namespace of message processing hints as defined in XEP-0334.
+ * @see <a href="http://xmpp.org/extensions/xep-0334.html">http://xmpp.org/extensions/xep-0334.html</a>
+ */
public static final String NAMESPACE = "urn:xmpp:hints";
+ /**
+ * The element name of the hint for an http upload.
+ */
public static final String ELEMENT_NAME = "httpupload";
public HttpUploadHint() {
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacket.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacket.java
index 961277cb..31186191 100644
--- a/src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacket.java
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacket.java
@@ -4,28 +4,69 @@ import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
/**
- * Created by tzur on 15.01.2016.
+ * Representation of a PubSub IQ packet as defined in XEP-0060.
+ * <br>One example:
+ * <pre>
+ * <iq type='get'
+ * from='romeo@montague.lit'
+ * to='pubsub.shakespeare.lit'
+ * id='items1'>
+ * <pubsub xmlns='http://jabber.org/protocol/pubsub'>
+ * <items node='urn:xmpp:pubsub:subscription'/>
+ * </pubsub>
+ * </iq>
+ * </pre>
+ * @see <a href="http://xmpp.org/extensions/xep-0330.html">http://xmpp.org/extensions/xep-0060.html</a>
*/
public class PubSubPacket extends IqPacket {
+ /**
+ * The namespace of pubsub.
+ */
public static final String NAMESPACE = "http://jabber.org/protocol/pubsub";
+ /**
+ * The name of the root element.
+ */
public static final String ELEMENT_NAME = "pubsub";
+ /**
+ * The PubSub element - everything which is added to this packet is a child of this element.
+ */
private Element pubSubElement;
+ /**
+ * Instantiate the PubSubPacket for the given type.
+ * @param type the IqPacket.TYPE
+ */
public PubSubPacket(IqPacket.TYPE type) {
super(type);
this.pubSubElement = super.addChild(PubSubPacket.ELEMENT_NAME, PubSubPacket.NAMESPACE);
}
+ /**
+ * Adds an element to the PubSub element instead of the IqPacket.
+ * @param child the children to be added
+ * @return the added children
+ */
@Override
public Element addChild(Element child) {
return this.pubSubElement.addChild(child);
}
+ /**
+ * Adds an element to the PubSub element instead of the IqPacket.
+ * @param name name of the children to be added
+ * @return the added children
+ */
@Override
public Element addChild(String name) {
return this.pubSubElement.addChild(name);
}
+ /**
+ * Adds an element to the PubSub element instead of the IqPacket.
+ * @param name name of the children to be added
+ * @param xmlns namespace of the children to be added
+ * @return the added children
+ */
@Override
public Element addChild(String name, String xmlns) {
return this.pubSubElement.addChild(name, xmlns);
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacketGenerator.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacketGenerator.java
index 398ec032..f72bf777 100644
--- a/src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacketGenerator.java
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacketGenerator.java
@@ -4,10 +4,32 @@ import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
/**
- * Created by tzur on 15.01.2016.
+ * Generates the IQ packets for Pubsub Subscription as defined in XEP-0060.
+ * @see <a href="http://xmpp.org/extensions/xep-0060.html">http://xmpp.org/extensions/xep-0060.html</a>
*/
public final class PubSubPacketGenerator {
+ /**
+ * Generates a pubsub publish packet.
+ * The attributes from and id are not set in here - this is added while sending the packet.
+ * <pre>
+ * <iq type='set'
+ * from='hamlet@denmark.lit/blogbot'
+ * to='pubsub.shakespeare.lit'
+ * id='publish1'>
+ * <pubsub xmlns='http://jabber.org/protocol/pubsub'>
+ * <publish node='princely_musings'>
+ * <item id='bnd81g37d61f49fgn581'>
+ * ...
+ * </item>
+ * </publish>
+ * </pubsub>
+ * </iq>
+ * </pre>
+ * @param nodeName the name of the publish node
+ * @param item the item element
+ * @return the generated PubSubPacket
+ */
public static PubSubPacket generatePubSubPublishPacket(String nodeName, Element item) {
final PubSubPacket pubsub = new PubSubPacket(IqPacket.TYPE.SET);
final Element publish = pubsub.addChild("publish");
@@ -16,6 +38,25 @@ public final class PubSubPacketGenerator {
return pubsub;
}
+ /**
+ * Generates a pubsub retrieve packet.
+ * The attributes from and id are not set in here - this is added while sending the packet.
+ * <pre>
+ * <iq type='get'
+ * from='romeo@montague.lit/home'
+ * to='juliet@capulet.lit'
+ * id='retrieve1'>
+ * <pubsub xmlns='http://jabber.org/protocol/pubsub'>
+ * <items node='urn:xmpp:avatar:data'>
+ * <item id='111f4b3c50d7b0df729d299bc6f8e9ef9066971f'/>
+ * </items>
+ * </pubsub>
+ * </iq>
+ * </pre>
+ * @param nodeName
+ * @param item
+ * @return
+ */
public static PubSubPacket generatePubSubRetrievePacket(String nodeName, Element item) {
final PubSubPacket pubsub = new PubSubPacket(IqPacket.TYPE.GET);
final Element items = pubsub.addChild("items");
@@ -26,6 +67,9 @@ public final class PubSubPacketGenerator {
return pubsub;
}
+ /**
+ * Utility class - avoid instantiation
+ */
private PubSubPacketGenerator() {
// Avoid instantiation
}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacketParser.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacketParser.java
index 394fb5b2..c8df0d5e 100644
--- a/src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacketParser.java
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/pubsub/PubSubPacketParser.java
@@ -4,16 +4,28 @@ import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
/**
- * Created by tzur on 15.01.2016.
+ * Parses the IQ Packets for handling pubsub
+ * as defined in XEP-0060.
+ * @see <a href="http://xmpp.org/extensions/xep-0060.html">http://xmpp.org/extensions/xep-0060.html</a>
*/
-public class PubSubPacketParser {
+public final class PubSubPacketParser {
+ /**
+ * Finds the pubsub element within an IQ packet.
+ * @param packet the retrieved IQ packet
+ * @return the {@value PubSubPacket#ELEMENT_NAME} Element or <code>null</code> if the IqPacket is null or the IQ packet does not contain an pubsub element.
+ */
public static Element findPubSubPacket(IqPacket packet){
if (null == packet) {
return null;
}
- return packet.findChild("pubsub", "http://jabber.org/protocol/pubsub");
+ return packet.findChild(PubSubPacket.ELEMENT_NAME, PubSubPacket.NAMESPACE);
}
+ /**
+ * Finds the "items" element within an pubSubPacket element.
+ * @param pubSubPacket the pubSubPacket element
+ * @return the items Element or <code>null</code> if the pubSubPacket is null or the pubSubPacket does not contain an items element.
+ */
public static Element findItemsFromPubSubElement(Element pubSubPacket) {
if (null == pubSubPacket) {
return null;
@@ -21,7 +33,19 @@ public class PubSubPacketParser {
return pubSubPacket.findChild("items");
}
+ /**
+ * Finds the "items" element within an pubSubPacket element.
+ * @param packet the IqPacket element
+ * @return the items Element or <code>null</code> if the IqPacket is null or the IQ packet does not contain an pubsub element with an items element.
+ */
public static Element findItems(IqPacket packet) {
return PubSubPacketParser.findItemsFromPubSubElement(PubSubPacketParser.findPubSubPacket(packet));
}
+
+ /**
+ * Utility class - avoid instantiation
+ */
+ private PubSubPacketParser() {
+ // Avoid instantiation
+ }
}
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/utils/ErrorIqPacketExceptionHelper.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/utils/ErrorIqPacketExceptionHelper.java
new file mode 100644
index 00000000..15771248
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/utils/ErrorIqPacketExceptionHelper.java
@@ -0,0 +1,45 @@
+package de.thedevstack.conversationsplus.xmpp.utils;
+
+import de.thedevstack.conversationsplus.xmpp.IqPacketParser;
+import de.thedevstack.conversationsplus.xmpp.exceptions.BadRequestIqErrorException;
+import de.thedevstack.conversationsplus.xmpp.exceptions.InternalServerErrorException;
+import de.thedevstack.conversationsplus.xmpp.exceptions.IqPacketErrorException;
+import de.thedevstack.conversationsplus.xmpp.exceptions.ServiceUnavailableException;
+import de.thedevstack.conversationsplus.xmpp.exceptions.UndefinedConditionException;
+
+import eu.siacs.conversations.xml.Element;
+
+/**
+ * Created by steckbrief on 22.08.2016.
+ */
+public final class ErrorIqPacketExceptionHelper {
+ private final static String ERROR_NAMESPACE = "urn:ietf:params:xml:ns:xmpp-stanzas";
+
+ public static void throwIqErrorException(Element packet) throws IqPacketErrorException {
+ if (hasErrorElement(packet, "bad-request")) {
+ throw new BadRequestIqErrorException(packet, getErrorText(packet));
+ }
+ if (hasErrorElement(packet, "service-unavailable")) {
+ throw new ServiceUnavailableException(packet, getErrorText(packet));
+ }
+ if (hasErrorElement(packet, "internal-server-error")) {
+ throw new InternalServerErrorException(packet, getErrorText(packet));
+ }
+ if (hasErrorElement(packet, "undefined-condition")) {
+ throw new UndefinedConditionException(packet, getErrorText(packet));
+ }
+ throw new IqPacketErrorException(packet, "Unknown error packet.");
+ }
+
+ private static boolean hasErrorElement(Element packet, String elementName) {
+ return null != IqPacketParser.findChild(packet, elementName, ERROR_NAMESPACE);
+ }
+
+ private static String getErrorText(Element packet) {
+ return IqPacketParser.findChildContent(packet, "text", ERROR_NAMESPACE);
+ }
+
+ private ErrorIqPacketExceptionHelper() {
+
+ }
+}