1 /*
2  * Copyright (C) 2007-2008 Esmertec AG.
3  * Copyright (C) 2007-2008 The Android Open Source Project
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 
18 package com.android.messaging.mmslib.pdu;
19 
20 import android.util.Log;
21 
22 import java.io.ByteArrayOutputStream;
23 import java.io.IOException;
24 import java.io.UnsupportedEncodingException;
25 import java.util.ArrayList;
26 
27 /**
28  * Encoded-string-value = Text-string | Value-length Char-set Text-string
29  */
30 public class EncodedStringValue implements Cloneable {
31     private static final String TAG = "EncodedStringValue";
32     private static final boolean DEBUG = false;
33     private static final boolean LOCAL_LOGV = false;
34 
35     /**
36      * The Char-set value.
37      */
38     private int mCharacterSet;
39 
40     /**
41      * The Text-string value.
42      */
43     private byte[] mData;
44 
45     /**
46      * Constructor.
47      *
48      * @param charset the Char-set value
49      * @param data    the Text-string value
50      * @throws NullPointerException if Text-string value is null.
51      */
EncodedStringValue(int charset, byte[] data)52     public EncodedStringValue(int charset, byte[] data) {
53         // TODO: CharSet needs to be validated against MIBEnum.
54         if (null == data) {
55             throw new NullPointerException("EncodedStringValue: Text-string is null.");
56         }
57 
58         mCharacterSet = charset;
59         mData = new byte[data.length];
60         System.arraycopy(data, 0, mData, 0, data.length);
61     }
62 
63     /**
64      * Constructor.
65      *
66      * @param data the Text-string value
67      * @throws NullPointerException if Text-string value is null.
68      */
EncodedStringValue(byte[] data)69     public EncodedStringValue(byte[] data) {
70         this(CharacterSets.DEFAULT_CHARSET, data);
71     }
72 
EncodedStringValue(String data)73     public EncodedStringValue(String data) {
74         this(CharacterSets.DEFAULT_CHARSET, data);
75     }
76 
77     /**
78      * Constructor
79      *
80      * @param charset
81      * @param data The text in Java String
82      * @throws NullPointerException if Text-string value is null.
83      */
EncodedStringValue(int charset, String data)84     public EncodedStringValue(int charset, String data) {
85         if (null == data) {
86             throw new NullPointerException("EncodedStringValue: Text-string is null");
87         }
88         mCharacterSet = charset;
89         try {
90             mData = data.getBytes(CharacterSets.getMimeName(charset));
91         } catch (UnsupportedEncodingException e) {
92             Log.e(TAG, "Input encoding " + charset + " must be supported.", e);
93             mData = data.getBytes();
94         }
95     }
96 
97     /**
98      * Get Char-set value.
99      *
100      * @return the value
101      */
getCharacterSet()102     public int getCharacterSet() {
103         return mCharacterSet;
104     }
105 
106     /**
107      * Set Char-set value.
108      *
109      * @param charset the Char-set value
110      */
setCharacterSet(int charset)111     public void setCharacterSet(int charset) {
112         // TODO: CharSet needs to be validated against MIBEnum.
113         mCharacterSet = charset;
114     }
115 
116     /**
117      * Get Text-string value.
118      *
119      * @return the value
120      */
getTextString()121     public byte[] getTextString() {
122         byte[] byteArray = new byte[mData.length];
123 
124         System.arraycopy(mData, 0, byteArray, 0, mData.length);
125         return byteArray;
126     }
127 
128     /**
129      * Set Text-string value.
130      *
131      * @param textString the Text-string value
132      * @throws NullPointerException if Text-string value is null.
133      */
setTextString(byte[] textString)134     public void setTextString(byte[] textString) {
135         if (null == textString) {
136             throw new NullPointerException("EncodedStringValue: Text-string is null.");
137         }
138 
139         mData = new byte[textString.length];
140         System.arraycopy(textString, 0, mData, 0, textString.length);
141     }
142 
143     /**
144      * Convert this object to a {@link java.lang.String}. If the encoding of
145      * the EncodedStringValue is null or unsupported, it will be
146      * treated as iso-8859-1 encoding.
147      *
148      * @return The decoded String.
149      */
getString()150     public String getString() {
151         if (CharacterSets.ANY_CHARSET == mCharacterSet) {
152             return new String(mData); // system default encoding.
153         } else {
154             try {
155                 String name = CharacterSets.getMimeName(mCharacterSet);
156                 return new String(mData, name);
157             } catch (UnsupportedEncodingException e) {
158                 if (LOCAL_LOGV) {
159                     Log.v(TAG, e.getMessage(), e);
160                 }
161                 try {
162                     return new String(mData, CharacterSets.MIMENAME_ISO_8859_1);
163                 } catch (UnsupportedEncodingException exception) {
164                     return new String(mData); // system default encoding.
165                 }
166             }
167         }
168     }
169 
170     /**
171      * Append to Text-string.
172      *
173      * @param textString the textString to append
174      * @throws NullPointerException if the text String is null
175      *                              or an IOException occured.
176      */
appendTextString(byte[] textString)177     public void appendTextString(byte[] textString) {
178         if (null == textString) {
179             throw new NullPointerException("Text-string is null.");
180         }
181 
182         if (null == mData) {
183             mData = new byte[textString.length];
184             System.arraycopy(textString, 0, mData, 0, textString.length);
185         } else {
186             ByteArrayOutputStream newTextString = new ByteArrayOutputStream();
187             try {
188                 newTextString.write(mData);
189                 newTextString.write(textString);
190             } catch (IOException e) {
191                 e.printStackTrace();
192                 throw new NullPointerException(
193                         "appendTextString: failed when write a new Text-string");
194             }
195 
196             mData = newTextString.toByteArray();
197         }
198     }
199 
200     /*
201      * (non-Javadoc)
202      * @see java.lang.Object#clone()
203      */
204     @Override
clone()205     public Object clone() throws CloneNotSupportedException {
206         super.clone();
207         int len = mData.length;
208         byte[] dstBytes = new byte[len];
209         System.arraycopy(mData, 0, dstBytes, 0, len);
210 
211         try {
212             return new EncodedStringValue(mCharacterSet, dstBytes);
213         } catch (Exception e) {
214             Log.e(TAG, "failed to clone an EncodedStringValue: " + this);
215             e.printStackTrace();
216             throw new CloneNotSupportedException(e.getMessage());
217         }
218     }
219 
220     /**
221      * Split this encoded string around matches of the given pattern.
222      *
223      * @param pattern the delimiting pattern
224      * @return the array of encoded strings computed by splitting this encoded
225      *         string around matches of the given pattern
226      */
split(String pattern)227     public EncodedStringValue[] split(String pattern) {
228         String[] temp = getString().split(pattern);
229         EncodedStringValue[] ret = new EncodedStringValue[temp.length];
230         for (int i = 0; i < ret.length; ++i) {
231             try {
232                 ret[i] = new EncodedStringValue(mCharacterSet,
233                         temp[i].getBytes());
234             } catch (NullPointerException exception) {
235                 // Can't arrive here
236                 return null;
237             }
238         }
239         return ret;
240     }
241 
242     /**
243      * Extract an EncodedStringValue[] from a given String.
244      */
extract(String src)245     public static EncodedStringValue[] extract(String src) {
246         String[] values = src.split(";");
247 
248         ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>();
249         for (int i = 0; i < values.length; i++) {
250             if (values[i].length() > 0) {
251                 list.add(new EncodedStringValue(values[i]));
252             }
253         }
254 
255         int len = list.size();
256         if (len > 0) {
257             return list.toArray(new EncodedStringValue[len]);
258         } else {
259             return null;
260         }
261     }
262 
263     /**
264      * Concatenate an EncodedStringValue[] into a single String.
265      */
concat(EncodedStringValue[] addr)266     public static String concat(EncodedStringValue[] addr) {
267         StringBuilder sb = new StringBuilder();
268         int maxIndex = addr.length - 1;
269         for (int i = 0; i <= maxIndex; i++) {
270             sb.append(addr[i].getString());
271             if (i < maxIndex) {
272                 sb.append(";");
273             }
274         }
275 
276         return sb.toString();
277     }
278 
copy(EncodedStringValue value)279     public static EncodedStringValue copy(EncodedStringValue value) {
280         if (value == null) {
281             return null;
282         }
283 
284         return new EncodedStringValue(value.mCharacterSet, value.mData);
285     }
286 
encodeStrings(String[] array)287     public static EncodedStringValue[] encodeStrings(String[] array) {
288         int count = array.length;
289         if (count > 0) {
290             EncodedStringValue[] encodedArray = new EncodedStringValue[count];
291             for (int i = 0; i < count; i++) {
292                 encodedArray[i] = new EncodedStringValue(array[i]);
293             }
294             return encodedArray;
295         }
296         return null;
297     }
298 }
299