3 import java.io.IOException;
4 import java.nio.ByteBuffer;
5 import java.util.Arrays;
6 import java.util.ArrayList;
7 import java.util.HashMap;
11 import java.lang.reflect.*;
13 import java.util.concurrent.locks.Lock;
14 import java.util.concurrent.locks.ReentrantLock;
17 /** Class IoTRMIObject is a class that stores info of an object.
19 * It stores object ID, methods, method ID, method's signature
21 * This class also receive calls from different objects as they
22 * ask to execute certain methods remotely. This will have the
23 * execution result (return value) sent back to
25 * @author Rahmadi Trimananda <rtrimana @ uci.edu>
29 public final class IoTRMIObject {
34 private List<String> listMethodId2Sign; // List of method signature (we use list index as method Id)
35 private IoTRMIUtil rmiUtil;
36 private IoTSocketServer rmiServer;
37 private byte[] methodBytes;
38 private Lock lock = new ReentrantLock();
44 public IoTRMIObject(int _port) throws
45 ClassNotFoundException, InstantiationException,
46 IllegalAccessException, IOException {
48 rmiUtil = new IoTRMIUtil();
50 rmiServer = new IoTSocketServer(_port);
56 * getMethodBytes() waits for method transmission in bytes
58 public byte[] getMethodBytes() throws IOException {
60 // Receive method info
61 //System.out.println("Method RMIObj before: " + Arrays.toString(methodBytes));
62 methodBytes = rmiServer.receiveBytes(methodBytes);
63 //System.out.println("Method RMIObj after: " + Arrays.toString(methodBytes));
69 * getObjectId() gets object Id from bytes
71 public int getObjectId() {
73 // Get object Id bytes
74 byte[] objectIdBytes = new byte[IoTRMIUtil.OBJECT_ID_LEN];
75 System.arraycopy(methodBytes, 0, objectIdBytes, 0, IoTRMIUtil.OBJECT_ID_LEN);
77 int objectId = IoTRMIUtil.byteArrayToInt(objectIdBytes);
83 * static version of getObjectId()
85 public static int getObjectId(byte[] methodBytes) {
87 // Get object Id bytes
88 byte[] objectIdBytes = new byte[IoTRMIUtil.OBJECT_ID_LEN];
89 System.arraycopy(methodBytes, 0, objectIdBytes, 0, IoTRMIUtil.OBJECT_ID_LEN);
91 int objectId = IoTRMIUtil.byteArrayToInt(objectIdBytes);
97 * getMethodId() gets method Id from bytes
99 public int getMethodId() {
101 // Get method Id bytes
102 byte[] methodIdBytes = new byte[IoTRMIUtil.METHOD_ID_LEN];
103 // Method Id is positioned after object Id in the byte array
104 System.arraycopy(methodBytes, IoTRMIUtil.OBJECT_ID_LEN, methodIdBytes, 0, IoTRMIUtil.METHOD_ID_LEN);
106 int methodId = IoTRMIUtil.byteArrayToInt(methodIdBytes);
112 * static version of getMethodId()
114 public static int getMethodId(byte[] methodBytes) {
116 // Get method Id bytes
117 byte[] methodIdBytes = new byte[IoTRMIUtil.METHOD_ID_LEN];
118 // Method Id is positioned after object Id in the byte array
119 System.arraycopy(methodBytes, IoTRMIUtil.OBJECT_ID_LEN, methodIdBytes, 0, IoTRMIUtil.METHOD_ID_LEN);
121 int methodId = IoTRMIUtil.byteArrayToInt(methodIdBytes);
127 * getMethodParams() gets method params based on byte array received
129 * Basically this is the format of a method in bytes:
130 * 1) 32-bit value of object ID
131 * 2) 32-bit value of method ID
132 * 3) m parameters with n-bit value each (m x n-bit)
133 * For the parameters that don't have definite length,
134 * we need to extract the length from a preceding 32-bit
135 * field in front of it.
137 * For primitive objects:
138 * | 32-bit object ID | 32-bit method ID | m-bit actual data (fixed length) | ...
140 * For string, arrays, and non-primitive objects:
141 * | 32-bit object ID | 32-bit method ID | 32-bit length | n-bit actual data | ...
144 public Object[] getMethodParams(Class<?>[] arrCls, Class<?>[] arrGenValCls) {
146 // Byte scanning position
147 int pos = IoTRMIUtil.OBJECT_ID_LEN + IoTRMIUtil.METHOD_ID_LEN;
148 Object[] paramObj = new Object[arrCls.length];
149 for (int i=0; i < arrCls.length; i++) {
151 String paramType = arrCls[i].getSimpleName();
152 int paramSize = rmiUtil.getTypeSize(paramType);
153 // Get the 32-bit field in the byte array to get the actual
154 // length (this is a param with indefinite length)
155 if (paramSize == -1) {
156 byte[] bytPrmLen = new byte[IoTRMIUtil.PARAM_LEN];
157 System.arraycopy(methodBytes, pos, bytPrmLen, 0, IoTRMIUtil.PARAM_LEN);
158 pos = pos + IoTRMIUtil.PARAM_LEN;
159 paramSize = IoTRMIUtil.byteArrayToInt(bytPrmLen);
161 byte[] paramBytes = new byte[paramSize];
162 System.arraycopy(methodBytes, pos, paramBytes, 0, paramSize);
163 pos = pos + paramSize;
164 paramObj[i] = IoTRMIUtil.getParamObject(arrCls[i], arrGenValCls[i], paramBytes);
172 * sendReturnObj() sends back return Object to client
174 public void sendReturnObj(Object retObj) throws IOException {
176 // Send back return value
177 byte[] retObjBytes = IoTRMIUtil.getObjectBytes(retObj);
178 rmiServer.sendBytes(retObjBytes);
183 * sendReturnObj() overloaded to send multiple return objects for structs
185 public void sendReturnObj(Class<?>[] retCls, Object[] retObj) throws IOException {
187 // Send back return value
188 byte[] retObjBytes = returnToBytes(retCls, retObj);
189 rmiServer.sendBytes(retObjBytes);
194 * returnToBytes() takes array of objects and generates bytes
196 public byte[] returnToBytes(Class<?>[] retCls, Object[] retObj) {
198 // Get byte arrays and calculate method bytes length
199 int numbRet = retObj.length;
201 byte[][] objBytesArr = new byte[numbRet][];
202 for (int i = 0; i < numbRet; i++) {
203 // Get byte arrays for the objects
204 objBytesArr[i] = IoTRMIUtil.getObjectBytes(retObj[i]);
205 String clsName = retCls[i].getSimpleName();
206 int retObjLen = rmiUtil.getTypeSize(clsName);
207 if (retObjLen == -1) { // indefinite length - store the length first
208 retLen = retLen + IoTRMIUtil.RETURN_LEN;
210 retLen = retLen + objBytesArr[i].length;
212 // Construct return in byte array
213 byte[] retBytes = new byte[retLen];
215 // Iteration for copying bytes
216 for (int i = 0; i < numbRet; i++) {
218 String clsName = retCls[i].getSimpleName();
219 int retObjLen = rmiUtil.getTypeSize(clsName);
220 if (retObjLen == -1) { // indefinite length
221 retObjLen = objBytesArr[i].length;
222 byte[] retLenBytes = IoTRMIUtil.intToByteArray(retObjLen);
223 System.arraycopy(retLenBytes, 0, retBytes, pos, IoTRMIUtil.RETURN_LEN);
224 pos = pos + IoTRMIUtil.RETURN_LEN;
226 System.arraycopy(objBytesArr[i], 0, retBytes, pos, retObjLen);
227 pos = pos + retObjLen;