/protocols/smpp/src/main/java/org/mobicents/protocols/smpp/message/tlv/TLVTableImpl.java

http://mobicents.googlecode.com/ · Java · 258 lines · 128 code · 22 blank · 108 comment · 21 complexity · 09950570ff79f759f1498d16db13428a MD5 · raw file

  1. /*
  2. * JBoss, Home of Professional Open Source
  3. * Copyright 2011, Red Hat, Inc. and individual contributors
  4. * by the @authors tag. See the copyright.txt in the distribution for a
  5. * full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.mobicents.protocols.smpp.message.tlv;
  23. import java.io.IOException;
  24. import java.text.MessageFormat;
  25. import java.util.BitSet;
  26. import java.util.LinkedHashMap;
  27. import java.util.Map;
  28. import org.mobicents.protocols.smpp.message.param.ParamDescriptor;
  29. import org.mobicents.protocols.smpp.util.PacketDecoder;
  30. import org.mobicents.protocols.smpp.util.PacketEncoder;
  31. /**
  32. * Implementation of the TLVTable interface.
  33. * This implementation will maintain the ordering of added parameters.
  34. * @version $Id: TLVTableImpl.java 457 2009-01-15 17:37:42Z orank $
  35. */
  36. public class TLVTableImpl extends LinkedHashMap<Tag, Object> implements TLVTable {
  37. private static final long serialVersionUID = 2L;
  38. public TLVTableImpl() {
  39. }
  40. /**
  41. * Decode a full set of optional parameters from a byte array.
  42. */
  43. public void readFrom(PacketDecoder decoder, int length) {
  44. int endIndex = (decoder.getParsePosition() + length) - 1;
  45. while (decoder.getParsePosition() < endIndex) {
  46. Object val = null;
  47. Tag tag = Tag.getTag(decoder.readUInt2());
  48. int valueLen = decoder.readUInt2();
  49. ParamDescriptor descriptor = tag.getParamDescriptor();
  50. val = descriptor.readObject(decoder, valueLen);
  51. put(tag, val);
  52. }
  53. }
  54. /**
  55. * Encode all the optional parameters in this table to an output stream.
  56. *
  57. * @param out
  58. * The output stream to encode the parameters to.
  59. * @throws java.io.IOException
  60. * If an error occurs writing to the output stream.
  61. */
  62. public void writeTo(PacketEncoder encoder) throws IOException {
  63. for (Map.Entry<Tag, Object> entry : entrySet()) {
  64. Tag tag = entry.getKey();
  65. Object value = entry.getValue();
  66. ParamDescriptor descriptor = tag.getParamDescriptor();
  67. int valueLen = descriptor.sizeOf(value);
  68. encoder.writeUInt2(tag.intValue());
  69. encoder.writeUInt2(valueLen);
  70. descriptor.writeObject(value, encoder);
  71. }
  72. }
  73. /**
  74. * Get the value for a tag. This is a convenience method to convert
  75. * the tag integer to its appropriate Tag object and then look that
  76. * tag up in the map.
  77. * @param tag The tag&apos;s integer value.
  78. */
  79. public Object get(int tag) {
  80. Tag tagObj = Tag.getTag(tag);
  81. return get(tagObj);
  82. }
  83. /**
  84. * Get the tag&apos;s value as a string.
  85. * @param tag The tag to retrieve the value for.
  86. * @return The value as a string, or <code>null</code> if the specified
  87. * tag is not set in this table.
  88. */
  89. public String getString(Tag tag) {
  90. Object obj = get(tag);
  91. return obj != null ? obj.toString() : null;
  92. }
  93. /**
  94. * Get the tag&apos;s value as an int.
  95. * @param tag The tag to retrieve the value for.
  96. * @return The value as an integer, or <code>-1</code> if the specified
  97. * tag is not set in this table.
  98. * @throws ClassCastException If the value for the specified tag is not
  99. * a number (castable as a <code>java.lang.Number</code>).
  100. */
  101. public int getInt(Tag tag) {
  102. Object obj = get(tag);
  103. if (obj != null) {
  104. return ((Number) obj).intValue();
  105. } else {
  106. return -1;
  107. }
  108. }
  109. /**
  110. * Get the tag&apos;s value as a long.
  111. * @param tag The tag to retrieve the value for.
  112. * @return The value as a long, or <code>-1</code> if the specified
  113. * tag is not set in this table.
  114. * @throws ClassCastException If the value for the specified tag is not
  115. * a number (castable as a <code>java.lang.Number</code>).
  116. */
  117. public long getLong(Tag tag) {
  118. Object obj = get(tag);
  119. if (obj != null) {
  120. return ((Number) obj).intValue();
  121. } else {
  122. return -1;
  123. }
  124. }
  125. /**
  126. * Get the tag&apos;s value as a bit set.
  127. * @param tag The tag to retrieve the value for.
  128. * @return The value, cast as a <code>java.util.BitSet</code>, or
  129. * <code>null</code> if the specified tag is not set in this table.
  130. * @throws ClassCastException If the value for the specified tag is not
  131. * a bit mask.
  132. */
  133. public BitSet getBitmask(Tag tag) {
  134. return ((BitSet) get(tag));
  135. }
  136. /**
  137. * Get the tag&apos;s value as a byte array.
  138. * @param tag The tag to retrieve the value for.
  139. * @return The value, cast as a <code>byte[]</code>, or <code>null</code>
  140. * if the specified tag is not set in this table.
  141. * @throws ClassCastException If the value for the specified tag is not
  142. * a byte array.
  143. */
  144. public byte[] getBytes(Tag tag) {
  145. return ((byte[]) get(tag));
  146. }
  147. /**
  148. * Set the value of a TLV.
  149. * @param tag The tag of the parameter to set.
  150. * @param value The tag&apos;s value.
  151. * @throws BadValueTypeException If <code>tag</code> does not accept
  152. * the type that <code>value</code> is.
  153. * @throws InvalidSizeForValueException If <code>value</code>
  154. * exceeds either the minimum or maximum size allowed by <code>tag</code>.
  155. */
  156. @Override
  157. public Object put(Tag tag, Object value)
  158. throws BadValueTypeException, InvalidSizeForValueException {
  159. ParamDescriptor descriptor = tag.getParamDescriptor();
  160. if (descriptor.equals(BasicDescriptors.NULL) && value != null) {
  161. String error = MessageFormat.format(
  162. "Tag {0} does not accept any value.",
  163. new Object[] {tag});
  164. throw new BadValueTypeException(error);
  165. } else if (value == null) {
  166. String error = MessageFormat.format(
  167. "Tag {0} does not accept a null value.",
  168. new Object[] {tag});
  169. throw new BadValueTypeException(error);
  170. }
  171. // Enforce the length restrictions on the Value specified by the
  172. // Tag.
  173. int min = tag.getMinLength();
  174. int max = tag.getMaxLength();
  175. int actual = descriptor.sizeOf(value);
  176. if ((min > -1 && actual < min) || (max > -1 && actual > max)) {
  177. throw new InvalidSizeForValueException("Tag "
  178. + tag.toHexString()
  179. + " must have a length in the range " + min
  180. + " <= len <= " + max);
  181. }
  182. return super.put(tag, value);
  183. }
  184. public Object put(Tag tag, char value) {
  185. return put(tag, Character.valueOf(value));
  186. }
  187. public Object put(Tag tag, short value) {
  188. return put(tag, Short.valueOf(value));
  189. }
  190. public Object put(Tag tag, int value) {
  191. return put(tag, Integer.valueOf(value));
  192. }
  193. public Object put(Tag tag, long value) {
  194. return put(tag, Long.valueOf(value));
  195. }
  196. /**
  197. * Remove (or un-set) a tag/value from this table.
  198. * @param tag The tag to remove from the table.
  199. */
  200. public void remove(int tag) {
  201. super.remove(Tag.getTag(tag));
  202. }
  203. @Override
  204. public String toString() {
  205. StringBuffer buffer = new StringBuffer();
  206. for (Map.Entry<Tag, Object> entry : entrySet()) {
  207. ParamDescriptor descriptor = entry.getKey().getParamDescriptor();
  208. Object value = entry.getValue();
  209. buffer.append('{')
  210. .append(entry.getKey().toHexString())
  211. .append(',').append(descriptor.sizeOf(value))
  212. .append(',').append(value);
  213. }
  214. return buffer.toString();
  215. }
  216. /**
  217. * Get the length the parameters in the table would encode as. The length of
  218. * an SMPP packet is determined by: <br>
  219. * <code>sizeof (smpp_header) + sizeof (mandatory_parameters)
  220. * + sizeof (optional_parameters).</code>
  221. * <br>
  222. * The value returned for this method is the last clause in this equation.
  223. *
  224. * @return The full length that the optional parameters would encode as.
  225. */
  226. public int getLength() {
  227. // Length is going to be (number of options) * (2 bytes for tag) * (2
  228. // bytes for length) + (size of all encoded values)
  229. int length = size() * 4;
  230. for (Map.Entry<Tag, Object> entry : entrySet()) {
  231. Tag tag = entry.getKey();
  232. length += tag.getParamDescriptor().sizeOf(entry.getValue());
  233. }
  234. return length;
  235. }
  236. }