/protocols/smpp/src/main/java/org/mobicents/protocols/smpp/encoding/EncodingFactory.java

http://mobicents.googlecode.com/ · Java · 227 lines · 111 code · 17 blank · 99 comment · 8 complexity · beda6cd19706db1b5fd009f0567e33b7 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.encoding;
  23. import java.io.UnsupportedEncodingException;
  24. import java.util.HashMap;
  25. import java.util.Iterator;
  26. import java.util.Map;
  27. import org.slf4j.Logger;
  28. import org.slf4j.LoggerFactory;
  29. import org.mobicents.protocols.smpp.SMPPRuntimeException;
  30. import org.mobicents.protocols.smpp.util.APIConfig;
  31. import org.mobicents.protocols.smpp.util.APIConfigFactory;
  32. /**
  33. * Factory class for obtaining message encoding instances.
  34. * By default, instances of this class are aware of the following encoding
  35. * types:
  36. * <ul>
  37. * <li>{@link DefaultAlphabetEncoding}</li>
  38. * <li>{@link ASCIIEncoding}</li>
  39. * <li>{@link Latin1Encoding}</li>
  40. * <li>{@link BinaryEncoding}</li>
  41. * <li>{@link UCS2Encoding} (only if the JVM supports the UCS2 charset).</li>
  42. * </ul>
  43. *
  44. * <p>Other encoding types may be added to an instance of the factory but
  45. * it should be noted that there can only be <b>one</b> encoding mapping
  46. * for any particular data coding value. If a second encoding is added which
  47. * has the same data coding value as another encoding, the existing encoding
  48. * will be overwritten in the factory.</p>
  49. *
  50. * <p>The rest of the SMPPAPI uses the singleton instance of this factory
  51. * as returned by the static {@link #getInstance()} method of this class.</p>
  52. */
  53. public class EncodingFactory {
  54. /**
  55. * Name of the system property that the 'default' alphabet encoding
  56. * will be read from.
  57. */
  58. static final String DEFAULT_ALPHABET_PROPNAME = "smpp.default_alphabet";
  59. private static final Logger LOG = LoggerFactory.getLogger(EncodingFactory.class);
  60. private static final EncodingFactory INSTANCE = new EncodingFactory();
  61. private final Map<Integer, MessageEncoding<?>> mappingTable =
  62. new HashMap<Integer, MessageEncoding<?>>();
  63. private final Map<String, AlphabetEncoding> langToAlphabet =
  64. new HashMap<String, AlphabetEncoding>();
  65. private AlphabetEncoding defaultAlphabet;
  66. public EncodingFactory() {
  67. addEncoding(new BinaryEncoding());
  68. AlphabetEncoding gsmDefault = new DefaultAlphabetEncoding();
  69. addEncoding(gsmDefault);
  70. langToAlphabet.put("en", gsmDefault);
  71. langToAlphabet.put("de", gsmDefault);
  72. langToAlphabet.put("fr", gsmDefault);
  73. langToAlphabet.put("it", gsmDefault);
  74. langToAlphabet.put("nl", gsmDefault);
  75. langToAlphabet.put("es", gsmDefault);
  76. try {
  77. ASCIIEncoding ascii = new ASCIIEncoding();
  78. addEncoding(ascii);
  79. langToAlphabet.put(null, ascii);
  80. } catch (UnsupportedEncodingException x) {
  81. LOG.debug("UCS2 encoding is not supported.");
  82. }
  83. try {
  84. Latin1Encoding latin1 = new Latin1Encoding();
  85. addEncoding(latin1);
  86. langToAlphabet.put(null, latin1);
  87. } catch (UnsupportedEncodingException x) {
  88. LOG.debug("UCS2 encoding is not supported.");
  89. }
  90. try {
  91. AlphabetEncoding ucs2 = new UCS2Encoding();
  92. addEncoding(ucs2);
  93. langToAlphabet.put(null, ucs2);
  94. } catch (UnsupportedEncodingException x) {
  95. LOG.debug("UCS2 encoding is not supported.");
  96. }
  97. LOG.debug("Using {} as the catch-all language alphabet.",
  98. langToAlphabet.get(null).getClass().getSimpleName());
  99. initDefaultAlphabet();
  100. }
  101. /**
  102. * Get a static instance of this factory class.
  103. * @return A static instance of <code>EncodingFactory</code>.
  104. */
  105. public static final EncodingFactory getInstance() {
  106. return INSTANCE;
  107. }
  108. /**
  109. * Get the message encoding represented by the specified data coding
  110. * value.
  111. * @param dataCoding The data coding to retrieve a message encoding instance
  112. * for.
  113. * @return The message encoding instance representing data coding value
  114. * <code>dataCoding</code> or <code>null</code> if there is no encoding
  115. * registered for that value.
  116. */
  117. public MessageEncoding<?> getEncoding(final int dataCoding) {
  118. return mappingTable.get(Integer.valueOf(dataCoding));
  119. }
  120. /**
  121. * Add a message encoding to this factory.
  122. * @param encoding The encoding to add to the factory.
  123. */
  124. public void addEncoding(final MessageEncoding<?> encoding) {
  125. mappingTable.put(Integer.valueOf(encoding.getDataCoding()), encoding);
  126. }
  127. /**
  128. * Add a message encoding to this factory. The supplied class must be
  129. * a sub-class of {@link MessageEncoding} and must have a
  130. * no-argument constructor. This method will swallow any exceptions
  131. * that may occur during instance creation - primarily to silently
  132. * fail on encodings that rely on a particular charset that the current
  133. * JVM does not support. Log messages will be generated for failure
  134. * conditions.
  135. * @param encodingClass The class of the <code>MessageEncoding</code> to
  136. * add.
  137. */
  138. public void addEncoding(final Class<? extends MessageEncoding<?>> encodingClass) {
  139. addEncoding(instantiateEncoding(encodingClass));
  140. }
  141. /**
  142. * Get an iterator over all known encodings by this factory.
  143. * @return An iterator over all the encodings known by this factory.
  144. */
  145. public Iterator<MessageEncoding<?>> getAllEncodings() {
  146. return mappingTable.values().iterator();
  147. }
  148. /**
  149. * Return the default alphabet for this runtime environment. The default
  150. * alphabet is usually {@link DefaultAlphabetEncoding}. This can be altered
  151. * by setting the <b>smpp.default_alphabet </b> system property to the name
  152. * of an implementation of {@link AlphabetEncoding}.
  153. *
  154. * <p>
  155. * For example:<br />
  156. * <code>java -cp .:smppapi.jar -Dsmpp.default_alphabet=myPackage.MyAlphabet
  157. * ...</code>
  158. * @return The default alphabet encoding.
  159. */
  160. public AlphabetEncoding getDefaultAlphabet() {
  161. return defaultAlphabet;
  162. }
  163. /**
  164. * Get the SMSAlphabet needed for encoding messages in a particular
  165. * language.
  166. * @param lang
  167. * The ISO code for the language the message is in.
  168. */
  169. public AlphabetEncoding getAlphabet(String lang) {
  170. AlphabetEncoding enc = langToAlphabet.get(lang);
  171. if (enc != null) {
  172. return enc;
  173. } else {
  174. return langToAlphabet.get(null);
  175. }
  176. }
  177. /**
  178. * Initialise the default alphabet.
  179. */
  180. private void initDefaultAlphabet() {
  181. String className = "";
  182. try {
  183. className = System.getProperty(DEFAULT_ALPHABET_PROPNAME);
  184. if (className != null) {
  185. Class<?> alphaClass = Class.forName(className);
  186. defaultAlphabet = instantiateEncoding(alphaClass);
  187. } else {
  188. APIConfig cfg = APIConfigFactory.getConfig();
  189. defaultAlphabet = cfg.getClassInstance(
  190. APIConfig.DEFAULT_ALPHABET,
  191. AlphabetEncoding.class,
  192. null);
  193. }
  194. } catch (Exception x) {
  195. LOG.warn("Couldn't load default alphabet {}: {}",
  196. className, x.getMessage());
  197. }
  198. if (defaultAlphabet == null) {
  199. defaultAlphabet = new DefaultAlphabetEncoding();
  200. }
  201. }
  202. private AlphabetEncoding instantiateEncoding(final Class<?> encodingClass) {
  203. try {
  204. return (AlphabetEncoding) encodingClass.newInstance();
  205. } catch (Exception x) {
  206. LOG.error("Could not instantiate a {}: {}", encodingClass, x);
  207. throw new SMPPRuntimeException(x);
  208. }
  209. }
  210. }