Early version of RMI system for Java part; supports primitives, one-dimensional array...
authorrtrimana <rtrimana@uci.edu>
Mon, 17 Oct 2016 18:35:05 +0000 (11:35 -0700)
committerrtrimana <rtrimana@uci.edu>
Mon, 17 Oct 2016 18:35:05 +0000 (11:35 -0700)
16 files changed:
iotjava/Makefile
iotjava/iotrmi/IoTRMITypes.java
iotjava/iotrmi/Java/IoTRMICall.java
iotjava/iotrmi/Java/IoTRMIObject.java
iotjava/iotrmi/Java/IoTRMIUtil.java
iotjava/iotrmi/Java/IoTSocket.java
iotjava/iotrmi/Java/sample/CallBack.java [new file with mode: 0644]
iotjava/iotrmi/Java/sample/CallBackInterface.java [new file with mode: 0644]
iotjava/iotrmi/Java/sample/CallBack_Skeleton.java [new file with mode: 0644]
iotjava/iotrmi/Java/sample/CallBack_Stub.java [new file with mode: 0644]
iotjava/iotrmi/Java/sample/TestClass.java [new file with mode: 0644]
iotjava/iotrmi/Java/sample/TestClass_Skeleton.java [new file with mode: 0644]
iotjava/iotrmi/Java/sample/TestClass_Stub.java [new file with mode: 0644]
iotjava/iotruntime/master/CommunicationHandler.java [new file with mode: 0644]
iotjava/iotruntime/master/ObjectCreationInfo.java [new file with mode: 0644]
iotjava/iotruntime/master/RuntimeOutput.java [new file with mode: 0644]

index c02a5fe..d9b968f 100644 (file)
@@ -22,11 +22,17 @@ PHONY += run-compiler
 run-compiler:
        cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler camerapolicy.pol camerarequires.pol lightbulbpolicy.pol lightbulbrequires.pol -cplus Cplus -java Java
 
+# Runtime system compilation
+PHONY += runtime
+runtime:
+       $(JAVAC) -classpath . iotruntime/master/*.java -d $(BIN_DIR)
+
 # RMI compilation and run
 PHONY += rmi
 rmi:
        $(JAVAC) -cp . -d $(BIN_DIR) iotrmi/*.java
        $(JAVAC) -cp .:../$(BIN_DIR) -d $(BIN_DIR) iotrmi/Java/*.java
+       $(JAVAC) -cp .:../$(BIN_DIR) -d $(BIN_DIR) iotrmi/Java/sample/*.java
 
 PHONY += run-rmiserver
 run-rmiserver:
index a0c682f..c8ebcf3 100644 (file)
@@ -40,7 +40,7 @@ public class IoTRMITypes {
                "void"                  // 0 byte
        };
 
-       
+
        /**
         * Primitive data types in C++ to map the primitives list
         */
@@ -137,4 +137,14 @@ public class IoTRMITypes {
                        map.put(arrKey[i], arrVal[i]);
                }
        }
+
+       // Inserting array members into a Map object
+       // that maps arrKey to arrVal objects
+       public static void arraysToMap(Map<Object,Object> map, Object[] arrKey, Object[] arrVal) {
+
+               for(int i = 0; i < arrKey.length; i++) {
+
+                       map.put(arrKey[i], arrVal[i]);
+               }
+       }
 }
index 9410662..9353f33 100644 (file)
@@ -9,6 +9,9 @@ import java.util.List;
 import java.util.Map;
 import java.lang.reflect.Method;
 
+import java.util.HashSet;
+import java.util.Set;
+
 
 /** Class IoTRMICall is a class that serves method calls on stub.
  *  <p>
@@ -22,6 +25,7 @@ import java.lang.reflect.Method;
  */
 public class IoTRMICall {
 
+
        /**
         * Class Properties
         */
@@ -42,15 +46,29 @@ public class IoTRMICall {
        /**
         * remoteCall() calls a method remotely by passing in parameters and getting a return Object
         */
-       public Object remoteCall(String methodSign, String retType, Class<?>[] paramCls, Object[] paramObj) throws IOException {
+       public Object remoteCall(String methodSign, Class<?> retType, Class<?> retGenTypeKey, 
+                       Class<?> retGenTypeVal, Class<?>[] paramCls, Object[] paramObj) {
 
                // Send method info
                byte[] methodBytes = methodToBytes(methodSign, paramCls, paramObj);
-               rmiClient.sendBytes(methodBytes);
+               try {
+                       rmiClient.sendBytes(methodBytes);
+               } catch (IOException ex) {
+                       ex.printStackTrace();
+                       throw new Error("IoTRMICall: Error when sending bytes - rmiClient.sendBytes()");
+               }
                // Receive return value and return it to caller
-               byte[] retObjBytes = null;
-               retObjBytes = rmiClient.receiveBytes(retObjBytes);
-               Object retObj = IoTRMIUtil.getParamObject(retType, retObjBytes);
+               Object retObj = null;
+               if (retType != void.class) {
+                       byte[] retObjBytes = null;
+                       try {
+                               retObjBytes = rmiClient.receiveBytes(retObjBytes);
+                       } catch (IOException ex) {
+                               ex.printStackTrace();
+                               throw new Error("IoTRMICall: Error when receiving bytes - rmiClient.receiveBytes()");
+                       }
+                       retObj = IoTRMIUtil.getParamObject(retType, retGenTypeKey, retGenTypeVal, retObjBytes);
+               }
                return retObj;
        }
 
@@ -104,17 +122,64 @@ public class IoTRMICall {
        
        public static void main(String[] args) throws Exception {
 
-               int port = 5010;
-               String address = "localhost";
-               int rev = 0;
-               IoTRMICall rmiCall = new IoTRMICall(port, address, rev);
-               String sign = "intsetACAndGetA(string,int)";
-               String retType = "int";
-               System.out.println("Calling function: " + sign);
-               Object retObj = rmiCall.remoteCall(sign, retType, new Class<?>[] { String.class, int.class }, 
-                       new Object[] { "Test param", 1234567 });
-               System.out.println("Returned object: " + retObj);
-
-               System.out.println();
+               String[] test = { "123", "456", "789" };
+               byte[] b = IoTRMIUtil.getObjectBytes(test);
+
+               Boolean[] test2 = new Boolean[] { true, false, false };
+               byte[] b2 = IoTRMIUtil.getObjectBytes(test2);
+
+               System.out.println(Arrays.toString(b));
+               System.out.println(Arrays.toString(b2));
+
+               String[] c = (String[]) IoTRMIUtil.getParamObjectArray(String[].class, b);
+               System.out.println(Arrays.toString(c));
+
+               Boolean[] c2 = (Boolean[]) IoTRMIUtil.getParamObjectArray(Boolean[].class, b2);
+               System.out.println(Arrays.toString(c2));
+
+               // Set
+               /*Set<String> set = new HashSet<String>();
+               set.add("1234");
+               set.add("5678");
+
+               byte[] objBytes = IoTRMIUtil.getObjectBytes(set);
+               System.out.println(Arrays.toString(objBytes));
+               Object obj = IoTRMIUtil.getParamObject(Set.class, null, String.class, objBytes);
+
+               @SuppressWarnings("unchecked")
+               Set<String> setStr = (Set<String>) obj;
+               System.out.println("Set: " + setStr.toString());*/
+
+               // List
+               /*List<Long> list = new ArrayList<Long>();
+               list.add(12345678l);
+               list.add(23455432l);
+               list.add(34566543l);
+
+               byte[] objBytes = IoTRMIUtil.getObjectBytes(list);
+               System.out.println(Arrays.toString(objBytes));
+               Object obj = IoTRMIUtil.getParamObject(List.class, null, Long.class, objBytes);
+
+               @SuppressWarnings("unchecked")
+               List<Long> listStr = (List<Long>) obj;
+               System.out.println("List: " + listStr.toString());*/
+
+               // Map
+               Map<Long,Integer> map = new HashMap<Long,Integer>();
+               map.put(12345678l, 1234);
+               map.put(23455432l, 5678);
+               map.put(34566543l, 4321);
+
+               byte[] objBytes = IoTRMIUtil.getObjectBytes(map);
+               System.out.println(Arrays.toString(objBytes));
+               Object obj = IoTRMIUtil.getParamObject(Map.class, Long.class, Integer.class, objBytes);
+
+               map = (Map<Long,Integer>) obj;
+               System.out.println("Received map: " + map.toString());
+
+               //@SuppressWarnings("unchecked")
+               //List<Long> listStr = (List<Long>) obj;
+               //System.out.println("List: " + listStr.toString());
+
        }
 }
index 9f40b82..c8fefa4 100644 (file)
@@ -28,109 +28,66 @@ public class IoTRMIObject {
        /**
         * Class Properties
         */
-       private Map<String,Method> mapSign2Method;      // Map from signature to method
        private Map<Integer,String> mapHash2Sign;       // Map from hashcode(method ID) to signature
        private IoTRMIUtil rmiUtil;
        private IoTSocketServer rmiServer;
-       private Object obj;
-       private Class<?> cls;
-       private Method[] methods;
+       private byte[] methodBytes;
 
 
        /**
         * Constructors
         */
-       public IoTRMIObject(String _clsName, int _port) throws 
-                       ClassNotFoundException, InstantiationException, 
-                               IllegalAccessException, IOException {
+       public IoTRMIObject(int _port, String[] _methodSign) throws  
+               ClassNotFoundException, InstantiationException, 
+                       IllegalAccessException, IOException {
 
                rmiUtil = new IoTRMIUtil();
-               cls = Class.forName(_clsName);
-               obj = cls.newInstance();
-               methods = cls.getDeclaredMethods();
-               mapSign2Method = new HashMap<String,Method>();
                mapHash2Sign = new HashMap<Integer,String>();
-               getMethodSignatures();  // Initialize the signature map
-               getMethodIds();                 // Initialize the method ID map
+               methodBytes = null;
+               getMethodIds(_methodSign);      // Initialize the method ID map
                rmiServer = new IoTSocketServer(_port);
                rmiServer.connect();
        }
 
 
        /**
-        * getName() gets class name
+        * sendReturnObj() sends back return Object to client
         */
-       public String getName() {
+       public void sendReturnObj(Object retObj) throws IOException {
 
-               return cls.getName();
+               // Send back return value
+               byte[] retObjBytes = IoTRMIUtil.getObjectBytes(retObj);
+               rmiServer.sendBytes(retObjBytes);
        }
 
 
        /**
-        * getSignatures() gets method signatures
-        */
-       public Set<String> getSignatures() {
-
-               return mapSign2Method.keySet();
-       }
-
-       
-       /**
-        * getMethodParamTypes() gets method parameter types
+        * getMethodBytes() waits for method transmission in bytes
         */
-       public Class<?>[] getMethodParamTypes(String signature) {
+       public void getMethodBytes() throws IOException {
 
-               Method method = mapSign2Method.get(signature);
-               return method.getParameterTypes();
+               // Receive method info
+               methodBytes = rmiServer.receiveBytes(methodBytes);
        }
 
 
        /**
-        * getMethodRetType() gets method return type
-        */
-       public Class<?> getMethodRetType(String signature) {
-
-               Method method = mapSign2Method.get(signature);
-               return method.getReturnType();
-       }
-       
-
-       /**
-        * invokeMethod() invokes a method based on signature and params
+        * getSignature() gets method signature from bytes
         */
-       public Object invokeMethod(String signature, Object[] params) {
-
-               Method method = mapSign2Method.get(signature);
-               Object retVal = null;
-               try {
-                       retVal = method.invoke(obj, params);
-               } catch (IllegalAccessException |
-                                InvocationTargetException ex) {
-                       ex.printStackTrace();
-                       throw new Error("IoTRMICall: Error invoking method: " + signature);
-               }
+       public String getSignature() {
 
-               return retVal;
+               // Get method ID
+               byte[] methodIdBytes = new byte[IoTRMIUtil.METHOD_ID_LEN];
+               System.arraycopy(methodBytes, 0, methodIdBytes, 0, IoTRMIUtil.METHOD_ID_LEN);
+               // Get Method object to handle method
+               int methodId = IoTRMIUtil.byteArrayToInt(methodIdBytes);
+               // Get method signature from the Map
+               return mapHash2Sign.get(methodId);
        }
 
 
        /**
-        * recvAndInvoke() waits for method transmission and invoke the method
-        */
-       private void recvAndInvoke() throws IOException {
-
-               // Receive method info and invoke
-               byte[] method = null;
-               method = rmiServer.receiveBytes(method);
-               Object retObj = invokeMethod(method);
-               // Send back return value
-               byte[] retObjBytes = IoTRMIUtil.getObjectBytes(retObj);
-               rmiServer.sendBytes(retObjBytes);
-       }
-       
-
-       /**
-        * invokeMethod() invokes a method based on byte array received
+        * getMethodParams() gets method params based on byte array received
         * <p>
         * Basically this is the format of a method in bytes:
         * 1) 32-bit value of method ID (hash code)
@@ -146,20 +103,10 @@ public class IoTRMIObject {
         * | 32-bit method ID | 32-bit length | n-bit actual data | ...
         * 
         */
-       public Object invokeMethod(byte[] methodBytes) {
+       public Object[] getMethodParams(Class<?>[] arrCls, Class<?>[] arrGenKeyCls, Class<?>[] arrGenValCls) {
 
                // Byte scanning position
-               int pos = 0;
-               // Get method ID
-               byte[] methodIdBytes = new byte[IoTRMIUtil.METHOD_ID_LEN];
-               System.arraycopy(methodBytes, pos, methodIdBytes, 0, IoTRMIUtil.METHOD_ID_LEN);
-               pos = pos + IoTRMIUtil.METHOD_ID_LEN;
-               // Get Method object to handle method
-               int methodId = IoTRMIUtil.byteArrayToInt(methodIdBytes);
-               String signature = mapHash2Sign.get(methodId);
-               Method method = mapSign2Method.get(signature);
-               // Get class name and then param length
-               Class<?>[] arrCls = method.getParameterTypes();
+               int pos = IoTRMIUtil.METHOD_ID_LEN;
                Object[] paramObj = new Object[arrCls.length];
                for (int i=0; i < arrCls.length; i++) {
 
@@ -176,56 +123,23 @@ public class IoTRMIObject {
                        byte[] paramBytes = new byte[paramSize];
                        System.arraycopy(methodBytes, pos, paramBytes, 0, paramSize);
                        pos = pos + paramSize;
-                       paramObj[i] = IoTRMIUtil.getParamObject(paramType, paramBytes);
+                       paramObj[i] = IoTRMIUtil.getParamObject(arrCls[i], arrGenKeyCls[i], 
+                               arrGenValCls[i], paramBytes);
                }
-               Object retObj = null;
-               try {
-                       retObj = method.invoke(obj, paramObj);
-               } catch (IllegalAccessException |
-                                InvocationTargetException ex) {
-                       ex.printStackTrace();
-                       throw new Error("IoTRMICall: Error invoking method: " + signature);
-               }
-
-               return retObj;
-       }
 
-
-       /**================
-        * Helper methods
-        **================
-        */
-       /**
-        * getMethodSignatures() gets methods signatures and store them in the Map
-        */
-       private void getMethodSignatures() {
-
-               for (Method m : methods) {
-                       String sign = rmiUtil.getSignature(m);
-                       //System.out.println("Signature: " + sign);
-                       mapSign2Method.put(sign, m);
-               }
+               return paramObj;
        }
        
-       
+
        /**
         * getMethodIds() gets methods identifiers (hash code) and store them in the Map
         */
-       private void getMethodIds() {
+       private void getMethodIds(String[] methodSign) {
 
-               Set<String> setSignatures = getSignatures();
-               for (String sign : setSignatures) {
+               for (String sign : methodSign) {
                        byte[] hashCode = IoTRMIUtil.getHashCodeBytes(sign);
                        int methodId = IoTRMIUtil.byteArrayToInt(hashCode);
                        mapHash2Sign.put(methodId, sign);
                }
        }
-
-
-       public static void main(String[] args) throws Exception {
-
-               int port = 5010;
-               IoTRMIObject rmiObj = new IoTRMIObject("TestClass", port);
-               rmiObj.recvAndInvoke();
-       }
 }
index df76959..50965ba 100644 (file)
@@ -7,9 +7,14 @@ import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
-import java.lang.reflect.Method;
+import java.util.Set;
 
 import iotrmi.IoTRMITypes;
 
@@ -37,6 +42,15 @@ public class IoTRMIUtil {
        public final static int METHOD_ID_LEN = 4;      // 4 bytes = 32 bits
        public final static int PARAM_LEN = 4;          // 4 bytes = 32 bits (4-byte field that stores the length of the param)
 
+       public final static int SHT_LEN = 2;
+       public final static int INT_LEN = 4;
+       public final static int LNG_LEN = 8;
+       public final static int FLT_LEN = 4;
+       public final static int DBL_LEN = 8;
+       public final static int CHR_LEN = 2;
+       public final static int BYT_LEN = 1;
+       public final static int BOL_LEN = 1;
+
        /**
         * Constructors
         */
@@ -57,27 +71,6 @@ public class IoTRMIUtil {
        }
 
 
-       /**
-        * getSignature() gets method signature, i.e. type, identifier, parameters
-        */
-       public String getSignature(Method m) {
-
-               String retType = translateType(m.getReturnType().getSimpleName());
-               String signature = retType + 
-                       m.getName() + "(";
-               Class<?>[] clsParam = m.getParameterTypes();
-               for (int i = 0; i < clsParam.length; i++) {
-                       String paramType = translateType(clsParam[i].getSimpleName());
-                       signature = signature + paramType;
-                       if (i < clsParam.length - 1) {
-                               signature = signature + ",";
-                       }
-               }
-               signature = signature + ")";
-               return signature;
-       }
-
-
        /**
         * getHashCodeBytes() gets hash value (in bytes) from method name
         */
@@ -123,41 +116,167 @@ public class IoTRMIUtil {
                        return -1; // Size is unknown
        }
        
+
+       /**
+        * getTypeSize() gets the size of a type
+        *
+        */
+       public static int getTypeSize(Class<?> type) {
+
+               int size = 0;
+               if (type == byte.class) {
+                       size = BYT_LEN;
+               } else if (type == Byte.class) {
+                       size = BYT_LEN;
+               } else if (type == short.class) {
+                       size = SHT_LEN;
+               } else if (type == Short.class) {
+                       size = SHT_LEN;
+               } else if (     type == int.class) {
+                       size = INT_LEN;
+               } else if (     type == Integer.class) {
+                       size = INT_LEN;
+               } else if (     type == long.class) {
+                       size = LNG_LEN;
+               } else if (     type == Long.class) {
+                       size = LNG_LEN;
+               } else if (     type == float.class) {
+                       size = FLT_LEN;
+               } else if (     type == Float.class) {
+                       size = FLT_LEN;
+               } else if (     type == double.class) {
+                       size = DBL_LEN;
+               } else if ( type == Double.class) {
+                       size = DBL_LEN;
+               } else if (     type == boolean.class) {
+                       size = BOL_LEN;
+               } else if (     type == Boolean.class) {
+                       size = BOL_LEN;
+               } else if (     type == char.class) {
+                       size = CHR_LEN;
+               } else if (     type == Character[].class) {
+                       size = CHR_LEN;
+               } else if (type == String[].class) {
+                       size = -1;
+               } else
+                       throw new Error("IoTRMIUtil: Unrecognizable type: " + type.getName());
+
+               return size;
+       }
+
        
        /**
         * getParamObject() converts byte array of certain object type into Object
         */
-       public static Object getParamObject(String type, byte[] paramBytes) {
+       public static Object getParamObject(Class<?> type, Class<?> genTypeKey, Class<?> genTypeVal, byte[] paramBytes) {
                
                Object retObj = null;
-               if (type.equals("byte") ||
-                       type.equals("Byte")) {
+               if (type == byte.class ||
+                       type == Byte.class) {
                        retObj = (Object) paramBytes[0];
-               } else if (     type.equals("short") ||
-                                       type.equals("Short")) {
+               } else if (     type == short.class ||
+                                       type == Short.class) {
                        retObj = (Object) byteArrayToShort(paramBytes);
-               } else if (     type.equals("int") ||
-                                       type.equals("Integer")) {
+               } else if (     type == int.class ||
+                                       type == Integer.class) {
                        retObj = (Object) byteArrayToInt(paramBytes);
-               } else if (     type.equals("long") ||
-                                       type.equals("Long")) {
+               } else if (     type == long.class ||
+                                       type == Long.class) {
                        retObj = (Object) byteArrayToLong(paramBytes);
-               } else if (     type.equals("float") ||
-                                       type.equals("Float")) {
+               } else if (     type == float.class ||
+                                       type == Float.class) {
                        retObj = (Object) byteArrayToFloat(paramBytes);
-               } else if (     type.equals("double") ||
-                                       type.equals("Double")) {
+               } else if (     type == double.class ||
+                                       type == Double.class) {
                        retObj = (Object) byteArrayToDouble(paramBytes);
-               } else if (     type.equals("boolean") ||
-                                       type.equals("Boolean")) {
+               } else if (     type == boolean.class ||
+                                       type == Boolean.class) {
                        retObj = (Object) byteArrayToBoolean(paramBytes);
-               } else if (     type.equals("char") ||
-                                       type.equals("Character")) {
+               } else if (     type == char.class ||
+                                       type == Character.class) {
                        retObj = (Object) byteArrayToChar(paramBytes);
-               } else if (type.equals("String")) {
-                       retObj = (Object) toString(paramBytes);
+               } else if (type == String.class) {
+                       retObj = (Object) byteArrayToString(paramBytes);
+               // Array
+               } else if (type.isArray()) {
+                       retObj = getParamObjectArray(type, paramBytes);
+               // Set
+               // e.g. Set<String> - type = Set.class, genTypeVal = String.class
+               } else if (type == Set.class) {
+                       retObj = getParamSetObject(genTypeVal, paramBytes);
+               // List
+               } else if (type == List.class) {
+                       retObj = getParamListObject(genTypeVal, paramBytes);
+               // Map
+               // e.g. Map<String,Integer> - type = Map.class, genTypeKey = String.class, genTypeVal = Integer.class
+               } else if (type == Map.class) {
+                       retObj = getParamMapObject(genTypeKey, genTypeVal, paramBytes);
                } else
-                       throw new Error("IoTRMIUtil: Unrecognizable type: " + type);
+                       throw new Error("IoTRMIUtil: Unrecognizable type: " + type.getName());
+               
+               return retObj;
+       }
+
+
+       /**
+        * getParamObjectArray() converts byte array of certain object type into array of Objects
+        */
+       public static Object getParamObjectArray(Class<?> type, byte[] paramBytes) {
+               
+               Object retObj = null;
+               if ((type == byte[].class)      ||
+                       (type == byte.class)) {
+                       retObj = (Object) paramBytes;
+               } else if ( (type == Byte[].class) ||
+                                       (type == Byte.class)) {
+                       retObj = (Object) byteArrayToByteArray(paramBytes);
+               } else if ( (type == short[].class) ||
+                                       (type == short.class)) {
+                       retObj = (Object) byteArrayToShtArray(paramBytes);
+               } else if ( (type == Short[].class) ||
+                                       (type == Short.class)) {
+                       retObj = (Object) byteArrayToShortArray(paramBytes);
+               } else if (     (type == int[].class) ||
+                                       (type == int.class)) {
+                       retObj = (Object) byteArrayToIntArray(paramBytes);
+               } else if (     (type == Integer[].class) ||
+                                       (type == Integer.class)) {
+                       retObj = (Object) byteArrayToIntegerArray(paramBytes);
+               } else if (     (type == long[].class) ||
+                                       (type == long.class)) {
+                       retObj = (Object) byteArrayToLngArray(paramBytes);
+               } else if (     (type == Long[].class) ||
+                                       (type == Long.class)) {
+                       retObj = (Object) byteArrayToLongArray(paramBytes);
+               } else if (     (type == float[].class) ||
+                                       (type == float.class)) {
+                       retObj = (Object) byteArrayToFltArray(paramBytes);
+               } else if (     (type == Float[].class) ||
+                                       (type == Float.class)) {
+                       retObj = (Object) byteArrayToFloatArray(paramBytes);
+               } else if (     (type == double[].class) ||
+                                       (type == double.class)) {
+                       retObj = (Object) byteArrayToDblArray(paramBytes);
+               } else if ( (type == Double[].class) ||
+                                       (type == Double.class)) {
+                       retObj = (Object) byteArrayToDoubleArray(paramBytes);
+               } else if (     (type == boolean[].class) || 
+                                       (type == boolean.class)) {
+                       retObj = (Object) byteArrayToBolArray(paramBytes);
+               } else if (     (type == Boolean[].class) ||
+                                       (type == Boolean.class)) {
+                       retObj = (Object) byteArrayToBooleanArray(paramBytes);
+               } else if (     (type == char[].class) ||
+                                       (type == char.class)) {
+                       retObj = (Object) byteArrayToChrArray(paramBytes);
+               } else if (     (type == Character[].class) ||
+                                       (type == Character.class)) {
+                       retObj = (Object) byteArrayToCharacterArray(paramBytes);
+               } else if ( (type == String[].class) ||
+                                       (type == String.class)) {
+                       retObj = (Object) byteArrayToStringArray(paramBytes);
+               } else
+                       throw new Error("IoTRMIUtil: Unrecognizable type: " + type.getName());
                
                return retObj;
        }
@@ -186,21 +305,338 @@ public class IoTRMIUtil {
                } else if (obj instanceof Boolean) {
                        retObjBytes = booleanToByteArray((boolean) obj);
                } else if (obj instanceof String) {
-                       retObjBytes = ((String) obj).getBytes();
+                       retObjBytes = stringToByteArray((String) obj);
+               // Arrays
+               } else if (obj.getClass().isArray()) {
+                       retObjBytes = getArrayObjectBytes(obj);
+               // Set and its implementations
+               } else if (obj instanceof Set<?>) {
+                       retObjBytes = setToByteArray((Set<?>) obj);
+               // List and its implementations
+               } else if (obj instanceof List<?>) {
+                       retObjBytes = listToByteArray((List<?>) obj);
+               // Map and its implementations
+               } else if (obj instanceof Map<?,?>) {
+                       retObjBytes = mapToByteArray((Map<?,?>) obj);
                } else
-                       throw new Error("IoTRMIUtil: Unrecognizable object: " + obj);
+                       throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
 
                return retObjBytes;
        }
-       
+
+
+       /**
+        * getArrayObjectBytes() converts array of objects into bytes array
+        */
+       public static byte[] getArrayObjectBytes(Object obj) {
+
+               byte[] retObjBytes = null;
+               if (obj instanceof byte[]) {
+                       retObjBytes = (byte[]) obj;
+               } else if (obj instanceof Byte[]) {
+                       retObjBytes = arrByteToByteArray((Byte[]) obj);
+               } else if (obj instanceof short[]) {
+                       retObjBytes = arrShortToByteArray((short[]) obj);
+               } else if (obj instanceof Short[]) {
+                       retObjBytes = arrShortToByteArray((Short[]) obj);
+               } else if (obj instanceof int[]) {
+                       retObjBytes = arrIntToByteArray((int[]) obj);
+               } else if (obj instanceof Integer[]) {
+                       retObjBytes = arrIntToByteArray((Integer[]) obj);
+               } else if (obj instanceof long[]) {
+                       retObjBytes = arrLongToByteArray((long[]) obj);
+               } else if (obj instanceof Long[]) {
+                       retObjBytes = arrLongToByteArray((Long[]) obj);
+               } else if (obj instanceof float[]) {
+                       retObjBytes = arrFloatToByteArray((float[]) obj);
+               } else if (obj instanceof Float[]) {
+                       retObjBytes = arrFloatToByteArray((Float[]) obj);
+               } else if (obj instanceof double[]) {
+                       retObjBytes = arrDoubleToByteArray((double[]) obj);
+               } else if (obj instanceof Double[]) {
+                       retObjBytes = arrDoubleToByteArray((Double[]) obj);
+               } else if (obj instanceof char[]) {
+                       retObjBytes = arrCharToByteArray((char[]) obj);
+               } else if (obj instanceof Character[]) {
+                       retObjBytes = arrCharToByteArray((Character[]) obj);
+               } else if (obj instanceof boolean[]) {
+                       retObjBytes = arrBooleanToByteArray((boolean[]) obj);
+               } else if (obj instanceof Boolean[]) {
+                       retObjBytes = arrBooleanToByteArray((Boolean[]) obj);
+               } else if (obj instanceof String[]) {
+                       retObjBytes = arrStringToByteArray((String[]) obj);
+               } else
+                       throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
+
+               return retObjBytes;     
+       }
+
+
+       // Collection data structures
+       public static byte[] setToByteArray(Set<?> set) {
+
+               // Find out the class of the type
+               Iterator<?> it = set.iterator();
+               Object[] arrObj = null;
+               Object obj = it.next();
+
+               if (obj instanceof Byte) {
+                       arrObj = set.toArray(new Byte[set.size()]);
+               } else if (obj instanceof Short) {
+                       arrObj = set.toArray(new Short[set.size()]);
+               } else if (obj instanceof Integer) {
+                       arrObj = set.toArray(new Integer[set.size()]);
+               } else if (obj instanceof Long) {
+                       arrObj = set.toArray(new Long[set.size()]);
+               } else if (obj instanceof Float) {
+                       arrObj = set.toArray(new Float[set.size()]);
+               } else if (obj instanceof Double) {
+                       arrObj = set.toArray(new Double[set.size()]);
+               } else if (obj instanceof Character) {
+                       arrObj = set.toArray(new Character[set.size()]);
+               } else if (obj instanceof Boolean) {
+                       arrObj = set.toArray(new Boolean[set.size()]);
+               } else if (obj instanceof String) {
+                       arrObj = set.toArray(new String[set.size()]);
+               } else
+                       throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
+
+               byte[] arrObjBytes = getArrayObjectBytes(arrObj);
+               return arrObjBytes;
+       }
+
+
+       public static byte[] listToByteArray(List<?> list) {
+
+               // Find out the class of the type
+               Iterator<?> it = list.iterator();
+               Object[] arrObj = null;
+               Object obj = it.next();
+
+               if (obj instanceof Byte) {
+                       arrObj = list.toArray(new Byte[list.size()]);
+               } else if (obj instanceof Short) {
+                       arrObj = list.toArray(new Short[list.size()]);
+               } else if (obj instanceof Integer) {
+                       arrObj = list.toArray(new Integer[list.size()]);
+               } else if (obj instanceof Long) {
+                       arrObj = list.toArray(new Long[list.size()]);
+               } else if (obj instanceof Float) {
+                       arrObj = list.toArray(new Float[list.size()]);
+               } else if (obj instanceof Double) {
+                       arrObj = list.toArray(new Double[list.size()]);
+               } else if (obj instanceof Character) {
+                       arrObj = list.toArray(new Character[list.size()]);
+               } else if (obj instanceof Boolean) {
+                       arrObj = list.toArray(new Boolean[list.size()]);
+               } else if (obj instanceof String) {
+                       arrObj = list.toArray(new String[list.size()]);
+               } else
+                       throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
+
+               byte[] arrObjBytes = getArrayObjectBytes(arrObj);
+               return arrObjBytes;
+       }
+
+
+       // Convert keySet of a Map
+       public static byte[] mapKeyToByteArray(Map<?,?> map) {
+
+               // Map<K,V>
+               // Find out the class of the type for K
+               Iterator<?> it = map.keySet().iterator();
+               Object[] arrObj = null;
+               Object obj = it.next();
+
+               if (obj instanceof Byte) {
+                       arrObj = map.keySet().toArray(new Byte[map.size()]);
+               } else if (obj instanceof Short) {
+                       arrObj = map.keySet().toArray(new Short[map.size()]);
+               } else if (obj instanceof Integer) {
+                       arrObj = map.keySet().toArray(new Integer[map.size()]);
+               } else if (obj instanceof Long) {
+                       arrObj = map.keySet().toArray(new Long[map.size()]);
+               } else if (obj instanceof Float) {
+                       arrObj = map.keySet().toArray(new Float[map.size()]);
+               } else if (obj instanceof Double) {
+                       arrObj = map.keySet().toArray(new Double[map.size()]);
+               } else if (obj instanceof Character) {
+                       arrObj = map.keySet().toArray(new Character[map.size()]);
+               } else if (obj instanceof Boolean) {
+                       arrObj = map.keySet().toArray(new Boolean[map.size()]);
+               } else if (obj instanceof String) {
+                       arrObj = map.keySet().toArray(new String[map.size()]);
+               } else
+                       throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
+               byte[] arrObjBytes = getArrayObjectBytes(arrObj);
+
+               return arrObjBytes;
+       }
+
+
+       // Convert entrySet of a Map
+       public static byte[] mapEntryToByteArray(Map<?,?> map) {
+
+               // Map<K,V>
+               // Find out the class of the type for V
+               Iterator<?> it = map.values().iterator();
+               Object[] arrObj = null;
+               Object obj = it.next();
+
+               if (obj instanceof Byte) {
+                       arrObj = map.values().toArray(new Byte[map.size()]);
+               } else if (obj instanceof Short) {
+                       arrObj = map.values().toArray(new Short[map.size()]);
+               } else if (obj instanceof Integer) {
+                       arrObj = map.values().toArray(new Integer[map.size()]);
+               } else if (obj instanceof Long) {
+                       arrObj = map.values().toArray(new Long[map.size()]);
+               } else if (obj instanceof Float) {
+                       arrObj = map.values().toArray(new Float[map.size()]);
+               } else if (obj instanceof Double) {
+                       arrObj = map.values().toArray(new Double[map.size()]);
+               } else if (obj instanceof Character) {
+                       arrObj = map.values().toArray(new Character[map.size()]);
+               } else if (obj instanceof Boolean) {
+                       arrObj = map.values().toArray(new Boolean[map.size()]);
+               } else if (obj instanceof String) {
+                       arrObj = map.values().toArray(new String[map.size()]);
+               } else
+                       throw new Error("IoTRMIUtil: Unrecognizable object: " + obj.getClass());
+
+               byte[] arrObjBytes = getArrayObjectBytes(arrObj);
+               return arrObjBytes;
+       }
+
+
+       // Merge keySet and entrySet of a Map into one long byte array
+       public static byte[] mapToByteArray(Map<?,?> map) {
+
+               // Put map size in the packet
+               byte[] numEntries = intToByteArray(map.size());
+               byte[] keySetBytes = mapKeyToByteArray(map);
+               byte[] entrySetBytes = mapEntryToByteArray(map);
+               byte[] mapBytes = new byte[INT_LEN + keySetBytes.length + entrySetBytes.length];
+               // Copy the bytes
+               System.arraycopy(numEntries, 0, mapBytes, 0, INT_LEN);
+               System.arraycopy(keySetBytes, 0, mapBytes, INT_LEN, keySetBytes.length);
+               System.arraycopy(entrySetBytes, 0, mapBytes, (INT_LEN + keySetBytes.length), entrySetBytes.length);
+
+               return mapBytes;
+       }
+
+
+       // Get a Set object from bytes
+       public static Object getParamSetObject(Class<?> genericType, byte[] paramBytes) {
+
+               Set<Object> retSet = new HashSet<Object>();
+               Object retObj = null;
+               if (genericType == Byte.class) {
+                       Byte[] retArr = byteArrayToByteArray(paramBytes);
+                       Collections.addAll(retSet, retArr);
+               } else if (genericType == Short.class) {
+                       Short[] retArr = byteArrayToShortArray(paramBytes);
+                       Collections.addAll(retSet, retArr);
+               } else if (genericType == Integer.class) {
+                       Integer[] retArr = byteArrayToIntegerArray(paramBytes);
+                       Collections.addAll(retSet, retArr);
+               } else if (genericType == Long.class) {
+                       Long[] retArr = byteArrayToLongArray(paramBytes);
+                       Collections.addAll(retSet, retArr);
+               } else if (genericType == Float.class) {
+                       Float[] retArr = byteArrayToFloatArray(paramBytes);
+                       Collections.addAll(retSet, retArr);
+               } else if (genericType == Double.class) {
+                       Double[] retArr = byteArrayToDoubleArray(paramBytes);
+                       Collections.addAll(retSet, retArr);
+               } else if (genericType == Boolean.class) {
+                       Boolean[] retArr = byteArrayToBooleanArray(paramBytes);
+                       Collections.addAll(retSet, retArr);
+               } else if (genericType == Character.class) {
+                       Character[] retArr = byteArrayToCharacterArray(paramBytes);
+                       Collections.addAll(retSet, retArr);
+               } else if (genericType == String.class) {
+                       String[] retArr = byteArrayToStringArray(paramBytes);
+                       Collections.addAll(retSet, retArr);
+               } else
+                       throw new Error("IoTRMIUtil: Unrecognizable object: " + genericType.getSimpleName());
+
+               return retSet;
+       }
+
+
+       // Get a List object from bytes
+       public static Object getParamListObject(Class<?> genericType, byte[] paramBytes) {
+
+               List<Object> retList = new ArrayList<Object>();
+               Object retObj = null;
+               if (genericType == Byte.class) {
+                       Byte[] retArr = byteArrayToByteArray(paramBytes);
+                       Collections.addAll(retList, retArr);
+               } else if (genericType == Short.class) {
+                       Short[] retArr = byteArrayToShortArray(paramBytes);
+                       Collections.addAll(retList, retArr);
+               } else if (genericType == Integer.class) {
+                       Integer[] retArr = byteArrayToIntegerArray(paramBytes);
+                       Collections.addAll(retList, retArr);
+               } else if (genericType == Long.class) {
+                       Long[] retArr = byteArrayToLongArray(paramBytes);
+                       Collections.addAll(retList, retArr);
+               } else if (genericType == Float.class) {
+                       Float[] retArr = byteArrayToFloatArray(paramBytes);
+                       Collections.addAll(retList, retArr);
+               } else if (genericType == Double.class) {
+                       Double[] retArr = byteArrayToDoubleArray(paramBytes);
+                       Collections.addAll(retList, retArr);
+               } else if (genericType == Boolean.class) {
+                       Boolean[] retArr = byteArrayToBooleanArray(paramBytes);
+                       Collections.addAll(retList, retArr);
+               } else if (genericType == Character.class) {
+                       Character[] retArr = byteArrayToCharacterArray(paramBytes);
+                       Collections.addAll(retList, retArr);
+               } else if (genericType == String.class) {
+                       String[] retArr = byteArrayToStringArray(paramBytes);
+                       Collections.addAll(retList, retArr);
+               } else
+                       throw new Error("IoTRMIUtil: Unrecognizable object: " + genericType.getSimpleName());
+
+               return retList;
+       }
+
+
+       // Get a Key array for Map object from bytes
+       public static Object getParamMapObject(Class<?> genTypeKey, Class<?> genTypeVal, byte[] paramBytes) {
+
+               // The complete set of bytes always consists of all keys followed by all values - <K,V> pairs
+               // Calculate number of elements
+               byte[] numElBytes = new byte[INT_LEN];
+               System.arraycopy(paramBytes, 0, numElBytes, 0, INT_LEN);
+               int numEl = byteArrayToInt(numElBytes);
+               int keyLen = numEl * getTypeSize(genTypeKey);
+               int valLen = numEl * getTypeSize(genTypeVal);
+               byte[] prmKeyBytes = new byte[keyLen];
+               byte[] prmValBytes = new byte[valLen];
+               // Copy bytes
+               System.arraycopy(paramBytes, INT_LEN, prmKeyBytes, 0, keyLen);
+               System.arraycopy(paramBytes, (INT_LEN + keyLen), prmValBytes, 0, valLen);
+               // Get array of keys
+               Object[] retObjKey = (Object[]) getParamObjectArray(genTypeKey, prmKeyBytes);
+               Object[] retObjVal = (Object[]) getParamObjectArray(genTypeVal, prmValBytes);
+               // Put everything back to a Map
+               Map<Object,Object> retMap = new HashMap<Object,Object>();
+               IoTRMITypes.arraysToMap(retMap, retObjKey, retObjVal);
+
+               return retMap;
+       }
+
 
        /**
         * Converters to byte array
         */
-       // Single variables
+       // Single variables     
        public static byte[] shortToByteArray(short s) {
 
-               ByteBuffer bb = ByteBuffer.allocate(2);
+               ByteBuffer bb = ByteBuffer.allocate(SHT_LEN);
                bb.putShort(s);
 
                return bb.array();
@@ -209,7 +645,7 @@ public class IoTRMIUtil {
 
        public static byte[] intToByteArray(int i) {
 
-               ByteBuffer bb = ByteBuffer.allocate(4);
+               ByteBuffer bb = ByteBuffer.allocate(INT_LEN);
                bb.putInt(i);
 
                return bb.array();
@@ -218,7 +654,7 @@ public class IoTRMIUtil {
 
        public static byte[] longToByteArray(long l) {
 
-               ByteBuffer bb = ByteBuffer.allocate(8);
+               ByteBuffer bb = ByteBuffer.allocate(LNG_LEN);
                bb.putLong(l);
 
                return bb.array();
@@ -227,7 +663,7 @@ public class IoTRMIUtil {
 
        public static byte[] floatToByteArray(float f) {
 
-               ByteBuffer bb = ByteBuffer.allocate(4);
+               ByteBuffer bb = ByteBuffer.allocate(FLT_LEN);
                bb.putFloat(f);
 
                return bb.array();
@@ -236,7 +672,7 @@ public class IoTRMIUtil {
 
        public static byte[] doubleToByteArray(double d) {
 
-               ByteBuffer bb = ByteBuffer.allocate(8);
+               ByteBuffer bb = ByteBuffer.allocate(DBL_LEN);
                bb.putDouble(d);
 
                return bb.array();
@@ -245,7 +681,7 @@ public class IoTRMIUtil {
 
        public static byte[] charToByteArray(char c) {
 
-               ByteBuffer bb = ByteBuffer.allocate(2);
+               ByteBuffer bb = ByteBuffer.allocate(CHR_LEN);
                bb.putChar(c);
 
                return bb.array();
@@ -254,7 +690,7 @@ public class IoTRMIUtil {
 
        public static byte[] booleanToByteArray(boolean b) {
 
-               ByteBuffer bb = ByteBuffer.allocate(1);
+               ByteBuffer bb = ByteBuffer.allocate(BOL_LEN);
                if (b)
                        bb.put((byte)1);
                else
@@ -264,10 +700,27 @@ public class IoTRMIUtil {
        }
 
 
+       public static byte[] stringToByteArray(String str) {
+
+               return str.getBytes();
+       }
+
+
        // Arrays
+       public static byte[] arrByteToByteArray(Byte[] arrByte) {
+
+               byte[] arrByt = new byte[arrByte.length];
+               for(int i = 0; i < arrByte.length; i++) {
+                       arrByt[i] = arrByte[i];
+               }
+
+               return arrByt;
+       }
+
+
        public static byte[] arrShortToByteArray(short[] arrShort) {
 
-               ByteBuffer bb = ByteBuffer.allocate(2 * arrShort.length);
+               ByteBuffer bb = ByteBuffer.allocate(SHT_LEN * arrShort.length);
                for(short s : arrShort) {
                        bb.putShort(s);
                }
@@ -276,9 +729,20 @@ public class IoTRMIUtil {
        }
 
 
+       public static byte[] arrShortToByteArray(Short[] arrShort) {
+
+               ByteBuffer bb = ByteBuffer.allocate(SHT_LEN * arrShort.length);
+               for(Short s : arrShort) {
+                       bb.putShort(s);
+               }
+
+               return bb.array();
+       }
+
+
        public static byte[] arrIntToByteArray(int[] arrInt) {
 
-               ByteBuffer bb = ByteBuffer.allocate(4 * arrInt.length);
+               ByteBuffer bb = ByteBuffer.allocate(INT_LEN * arrInt.length);
                for(int i : arrInt) {
                        bb.putInt(i);
                }
@@ -287,9 +751,20 @@ public class IoTRMIUtil {
        }
 
 
+       public static byte[] arrIntToByteArray(Integer[] arrInt) {
+
+               ByteBuffer bb = ByteBuffer.allocate(INT_LEN * arrInt.length);
+               for(Integer i : arrInt) {
+                       bb.putInt(i);
+               }
+
+               return bb.array();
+       }
+
+
        public static byte[] arrLongToByteArray(long[] arrLong) {
 
-               ByteBuffer bb = ByteBuffer.allocate(8 * arrLong.length);
+               ByteBuffer bb = ByteBuffer.allocate(LNG_LEN * arrLong.length);
                for(long l : arrLong) {
                        bb.putLong(l);
                }
@@ -298,9 +773,20 @@ public class IoTRMIUtil {
        }
 
 
+       public static byte[] arrLongToByteArray(Long[] arrLong) {
+
+               ByteBuffer bb = ByteBuffer.allocate(LNG_LEN * arrLong.length);
+               for(Long l : arrLong) {
+                       bb.putLong(l);
+               }
+
+               return bb.array();
+       }
+
+
        public static byte[] arrFloatToByteArray(float[] arrFloat) {
 
-               ByteBuffer bb = ByteBuffer.allocate(4 * arrFloat.length);
+               ByteBuffer bb = ByteBuffer.allocate(FLT_LEN * arrFloat.length);
                for(float f : arrFloat) {
                        bb.putFloat(f);
                }
@@ -309,9 +795,20 @@ public class IoTRMIUtil {
        }
 
 
+       public static byte[] arrFloatToByteArray(Float[] arrFloat) {
+
+               ByteBuffer bb = ByteBuffer.allocate(FLT_LEN * arrFloat.length);
+               for(Float f : arrFloat) {
+                       bb.putFloat(f);
+               }
+
+               return bb.array();
+       }
+
+
        public static byte[] arrDoubleToByteArray(double[] arrDouble) {
 
-               ByteBuffer bb = ByteBuffer.allocate(8 * arrDouble.length);
+               ByteBuffer bb = ByteBuffer.allocate(DBL_LEN * arrDouble.length);
                for(double d : arrDouble) {
                        bb.putDouble(d);
                }
@@ -320,9 +817,20 @@ public class IoTRMIUtil {
        }
 
 
+       public static byte[] arrDoubleToByteArray(Double[] arrDouble) {
+
+               ByteBuffer bb = ByteBuffer.allocate(DBL_LEN * arrDouble.length);
+               for(Double d : arrDouble) {
+                       bb.putDouble(d);
+               }
+
+               return bb.array();
+       }
+
+
        public static byte[] arrCharToByteArray(char[] arrChar) {
 
-               ByteBuffer bb = ByteBuffer.allocate(2 * arrChar.length);
+               ByteBuffer bb = ByteBuffer.allocate(CHR_LEN * arrChar.length);
                for(char c : arrChar) {
                        bb.putChar(c);
                }
@@ -331,9 +839,20 @@ public class IoTRMIUtil {
        }
 
 
+       public static byte[] arrCharToByteArray(Character[] arrChar) {
+
+               ByteBuffer bb = ByteBuffer.allocate(CHR_LEN * arrChar.length);
+               for(Character c : arrChar) {
+                       bb.putChar(c);
+               }
+
+               return bb.array();
+       }
+
+
        public static byte[] arrBooleanToByteArray(boolean[] arrBool) {
 
-               ByteBuffer bb = ByteBuffer.allocate(1 * arrBool.length);
+               ByteBuffer bb = ByteBuffer.allocate(BOL_LEN * arrBool.length);
                for(boolean b : arrBool) {
                        if (b)
                                bb.put((byte)1);
@@ -345,10 +864,55 @@ public class IoTRMIUtil {
        }
 
 
+       public static byte[] arrBooleanToByteArray(Boolean[] arrBool) {
+
+               ByteBuffer bb = ByteBuffer.allocate(BOL_LEN * arrBool.length);
+               for(Boolean b : arrBool) {
+                       if (b)
+                               bb.put((byte)1);
+                       else
+                               bb.put((byte)0);
+               }
+
+               return bb.array();
+       }
+
+
+       public static byte[] arrStringToByteArray(String[] arrString) {
+
+               // Format of bytes: | array length | length #1 | string #1 | length #2 | string #2 | ...
+               // Prepare array of bytes
+               int arrLen = INT_LEN;   // First allocation for array length
+               for (int i = 0; i < arrString.length; i++) {
+                       arrLen = arrLen + INT_LEN + arrString[i].length();
+               }       
+               byte[] arrStrBytes = new byte[arrLen];
+               // Copy bytes
+               int pos = 0;
+               byte[] strArrLenBytes = intToByteArray(arrString.length);
+               System.arraycopy(strArrLenBytes, 0, arrStrBytes, pos, INT_LEN);
+               pos = pos + INT_LEN;
+               for (String str : arrString) {
+
+                       // Copy string length
+                       int strLen = str.length();
+                       byte[] strLenBytes = intToByteArray(strLen);
+                       System.arraycopy(strLenBytes, 0, arrStrBytes, pos, INT_LEN);
+                       pos = pos + INT_LEN;
+                       // Copy string
+                       byte[] strBytes = stringToByteArray(str);
+                       System.arraycopy(strBytes, 0, arrStrBytes, pos, strLen);
+                       pos = pos + strLen;
+               }
+
+               return arrStrBytes;
+       }
+
+
        /**
         * Converters from byte array
         */
-       // Single variables
+       // Single variables     
        public static short byteArrayToShort(byte[] bytes) {
 
                return ByteBuffer.wrap(bytes).getShort();
@@ -396,11 +960,291 @@ public class IoTRMIUtil {
        }
 
 
-    public static String toString(byte[] bytes) {
+    public static String byteArrayToString(byte[] bytes) {
         return new String(bytes);
     }
 
 
+       // Arrays
+       public static Byte[] byteArrayToByteArray(byte[] arrByt) {
+
+               Byte[] arrByte = new Byte[arrByt.length];
+               for(int i = 0; i < arrByt.length; i++) {
+                       arrByte[i] = arrByt[i];
+               }
+
+               return arrByte;
+       }
+       
+       
+       public static short[] byteArrayToShtArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[SHT_LEN];
+               // Prepare array
+               int arrLen = bytes.length / SHT_LEN;
+               short[] arr = new short[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * SHT_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, SHT_LEN);              
+                       arr[i] = byteArrayToShort(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static Short[] byteArrayToShortArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[SHT_LEN];
+               // Prepare array
+               int arrLen = bytes.length / SHT_LEN;
+               Short[] arr = new Short[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * SHT_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, SHT_LEN);              
+                       arr[i] = byteArrayToShort(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static int[] byteArrayToIntArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[INT_LEN];
+               // Prepare array
+               int arrLen = bytes.length / INT_LEN;
+               int[] arr = new int[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * INT_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, INT_LEN);              
+                       arr[i] = byteArrayToInt(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static Integer[] byteArrayToIntegerArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[INT_LEN];
+               // Prepare array
+               int arrLen = bytes.length / INT_LEN;
+               Integer[] arr = new Integer[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * INT_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, INT_LEN);
+                       arr[i] = byteArrayToInt(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static long[] byteArrayToLngArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[LNG_LEN];
+               // Prepare array
+               int arrLen = bytes.length / LNG_LEN;
+               long[] arr = new long[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * LNG_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, LNG_LEN);              
+                       arr[i] = byteArrayToLong(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static Long[] byteArrayToLongArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[LNG_LEN];
+               // Prepare array
+               int arrLen = bytes.length / LNG_LEN;
+               Long[] arr = new Long[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * LNG_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, LNG_LEN);
+                       arr[i] = byteArrayToLong(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static float[] byteArrayToFltArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[FLT_LEN];
+               // Prepare array
+               int arrLen = bytes.length / FLT_LEN;
+               float[] arr = new float[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * FLT_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, FLT_LEN);              
+                       arr[i] = byteArrayToFloat(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static Float[] byteArrayToFloatArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[FLT_LEN];
+               // Prepare array
+               int arrLen = bytes.length / FLT_LEN;
+               Float[] arr = new Float[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * FLT_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, FLT_LEN);
+                       arr[i] = byteArrayToFloat(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static double[] byteArrayToDblArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[DBL_LEN];
+               // Prepare array
+               int arrLen = bytes.length / DBL_LEN;
+               double[] arr = new double[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * DBL_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, DBL_LEN);
+                       arr[i] = byteArrayToDouble(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static Double[] byteArrayToDoubleArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[DBL_LEN];
+               // Prepare array
+               int arrLen = bytes.length / DBL_LEN;
+               Double[] arr = new Double[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * DBL_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, DBL_LEN);
+                       arr[i] = byteArrayToDouble(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static char[] byteArrayToChrArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[CHR_LEN];
+               // Prepare array
+               int arrLen = bytes.length / CHR_LEN;
+               char[] arr = new char[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * CHR_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, CHR_LEN);
+                       arr[i] = byteArrayToChar(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static Character[] byteArrayToCharacterArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[CHR_LEN];
+               // Prepare array
+               int arrLen = bytes.length / CHR_LEN;
+               Character[] arr = new Character[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * CHR_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, CHR_LEN);
+                       arr[i] = byteArrayToChar(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static boolean[] byteArrayToBolArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[BOL_LEN];
+               // Prepare array
+               int arrLen = bytes.length / BOL_LEN;
+               boolean[] arr = new boolean[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * BOL_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, BOL_LEN);
+                       arr[i] = byteArrayToBoolean(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static Boolean[] byteArrayToBooleanArray(byte[] bytes) {
+
+               // Single element bytes
+               byte[] elmt = new byte[BOL_LEN];
+               // Prepare array
+               int arrLen = bytes.length / BOL_LEN;
+               Boolean[] arr = new Boolean[arrLen];
+               for(int i = 0; i < arrLen; i++) {
+                       int offset = i * BOL_LEN;
+                       System.arraycopy(bytes, offset, elmt, 0, BOL_LEN);
+                       arr[i] = byteArrayToBoolean(elmt);
+               }
+
+               return arr;
+       }
+
+
+       public static String[] byteArrayToStringArray(byte[] bytes) {
+
+               // Format of bytes: | array length | length #1 | string #1 | length #2 | string #2 | ...
+               // Get string array length
+               int pos = 0;
+               byte[] strArrLenBytes = new byte[INT_LEN];
+               System.arraycopy(bytes, pos, strArrLenBytes, 0, INT_LEN);
+               int strArrLen = byteArrayToInt(strArrLenBytes);
+               pos = pos + INT_LEN;
+               // Prepare string array
+               String[] strArray = new String[strArrLen];
+               // Extract array of strings
+               for(int i = 0; i < strArrLen; i++) {
+
+                       // Extract string length
+                       byte[] strLenBytes = new byte[INT_LEN];
+                       System.arraycopy(bytes, pos, strLenBytes, 0, INT_LEN);
+                       int strLen = byteArrayToInt(strLenBytes);
+                       pos = pos + INT_LEN;
+                       // Extract string
+                       byte[] strBytes = new byte[strLen];
+                       System.arraycopy(bytes, pos, strBytes, 0, strLen);
+                       pos = pos + strLen;
+                       strArray[i] = byteArrayToString(strBytes);
+               }
+
+               return strArray;
+       }
+
+
        /**
         * toByteArray() gets Object and return its byte array
         * <p>
index f941e91..60aac84 100644 (file)
@@ -68,6 +68,8 @@ public abstract class IoTSocket {
                int i;
                int totalbytes = 0;
                int numbytes;
+               // Wait until input is available
+               while(input.available() == 0);
                // Read the maxlen first
                int maxlen = (int)input.read();
                if (maxlen>BUFFSIZE)
diff --git a/iotjava/iotrmi/Java/sample/CallBack.java b/iotjava/iotrmi/Java/sample/CallBack.java
new file mode 100644 (file)
index 0000000..9c4c368
--- /dev/null
@@ -0,0 +1,30 @@
+package iotrmi.Java.sample;
+
+public class CallBack implements CallBackInterface {
+
+       /**
+        * Class Properties
+        */
+       private int intA;
+
+       /**
+        * Constructors
+        */
+       public CallBack(int _i) {
+
+               intA = _i;
+       }
+
+
+       public int printInt() {
+
+               System.out.println("Integer: " + intA);
+               return intA;
+       }
+
+
+       public void setInt(int _i) {
+
+               intA = _i;
+       }
+}
diff --git a/iotjava/iotrmi/Java/sample/CallBackInterface.java b/iotjava/iotrmi/Java/sample/CallBackInterface.java
new file mode 100644 (file)
index 0000000..e29359f
--- /dev/null
@@ -0,0 +1,8 @@
+package iotrmi.Java.sample;
+
+public interface CallBackInterface {
+
+       public int printInt();
+       public void setInt(int _i);
+
+}
diff --git a/iotjava/iotrmi/Java/sample/CallBack_Skeleton.java b/iotjava/iotrmi/Java/sample/CallBack_Skeleton.java
new file mode 100644 (file)
index 0000000..46e0df6
--- /dev/null
@@ -0,0 +1,71 @@
+package iotrmi.Java.sample;
+
+import java.io.IOException;
+import java.util.Set;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMIObject;
+
+public class CallBack_Skeleton {
+
+       private String[] methodSignatures = {
+
+               "intprintInt()",
+               "voidsetInt(int)"
+       };
+
+       private CallBackInterface cb;
+       private IoTRMIObject rmiObj;
+
+
+       /**
+        * Constructors
+        */
+       public CallBack_Skeleton(CallBackInterface _cb, int _port) throws
+               ClassNotFoundException, InstantiationException,
+                       IllegalAccessException, IOException {
+
+               cb = _cb;
+               System.out.println("Creating CallBack_Skeleton and waiting!");
+               rmiObj = new IoTRMIObject(_port, methodSignatures);
+       }
+
+
+       public void waitRequestInvokeMethod() throws IOException {
+
+               // Loop continuously waiting for incoming bytes
+               while (true) {
+
+                       rmiObj.getMethodBytes();
+                       String methodSign = rmiObj.getSignature();
+                       Object[] paramObj = null;
+                       Object retObj = null;
+                       System.out.println("Method sign: " + methodSign);
+
+                       if (methodSign.equals("intprintInt()")) {
+                               //paramObj = rmiObj.getMethodParams(new Class<?>[] { }, 
+                               //      new Class<?>[] { null }, new Class<?>[] { null });
+                               retObj = cb.printInt();
+                       } else if (methodSign.equals("voidsetInt(int)")) {
+                               paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class }, 
+                                       new Class<?>[] { null }, new Class<?>[] { null });
+                               cb.setInt((int) paramObj[0]);
+                       } else
+                               throw new Error("Signature un-recognized!");
+                       System.out.println("Return object: " + retObj);
+
+                       if (retObj != null) {
+                               rmiObj.sendReturnObj(retObj);
+                       }
+                       System.out.println("Servicing remote call for method: " + methodSign);
+               }
+       }
+
+
+       public static void main(String[] args) throws Exception {
+
+               int port = 5010;
+               CallBack cb = new CallBack(23);
+               CallBack_Skeleton cbSkel = new CallBack_Skeleton(cb, port);
+               cbSkel.waitRequestInvokeMethod();
+       }
+}
diff --git a/iotjava/iotrmi/Java/sample/CallBack_Stub.java b/iotjava/iotrmi/Java/sample/CallBack_Stub.java
new file mode 100644 (file)
index 0000000..3ec19d5
--- /dev/null
@@ -0,0 +1,53 @@
+package iotrmi.Java.sample;
+
+import java.io.IOException;
+import iotrmi.Java.IoTRMICall;
+
+public class CallBack_Stub implements CallBackInterface {
+
+       /**
+        * Class Properties
+        */
+       private IoTRMICall rmiCall;
+
+       /**
+        * Constructors
+        */
+       public CallBack_Stub(int _port, String _address, int _rev) throws IOException {
+
+               rmiCall = new IoTRMICall(_port, _address, _rev);
+       }
+
+
+       public int printInt() {
+
+               String sign = "intprintInt()";
+               Class<?> retType = int.class;
+               Class<?>[] paramCls = new Class<?>[] { };
+               Object[] paramObj = new Object[] { };
+               Object retObj = rmiCall.remoteCall(sign, retType, null, null, paramCls, paramObj);
+               return (int)retObj;
+       }
+
+
+       public void setInt(int _i) {
+
+               String sign = "voidsetInt(int)";
+               Class<?> retType = void.class;
+               Class<?>[] paramCls = new Class<?>[] { int.class };
+               Object[] paramObj = new Object[] { _i };
+               rmiCall.remoteCall(sign, retType, null, null, paramCls, paramObj);
+       }
+
+
+       public static void main(String[] args) throws Exception {
+
+               int port = 5010;
+               String address = "localhost";
+               int rev = 0;
+
+               CallBack_Stub cbstub = new CallBack_Stub(port, address, rev);
+               cbstub.setInt(23);
+               cbstub.printInt();
+       }
+}
diff --git a/iotjava/iotrmi/Java/sample/TestClass.java b/iotjava/iotrmi/Java/sample/TestClass.java
new file mode 100644 (file)
index 0000000..0b9f408
--- /dev/null
@@ -0,0 +1,99 @@
+package iotrmi.Java.sample;
+
+import java.util.Set;
+
+public class TestClass {
+
+       /**
+        * Class Properties
+        */
+       private int intA;
+       private float floatB;
+       private String stringC;
+       private CallBackInterface cb;
+
+       /**
+        * Constructors
+        */
+       public TestClass() {
+
+               intA = 1;
+               floatB = 2;
+               stringC = "345";
+               cb = null;
+       }
+
+
+       public TestClass(int _int, float _float, String _string) {
+
+               intA = _int;
+               floatB = _float;
+               stringC = _string;
+       }
+
+
+       public void setA(int _int) {
+
+               intA = _int;
+       }
+
+
+       public void setB(float _float) {
+
+               floatB = _float;
+       }
+
+
+       public void setC(String _string) {
+
+               stringC = _string;
+       }
+
+
+       // Getters
+       public String sumArray(String[] newA) {
+
+               String sum = "";
+               for (String i : newA) 
+                       sum = sum + i;
+               return sum;
+       }
+
+
+       public int setAndGetA(int newA) {
+
+               intA = newA;
+               return intA;
+       }
+
+
+       public int setACAndGetA(String newC, int newA) {
+
+               stringC = newC;
+               intA = newA;
+               return intA;
+       }
+
+
+       public void registerCallback(CallBackInterface _cb) {
+
+               cb = _cb;
+       }
+
+
+       public int callBack() {
+
+               System.out.println("This callBack function is called inside TestClass!");
+               return cb.printInt();
+       }
+
+
+       public static void main(String[] args) {
+
+               TestClass tc = new TestClass();
+               CallBack cb = new CallBack(3);
+
+               tc.registerCallback(cb);
+               System.out.println("Return value: " + tc.callBack());
+       }
+}
diff --git a/iotjava/iotrmi/Java/sample/TestClass_Skeleton.java b/iotjava/iotrmi/Java/sample/TestClass_Skeleton.java
new file mode 100644 (file)
index 0000000..07dbda8
--- /dev/null
@@ -0,0 +1,103 @@
+package iotrmi.Java.sample;
+
+import java.io.IOException;
+import java.util.Set;
+import iotrmi.Java.IoTRMIObject;
+
+import java.util.Arrays;
+
+public class TestClass_Skeleton {
+
+       private String[] methodSignatures = {
+
+               "voidsetA(int)",
+               "voidsetB(float)",
+               "voidsetC(string)",
+               "sumArray(string[])",
+               "intsetAndGetA(int)",
+               "intsetACAndGetA(string,int)",
+               "intcallBack()",
+               "voidregisterCallBack(CallBackInterface)"
+       };
+
+       private TestClass tc;
+       private IoTRMIObject rmiObj;
+       private CallBackInterface cbstub;
+
+
+       /**
+        * Constructors
+        */
+       //public TestClass_Skeleton(Object[] paramObj, int _port) throws
+       public TestClass_Skeleton(TestClass _tc, int _port) throws
+               ClassNotFoundException, InstantiationException,
+                       IllegalAccessException, IOException {
+
+               //tc = new TestClass((int)paramObj[0], (float)paramObj[1], (String)paramObj[2]);
+               tc = _tc;
+               rmiObj = new IoTRMIObject(_port, methodSignatures);
+       }
+
+
+       public void waitRequestInvokeMethod() throws IOException {
+
+               // Loop continuously waiting for incoming bytes
+               while (true) {
+
+                       rmiObj.getMethodBytes();
+                       String methodSign = rmiObj.getSignature();
+                       Object[] paramObj = null;
+                       Object retObj = null;
+                       System.out.println("Method sign: " + methodSign);
+
+                       if (methodSign.equals("voidsetA(int)")) {
+                               paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class }, 
+                                       new Class<?>[] { null }, new Class<?>[] { null });
+                               tc.setA((int) paramObj[0]);
+                       } else if (methodSign.equals("voidsetB(float)")) {
+                               paramObj = rmiObj.getMethodParams(new Class<?>[] { float.class }, 
+                                       new Class<?>[] { null }, new Class<?>[] { null });
+                               tc.setB((float) paramObj[0]);
+                       } else if (methodSign.equals("voidsetC(string)")) {
+                               paramObj = rmiObj.getMethodParams(new Class<?>[] { String.class }, 
+                                       new Class<?>[] { null }, new Class<?>[] { null });
+                               tc.setC((String) paramObj[0]);
+                       } else if (methodSign.equals("sumArray(string[])")) {
+                               paramObj = rmiObj.getMethodParams(new Class<?>[] { String[].class }, 
+                                       new Class<?>[] { null }, new Class<?>[] { null });
+                               retObj = tc.sumArray((String[]) paramObj[0]);
+                       } else if (methodSign.equals("intsetAndGetA(int)")) {
+                               paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class }, 
+                                       new Class<?>[] { null }, new Class<?>[] { null });
+                               retObj = tc.setAndGetA((int) paramObj[0]);
+                       } else if (methodSign.equals("intsetACAndGetA(string,int)")) {
+                               paramObj = rmiObj.getMethodParams(new Class<?>[] { String.class, int.class }, 
+                                       new Class<?>[] { null, null }, new Class<?>[] { null, null });
+                               retObj = tc.setACAndGetA((String) paramObj[0], (int) paramObj[1]);
+                       } else if (methodSign.equals("voidregisterCallBack(CallBackInterface)")) {
+                               paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class, String.class, int.class }, 
+                                       new Class<?>[] { null, null, null }, new Class<?>[] { null, null, null });
+                               CallBackInterface cbstub = new CallBack_Stub((int) paramObj[0], (String) paramObj[1], (int) paramObj[2]);
+                               tc.registerCallback((CallBackInterface) cbstub);
+                       } else if (methodSign.equals("intcallBack()")) {
+                               retObj = tc.callBack();
+                       } else
+                               throw new Error("Signature un-recognized!");
+
+                       if (retObj != null) {
+                               rmiObj.sendReturnObj(retObj);
+                       }
+                       System.out.println("Servicing remote call for method: " + methodSign);
+               }
+       }
+
+
+       public static void main(String[] args) throws Exception {
+
+               int port = 5010;
+               TestClass tc = new TestClass(3, 5f, "7911");
+               //TestClass_Skeleton tcSkel = new TestClass_Skeleton(new Object[] { 3, 5f, "7911"}, port);
+               TestClass_Skeleton tcSkel = new TestClass_Skeleton(tc, port);
+               tcSkel.waitRequestInvokeMethod();
+       }
+}
diff --git a/iotjava/iotrmi/Java/sample/TestClass_Stub.java b/iotjava/iotrmi/Java/sample/TestClass_Stub.java
new file mode 100644 (file)
index 0000000..a57f036
--- /dev/null
@@ -0,0 +1,167 @@
+package iotrmi.Java.sample;
+
+import java.io.IOException;
+import iotrmi.Java.IoTRMICall;
+import iotruntime.master.CommunicationHandler;
+
+import java.util.Arrays;
+
+public class TestClass_Stub {
+
+       /**
+        * Class Properties
+        */
+       private IoTRMICall rmiCall;
+       private String address;
+       private int[] ports;
+
+       /**
+        * Class Constants
+        */
+       private final static int NUM_CB_OBJ = 1;
+
+       /**
+        * Constructors
+        */
+       public TestClass_Stub(int _port, String _address, int _rev, int[] _ports) throws IOException {
+
+               address = _address;
+               ports = _ports;
+               rmiCall = new IoTRMICall(_port, _address, _rev);
+       }
+
+
+       /**
+        * Instantiation of callback objects
+        */
+       public static int numCallbackObjects() {
+
+               return NUM_CB_OBJ;      // Generated by the IoTCompiler
+       }
+
+
+       private void registerCallback(CallBackInterface _cb) {
+
+               //int port = 5011;      // Send this info to the other end to start the stub
+               //String address = "localhost";
+
+               Thread thread = new Thread() {
+                       public void run() {
+                   try{
+                                       CallBack_Skeleton cbskel = new CallBack_Skeleton(_cb, ports[0]);
+                                       cbskel.waitRequestInvokeMethod();
+                               } catch (Exception ex){
+                                       ex.printStackTrace();
+                                       throw new Error("Error instantiating class CallBack_Skeleton!");
+                   }
+               }
+           };
+               thread.start();
+
+               String sign = "voidregisterCallBack(CallBackInterface)";
+               Class<?> retType = void.class;
+               // port, address, and rev
+               Class<?>[] paramCls = new Class<?>[] { int.class, String.class, int.class };
+               Object[] paramObj = new Object[] { ports[0], address, 0 };
+               rmiCall.remoteCall(sign, retType, null, null, paramCls, paramObj);
+       }
+
+
+       public void setA(int _int) {
+
+               String sign = "voidsetA(int)";
+               Class<?> retType = void.class;
+               Class<?>[] paramCls = new Class<?>[] { int.class };
+               Object[] paramObj = new Object[] { _int };
+               rmiCall.remoteCall(sign, retType, null, null, paramCls, paramObj);
+       }
+
+
+       public void setB(float _float) {
+
+               String sign = "voidsetB(float)";
+               Class<?> retType = void.class;
+               Class<?>[] paramCls = new Class<?>[] { float.class };
+               Object[] paramObj = new Object[] { _float };
+               rmiCall.remoteCall(sign, retType, null, null, paramCls, paramObj);
+       }
+
+
+       public void setC(String _string) {
+
+               String sign = "voidsetC(string)";
+               Class<?> retType = void.class;
+               Class<?>[] paramCls = new Class<?>[] { String.class };
+               Object[] paramObj = new Object[] { _string };
+               rmiCall.remoteCall(sign, retType, null, null, paramCls, paramObj);
+       }
+
+
+       // Getters
+       public String sumArray(String[] newA) {
+
+               String sign = "sumArray(string[])";
+               Class<?> retType = String.class;
+               Class<?>[] paramCls = new Class<?>[] { String[].class };
+               Object[] paramObj = new Object[] { newA };
+               Object retObj = rmiCall.remoteCall(sign, retType, null, null, paramCls, paramObj);
+               return (String)retObj;
+       }
+
+
+       public int setAndGetA(int newA) {
+               String sign = "intsetAndGetA(int)";
+               Class<?> retType = int.class;
+               Class<?>[] paramCls = new Class<?>[] { int.class };
+               Object[] paramObj = new Object[] { newA };
+               Object retObj = rmiCall.remoteCall(sign, retType, null, null, paramCls, paramObj);
+               return (int)retObj;
+       }
+
+
+       public int setACAndGetA(String newC, int newA) {
+
+               String sign = "intsetACAndGetA(string,int)";
+               Class<?> retType = int.class;
+               Class<?>[] paramCls = new Class<?>[] { String.class, int.class };
+               Object[] paramObj = new Object[] { newC, newA };
+               Object retObj = rmiCall.remoteCall(sign, retType, null, null, paramCls, paramObj);
+               return (int)retObj;
+       }
+
+
+       public int callBack() {
+
+               String sign = "intcallBack()";
+               Class<?> retType = int.class;
+               Class<?>[] paramCls = new Class<?>[] { };
+               Object[] paramObj = new Object[] { };
+               Object retObj = rmiCall.remoteCall(sign, retType, null, null, paramCls, paramObj);
+               return (int)retObj;
+
+       }
+
+
+       public static void main(String[] args) throws Exception {
+
+               CommunicationHandler comHan = new CommunicationHandler(true);
+               int numOfPorts = TestClass_Stub.numCallbackObjects();
+               int[] ports = comHan.getCallbackPorts(numOfPorts);
+
+               System.out.println("Allocated ports: " + Arrays.toString(ports));
+
+               int port = 5010;
+               String address = "localhost";
+               int rev = 0;
+
+               TestClass_Stub tcstub = new TestClass_Stub(port, address, rev, ports);
+               System.out.println("Return value: " + tcstub.setAndGetA(123));
+               System.out.println("Return value: " + tcstub.setACAndGetA("string", 123));
+               System.out.println("Return value: " + tcstub.sumArray(new String[] { "123", "456", "987" }));
+
+               CallBack cb = new CallBack(23);
+               tcstub.registerCallback(cb);
+               System.out.println("Return value from callback: " + tcstub.callBack());
+               //System.out.println("Return value: " + tcstub.setAndGetA(1234));
+       }
+}
diff --git a/iotjava/iotruntime/master/CommunicationHandler.java b/iotjava/iotruntime/master/CommunicationHandler.java
new file mode 100644 (file)
index 0000000..1026b0c
--- /dev/null
@@ -0,0 +1,459 @@
+package iotruntime.master;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+/** Class CommunicationHandler is a class that maintains
+ *  a data structure that preserves a collection of host name,
+ *  port numbers, and objects that are running
+ *  +-----------------+----+--------+------------------+--------------+----------------+
+ *  | HOST-ADDRESS    | ...|IN-PORT | RMIREGISTRY-PORT | RMISTUB-PORT | ACTIVE OBJECTS |
+ *  +-----------------+----+--------+------------------+--------------+----------------+
+ *  | XXX.XXX.XXX.XXX |    | XXXXX  | XXXXX            | XXXXX        | XXXXXXXXXXXXXX |
+ *  |                 |    | XXXXX  | XXXXX            | XXXXX        | XXXXXXXXXXXXXX |
+ *  |                 |    | XXXXX  | XXXXX            | XXXXX        | XXXXXXXXXXXXXX |
+ *  |                 | ...| ...    | ...              | ...          | ...            |
+ *  +-----------------+----+--------+------------------+--------------+----------------+
+ *  In this case we use ACTIVE OBJECTS names as the key
+ *  So ACTIVE OBJECTS maps to numbers and these numbers map to each other
+ *  entry in hashmaps (HostAddress can be repetitive)
+ *  e.g. ACTIVE OBJECTS ProximitySensorPS0 - 0
+ *                      ProximitySensorPS1 - 1
+ *                      TempSensorTS1      - 2
+ *                      ...
+ *       IN-PORT / RMIREGISTRY-PORT / RMISTUB-PORT / HOST-ADDRESS: 0 - XXXXX
+ *                                                                 1 - XXXXX
+ *                                                                 2 - XXXXX
+ *  +-------------+
+ *  | DEVICE-PORT |
+ *  +-------------+
+ *  | XXXXX       |
+ *  | XXXXX       |
+ *  | XXXXX       |
+ *  | ...         |
+ *  +-------------+
+ *  We add a Set structure to handle all the other ports that are used by devices
+ *  when communicating with their respective drivers
+ *
+ * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version     1.0
+ * @since       2016-01-07
+ */
+public final class CommunicationHandler {
+
+       /**
+        * CommunicationHandler class properties
+        * <p>
+        * Random, host name, port number, active objects
+        * HostAdd is the key to the table so we use it
+        * as a key to elements
+        * HostList gives a mapping from hostname to list of objects
+        */
+       private Random random;
+       private List<String> listActiveControllerObj;
+       private List<String> listFieldObjectID;
+       private List<ObjectCreationInfo> listObjCrtInfo;
+       private List<Object[]> listArrFieldValues;
+       private List<Class[]> listArrFieldClasses;
+       private Map<String, Integer> hmActiveObj;
+       private Map<Integer, String> hmHostAdd;
+       private Map<String, ArrayList<String> > hmHostList;
+       private Map<Integer, Integer> hmComPort;
+       private Map<Integer, Integer> hmRMIRegPort;
+       private Map<Integer, Integer> hmRMIStubPort;
+       private Set<Integer> hsDevicePort;
+       private Set<Integer> hsCallbackPort;
+       private int iNumOfObjects;
+       private int iNumOfHosts;
+       private boolean bVerbose;
+
+       /**
+        * CommunicationHandler class constants
+        */
+       private final int INT_MAX_PORT = 65535;
+       private final int INT_MIN_PORT = 10000;
+
+       /**
+        * Empty constructor
+        */
+       public CommunicationHandler(boolean _bVerbose) {
+
+               random = new Random();
+               listActiveControllerObj = new ArrayList<String>();
+               listFieldObjectID = new ArrayList<String>();
+               listObjCrtInfo = new ArrayList<ObjectCreationInfo>();
+               listArrFieldValues = new ArrayList<Object[]>();
+               listArrFieldClasses = new ArrayList<Class[]>();
+               hmActiveObj = new HashMap<String, Integer>();
+               hmHostAdd = new HashMap<Integer, String>();
+               hmHostList = new HashMap<String, ArrayList<String>>();
+               hmComPort = new HashMap<Integer, Integer>();
+               hmRMIRegPort = new HashMap<Integer, Integer>();
+               hmRMIStubPort = new HashMap<Integer, Integer>();
+               hsDevicePort = new HashSet<Integer>();
+               hsCallbackPort = new HashSet<Integer>();
+               iNumOfObjects = 0;
+               iNumOfHosts = 0;
+               bVerbose = _bVerbose;
+               RuntimeOutput.print("CommunicationHandler: Creating a new CommunicationHandler object!", bVerbose);
+       }
+
+       /**
+        * Method addPortConnection()
+        * <p>
+        * Add a new connection then generate new in-port and out-port numbers
+        *
+        * @param   sHAddress                   String host address
+        * @param   sAObject                    String active object name
+        * @return  void
+        */
+       public void addPortConnection(String sHAddress, String sAObject) {
+
+               // Increment counter first before we add objects as we start from 0
+               // Objects are named uniquely so we record this and match with the host
+               // Hostname occurrence can be repetitive as there can be more than
+               // one host on one compute node
+
+               // Add a new object in the list of objects
+               hmActiveObj.put(sAObject, iNumOfObjects);
+
+               // Check host existence in our data structure
+               // Add a new host and a new object
+               if(hmHostList.containsKey(sHAddress) == false) {
+                       iNumOfHosts++;
+                       hmHostList.put(sHAddress, new ArrayList<String>());
+               }
+               hmHostList.get(sHAddress).add(sAObject);
+
+               // Map object to host
+               hmHostAdd.put(iNumOfObjects, sHAddress);
+
+               int iComPort = 0;
+               do {
+                       iComPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
+                       // Check port existence in HashMap
+               } while (portIsAvailable(iComPort) == false);
+               hmComPort.put(iNumOfObjects, iComPort);
+
+               int iRMIRegPort = 0;
+               do {
+                       iRMIRegPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
+                       // Check port existence in HashMap
+               } while (portIsAvailable(iRMIRegPort) == false);
+               hmRMIRegPort.put(iNumOfObjects, iRMIRegPort);
+
+               int iRMIStubPort = 0;
+               do {
+                       iRMIStubPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
+                       // Check port existence in HashMap
+               } while (portIsAvailable(iRMIStubPort) == false);
+               hmRMIStubPort.put(iNumOfObjects, iRMIStubPort);
+
+               iNumOfObjects++;
+       }
+
+       /**
+        * A private method to add a new active controller object
+        *
+        * @params  strFieldObjectID                    String field object ID
+        * @params  strObjName                                  String object name
+        * @params  strObjClassName                     String object class name
+        * @params  strObjClassInterfaceName    String object class interface name
+        * @params  strIoTSlaveObjectHostAdd    String IoTSlave host address
+        * @params  arrFieldValues                              Array of field values
+        * @params  arrFieldClasses                             Array of field classes
+        * @return  void
+        */
+       public void addActiveControllerObject(String strFieldObjectID, String strObjName, String strObjClassName,
+               String strObjClassInterfaceName, String strIoTSlaveObjectHostAdd, Object[] arrFieldValues, 
+               Class[] arrFieldClasses) {
+
+               listActiveControllerObj.add(strObjName);
+               listFieldObjectID.add(strFieldObjectID);
+               listArrFieldValues.add(arrFieldValues);
+               listArrFieldClasses.add(arrFieldClasses);
+               ObjectCreationInfo objCrtInfo = new ObjectCreationInfo(strIoTSlaveObjectHostAdd, strObjName,
+                       strObjClassName, strObjClassInterfaceName);
+               listObjCrtInfo.add(objCrtInfo);
+       }
+
+
+       /**
+        * Method getCallbackPort()
+        * <p>
+        * Get a new port for new connections for callback objects in the program.
+        * This newly generated port number will be recorded.
+        *
+        * @return  int[]       A set of callback ports
+        */
+       public int[] getCallbackPorts(int numOfPorts) {
+
+               int[] ports = new int[numOfPorts];
+
+               for(int i = 0; i < numOfPorts; i++) {
+                       do {
+                               ports[i] = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
+                               // Check port existence in HashMap
+                       } while (portIsAvailable(ports[i]) == false);
+                       hsCallbackPort.add(ports[i]);
+               }
+
+               return ports;
+       }
+
+
+       /**
+        * Method addDevicePort()
+        * <p>
+        * Add a port that is used by a device when communicating with its driver
+        * This port will be taken into account when checking for port availability
+        *
+        * @param   iDevPort  Device port number
+        * @return  void
+        */
+       public void addDevicePort(int iDevPort) {
+
+               hsDevicePort.add(iDevPort);
+
+       }
+
+       /**
+        * Method portIsAvailable()
+        * <p>
+        * Checks the availability of the newly generated port.
+        * If port number has been used in any of the lists then
+        * it is not available
+        *
+        * @param   iPortNumber  Device port number
+        * @return  boolean
+        */
+       public boolean portIsAvailable(int iPortNumber) {
+
+               if (hmComPort.containsValue(iPortNumber) == true) {
+                       return false;
+               } else if (hmRMIRegPort.containsValue(iPortNumber) == true) {
+                       return false;
+               } else if (hmRMIStubPort.containsValue(iPortNumber) == true) {
+                       return false;
+               } else if (hsDevicePort.contains(iPortNumber) == true) {
+                       return false;
+               } else if (hsCallbackPort.contains(iPortNumber) == true) {
+                       return false;
+               } else {
+                       return true;
+               }
+       }
+
+       /**
+        * Method getNumOfObjects()
+        *
+        * @return  int
+        */
+       public int getNumOfObjects() {
+
+               return iNumOfObjects;
+
+       }
+
+       /**
+        * Method getNumOfHosts()
+        *
+        * @return  int
+        */
+       public int getNumOfHosts() {
+
+               return iNumOfHosts;
+
+       }
+
+       /**
+        * Method objectExists()
+        *
+        * @param   sObjName  String object name
+        * @return  boolean
+        */
+       public boolean objectExists(String sObjName) {
+
+               return hmActiveObj.containsKey(sObjName);
+
+       }
+
+       /**
+        * Method hostExists()
+        *
+        * @param   sHostName  String host name
+        * @return  boolean
+        */
+       public boolean hostExists(String sHostName) {
+
+               return hmHostList.containsKey(sHostName);
+
+       }
+
+       /**
+        * Method getHostAddress()
+        * <p>
+        * User finds HostAddress using Object name
+        *
+        * @param   sAObject  String active object name
+        * @return  String
+        */
+       public String getHostAddress(String sAObject) {
+
+               return hmHostAdd.get(hmActiveObj.get(sAObject));
+
+       }
+
+       /**
+        * Method getHosts()
+        * <p>
+        * User gets the set of hostnames
+        *
+        * @return  String
+        */
+       public Set<String> getHosts() {
+
+               return hmHostList.keySet();
+
+       }
+
+       /**
+        * Method getComPort()
+        * <p>
+        * User finds In-Port number using Object name
+        *
+        * @param   sAObject  String active object name
+        * @return  Integer
+        */
+       public Integer getComPort(String sAObject) {
+
+               return hmComPort.get(hmActiveObj.get(sAObject));
+       }
+
+       /**
+        * Method getRMIRegPort()
+        * <p>
+        * User finds Out-Port number using Object name
+        *
+        * @param   sAObject  String active object name
+        * @return  Integer
+        */
+       public Integer getRMIRegPort(String sAObject) {
+
+               return hmRMIRegPort.get(hmActiveObj.get(sAObject));
+
+       }
+
+       /**
+        * Method getRMIStubPort()
+        * <p>
+        * User finds Out-Port number using Object name
+        *
+        * @param   sAObject  String active object name
+        * @return  Integer
+        */
+       public Integer getRMIStubPort(String sAObject) {
+
+               return hmRMIStubPort.get(hmActiveObj.get(sAObject));
+
+       }
+
+       /**
+        * Method getFieldObjectID()
+        * <p>
+        * User finds field object ID using Object name
+        *
+        * @param   sAObject  String active object name
+        * @return  String
+        */
+       public String getFieldObjectID(String sAObject) {
+
+               return listFieldObjectID.get(listActiveControllerObj.indexOf(sAObject));
+
+       }
+
+       /**
+        * Method getObjectCreationInfo()
+        * <p>
+        * User finds ObjectCreationInfo using Object name
+        *
+        * @param   sAObject  String active object name
+        * @return  ObjectCreationInfo
+        */
+       public ObjectCreationInfo getObjectCreationInfo(String sAObject) {
+
+               return listObjCrtInfo.get(listActiveControllerObj.indexOf(sAObject));
+
+       }
+
+       /**
+        * Method getArrayFieldClasses()
+        * <p>
+        * User finds array of field classes using Object name
+        *
+        * @param   sAObject  String active object name
+        * @return  Class[]
+        */
+       public Class[] getArrayFieldClasses(String sAObject) {
+
+               return listArrFieldClasses.get(listActiveControllerObj.indexOf(sAObject));
+
+       }
+
+       /**
+        * Method getArrayFieldValues()
+        * <p>
+        * User finds array of field values using Object name
+        *
+        * @param   sAObject  String active object name
+        * @return  Object[]
+        */
+       public Object[] getArrayFieldValues(String sAObject) {
+
+               return listArrFieldValues.get(listActiveControllerObj.indexOf(sAObject));
+
+       }
+
+       /**
+        * Method getActiveControllerObjectList()
+        *
+        * @return  List<String>
+        */
+       public List<String> getActiveControllerObjectList() {
+
+               return listActiveControllerObj;
+
+       }
+
+       /**
+        * Method printLists()
+        *
+        * @return  void
+        */
+       public void printLists() {
+
+               // Iterate on HostAddress
+               for(String s : hmHostList.keySet()) {
+
+                       for(String str : hmHostList.get(s)) {
+
+                               int iIndex = hmActiveObj.get(str);
+                               RuntimeOutput.print("Active Object: " + str, bVerbose);
+                               RuntimeOutput.print("Communication Port: " + hmComPort.get(iIndex), bVerbose);
+                               RuntimeOutput.print("RMI Registry Port: " + hmRMIRegPort.get(iIndex), bVerbose);
+                               RuntimeOutput.print("RMI Stub Port: " + hmRMIStubPort.get(iIndex), bVerbose);
+                       }
+               }
+
+               for(int iPort : hsDevicePort) {
+
+                       RuntimeOutput.print("Device Port: " + iPort, bVerbose);
+
+               }
+       }
+}
diff --git a/iotjava/iotruntime/master/ObjectCreationInfo.java b/iotjava/iotruntime/master/ObjectCreationInfo.java
new file mode 100644 (file)
index 0000000..59161be
--- /dev/null
@@ -0,0 +1,59 @@
+package iotruntime.master;
+
+/** A class that construct object creation info
+ *
+ * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version     1.0
+ * @since       2015-05-13
+ */
+
+public class ObjectCreationInfo {
+
+       /**
+        * ObjectCreationInfo properties
+        */
+       protected String strIoTSlaveObjectHostAdd;
+       protected String strObjName;
+       protected String strObjClassName;
+       protected String strObjClassInterfaceName;
+
+       /**
+        * Constructor
+        */
+       public ObjectCreationInfo(String _strIoTSlaveObjectHostAdd, String _strObjName, 
+               String _strObjClassName, String _strObjClassInterfaceName) {
+
+               strIoTSlaveObjectHostAdd = _strIoTSlaveObjectHostAdd;
+               strObjName = _strObjName;
+               strObjClassName = _strObjClassName;
+               strObjClassInterfaceName = _strObjClassInterfaceName;
+       }
+
+       /**
+        * Method getIoTSlaveObjectHostAdd()
+        */
+       public String getIoTSlaveObjectHostAdd() {
+               return strIoTSlaveObjectHostAdd;
+       }
+
+       /**
+        * Method getObjectName()
+        */
+       public String getObjectName() {
+               return strObjName;
+       }
+
+       /**
+        * Method getObjectClassName()
+        */
+       public String getObjectClassName() {
+               return strObjClassName;
+       }
+
+       /**
+        * Method getObjectClassInterfaceName()
+        */
+       public String getObjectClassInterfaceName() {
+               return strObjClassInterfaceName;
+       }
+}
diff --git a/iotjava/iotruntime/master/RuntimeOutput.java b/iotjava/iotruntime/master/RuntimeOutput.java
new file mode 100644 (file)
index 0000000..5be24d3
--- /dev/null
@@ -0,0 +1,24 @@
+package iotruntime.master;
+
+/** Class RuntimeOutput is a class that controls the verboseness
+ *  of the runtime system
+ *
+ * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version     1.0
+ * @since       2016-05-11
+ */
+public final class RuntimeOutput {
+
+       /**
+        * print() method to print messages
+        *
+        * @param       strMessage      Message to print out
+        * @return  void
+        */
+       public static void print(String strMessage, boolean bVerbose) {
+
+               if (bVerbose == true) {
+                       System.out.println(strMessage);
+               }
+       }
+}