PageRenderTime 33ms CodeModel.GetById 18ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 1ms

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