From 4addb6419080db814094ab501d69111adffeb5be Mon Sep 17 00:00:00 2001 From: Tarun Gupta Date: Tue, 16 Jun 2015 03:50:01 +0530 Subject: Add IBB Element. Adds IBB Element, its Parser and Serializer. License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details. Test-Information: Tests added for both IBB Parser and Serializer, which passes. Change-Id: I0f2657de89d5395652c62ee5d5a88fbe9acb25e9 diff --git a/src/com/isode/stroke/elements/IBB.java b/src/com/isode/stroke/elements/IBB.java new file mode 100644 index 0000000..93864da --- /dev/null +++ b/src/com/isode/stroke/elements/IBB.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +package com.isode.stroke.elements; + +import com.isode.stroke.elements.Payload; +import java.util.Vector; +import com.isode.stroke.base.NotNull; +import com.isode.stroke.base.ByteArray; + +public class IBB extends Payload { + + public enum Action { + Open, + Close, + Data + }; + + public enum StanzaType { + IQStanza, + MessageStanza + }; + + private Action action; + private String streamID = ""; + private ByteArray data = new ByteArray(); + private StanzaType stanzaType; + private int blockSize; + private int sequenceNumber; + + /** + * Default Constructor. + */ + public IBB() { + this(Action.Open, ""); + } + + /** + * Parameterized Constructor + * @param action, NotNull. + */ + public IBB(Action action) { + this(action, ""); + } + + /** + * Parameterized Constructor + * @param streamID, NotNull. + * @param action, NotNull. + */ + public IBB(Action action, String streamID) { + NotNull.exceptIfNull(action, "action"); + NotNull.exceptIfNull(streamID, "streamID"); + this.action = action; + this.streamID = streamID; + this.stanzaType = StanzaType.IQStanza; + this.blockSize = -1; + this.sequenceNumber = -1; + } + + /** + * @param streamID, NotNull. + * @param blockSize. + * @return IBB Object. + */ + public static IBB createIBBOpen(String streamID, int blockSize) { + NotNull.exceptIfNull(streamID, "streamID"); + IBB result = new IBB(Action.Open, streamID); + result.setBlockSize(blockSize); + return result; + } + + /** + * @param streamID, NotNull. + * @param sequenceNumber. + * @param data, NotNull. + * @return IBB Object. + */ + public static IBB createIBBData(String streamID, int sequenceNumber, ByteArray data) { + NotNull.exceptIfNull(streamID, "streamID"); + NotNull.exceptIfNull(data, "data"); + IBB result = new IBB(Action.Data, streamID); + result.setSequenceNumber(sequenceNumber); + result.setData(data); + return result; + } + + + /** + * @param streamID, NotNull. + * @return IBB Object. + */ + public static IBB createIBBClose(String streamID) { + return new IBB(Action.Close, streamID); + } + + /** + * @param action, Not Null. + */ + public void setAction(Action action) { + NotNull.exceptIfNull(action, "action"); + this.action = action; + } + + /** + * @return action, Not Null. + */ + public Action getAction() { + return action; + } + + /** + * @param stanzaType, Not Null. + */ + public void setStanzaType(StanzaType stanzaType) { + NotNull.exceptIfNull(stanzaType, "stanzaType"); + this.stanzaType = stanzaType; + } + + /** + * @return stanzaType, Not Null. + */ + public StanzaType getStanzaType() { + return stanzaType; + } + + /** + * @param id, Not Null. + */ + public void setStreamID(String id) { + NotNull.exceptIfNull(id, "id"); + streamID = id; + } + + /** + * @return id, Not Null. + */ + public String getStreamID() { + return streamID; + } + + /** + * @return data, Not Null. + */ + public ByteArray getData() { + return data; + } + + /** + * @param data, Not Null. + */ + public void setData(ByteArray data) { + NotNull.exceptIfNull(data, "data"); + this.data = data; + } + + /** + * @return blockSize. + */ + public int getBlockSize() { + return blockSize; + } + + /** + * @param blockSize. + */ + public void setBlockSize(int blockSize) { + this.blockSize = blockSize; + } + + /** + * @return sequenceNumber. + */ + public int getSequenceNumber() { + return sequenceNumber; + } + + /** + * @param sequenceNumber. + */ + public void setSequenceNumber(int i) { + sequenceNumber = i; + } +} \ No newline at end of file diff --git a/src/com/isode/stroke/parser/payloadparsers/FullPayloadParserFactoryCollection.java b/src/com/isode/stroke/parser/payloadparsers/FullPayloadParserFactoryCollection.java index 5bdf421..84a0b43 100644 --- a/src/com/isode/stroke/parser/payloadparsers/FullPayloadParserFactoryCollection.java +++ b/src/com/isode/stroke/parser/payloadparsers/FullPayloadParserFactoryCollection.java @@ -27,6 +27,7 @@ public class FullPayloadParserFactoryCollection extends PayloadParserFactoryColl addFactory(new GenericPayloadParserFactory("delegate", "http://isode.com/iq_delegation", IsodeIQDelegationParser.class)); addFactory(new GenericPayloadParserFactory("storage", "storage:bookmarks", StorageParser.class)); addFactory(new RosterParserFactory()); + addFactory(new GenericPayloadParserFactory("data", "http://jabber.org/protocol/ibb", IBBParser.class)); addFactory(new GenericPayloadParserFactory("query", "http://jabber.org/protocol/disco#info", DiscoInfoParser.class)); addFactory(new GenericPayloadParserFactory("query", "http://jabber.org/protocol/disco#items", DiscoItemsParser.class)); addFactory(new GenericPayloadParserFactory ("c", "http://jabber.org/protocol/caps", CapsInfoParser.class)); diff --git a/src/com/isode/stroke/parser/payloadparsers/IBBParser.java b/src/com/isode/stroke/parser/payloadparsers/IBBParser.java new file mode 100644 index 0000000..cb405af --- /dev/null +++ b/src/com/isode/stroke/parser/payloadparsers/IBBParser.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +package com.isode.stroke.parser.payloadparsers; + +import com.isode.stroke.parser.GenericPayloadParser; +import com.isode.stroke.parser.AttributeMap; +import com.isode.stroke.elements.IBB; +import com.isode.stroke.stringcodecs.Base64; +import com.isode.stroke.base.NotNull; +import com.isode.stroke.base.ByteArray; +import java.util.Vector; + +public class IBBParser extends GenericPayloadParser { + + public IBBParser() { + super(new IBB()); + } + + private final int TopLevel = 0; + private int level; + private String currentText = ""; + + /** + * @param element, NotNull. + * @param ns. + * @param attributes. + */ + @Override + public void handleStartElement(String element, String ns, AttributeMap attributes) { + NotNull.exceptIfNull(element, "element"); + NotNull.exceptIfNull(attributes, "attributes"); + if (level == TopLevel) { + if (element.equals("data")) { + getPayloadInternal().setAction(IBB.Action.Data); + getPayloadInternal().setStreamID(attributes.getAttribute("sid")); + try { + getPayloadInternal().setSequenceNumber(Integer.parseInt(attributes.getAttribute("seq"))); + } + catch (NumberFormatException e) { + + } + } + else if (element.equals("open")) { + getPayloadInternal().setAction(IBB.Action.Open); + getPayloadInternal().setStreamID(attributes.getAttribute("sid")); + if (attributes.getAttribute("stanza").equals("message")) { + getPayloadInternal().setStanzaType(IBB.StanzaType.MessageStanza); + } + else { + getPayloadInternal().setStanzaType(IBB.StanzaType.IQStanza); + } + try { + getPayloadInternal().setBlockSize(Integer.parseInt(attributes.getAttribute("block-size"))); + } + catch (NumberFormatException e) { + + } + } + else if (element.equals("close")) { + getPayloadInternal().setAction(IBB.Action.Close); + getPayloadInternal().setStreamID(attributes.getAttribute("sid")); + } + } + ++level; + } + + /** + * @param element, NotNull. + * @param ns. + */ + @Override + public void handleEndElement(String element, String ns) { + NotNull.exceptIfNull(element, "element"); + --level; + if (level == TopLevel) { + if (element.equals("data")) { + ByteArray data = new ByteArray(currentText); + getPayloadInternal().setData(Base64.decode(data.toString())); + } + } + } + + /** + * @param data, NotNull. + */ + @Override + public void handleCharacterData(String data) { + NotNull.exceptIfNull(data, "data"); + currentText += data; + } +} \ No newline at end of file diff --git a/src/com/isode/stroke/serializer/payloadserializers/FullPayloadSerializerCollection.java b/src/com/isode/stroke/serializer/payloadserializers/FullPayloadSerializerCollection.java index a273fa0..d8f90c3 100644 --- a/src/com/isode/stroke/serializer/payloadserializers/FullPayloadSerializerCollection.java +++ b/src/com/isode/stroke/serializer/payloadserializers/FullPayloadSerializerCollection.java @@ -23,6 +23,7 @@ public class FullPayloadSerializerCollection extends PayloadSerializerCollection //addSerializer(new PrioritySerializer()); addSerializer(new ErrorSerializer()); addSerializer(new InBandRegistrationPayloadSerializer()); + addSerializer(new IBBSerializer()); addSerializer(new RosterSerializer()); addSerializer(new MUCPayloadSerializer()); addSerializer(new MUCDestroyPayloadSerializer()); diff --git a/src/com/isode/stroke/serializer/payloadserializers/IBBSerializer.java b/src/com/isode/stroke/serializer/payloadserializers/IBBSerializer.java new file mode 100644 index 0000000..cb2f88c --- /dev/null +++ b/src/com/isode/stroke/serializer/payloadserializers/IBBSerializer.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +package com.isode.stroke.serializer.payloadserializers; + +import com.isode.stroke.serializer.GenericPayloadSerializer; +import com.isode.stroke.serializer.xml.XMLTextNode; +import com.isode.stroke.serializer.xml.XMLElement; +import com.isode.stroke.elements.IBB; +import com.isode.stroke.stringcodecs.Base64; +import com.isode.stroke.base.NotNull; + +public class IBBSerializer extends GenericPayloadSerializer { + + public IBBSerializer() { + super(IBB.class); + } + + public String serializePayload(IBB ibb) { + switch(ibb.getAction()) { + case Data: { + XMLElement ibbElement = new XMLElement("data", "http://jabber.org/protocol/ibb"); + ibbElement.setAttribute("sid", ibb.getStreamID()); + if (ibb.getSequenceNumber() >= 0) { + ibbElement.setAttribute("seq", Integer.toString(ibb.getSequenceNumber())); + } + ibbElement.addNode(new XMLTextNode(Base64.encode(ibb.getData()))); + return ibbElement.serialize(); + } + case Open: { + XMLElement ibbElement = new XMLElement("open", "http://jabber.org/protocol/ibb"); + ibbElement.setAttribute("sid", ibb.getStreamID()); + switch (ibb.getStanzaType()) { + case IQStanza: ibbElement.setAttribute("stanza", "iq"); break; + case MessageStanza: ibbElement.setAttribute("stanza", "message"); break; + } + assert(ibb.getBlockSize() > 0); + ibbElement.setAttribute("block-size", Integer.toString(ibb.getBlockSize())); + return ibbElement.serialize(); + } + case Close: { + XMLElement ibbElement = new XMLElement("close", "http://jabber.org/protocol/ibb"); + ibbElement.setAttribute("sid", ibb.getStreamID()); + return ibbElement.serialize(); + } + } + assert(false); + return ""; + } +} \ No newline at end of file diff --git a/test/com/isode/stroke/parser/payloadparsers/IBBParserTest.java b/test/com/isode/stroke/parser/payloadparsers/IBBParserTest.java new file mode 100644 index 0000000..ddae5c8 --- /dev/null +++ b/test/com/isode/stroke/parser/payloadparsers/IBBParserTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +package com.isode.stroke.parser.payloadparsers; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import org.junit.Test; +import com.isode.stroke.elements.IBB; +import com.isode.stroke.base.ByteArray; +import com.isode.stroke.parser.payloadparsers.IBBParser; +import com.isode.stroke.parser.payloadparsers.PayloadsParserTester; +import com.isode.stroke.eventloop.DummyEventLoop; + +public class IBBParserTest { + + public IBBParserTest() { + + } + + @Test + public void testParse_Data() { + DummyEventLoop eventLoop = new DummyEventLoop(); + PayloadsParserTester parser = new PayloadsParserTester(eventLoop); + assertNotNull(parser.parse("\n" + + "\t YWJjZGVmZ2loamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjEyMzQ1\n" + + "\t Njc4OTAK\n" + + "")); + + IBB ibb = (IBB)parser.getPayload(); + assertEquals(ibb.getAction(), IBB.Action.Data); + assertEquals(new ByteArray("abcdefgihjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\n"), ibb.getData()); + assertEquals(4, ibb.getSequenceNumber()); + } +} \ No newline at end of file diff --git a/test/com/isode/stroke/serializer/payloadserializers/IBBSerializerTest.java b/test/com/isode/stroke/serializer/payloadserializers/IBBSerializerTest.java new file mode 100644 index 0000000..6244277 --- /dev/null +++ b/test/com/isode/stroke/serializer/payloadserializers/IBBSerializerTest.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +package com.isode.stroke.serializer.payloadserializers; + +import static org.junit.Assert.assertEquals; +import org.junit.Test; +import com.isode.stroke.serializer.payloadserializers.IBBSerializer; +import com.isode.stroke.elements.IBB; +import com.isode.stroke.base.ByteArray; + +public class IBBSerializerTest { + + /** + * Default Constructor. + */ + public IBBSerializerTest() { + + } + + @Test + public void testSerialize_data() { + IBBSerializer testling = new IBBSerializer(); + IBB ibb = new IBB(); + ibb.setAction(IBB.Action.Data); + ibb.setData(new ByteArray("abcdefgihjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\n")); + ibb.setSequenceNumber(4); + String expectedResult = "" + + "YWJjZGVmZ2loamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjEyMzQ1" + + "Njc4OTAK" + + ""; + assertEquals(expectedResult, testling.serialize(ibb)); + } +} \ No newline at end of file -- cgit v0.10.2-6-g49f6