diff options
author | steckbrief <steckbrief@chefmail.de> | 2016-08-22 08:55:37 +0200 |
---|---|---|
committer | steckbrief <steckbrief@chefmail.de> | 2016-08-22 08:55:37 +0200 |
commit | 77d0c1110a8ae7a980f1c4420d719af803990da8 (patch) | |
tree | 20d3ce434f3c6d740141727d4c143ea5f027a646 /src/main/java/de/thedevstack/conversationsplus/xmpp | |
parent | 97100834a5bcb08f2fdf2eb6c580d3ceeb8b6b2f (diff) | |
parent | f45ad10b1baaf09fd4a40d6b63d1cd093623eedc (diff) |
Merge remote-tracking branch 'remotes/origin/filetransfer'
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/xmpp')
18 files changed, 471 insertions, 23 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/AbstractIqPacketParser.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/AbstractIqPacketParser.java new file mode 100644 index 00000000..d777cb64 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/AbstractIqPacketParser.java @@ -0,0 +1,43 @@ +package de.thedevstack.conversationsplus.xmpp; + +import de.thedevstack.conversationsplus.xml.Element; +import de.thedevstack.conversationsplus.xmpp.exceptions.MissingRequiredContentException; +import de.thedevstack.conversationsplus.xmpp.exceptions.MissingRequiredElementException; + +/** + * + */ +public abstract class AbstractIqPacketParser { + protected static Element findRequiredChild(Element element, String elementName, String namespace) throws MissingRequiredElementException { + if (null == element) { + return null; + } + Element child = element.findChild(elementName, namespace); + if (child == null) { + throw new MissingRequiredElementException(elementName, namespace, element); + } + return child; + } + + protected 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; + } + + protected static String findRequiredChildContent(Element element, String elementName, String namespace) throws MissingRequiredContentException { + if (null == element) { + return null; + } + String childContent = element.findChildContent(elementName, namespace); + if (null == childContent) { + throw new MissingRequiredContentException(elementName, namespace, element); + } + return childContent; + } +} diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/XmppConnection.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/XmppConnection.java index a89f308f..c5a8fe3b 100644 --- a/src/main/java/de/thedevstack/conversationsplus/xmpp/XmppConnection.java +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/XmppConnection.java @@ -2,7 +2,6 @@ package de.thedevstack.conversationsplus.xmpp; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.SystemClock; import android.security.KeyChain; @@ -50,6 +49,7 @@ import javax.net.ssl.X509TrustManager; import de.duenndns.ssl.MemorizingTrustManager; import de.thedevstack.android.logcat.Logging; +import de.thedevstack.conversationsplus.ConversationsPlusApplication; import de.thedevstack.conversationsplus.ConversationsPlusPreferences; import de.thedevstack.conversationsplus.dto.SrvRecord; import de.thedevstack.conversationsplus.Config; @@ -199,8 +199,7 @@ public class XmppConnection implements Runnable { public XmppConnection(final Account account, final XmppConnectionService service) { this.account = account; - this.wakeLock = service.getPowerManager().newWakeLock( - PowerManager.PARTIAL_WAKE_LOCK, account.getJid().toBareJid().toString()); + this.wakeLock = ConversationsPlusApplication.createPartialWakeLock(account.getJid().toBareJid().toString()); tagWriter = new TagWriter(); mXmppConnectionService = service; } @@ -382,14 +381,14 @@ public class XmppConnection implements Runnable { private TlsFactoryVerifier getTlsFactoryVerifier() throws NoSuchAlgorithmException, KeyManagementException, IOException { final SSLContext sc = SSLSocketHelper.getSSLContext(); - MemorizingTrustManager trustManager = this.mXmppConnectionService.getMemorizingTrustManager(); + MemorizingTrustManager trustManager = ConversationsPlusApplication.getMemorizingTrustManager(); KeyManager[] keyManager; if (account.getPrivateKeyAlias() != null && account.getPassword().isEmpty()) { keyManager = new KeyManager[]{mKeyManager}; } else { keyManager = null; } - sc.init(keyManager, new X509TrustManager[]{mInteractive ? trustManager : trustManager.getNonInteractive()}, mXmppConnectionService.getRNG()); + sc.init(keyManager, new X509TrustManager[]{mInteractive ? trustManager : trustManager.getNonInteractive()}, ConversationsPlusApplication.getSecureRandom()); final SSLSocketFactory factory = sc.getSocketFactory(); final HostnameVerifier verifier; if (mInteractive) { @@ -737,13 +736,13 @@ public class XmppConnection implements Runnable { final Element auth = new Element("auth"); auth.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl"); if (mechanisms.contains("EXTERNAL") && account.getPrivateKeyAlias() != null) { - saslMechanism = new External(tagWriter, account, mXmppConnectionService.getRNG()); + saslMechanism = new External(tagWriter, account, ConversationsPlusApplication.getSecureRandom()); } else if (mechanisms.contains("SCRAM-SHA-1")) { - saslMechanism = new ScramSha1(tagWriter, account, mXmppConnectionService.getRNG()); + saslMechanism = new ScramSha1(tagWriter, account, ConversationsPlusApplication.getSecureRandom()); } else if (mechanisms.contains("PLAIN")) { saslMechanism = new Plain(tagWriter, account); } else if (mechanisms.contains("DIGEST-MD5")) { - saslMechanism = new DigestMd5(tagWriter, account, mXmppConnectionService.getRNG()); + saslMechanism = new DigestMd5(tagWriter, account, ConversationsPlusApplication.getSecureRandom()); } if (saslMechanism != null) { final JSONObject keys = account.getKeys(); @@ -1171,7 +1170,7 @@ public class XmppConnection implements Runnable { } private String nextRandomId() { - return new BigInteger(50, mXmppConnectionService.getRNG()).toString(32); + return new BigInteger(50, ConversationsPlusApplication.getSecureRandom()).toString(32); } public String sendIqPacket(final IqPacket packet, final OnIqPacketReceived callback) { 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..8b21cb9c --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/MissingRequiredContentException.java @@ -0,0 +1,26 @@ +package de.thedevstack.conversationsplus.xmpp.exceptions; + +import de.thedevstack.conversationsplus.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..8c8162ef --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/MissingRequiredElementException.java @@ -0,0 +1,26 @@ +package de.thedevstack.conversationsplus.xmpp.exceptions; + +import de.thedevstack.conversationsplus.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/UnexpectedIqPacketTypeException.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/UnexpectedIqPacketTypeException.java new file mode 100644 index 00000000..333f5dca --- /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 de.thedevstack.conversationsplus.xml.Element; +import de.thedevstack.conversationsplus.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..8c692f5b --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/exceptions/XmppException.java @@ -0,0 +1,56 @@ +package de.thedevstack.conversationsplus.xmpp.exceptions; + +import de.thedevstack.conversationsplus.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/httpupload/HttpUpload.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/httpupload/HttpUpload.java new file mode 100644 index 00000000..28cba280 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/httpupload/HttpUpload.java @@ -0,0 +1,9 @@ +package de.thedevstack.conversationsplus.xmpp.httpupload; + +/** + * + */ +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/httpupload/HttpUploadRequestSlotPacketGenerator.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/httpupload/HttpUploadRequestSlotPacketGenerator.java new file mode 100644 index 00000000..59851417 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/httpupload/HttpUploadRequestSlotPacketGenerator.java @@ -0,0 +1,46 @@ +package de.thedevstack.conversationsplus.xmpp.httpupload; + +import de.thedevstack.conversationsplus.xmpp.jid.Jid; +import de.thedevstack.conversationsplus.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/httpupload/HttpUploadSlot.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/httpupload/HttpUploadSlot.java new file mode 100644 index 00000000..14fe5103 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/httpupload/HttpUploadSlot.java @@ -0,0 +1,22 @@ +package de.thedevstack.conversationsplus.xmpp.httpupload; + +/** + * + */ +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/httpupload/SlotPacketParser.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/httpupload/SlotPacketParser.java new file mode 100644 index 00000000..0630449a --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/httpupload/SlotPacketParser.java @@ -0,0 +1,27 @@ +package de.thedevstack.conversationsplus.xmpp.httpupload; + +import de.thedevstack.conversationsplus.xml.Element; +import de.thedevstack.conversationsplus.xmpp.AbstractIqPacketParser; +import de.thedevstack.conversationsplus.xmpp.exceptions.UnexpectedIqPacketTypeException; +import de.thedevstack.conversationsplus.xmpp.exceptions.XmppException; +import de.thedevstack.conversationsplus.xmpp.stanzas.IqPacket; + +/** + * + */ +public final class SlotPacketParser extends AbstractIqPacketParser { + public static HttpUploadSlot parseGetAndPutUrl(IqPacket packet) throws XmppException { + if (packet.getType() == IqPacket.TYPE.RESULT) { + Element slot = findRequiredChild(packet, "slot", HttpUpload.NAMESPACE); + + String getUrl = findRequiredChildContent(slot, "get"); + String putUrl = findRequiredChildContent(slot, "put"); + + return new HttpUploadSlot(getUrl, putUrl); + } else if (packet.getType() == IqPacket.TYPE.ERROR) { + throw new XmppException(); // Do proper handling of error cases + } else { + throw new UnexpectedIqPacketTypeException(packet, packet.getType(), IqPacket.TYPE.RESULT, IqPacket.TYPE.ERROR); + } + } +} diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/httpupload/SlotRequestPacket.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/httpupload/SlotRequestPacket.java new file mode 100644 index 00000000..d470d2f5 --- /dev/null +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/httpupload/SlotRequestPacket.java @@ -0,0 +1,53 @@ +package de.thedevstack.conversationsplus.xmpp.httpupload; + +import de.thedevstack.conversationsplus.xml.Element; +import de.thedevstack.conversationsplus.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 3e9d7f2b..13fb5ad1 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 de.thedevstack.conversationsplus.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/jingle/JingleConnection.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/jingle/JingleConnection.java index 422bdff0..ca823926 100644 --- a/src/main/java/de/thedevstack/conversationsplus/xmpp/jingle/JingleConnection.java +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/jingle/JingleConnection.java @@ -33,6 +33,7 @@ import de.thedevstack.conversationsplus.persistance.FileBackend; import de.thedevstack.conversationsplus.services.AbstractConnectionManager; import de.thedevstack.conversationsplus.services.XmppConnectionService; import de.thedevstack.conversationsplus.utils.FileUtils; +import de.thedevstack.conversationsplus.utils.XmppConnectionServiceAccessor; import de.thedevstack.conversationsplus.xml.Element; import de.thedevstack.conversationsplus.xmpp.OnIqPacketReceived; import de.thedevstack.conversationsplus.xmpp.jid.Jid; @@ -157,8 +158,7 @@ public class JingleConnection implements Transferable { public JingleConnection(JingleConnectionManager mJingleConnectionManager) { this.mJingleConnectionManager = mJingleConnectionManager; - this.mXmppConnectionService = mJingleConnectionManager - .getXmppConnectionService(); + this.mXmppConnectionService = XmppConnectionServiceAccessor.xmppConnectionService; } public String getSessionId() { diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/jingle/JingleConnectionManager.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/jingle/JingleConnectionManager.java index 2deb79c6..30ed9024 100644 --- a/src/main/java/de/thedevstack/conversationsplus/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/jingle/JingleConnectionManager.java @@ -31,10 +31,6 @@ public class JingleConnectionManager extends AbstractConnectionManager { @SuppressLint("TrulyRandom") private SecureRandom random = new SecureRandom(); - public JingleConnectionManager(XmppConnectionService service) { - super(service); - } - public void deliverPacket(Account account, JinglePacket packet) { if (packet.isAction("session-initiate")) { JingleConnection connection = new JingleConnection(this); diff --git a/src/main/java/de/thedevstack/conversationsplus/xmpp/jingle/JingleSocks5Transport.java b/src/main/java/de/thedevstack/conversationsplus/xmpp/jingle/JingleSocks5Transport.java index 9ea268d5..6480251f 100644 --- a/src/main/java/de/thedevstack/conversationsplus/xmpp/jingle/JingleSocks5Transport.java +++ b/src/main/java/de/thedevstack/conversationsplus/xmpp/jingle/JingleSocks5Transport.java @@ -14,6 +14,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import de.thedevstack.android.logcat.Logging; +import de.thedevstack.conversationsplus.ConversationsPlusApplication; import de.thedevstack.conversationsplus.utils.StreamUtil; import de.thedevstack.conversationsplus.Config; import de.thedevstack.conversationsplus.entities.DownloadableFile; @@ -84,7 +85,7 @@ public class JingleSocks5Transport extends JingleTransport { @Override public void run() { InputStream fileInputStream = null; - final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_send_"+connection.getSessionId()); + final PowerManager.WakeLock wakeLock = ConversationsPlusApplication.createPartialWakeLock("jingle_send_"+connection.getSessionId()); try { wakeLock.acquire(); MessageDigest digest = MessageDigest.getInstance("SHA-1"); @@ -134,7 +135,7 @@ public class JingleSocks5Transport extends JingleTransport { @Override public void run() { OutputStream fileOutputStream = null; - final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_receive_"+connection.getSessionId()); + final PowerManager.WakeLock wakeLock = ConversationsPlusApplication.createPartialWakeLock("jingle_receive_"+connection.getSessionId()); try { wakeLock.acquire(); MessageDigest digest = MessageDigest.getInstance("SHA-1"); 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 fea1383c..fe485de0 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 de.thedevstack.conversationsplus.xml.Element; import de.thedevstack.conversationsplus.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 1eb44b5e..a93c37aa 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 de.thedevstack.conversationsplus.xml.Element; import de.thedevstack.conversationsplus.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 682803c4..0f803b56 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 de.thedevstack.conversationsplus.xml.Element; import de.thedevstack.conversationsplus.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 + } } |