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.*;
14 /** Class IoTRMIObject is a class that stores info of an object.
16 * It stores object ID, methods, method ID, method's signature
18 * This class also receive calls from different objects as they
19 * ask to execute certain methods remotely. This will have the
20 * execution result (return value) sent back to
22 * @author Rahmadi Trimananda <rtrimana @ uci.edu>
26 public class IoTRMIObject {
31 private List<String> listMethodId2Sign; // List of method signature (we use list index as method Id)
32 private IoTRMIUtil rmiUtil;
33 private IoTSocketServer rmiServer;
34 private byte[] methodBytes;
40 public IoTRMIObject(int _port) throws
41 ClassNotFoundException, InstantiationException,
42 IllegalAccessException, IOException {
44 rmiUtil = new IoTRMIUtil();
46 rmiServer = new IoTSocketServer(_port);
52 * getMethodBytes() waits for method transmission in bytes
54 public byte[] getMethodBytes() throws IOException {
56 // Receive method info
57 methodBytes = rmiServer.receiveBytes(methodBytes);
58 //System.out.println("Method: " + Arrays.toString(methodBytes));
64 * getObjectId() gets object Id from bytes
66 public int getObjectId() {
68 // Get object Id bytes
69 byte[] objectIdBytes = new byte[IoTRMIUtil.OBJECT_ID_LEN];
70 System.arraycopy(methodBytes, 0, objectIdBytes, 0, IoTRMIUtil.OBJECT_ID_LEN);
72 int objectId = IoTRMIUtil.byteArrayToInt(objectIdBytes);
78 * static version of getObjectId()
80 public static int getObjectId(byte[] methodBytes) {
82 // Get object Id bytes
83 byte[] objectIdBytes = new byte[IoTRMIUtil.OBJECT_ID_LEN];
84 System.arraycopy(methodBytes, 0, objectIdBytes, 0, IoTRMIUtil.OBJECT_ID_LEN);
86 int objectId = IoTRMIUtil.byteArrayToInt(objectIdBytes);
92 * setMethodBytes() sets bytes for method
94 /*public void setMethodBytes(byte[] _methodBytes) throws IOException {
97 methodBytes = _methodBytes;
102 * getMethodId() gets method Id from bytes
104 public int getMethodId() {
106 // Get method Id bytes
107 byte[] methodIdBytes = new byte[IoTRMIUtil.METHOD_ID_LEN];
108 // Method Id is positioned after object Id in the byte array
109 System.arraycopy(methodBytes, IoTRMIUtil.OBJECT_ID_LEN, methodIdBytes, 0, IoTRMIUtil.METHOD_ID_LEN);
111 int methodId = IoTRMIUtil.byteArrayToInt(methodIdBytes);
118 * static version of getMethodId()
120 public static int getMethodId(byte[] methodBytes) {
122 // Get method Id bytes
123 byte[] methodIdBytes = new byte[IoTRMIUtil.METHOD_ID_LEN];
124 // Method Id is positioned after object Id in the byte array
125 System.arraycopy(methodBytes, IoTRMIUtil.OBJECT_ID_LEN, methodIdBytes, 0, IoTRMIUtil.METHOD_ID_LEN);
127 int methodId = IoTRMIUtil.byteArrayToInt(methodIdBytes);
134 * getMethodParams() gets method params based on byte array received
136 * Basically this is the format of a method in bytes:
137 * 1) 32-bit value of object ID
138 * 2) 32-bit value of method ID
139 * 3) m parameters with n-bit value each (m x n-bit)
140 * For the parameters that don't have definite length,
141 * we need to extract the length from a preceding 32-bit
142 * field in front of it.
144 * For primitive objects:
145 * | 32-bit object ID | 32-bit method ID | m-bit actual data (fixed length) | ...
147 * For string, arrays, and non-primitive objects:
148 * | 32-bit object ID | 32-bit method ID | 32-bit length | n-bit actual data | ...
151 public Object[] getMethodParams(Class<?>[] arrCls, Class<?>[] arrGenValCls) {
153 // Byte scanning position
154 int pos = IoTRMIUtil.OBJECT_ID_LEN + IoTRMIUtil.METHOD_ID_LEN;
155 Object[] paramObj = new Object[arrCls.length];
156 for (int i=0; i < arrCls.length; i++) {
158 String paramType = arrCls[i].getSimpleName();
159 int paramSize = rmiUtil.getTypeSize(paramType);
160 // Get the 32-bit field in the byte array to get the actual
161 // length (this is a param with indefinite length)
162 if (paramSize == -1) {
163 byte[] bytPrmLen = new byte[IoTRMIUtil.PARAM_LEN];
164 System.arraycopy(methodBytes, pos, bytPrmLen, 0, IoTRMIUtil.PARAM_LEN);
165 pos = pos + IoTRMIUtil.PARAM_LEN;
166 paramSize = IoTRMIUtil.byteArrayToInt(bytPrmLen);
168 byte[] paramBytes = new byte[paramSize];
169 System.arraycopy(methodBytes, pos, paramBytes, 0, paramSize);
170 pos = pos + paramSize;
171 paramObj[i] = IoTRMIUtil.getParamObject(arrCls[i], arrGenValCls[i], paramBytes);
179 * sendReturnObj() sends back return Object to client
181 public void sendReturnObj(Object retObj) throws IOException {
183 // Send back return value
184 byte[] retObjBytes = IoTRMIUtil.getObjectBytes(retObj);
185 rmiServer.sendBytes(retObjBytes);
190 * sendReturnObj() overloaded to send multiple return objects for structs
192 public void sendReturnObj(Class<?>[] retCls, Object[] retObj) throws IOException {
194 // Send back return value
195 byte[] retObjBytes = returnToBytes(retCls, retObj);
196 rmiServer.sendBytes(retObjBytes);
201 * returnToBytes() takes array of objects and generates bytes
203 public byte[] returnToBytes(Class<?>[] retCls, Object[] retObj) {
205 // Get byte arrays and calculate method bytes length
206 int numbRet = retObj.length;
208 byte[][] objBytesArr = new byte[numbRet][];
209 for (int i = 0; i < numbRet; i++) {
210 // Get byte arrays for the objects
211 objBytesArr[i] = IoTRMIUtil.getObjectBytes(retObj[i]);
212 String clsName = retCls[i].getSimpleName();
213 int retObjLen = rmiUtil.getTypeSize(clsName);
214 if (retObjLen == -1) { // indefinite length - store the length first
215 retLen = retLen + IoTRMIUtil.RETURN_LEN;
217 retLen = retLen + objBytesArr[i].length;
219 // Construct return in byte array
220 byte[] retBytes = new byte[retLen];
222 // Iteration for copying bytes
223 for (int i = 0; i < numbRet; i++) {
225 String clsName = retCls[i].getSimpleName();
226 int retObjLen = rmiUtil.getTypeSize(clsName);
227 if (retObjLen == -1) { // indefinite length
228 retObjLen = objBytesArr[i].length;
229 byte[] retLenBytes = IoTRMIUtil.intToByteArray(retObjLen);
230 System.arraycopy(retLenBytes, 0, retBytes, pos, IoTRMIUtil.RETURN_LEN);
231 pos = pos + IoTRMIUtil.RETURN_LEN;
233 System.arraycopy(objBytesArr[i], 0, retBytes, pos, retObjLen);
234 pos = pos + retObjLen;
241 public static void main(String[] args) throws Exception {
244 IoTRMIObject rmiObj = new IoTRMIObject(port);
246 Class<?>[] retCls = new Class<?>[] { int.class, String.class, int.class };
247 Object[] retObj = new Object[] { 1234, "teststring", 5432 };
249 System.out.println("Bytes: " + Arrays.toString(rmiObj.returnToBytes(retCls, retObj)));