diff options
author | steckbrief <steckbrief@chefmail.de> | 2016-10-20 19:45:26 +0200 |
---|---|---|
committer | steckbrief <steckbrief@chefmail.de> | 2016-10-20 19:45:26 +0200 |
commit | 59e861ee6904296cbe8dd43c4a29513c2e928981 (patch) | |
tree | a3bf768814ece1c377caefca35bc535c758a47c5 /src/main/java/de/thedevstack/conversationsplus/xmpp | |
parent | 2860088f0ea1cd5753756861c71cc7c118094f32 (diff) | |
parent | 9ec29bb1dcf664fea606105b7e700641a4b44ae4 (diff) |
Merge remote-tracking branch 'remotes/origin/trz/rename' into trz/rebase
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/xmpp')
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() { + + } +} |