View Javadoc

1   /* ***** BEGIN LICENSE BLOCK *****
2    * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3    *
4    * The contents of this file are subject to the Mozilla Public License Version
5    * 1.1 (the "License"); you may not use this file except in compliance with
6    * the License. You may obtain a copy of the License at
7    * http://www.mozilla.org/MPL/
8    *
9    * Software distributed under the License is distributed on an "AS IS" basis,
10   * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11   * for the specific language governing rights and limitations under the
12   * License.
13   *
14   * The Original Code is "SMS Library for the Java platform".
15   *
16   * The Initial Developer of the Original Code is Markus Eriksson.
17   * Portions created by the Initial Developer are Copyright (C) 2002
18   * the Initial Developer. All Rights Reserved.
19   *
20   * Contributor(s):
21   *
22   * Alternatively, the contents of this file may be used under the terms of
23   * either the GNU General Public License Version 2 or later (the "GPL"), or
24   * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
25   * in which case the provisions of the GPL or the LGPL are applicable instead
26   * of those above. If you wish to allow use of your version of this file only
27   * under the terms of either the GPL or the LGPL, and not to allow others to
28   * use your version of this file under the terms of the MPL, indicate your
29   * decision by deleting the provisions above and replace them with the notice
30   * and other provisions required by the GPL or the LGPL. If you do not delete
31   * the provisions above, a recipient may use your version of this file under
32   * the terms of any one of the MPL, the GPL or the LGPL.
33   *
34   * ***** END LICENSE BLOCK ***** */
35  package org.marre.sms;
36  
37  import java.util.Random;
38  
39  /***
40   * Baseclass for messages that needs to be concatenated.
41   * <p>- Only usable for messages that uses the same UDH fields for all message
42   * parts. <br>- This class could be better written. There are several parts
43   * that are copy- pasted. <br>- The septet coding could be a bit optimized.
44   * <br>
45   * 
46   * @author Markus Eriksson
47   * @version $Id: SmsConcatMessage.java,v 1.16 2005/05/06 13:55:11 c95men Exp $
48   */
49  public abstract class SmsConcatMessage implements SmsMessage
50  {
51      private static Random myRnd = new Random();
52  
53      /***
54       * Creates an empty SmsConcatMessage.
55       */
56      protected SmsConcatMessage()
57      {
58          // Empty
59      }
60  
61      /***
62       * Returns the whole UD
63       * 
64       * @return the UD
65       */
66      public abstract SmsUserData getUserData();
67      
68      /***
69       * Returns the udh elements
70       * <p>
71       * The returned UDH is the same as specified when the message was created.
72       * No concat headers are added.
73       * 
74       * @return the UDH as SmsUdhElements
75       */
76      public abstract SmsUdhElement[] getUdhElements();
77  
78      private SmsPdu[] createOctalPdus(SmsUdhElement[] theUdhElements, SmsUserData theUd, int theMaxBytes)
79      {
80          int nMaxChars;
81          int nMaxConcatChars;
82          SmsPdu[] smsPdus = null;
83  
84          // 8-bit concat header is 6 bytes...
85          nMaxConcatChars = theMaxBytes - 6;
86          nMaxChars = theMaxBytes;
87  
88          if (theUd.getLength() <= nMaxChars)
89          {
90              smsPdus = new SmsPdu[]{new SmsPdu(theUdhElements, theUd)};
91          }
92          else
93          {
94              int refno = myRnd.nextInt(256);
95  
96              // Calculate number of SMS needed
97              int nSms = theUd.getLength() / nMaxConcatChars;
98              if ((theUd.getLength() % nMaxConcatChars) > 0)
99              {
100                 nSms += 1;
101             }
102             smsPdus = new SmsPdu[nSms];
103 
104             // Calculate number of UDHI
105             SmsUdhElement[] pduUdhElements = null;
106             if (theUdhElements == null)
107             {
108                 pduUdhElements = new SmsUdhElement[1];
109             }
110             else
111             {
112                 pduUdhElements = new SmsUdhElement[theUdhElements.length + 1];
113 
114                 // Copy the UDH headers
115                 for (int j = 0; j < theUdhElements.length; j++)
116                 {
117                     // Leave position pduUdhElements[0] for the concat UDHI
118                     pduUdhElements[j + 1] = theUdhElements[j];
119                 }
120             }
121 
122             // Create pdus
123             for (int i = 0; i < nSms; i++)
124             {
125                 byte[] pduUd;
126                 int udBytes;
127                 int udLength;
128                 int udOffset;
129 
130                 // Create concat header
131                 pduUdhElements[0] = SmsUdhUtil.get8BitConcatUdh(refno, nSms, i + 1);
132 
133                 // Create
134                 // Must concatenate messages
135                 // Calc pdu length
136                 udOffset = nMaxConcatChars * i;
137                 udBytes = theUd.getLength() - udOffset;
138                 if (udBytes > nMaxConcatChars)
139                 {
140                     udBytes = nMaxConcatChars;
141                 }
142                 udLength = udBytes;
143 
144                 pduUd = new byte[udBytes];
145                 SmsPduUtil.arrayCopy(theUd.getData(), udOffset, pduUd, 0, udBytes);
146                 smsPdus[i] = new SmsPdu(pduUdhElements, pduUd, udLength, theUd.getDcs());
147             }
148         }
149         return smsPdus;
150     }
151 
152     private SmsPdu[] createUnicodePdus(SmsUdhElement[] theUdhElements, SmsUserData theUd, int theMaxBytes)
153     {
154         int nMaxChars;
155         int nMaxConcatChars;
156         SmsPdu[] smsPdus = null;
157 
158         // 8-bit concat header is 6 bytes...
159         nMaxConcatChars = (theMaxBytes - 6) / 2;
160         nMaxChars = theMaxBytes / 2;
161 
162         if (theUd.getLength() <= nMaxChars)
163         {
164             smsPdus = new SmsPdu[]{new SmsPdu(theUdhElements, theUd)};
165         }
166         else
167         {
168             int refno = myRnd.nextInt(256);
169 
170             // Calculate number of SMS needed
171             int nSms = (theUd.getLength() / 2) / nMaxConcatChars;
172             if (((theUd.getLength() / 2) % nMaxConcatChars) > 0)
173             {
174                 nSms += 1;
175             }
176             smsPdus = new SmsPdu[nSms];
177 
178             // Calculate number of UDHI
179             SmsUdhElement[] pduUdhElements = null;
180             if (theUdhElements == null)
181             {
182                 pduUdhElements = new SmsUdhElement[1];
183             }
184             else
185             {
186                 pduUdhElements = new SmsUdhElement[theUdhElements.length + 1];
187 
188                 // Copy the UDH headers
189                 for (int j = 0; j < theUdhElements.length; j++)
190                 {
191                     // Leave position pduUdhElements[0] for the concat UDHI
192                     pduUdhElements[j + 1] = theUdhElements[j];
193                 }
194             }
195 
196             // Create pdus
197             for (int i = 0; i < nSms; i++)
198             {
199                 byte[] pduUd;
200                 int udBytes;
201                 int udLength;
202                 int udOffset;
203 
204                 // Create concat header
205                 pduUdhElements[0] = SmsUdhUtil.get8BitConcatUdh(refno, nSms, i + 1);
206 
207                 // Create
208                 // Must concatenate messages
209                 // Calc pdu length
210                 udOffset = nMaxConcatChars * i;
211                 udLength = (theUd.getLength() / 2) - udOffset;
212                 if (udLength > nMaxConcatChars)
213                 {
214                     udLength = nMaxConcatChars;
215                 }
216                 udBytes = udLength * 2;
217 
218                 pduUd = new byte[udBytes];
219                 SmsPduUtil.arrayCopy(theUd.getData(), udOffset * 2, pduUd, 0, udBytes);
220                 smsPdus[i] = new SmsPdu(pduUdhElements, pduUd, udBytes, theUd.getDcs());
221             }
222         }
223         return smsPdus;
224     }
225 
226     private SmsPdu[] createSeptetPdus(SmsUdhElement[] theUdhElements, SmsUserData theUd, int theMaxBytes)
227     {
228         int nMaxChars;
229         int nMaxConcatChars;
230         SmsPdu[] smsPdus = null;
231 
232         // 8-bit concat header is 6 bytes...
233         nMaxConcatChars = ((theMaxBytes - 6) * 8) / 7;
234         nMaxChars = (theMaxBytes * 8) / 7;
235 
236         if (theUd.getLength() <= nMaxChars)
237         {
238             smsPdus = new SmsPdu[]{new SmsPdu(theUdhElements, theUd)};
239         }
240         else
241         {
242             int refno = myRnd.nextInt(256);
243 
244             // Calculate number of SMS needed
245             int nSms = theUd.getLength() / nMaxConcatChars;
246             if ((theUd.getLength() % nMaxConcatChars) > 0)
247             {
248                 nSms += 1;
249             }
250             smsPdus = new SmsPdu[nSms];
251 
252             // Calculate number of UDHI
253             SmsUdhElement[] pduUdhElements = null;
254             if (theUdhElements == null)
255             {
256                 pduUdhElements = new SmsUdhElement[1];
257             }
258             else
259             {
260                 pduUdhElements = new SmsUdhElement[theUdhElements.length + 1];
261 
262                 // Copy the UDH headers
263                 for (int j = 0; j < theUdhElements.length; j++)
264                 {
265                     // Leave position pduUdhElements[0] for the concat UDHI
266                     pduUdhElements[j + 1] = theUdhElements[j];
267                 }
268             }
269 
270             // Convert septets into a string...
271             String msg = SmsPduUtil.readSeptets(theUd.getData(), theUd.getLength());
272 
273             // Create pdus
274             for (int i = 0; i < nSms; i++)
275             {
276                 byte[] pduUd;
277                 int udOffset;
278                 int udLength;
279 
280                 // Create concat header
281                 pduUdhElements[0] = SmsUdhUtil.get8BitConcatUdh(refno, nSms, i + 1);
282 
283                 // Create
284                 // Must concatenate messages
285                 // Calc pdu length
286                 udOffset = nMaxConcatChars * i;
287                 udLength = theUd.getLength() - udOffset;
288                 if (udLength > nMaxConcatChars)
289                 {
290                     udLength = nMaxConcatChars;
291                 }
292 
293                 pduUd = SmsPduUtil.getSeptets(msg.substring(udOffset, udOffset + udLength));
294                 smsPdus[i] = new SmsPdu(pduUdhElements, pduUd, udLength, theUd.getDcs());
295             }
296         }
297         return smsPdus;
298     }
299 
300     /***
301      * Converts this message into SmsPdu:s
302      * <p>
303      * If the message is too long to fit in one SmsPdu the message is divided
304      * into many SmsPdu:s with a 8-bit concat pdu UDH element.
305      * 
306      * @return Returns the message as SmsPdu:s
307      */
308     public SmsPdu[] getPdus()
309     {
310         SmsPdu[] smsPdus;
311         SmsUserData ud = getUserData();
312         SmsUdhElement[] udhElements = getUdhElements();        
313         int udhLength = SmsUdhUtil.getTotalSize(udhElements);
314         int nBytesLeft = 140 - udhLength;
315 
316         switch (ud.getDcs().getAlphabet())
317         {
318         case SmsDcs.ALPHABET_GSM:
319             smsPdus = createSeptetPdus(udhElements, ud, nBytesLeft);
320             break;
321         case SmsDcs.ALPHABET_UCS2:
322             smsPdus = createUnicodePdus(udhElements, ud, nBytesLeft);
323             break;
324         case SmsDcs.ALPHABET_8BIT:
325         default:
326             smsPdus = createOctalPdus(udhElements, ud, nBytesLeft);
327             break;
328         }
329 
330         return smsPdus;
331     }
332 }