DataPacketExtension.java

  1. /**
  2.  *
  3.  * Copyright the original author or authors
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smackx.bytestreams.ibb.packet;

  18. import org.jivesoftware.smack.packet.ExtensionElement;
  19. import org.jivesoftware.smack.packet.IQ.IQChildElementXmlStringBuilder;
  20. import org.jivesoftware.smack.util.XmlStringBuilder;
  21. import org.jivesoftware.smack.util.stringencoder.Base64;

  22. /**
  23.  * Represents a chunk of data of an In-Band Bytestream within an IQ stanza or a
  24.  * message stanza
  25.  *
  26.  * @author Henning Staib
  27.  */
  28. public class DataPacketExtension implements ExtensionElement {

  29.     /**
  30.      * The element name of the data packet extension.
  31.      */
  32.     public final static String ELEMENT = "data";

  33.     /**
  34.      * The XMPP namespace of the In-Band Bytestream
  35.      */
  36.     public static final String NAMESPACE = "http://jabber.org/protocol/ibb";

  37.     /* unique session ID identifying this In-Band Bytestream */
  38.     private final String sessionID;

  39.     /* sequence of this packet in regard to the other data packets */
  40.     private final long seq;

  41.     /* the data contained in this packet */
  42.     private final String data;

  43.     private byte[] decodedData;

  44.     /**
  45.      * Creates a new In-Band Bytestream data packet.
  46.      *
  47.      * @param sessionID unique session ID identifying this In-Band Bytestream
  48.      * @param seq sequence of this packet in regard to the other data packets
  49.      * @param data the base64 encoded data contained in this packet
  50.      */
  51.     public DataPacketExtension(String sessionID, long seq, String data) {
  52.         if (sessionID == null || "".equals(sessionID)) {
  53.             throw new IllegalArgumentException("Session ID must not be null or empty");
  54.         }
  55.         if (seq < 0 || seq > 65535) {
  56.             throw new IllegalArgumentException("Sequence must not be between 0 and 65535");
  57.         }
  58.         if (data == null) {
  59.             throw new IllegalArgumentException("Data must not be null");
  60.         }
  61.         this.sessionID = sessionID;
  62.         this.seq = seq;
  63.         this.data = data;
  64.     }

  65.     /**
  66.      * Returns the unique session ID identifying this In-Band Bytestream.
  67.      *
  68.      * @return the unique session ID identifying this In-Band Bytestream
  69.      */
  70.     public String getSessionID() {
  71.         return sessionID;
  72.     }

  73.     /**
  74.      * Returns the sequence of this packet in regard to the other data packets.
  75.      *
  76.      * @return the sequence of this packet in regard to the other data packets.
  77.      */
  78.     public long getSeq() {
  79.         return seq;
  80.     }

  81.     /**
  82.      * Returns the data contained in this packet.
  83.      *
  84.      * @return the data contained in this packet.
  85.      */
  86.     public String getData() {
  87.         return data;
  88.     }

  89.     /**
  90.      * Returns the decoded data or null if data could not be decoded.
  91.      * <p>
  92.      * The encoded data is invalid if it contains bad Base64 input characters or
  93.      * if it contains the pad ('=') character on a position other than the last
  94.      * character(s) of the data. See <a
  95.      * href="http://xmpp.org/extensions/xep-0047.html#sec">XEP-0047</a> Section
  96.      * 6.
  97.      *
  98.      * @return the decoded data
  99.      */
  100.     public byte[] getDecodedData() {
  101.         // return cached decoded data
  102.         if (this.decodedData != null) {
  103.             return this.decodedData;
  104.         }

  105.         // data must not contain the pad (=) other than end of data
  106.         if (data.matches(".*={1,2}+.+")) {
  107.             return null;
  108.         }

  109.         // decodeBase64 will return null if bad characters are included
  110.         this.decodedData = Base64.decode(data);
  111.         return this.decodedData;
  112.     }

  113.     public String getElementName() {
  114.         return ELEMENT;
  115.     }

  116.     public String getNamespace() {
  117.         return NAMESPACE;
  118.     }

  119.     @Override
  120.     public XmlStringBuilder toXML() {
  121.         XmlStringBuilder xml = getIQChildElementBuilder(new IQChildElementXmlStringBuilder(this));
  122.         xml.closeElement(this);
  123.         return xml;
  124.     }

  125.     protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
  126.         xml.attribute("seq", Long.toString(seq));
  127.         xml.attribute("sid", sessionID);
  128.         xml.rightAngleBracket();
  129.         xml.append(data);
  130.         return xml;
  131.     }
  132. }