Cleaning up code for runtime, installer, RMI, compiler for the Java side
[iot2.git] / iotjava / iotrmi / Java / IoTRMIUtil.java
1 package iotrmi.Java;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.IOException;
6 import java.io.ObjectInputStream;
7 import java.io.ObjectOutputStream;
8 import java.nio.ByteBuffer;
9 import java.util.Arrays;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18
19
20 /** Class IoTRMI provides utility services.
21  *  <p>
22  *  It provides miscellaneous (data type/value) translations.
23  *
24  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
25  * @version     1.0
26  * @since       2016-10-04
27  */
28 public final class IoTRMIUtil {
29
30         /**
31          * Class Properties
32          */
33         private Map<String,String> mapPrimitives;
34         private Map<String,Integer> mapPrimitiveSizes;
35         private Map<String,String> mapNonPrimitives;
36
37         /**
38          * Class Constants
39          */
40         public final static int OBJECT_ID_LEN = 4;              // 4 bytes = 32 bits
41         public final static int METHOD_ID_LEN = 4;              // 4 bytes = 32 bits
42         public final static int PACKET_TYPE_LEN = 4;    // 4 bytes = 32 bits
43         public final static int PARAM_LEN = 4;                  // 4 bytes = 32 bits (4-byte field that stores the length of the param)
44         public final static int RETURN_LEN = 4;                 // 4 bytes = 32 bits (4-byte field that stores the length of the return object)
45         public final static int RET_VAL_TYPE = -1;              // Packet type of return value
46         public final static int METHOD_TYPE = 1;                // Packet type of method
47
48         public final static int SHT_LEN = 2;
49         public final static int INT_LEN = 4;
50         public final static int LNG_LEN = 8;
51         public final static int FLT_LEN = 4;
52         public final static int DBL_LEN = 8;
53         public final static int CHR_LEN = 2;
54         public final static int BYT_LEN = 1;
55         public final static int BOL_LEN = 1;
56
57         /**
58          * Public static data structure to keep track of multiple skeletons and stubs
59          */
60         public static Map<Integer,Object> mapStub = new HashMap<Integer,Object>();              // Map object to its stub ID
61         public static Map<Object,Object> mapSkel = new HashMap<Object,Object>();                // Map object to its skeleton
62         public static Map<Object,Integer> mapSkelId = new HashMap<Object,Integer>();    // Map object to its skeleton ID
63
64
65         /**
66          * Constructors
67          */
68         public IoTRMIUtil() {
69
70                 mapPrimitives = new HashMap<String,String>();
71                         IoTRMITypes.arraysToMap(mapPrimitives, 
72                                 IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus);
73                 mapPrimitiveSizes = new HashMap<String,Integer>();
74                         IoTRMITypes.arraysToMap(mapPrimitiveSizes, 
75                                 IoTRMITypes.primitivesJava, IoTRMITypes.primitivesSizes);
76                 mapNonPrimitives = new HashMap<String,String>();
77                         IoTRMITypes.arraysToMap(mapNonPrimitives, 
78                                 IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus);
79         }
80
81
82         /**
83          * getHashCodeBytes() gets hash value (in bytes) from method name
84          */
85         public static byte[] getHashCodeBytes(String string) {
86
87                 int hash = string.hashCode();
88                 byte[] hashBytes = ByteBuffer.allocate(4).putInt(hash).array();
89                 return hashBytes;
90         }
91
92
93         /**================
94          * Helper methods
95          **================
96          */
97         /**
98          * translateType() try to translate a type
99          * <p>
100          * It returns the original type when fails.
101          */
102         public String translateType(String type) {
103
104                 if (mapPrimitives.containsKey(type))
105                         return mapPrimitives.get(type);
106                 else if (mapNonPrimitives.containsKey(type))
107                         return mapNonPrimitives.get(type);
108                 else
109                         return type;
110         }
111
112
113         /**
114          * getTypeSize() gets the size of a type
115          *
116          */
117         public int getTypeSize(String type) {
118
119                 if (mapPrimitiveSizes.containsKey(type))
120                         return mapPrimitiveSizes.get(type);
121                 else
122                         return -1; // Size is unknown (variable length)
123         }
124         
125
126         /**
127          * getTypeSize() gets the size of a type
128          *
129          */
130         public static int getTypeSize(Class<?> type) {
131
132                 int size = 0;
133                 if (type == byte.class) {
134                         size = BYT_LEN;
135                 } else if (type == Byte.class) {
136                         size = BYT_LEN;
137                 } else if (type == short.class) {
138                         size = SHT_LEN;
139                 } else if (type == Short.class) {
140                         size = SHT_LEN;
141                 } else if (     type == int.class) {
142                         size = INT_LEN;
143                 } else if (     type == Integer.class) {
144                         size = INT_LEN;
145                 } else if (     type == long.class) {
146                         size = LNG_LEN;
147                 } else if (     type == Long.class) {
148                         size = LNG_LEN;
149                 } else if (     type == float.class) {
150                         size = FLT_LEN;
151                 } else if (     type == Float.class) {
152                         size = FLT_LEN;
153                 } else if (     type == double.class) {
154                         size = DBL_LEN;
155                 } else if ( type == Double.class) {
156                         size = DBL_LEN;
157                 } else if (     type == boolean.class) {
158                         size = BOL_LEN;
159                 } else if (     type == Boolean.class) {
160                         size = BOL_LEN;
161                 } else if (     type == char.class) {
162                         size = CHR_LEN;
163                 } else if (     type == Character[].class) {
164                         size = CHR_LEN;
165                 } else if (type == String[].class) {
166                         size = -1;
167                 } else
168                         throw new Error("IoTRMIUtil: Unrecognizable type: " + type.getName());
169
170                 return size;
171         }
172
173         
174         /**
175          * getParamObject() converts byte array of certain object type into Object
176          */
177         public static Object getParamObject(Class<?> type, Class<?> genTypeVal, byte[] paramBytes) {
178                 
179                 Object retObj = null;
180                 if (type == byte.class ||
181                         type == Byte.class) {
182                         retObj = (Object) paramBytes[0];
183                 } else if (     type == short.class ||
184                                         type == Short.class) {
185                         retObj = (Object) byteArrayToShort(paramBytes);
186                 } else if (     type == int.class ||
187                                         type == Integer.class) {
188                         retObj = (Object) byteArrayToInt(paramBytes);
189                 } else if (     type == long.class ||
190                                         type == Long.class) {
191                         retObj = (Object) byteArrayToLong(paramBytes);
192                 } else if (     type == float.class ||
193                                         type == Float.class) {
194                         retObj = (Object) byteArrayToFloat(paramBytes);
195                 } else if (     type == double.class ||
196                                         type == Double.class) {
197                         retObj = (Object) byteArrayToDouble(paramBytes);
198                 } else if (     type == boolean.class ||
199                                         type == Boolean.class) {
200                         retObj = (Object) byteArrayToBoolean(paramBytes);
201                 } else if (     type == char.class ||
202                                         type == Character.class) {
203                         retObj = (Object) byteArrayToChar(paramBytes);
204                 } else if (type == String.class) {
205                         retObj = (Object) byteArrayToString(paramBytes);
206                 // Array
207                 } else if (type.isArray()) {
208                         retObj = getParamObjectArray(type, paramBytes);
209                 // List
210                 } else if (type == List.class) {
211                         retObj = getParamListObject(genTypeVal, paramBytes);
212                 } else
213                         throw new Error("IoTRMIUtil: Unrecognizable type: " + type.getName());
214                 
215                 return retObj;
216         }
217
218
219         /**
220          * getParamObjectArray() converts byte array of certain object type into array of Objects
221          */
222         public static Object getParamObjectArray(Class<?> type, byte[] paramBytes) {
223                 
224                 Object retObj = null;
225                 if ((type == byte[].class)      ||
226                         (type == byte.class)) {
227                         retObj = (Object) paramBytes;
228                 } else if ( (type == Byte[].class) ||
229                                         (type == Byte.class)) {
230                         retObj = (Object) byteArrayToByteArray(paramBytes);
231                 } else if ( (type == short[].class) ||
232                                         (type == short.class)) {
233                         retObj = (Object) byteArrayToShtArray(paramBytes);
234                 } else if ( (type == Short[].class) ||
235                                         (type == Short.class)) {
236                         retObj = (Object) byteArrayToShortArray(paramBytes);
237                 } else if (     (type == int[].class) ||
238                                         (type == int.class)) {
239                         retObj = (Object) byteArrayToIntArray(paramBytes);
240                 } else if (     (type == Integer[].class) ||
241                                         (type == Integer.class)) {
242                         retObj = (Object) byteArrayToIntegerArray(paramBytes);
243                 } else if (     (type == long[].class) ||
244                                         (type == long.class)) {
245                         retObj = (Object) byteArrayToLngArray(paramBytes);
246                 } else if (     (type == Long[].class) ||
247                                         (type == Long.class)) {
248                         retObj = (Object) byteArrayToLongArray(paramBytes);
249                 } else if (     (type == float[].class) ||
250                                         (type == float.class)) {
251                         retObj = (Object) byteArrayToFltArray(paramBytes);
252                 } else if (     (type == Float[].class) ||
253                                         (type == Float.class)) {
254                         retObj = (Object) byteArrayToFloatArray(paramBytes);
255                 } else if (     (type == double[].class) ||
256                                         (type == double.class)) {
257                         retObj = (Object) byteArrayToDblArray(paramBytes);
258                 } else if ( (type == Double[].class) ||
259                                         (type == Double.class)) {
260                         retObj = (Object) byteArrayToDoubleArray(paramBytes);
261                 } else if (     (type == boolean[].class) || 
262                                         (type == boolean.class)) {
263                         retObj = (Object) byteArrayToBolArray(paramBytes);
264                 } else if (     (type == Boolean[].class) ||
265                                         (type == Boolean.class)) {
266                         retObj = (Object) byteArrayToBooleanArray(paramBytes);
267                 } else if (     (type == char[].class) ||
268                                         (type == char.class)) {
269                         retObj = (Object) byteArrayToChrArray(paramBytes);
270                 } else if (     (type == Character[].class) ||
271                                         (type == Character.class)) {
272                         retObj = (Object) byteArrayToCharacterArray(paramBytes);
273                 } else if ( (type == String[].class) ||
274                                         (type == String.class)) {
275                         retObj = (Object) byteArrayToStringArray(paramBytes);
276                 } else
277                         throw new Error("IoTRMIUtil: Unrecognizable type: " + type.getName());
278                 
279                 return retObj;
280         }
281
282
283         /**
284          * getObjectBytes() converts an object into byte array
285          */
286         public static byte[] getObjectBytes(Object obj) {
287                 
288                 byte[] retObjBytes = null;
289                 if (obj instanceof Byte) {
290                         retObjBytes = new byte[] { (byte) obj };
291                 } else if (obj instanceof Short) {
292                         retObjBytes = shortToByteArray((short) obj);
293                 } else if (obj instanceof Integer) {
294                         retObjBytes = intToByteArray((int) obj);
295                 } else if (obj instanceof Long) {
296                         retObjBytes = longToByteArray((long) obj);
297                 } else if (obj instanceof Float) {
298                         retObjBytes = floatToByteArray((float) obj);
299                 } else if (obj instanceof Double) {
300                         retObjBytes = doubleToByteArray((double) obj);
301                 } else if (obj instanceof Character) {
302                         retObjBytes = charToByteArray((char) obj);
303                 } else if (obj instanceof Boolean) {
304                         retObjBytes = booleanToByteArray((boolean) obj);
305                 } else if (obj instanceof String) {
306                         retObjBytes = stringToByteArray((String) obj);
307                 // Arrays
308                 } else if (obj.getClass().isArray()) {
309                         retObjBytes = getArrayObjectBytes(obj);
310                 // List and its implementations
311                 } else if (obj instanceof List<?>) {
312                         retObjBytes = listToByteArray((List<?>) obj);
313                 } else
314                         throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
315
316                 return retObjBytes;
317         }
318
319
320         /**
321          * getArrayObjectBytes() converts array of objects into bytes array
322          */
323         public static byte[] getArrayObjectBytes(Object obj) {
324
325                 byte[] retObjBytes = null;
326                 if (obj instanceof byte[]) {
327                         retObjBytes = (byte[]) obj;
328                 } else if (obj instanceof Byte[]) {
329                         retObjBytes = arrByteToByteArray((Byte[]) obj);
330                 } else if (obj instanceof short[]) {
331                         retObjBytes = arrShortToByteArray((short[]) obj);
332                 } else if (obj instanceof Short[]) {
333                         retObjBytes = arrShortToByteArray((Short[]) obj);
334                 } else if (obj instanceof int[]) {
335                         retObjBytes = arrIntToByteArray((int[]) obj);
336                 } else if (obj instanceof Integer[]) {
337                         retObjBytes = arrIntToByteArray((Integer[]) obj);
338                 } else if (obj instanceof long[]) {
339                         retObjBytes = arrLongToByteArray((long[]) obj);
340                 } else if (obj instanceof Long[]) {
341                         retObjBytes = arrLongToByteArray((Long[]) obj);
342                 } else if (obj instanceof float[]) {
343                         retObjBytes = arrFloatToByteArray((float[]) obj);
344                 } else if (obj instanceof Float[]) {
345                         retObjBytes = arrFloatToByteArray((Float[]) obj);
346                 } else if (obj instanceof double[]) {
347                         retObjBytes = arrDoubleToByteArray((double[]) obj);
348                 } else if (obj instanceof Double[]) {
349                         retObjBytes = arrDoubleToByteArray((Double[]) obj);
350                 } else if (obj instanceof char[]) {
351                         retObjBytes = arrCharToByteArray((char[]) obj);
352                 } else if (obj instanceof Character[]) {
353                         retObjBytes = arrCharToByteArray((Character[]) obj);
354                 } else if (obj instanceof boolean[]) {
355                         retObjBytes = arrBooleanToByteArray((boolean[]) obj);
356                 } else if (obj instanceof Boolean[]) {
357                         retObjBytes = arrBooleanToByteArray((Boolean[]) obj);
358                 } else if (obj instanceof String[]) {
359                         retObjBytes = arrStringToByteArray((String[]) obj);
360                 } else
361                         throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
362
363                 return retObjBytes;     
364         }
365
366
367         public static byte[] listToByteArray(List<?> list) {
368
369                 // Find out the class of the type
370                 Iterator<?> it = list.iterator();
371                 Object[] arrObj = null;
372                 Object obj = it.next();
373
374                 if (obj instanceof Byte) {
375                         arrObj = list.toArray(new Byte[list.size()]);
376                 } else if (obj instanceof Short) {
377                         arrObj = list.toArray(new Short[list.size()]);
378                 } else if (obj instanceof Integer) {
379                         arrObj = list.toArray(new Integer[list.size()]);
380                 } else if (obj instanceof Long) {
381                         arrObj = list.toArray(new Long[list.size()]);
382                 } else if (obj instanceof Float) {
383                         arrObj = list.toArray(new Float[list.size()]);
384                 } else if (obj instanceof Double) {
385                         arrObj = list.toArray(new Double[list.size()]);
386                 } else if (obj instanceof Character) {
387                         arrObj = list.toArray(new Character[list.size()]);
388                 } else if (obj instanceof Boolean) {
389                         arrObj = list.toArray(new Boolean[list.size()]);
390                 } else if (obj instanceof String) {
391                         arrObj = list.toArray(new String[list.size()]);
392                 } else
393                         throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
394
395                 byte[] arrObjBytes = getArrayObjectBytes(arrObj);
396                 return arrObjBytes;
397         }
398
399
400         // Get a List object from bytes
401         public static Object getParamListObject(Class<?> genericType, byte[] paramBytes) {
402
403                 List<Object> retList = new ArrayList<Object>();
404                 Object retObj = null;
405                 if (genericType == Byte.class) {
406                         Byte[] retArr = byteArrayToByteArray(paramBytes);
407                         Collections.addAll(retList, retArr);
408                 } else if (genericType == Short.class) {
409                         Short[] retArr = byteArrayToShortArray(paramBytes);
410                         Collections.addAll(retList, retArr);
411                 } else if (genericType == Integer.class) {
412                         Integer[] retArr = byteArrayToIntegerArray(paramBytes);
413                         Collections.addAll(retList, retArr);
414                 } else if (genericType == Long.class) {
415                         Long[] retArr = byteArrayToLongArray(paramBytes);
416                         Collections.addAll(retList, retArr);
417                 } else if (genericType == Float.class) {
418                         Float[] retArr = byteArrayToFloatArray(paramBytes);
419                         Collections.addAll(retList, retArr);
420                 } else if (genericType == Double.class) {
421                         Double[] retArr = byteArrayToDoubleArray(paramBytes);
422                         Collections.addAll(retList, retArr);
423                 } else if (genericType == Boolean.class) {
424                         Boolean[] retArr = byteArrayToBooleanArray(paramBytes);
425                         Collections.addAll(retList, retArr);
426                 } else if (genericType == Character.class) {
427                         Character[] retArr = byteArrayToCharacterArray(paramBytes);
428                         Collections.addAll(retList, retArr);
429                 } else if (genericType == String.class) {
430                         String[] retArr = byteArrayToStringArray(paramBytes);
431                         Collections.addAll(retList, retArr);
432                 } else
433                         throw new Error("IoTRMIUtil: Unrecognizable object: " + genericType.getSimpleName());
434
435                 return retList;
436         }
437
438
439         /**
440          * Converters to byte array
441          */
442         // Single variables     
443         public static byte[] shortToByteArray(short s) {
444
445                 ByteBuffer bb = ByteBuffer.allocate(SHT_LEN);
446                 bb.putShort(s);
447
448                 return bb.array();
449         }
450
451
452         public static byte[] intToByteArray(int i) {
453
454                 ByteBuffer bb = ByteBuffer.allocate(INT_LEN);
455                 bb.putInt(i);
456
457                 return bb.array();
458         }
459
460
461         public static byte[] longToByteArray(long l) {
462
463                 ByteBuffer bb = ByteBuffer.allocate(LNG_LEN);
464                 bb.putLong(l);
465
466                 return bb.array();
467         }
468
469
470         public static byte[] floatToByteArray(float f) {
471
472                 ByteBuffer bb = ByteBuffer.allocate(FLT_LEN);
473                 bb.putFloat(f);
474
475                 return bb.array();
476         }
477
478
479         public static byte[] doubleToByteArray(double d) {
480
481                 ByteBuffer bb = ByteBuffer.allocate(DBL_LEN);
482                 bb.putDouble(d);
483
484                 return bb.array();
485         }
486
487
488         public static byte[] charToByteArray(char c) {
489
490                 ByteBuffer bb = ByteBuffer.allocate(CHR_LEN);
491                 bb.putChar(c);
492
493                 return bb.array();
494         }
495
496
497         public static byte[] booleanToByteArray(boolean b) {
498
499                 ByteBuffer bb = ByteBuffer.allocate(BOL_LEN);
500                 if (b)
501                         bb.put((byte)1);
502                 else
503                         bb.put((byte)0);
504
505                 return bb.array();
506         }
507
508
509         public static byte[] stringToByteArray(String str) {
510
511                 return str.getBytes();
512         }
513
514
515         // Arrays
516         public static byte[] arrByteToByteArray(Byte[] arrByte) {
517
518                 byte[] arrByt = new byte[arrByte.length];
519                 for(int i = 0; i < arrByte.length; i++) {
520                         arrByt[i] = arrByte[i];
521                 }
522
523                 return arrByt;
524         }
525
526
527         public static byte[] arrShortToByteArray(short[] arrShort) {
528
529                 ByteBuffer bb = ByteBuffer.allocate(SHT_LEN * arrShort.length);
530                 for(short s : arrShort) {
531                         bb.putShort(s);
532                 }
533
534                 return bb.array();
535         }
536
537
538         public static byte[] arrShortToByteArray(Short[] arrShort) {
539
540                 ByteBuffer bb = ByteBuffer.allocate(SHT_LEN * arrShort.length);
541                 for(Short s : arrShort) {
542                         bb.putShort(s);
543                 }
544
545                 return bb.array();
546         }
547
548
549         public static byte[] arrIntToByteArray(int[] arrInt) {
550
551                 ByteBuffer bb = ByteBuffer.allocate(INT_LEN * arrInt.length);
552                 for(int i : arrInt) {
553                         bb.putInt(i);
554                 }
555
556                 return bb.array();
557         }
558
559
560         public static byte[] arrIntToByteArray(Integer[] arrInt) {
561
562                 ByteBuffer bb = ByteBuffer.allocate(INT_LEN * arrInt.length);
563                 for(Integer i : arrInt) {
564                         bb.putInt(i);
565                 }
566
567                 return bb.array();
568         }
569
570
571         public static byte[] arrLongToByteArray(long[] arrLong) {
572
573                 ByteBuffer bb = ByteBuffer.allocate(LNG_LEN * arrLong.length);
574                 for(long l : arrLong) {
575                         bb.putLong(l);
576                 }
577
578                 return bb.array();
579         }
580
581
582         public static byte[] arrLongToByteArray(Long[] arrLong) {
583
584                 ByteBuffer bb = ByteBuffer.allocate(LNG_LEN * arrLong.length);
585                 for(Long l : arrLong) {
586                         bb.putLong(l);
587                 }
588
589                 return bb.array();
590         }
591
592
593         public static byte[] arrFloatToByteArray(float[] arrFloat) {
594
595                 ByteBuffer bb = ByteBuffer.allocate(FLT_LEN * arrFloat.length);
596                 for(float f : arrFloat) {
597                         bb.putFloat(f);
598                 }
599
600                 return bb.array();
601         }
602
603
604         public static byte[] arrFloatToByteArray(Float[] arrFloat) {
605
606                 ByteBuffer bb = ByteBuffer.allocate(FLT_LEN * arrFloat.length);
607                 for(Float f : arrFloat) {
608                         bb.putFloat(f);
609                 }
610
611                 return bb.array();
612         }
613
614
615         public static byte[] arrDoubleToByteArray(double[] arrDouble) {
616
617                 ByteBuffer bb = ByteBuffer.allocate(DBL_LEN * arrDouble.length);
618                 for(double d : arrDouble) {
619                         bb.putDouble(d);
620                 }
621
622                 return bb.array();
623         }
624
625
626         public static byte[] arrDoubleToByteArray(Double[] arrDouble) {
627
628                 ByteBuffer bb = ByteBuffer.allocate(DBL_LEN * arrDouble.length);
629                 for(Double d : arrDouble) {
630                         bb.putDouble(d);
631                 }
632
633                 return bb.array();
634         }
635
636
637         public static byte[] arrCharToByteArray(char[] arrChar) {
638
639                 ByteBuffer bb = ByteBuffer.allocate(CHR_LEN * arrChar.length);
640                 for(char c : arrChar) {
641                         bb.putChar(c);
642                 }
643
644                 return bb.array();
645         }
646
647
648         public static byte[] arrCharToByteArray(Character[] arrChar) {
649
650                 ByteBuffer bb = ByteBuffer.allocate(CHR_LEN * arrChar.length);
651                 for(Character c : arrChar) {
652                         bb.putChar(c);
653                 }
654
655                 return bb.array();
656         }
657
658
659         public static byte[] arrBooleanToByteArray(boolean[] arrBool) {
660
661                 ByteBuffer bb = ByteBuffer.allocate(BOL_LEN * arrBool.length);
662                 for(boolean b : arrBool) {
663                         if (b)
664                                 bb.put((byte)1);
665                         else
666                                 bb.put((byte)0);
667                 }
668
669                 return bb.array();
670         }
671
672
673         public static byte[] arrBooleanToByteArray(Boolean[] arrBool) {
674
675                 ByteBuffer bb = ByteBuffer.allocate(BOL_LEN * arrBool.length);
676                 for(Boolean b : arrBool) {
677                         if (b)
678                                 bb.put((byte)1);
679                         else
680                                 bb.put((byte)0);
681                 }
682
683                 return bb.array();
684         }
685
686
687         public static byte[] arrStringToByteArray(String[] arrString) {
688
689                 // Format of bytes: | array length | length #1 | string #1 | length #2 | string #2 | ...
690                 // Prepare array of bytes
691                 int arrLen = INT_LEN;   // First allocation for array length
692                 for (int i = 0; i < arrString.length; i++) {
693                         arrLen = arrLen + INT_LEN + arrString[i].length();
694                 }       
695                 byte[] arrStrBytes = new byte[arrLen];
696                 // Copy bytes
697                 int pos = 0;
698                 byte[] strArrLenBytes = intToByteArray(arrString.length);
699                 System.arraycopy(strArrLenBytes, 0, arrStrBytes, pos, INT_LEN);
700                 pos = pos + INT_LEN;
701                 for (String str : arrString) {
702
703                         // Copy string length
704                         int strLen = str.length();
705                         byte[] strLenBytes = intToByteArray(strLen);
706                         System.arraycopy(strLenBytes, 0, arrStrBytes, pos, INT_LEN);
707                         pos = pos + INT_LEN;
708                         // Copy string
709                         byte[] strBytes = stringToByteArray(str);
710                         System.arraycopy(strBytes, 0, arrStrBytes, pos, strLen);
711                         pos = pos + strLen;
712                 }
713
714                 return arrStrBytes;
715         }
716
717
718         /**
719          * Converters from byte array
720          */
721         // Single variables     
722         public static short byteArrayToShort(byte[] bytes) {
723
724                 return ByteBuffer.wrap(bytes).getShort();
725         }
726
727
728         public static int byteArrayToInt(byte[] bytes) {
729
730                 return ByteBuffer.wrap(bytes).getInt();
731         }
732
733
734         public static long byteArrayToLong(byte[] bytes) {
735
736                 return ByteBuffer.wrap(bytes).getLong();
737         }
738
739
740         public static float byteArrayToFloat(byte[] bytes) {
741
742                 return ByteBuffer.wrap(bytes).getFloat();
743         }
744
745
746         public static double byteArrayToDouble(byte[] bytes) {
747
748                 return ByteBuffer.wrap(bytes).getDouble();
749         }
750
751
752         public static char byteArrayToChar(byte[] bytes) {
753
754                 return ByteBuffer.wrap(bytes).getChar();
755         }
756
757
758         public static boolean byteArrayToBoolean(byte[] bytes) {
759
760                 Byte boolValByte = ByteBuffer.wrap(bytes).get();
761                 short boolVal = boolValByte.shortValue();
762                 if (boolVal == 1)
763                         return true;
764                 else
765                         return false;
766         }
767
768
769     public static String byteArrayToString(byte[] bytes) {
770         return new String(bytes);
771     }
772
773
774         // Arrays
775         public static Byte[] byteArrayToByteArray(byte[] arrByt) {
776
777                 Byte[] arrByte = new Byte[arrByt.length];
778                 for(int i = 0; i < arrByt.length; i++) {
779                         arrByte[i] = arrByt[i];
780                 }
781
782                 return arrByte;
783         }
784         
785         
786         public static short[] byteArrayToShtArray(byte[] bytes) {
787
788                 // Single element bytes
789                 byte[] elmt = new byte[SHT_LEN];
790                 // Prepare array
791                 int arrLen = bytes.length / SHT_LEN;
792                 short[] arr = new short[arrLen];
793                 for(int i = 0; i < arrLen; i++) {
794                         int offset = i * SHT_LEN;
795                         System.arraycopy(bytes, offset, elmt, 0, SHT_LEN);              
796                         arr[i] = byteArrayToShort(elmt);
797                 }
798
799                 return arr;
800         }
801
802
803         public static Short[] byteArrayToShortArray(byte[] bytes) {
804
805                 // Single element bytes
806                 byte[] elmt = new byte[SHT_LEN];
807                 // Prepare array
808                 int arrLen = bytes.length / SHT_LEN;
809                 Short[] arr = new Short[arrLen];
810                 for(int i = 0; i < arrLen; i++) {
811                         int offset = i * SHT_LEN;
812                         System.arraycopy(bytes, offset, elmt, 0, SHT_LEN);              
813                         arr[i] = byteArrayToShort(elmt);
814                 }
815
816                 return arr;
817         }
818
819
820         public static int[] byteArrayToIntArray(byte[] bytes) {
821
822                 // Single element bytes
823                 byte[] elmt = new byte[INT_LEN];
824                 // Prepare array
825                 int arrLen = bytes.length / INT_LEN;
826                 int[] arr = new int[arrLen];
827                 for(int i = 0; i < arrLen; i++) {
828                         int offset = i * INT_LEN;
829                         System.arraycopy(bytes, offset, elmt, 0, INT_LEN);              
830                         arr[i] = byteArrayToInt(elmt);
831                 }
832
833                 return arr;
834         }
835
836
837         public static Integer[] byteArrayToIntegerArray(byte[] bytes) {
838
839                 // Single element bytes
840                 byte[] elmt = new byte[INT_LEN];
841                 // Prepare array
842                 int arrLen = bytes.length / INT_LEN;
843                 Integer[] arr = new Integer[arrLen];
844                 for(int i = 0; i < arrLen; i++) {
845                         int offset = i * INT_LEN;
846                         System.arraycopy(bytes, offset, elmt, 0, INT_LEN);
847                         arr[i] = byteArrayToInt(elmt);
848                 }
849
850                 return arr;
851         }
852
853
854         public static long[] byteArrayToLngArray(byte[] bytes) {
855
856                 // Single element bytes
857                 byte[] elmt = new byte[LNG_LEN];
858                 // Prepare array
859                 int arrLen = bytes.length / LNG_LEN;
860                 long[] arr = new long[arrLen];
861                 for(int i = 0; i < arrLen; i++) {
862                         int offset = i * LNG_LEN;
863                         System.arraycopy(bytes, offset, elmt, 0, LNG_LEN);              
864                         arr[i] = byteArrayToLong(elmt);
865                 }
866
867                 return arr;
868         }
869
870
871         public static Long[] byteArrayToLongArray(byte[] bytes) {
872
873                 // Single element bytes
874                 byte[] elmt = new byte[LNG_LEN];
875                 // Prepare array
876                 int arrLen = bytes.length / LNG_LEN;
877                 Long[] arr = new Long[arrLen];
878                 for(int i = 0; i < arrLen; i++) {
879                         int offset = i * LNG_LEN;
880                         System.arraycopy(bytes, offset, elmt, 0, LNG_LEN);
881                         arr[i] = byteArrayToLong(elmt);
882                 }
883
884                 return arr;
885         }
886
887
888         public static float[] byteArrayToFltArray(byte[] bytes) {
889
890                 // Single element bytes
891                 byte[] elmt = new byte[FLT_LEN];
892                 // Prepare array
893                 int arrLen = bytes.length / FLT_LEN;
894                 float[] arr = new float[arrLen];
895                 for(int i = 0; i < arrLen; i++) {
896                         int offset = i * FLT_LEN;
897                         System.arraycopy(bytes, offset, elmt, 0, FLT_LEN);              
898                         arr[i] = byteArrayToFloat(elmt);
899                 }
900
901                 return arr;
902         }
903
904
905         public static Float[] byteArrayToFloatArray(byte[] bytes) {
906
907                 // Single element bytes
908                 byte[] elmt = new byte[FLT_LEN];
909                 // Prepare array
910                 int arrLen = bytes.length / FLT_LEN;
911                 Float[] arr = new Float[arrLen];
912                 for(int i = 0; i < arrLen; i++) {
913                         int offset = i * FLT_LEN;
914                         System.arraycopy(bytes, offset, elmt, 0, FLT_LEN);
915                         arr[i] = byteArrayToFloat(elmt);
916                 }
917
918                 return arr;
919         }
920
921
922         public static double[] byteArrayToDblArray(byte[] bytes) {
923
924                 // Single element bytes
925                 byte[] elmt = new byte[DBL_LEN];
926                 // Prepare array
927                 int arrLen = bytes.length / DBL_LEN;
928                 double[] arr = new double[arrLen];
929                 for(int i = 0; i < arrLen; i++) {
930                         int offset = i * DBL_LEN;
931                         System.arraycopy(bytes, offset, elmt, 0, DBL_LEN);
932                         arr[i] = byteArrayToDouble(elmt);
933                 }
934
935                 return arr;
936         }
937
938
939         public static Double[] byteArrayToDoubleArray(byte[] bytes) {
940
941                 // Single element bytes
942                 byte[] elmt = new byte[DBL_LEN];
943                 // Prepare array
944                 int arrLen = bytes.length / DBL_LEN;
945                 Double[] arr = new Double[arrLen];
946                 for(int i = 0; i < arrLen; i++) {
947                         int offset = i * DBL_LEN;
948                         System.arraycopy(bytes, offset, elmt, 0, DBL_LEN);
949                         arr[i] = byteArrayToDouble(elmt);
950                 }
951
952                 return arr;
953         }
954
955
956         public static char[] byteArrayToChrArray(byte[] bytes) {
957
958                 // Single element bytes
959                 byte[] elmt = new byte[CHR_LEN];
960                 // Prepare array
961                 int arrLen = bytes.length / CHR_LEN;
962                 char[] arr = new char[arrLen];
963                 for(int i = 0; i < arrLen; i++) {
964                         int offset = i * CHR_LEN;
965                         System.arraycopy(bytes, offset, elmt, 0, CHR_LEN);
966                         arr[i] = byteArrayToChar(elmt);
967                 }
968
969                 return arr;
970         }
971
972
973         public static Character[] byteArrayToCharacterArray(byte[] bytes) {
974
975                 // Single element bytes
976                 byte[] elmt = new byte[CHR_LEN];
977                 // Prepare array
978                 int arrLen = bytes.length / CHR_LEN;
979                 Character[] arr = new Character[arrLen];
980                 for(int i = 0; i < arrLen; i++) {
981                         int offset = i * CHR_LEN;
982                         System.arraycopy(bytes, offset, elmt, 0, CHR_LEN);
983                         arr[i] = byteArrayToChar(elmt);
984                 }
985
986                 return arr;
987         }
988
989
990         public static boolean[] byteArrayToBolArray(byte[] bytes) {
991
992                 // Single element bytes
993                 byte[] elmt = new byte[BOL_LEN];
994                 // Prepare array
995                 int arrLen = bytes.length / BOL_LEN;
996                 boolean[] arr = new boolean[arrLen];
997                 for(int i = 0; i < arrLen; i++) {
998                         int offset = i * BOL_LEN;
999                         System.arraycopy(bytes, offset, elmt, 0, BOL_LEN);
1000                         arr[i] = byteArrayToBoolean(elmt);
1001                 }
1002
1003                 return arr;
1004         }
1005
1006
1007         public static Boolean[] byteArrayToBooleanArray(byte[] bytes) {
1008
1009                 // Single element bytes
1010                 byte[] elmt = new byte[BOL_LEN];
1011                 // Prepare array
1012                 int arrLen = bytes.length / BOL_LEN;
1013                 Boolean[] arr = new Boolean[arrLen];
1014                 for(int i = 0; i < arrLen; i++) {
1015                         int offset = i * BOL_LEN;
1016                         System.arraycopy(bytes, offset, elmt, 0, BOL_LEN);
1017                         arr[i] = byteArrayToBoolean(elmt);
1018                 }
1019
1020                 return arr;
1021         }
1022
1023
1024         public static String[] byteArrayToStringArray(byte[] bytes) {
1025
1026                 // Format of bytes: | array length | length #1 | string #1 | length #2 | string #2 | ...
1027                 // Get string array length
1028                 int pos = 0;
1029                 byte[] strArrLenBytes = new byte[INT_LEN];
1030                 System.arraycopy(bytes, pos, strArrLenBytes, 0, INT_LEN);
1031                 int strArrLen = byteArrayToInt(strArrLenBytes);
1032                 pos = pos + INT_LEN;
1033                 // Prepare string array
1034                 String[] strArray = new String[strArrLen];
1035                 // Extract array of strings
1036                 for(int i = 0; i < strArrLen; i++) {
1037
1038                         // Extract string length
1039                         byte[] strLenBytes = new byte[INT_LEN];
1040                         System.arraycopy(bytes, pos, strLenBytes, 0, INT_LEN);
1041                         int strLen = byteArrayToInt(strLenBytes);
1042                         pos = pos + INT_LEN;
1043                         // Extract string
1044                         byte[] strBytes = new byte[strLen];
1045                         System.arraycopy(bytes, pos, strBytes, 0, strLen);
1046                         pos = pos + strLen;
1047                         strArray[i] = byteArrayToString(strBytes);
1048                 }
1049
1050                 return strArray;
1051         }
1052
1053
1054         /**
1055          * toByteArray() gets Object and return its byte array
1056          * <p>
1057          * Adapted from http://www.java2s.com/
1058          *              @see <a href="http://www.java2s.com/Code/Java/File-Input-
1059          *              Output/Convertobjecttobytearrayandconvertbytearraytoobject.htm"</a>
1060          */
1061     // toByteArray and toObject are taken from: http://tinyurl.com/69h8l7x
1062     public static byte[] toByteArray(Object obj) throws IOException {
1063
1064         byte[] bytes = null;
1065         ByteArrayOutputStream bos = null;
1066         ObjectOutputStream oos = null;
1067         try {
1068
1069             bos = new ByteArrayOutputStream();
1070             oos = new ObjectOutputStream(bos);
1071             oos.writeObject(obj);
1072             oos.flush();
1073             bytes = bos.toByteArray();
1074         } finally {
1075
1076             if (oos != null) {
1077                 oos.close();
1078             }
1079             if (bos != null) {
1080                 bos.close();
1081             }
1082         }
1083         return bytes;
1084     }
1085
1086
1087         /**
1088          * toObject() gets byte array and return its Object
1089          * <p>
1090          * Adapted from http://www.java2s.com/
1091          *              @see <a href="http://www.java2s.com/Code/Java/File-Input-
1092          *              Output/Convertobjecttobytearrayandconvertbytearraytoobject.htm"</a>
1093          */
1094     public static Object toObject(byte[] bytes) throws IOException, ClassNotFoundException {
1095
1096         Object obj = null;
1097         ByteArrayInputStream bis = null;
1098         ObjectInputStream ois = null;
1099         try {
1100
1101             bis = new ByteArrayInputStream(bytes);
1102             ois = new ObjectInputStream(bis);
1103             obj = ois.readObject();
1104         } finally {
1105
1106             if (bis != null) {
1107                 bis.close();
1108             }
1109             if (ois != null) {
1110                 ois.close();
1111             }
1112         }
1113         return obj;
1114     }
1115 }