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 Map<Integer,String> mapHash2Sign; // Map from hashcode(method ID) to signature
32 private IoTRMIUtil rmiUtil;
33 private IoTSocketServer rmiServer;
34 private byte[] methodBytes;
40 public IoTRMIObject(int _port, String[] _methodSign) throws
41 ClassNotFoundException, InstantiationException,
42 IllegalAccessException, IOException {
44 rmiUtil = new IoTRMIUtil();
45 mapHash2Sign = new HashMap<Integer,String>();
47 getMethodIds(_methodSign); // Initialize the method ID map
48 rmiServer = new IoTSocketServer(_port);
54 * sendReturnObj() sends back return Object to client
56 public void sendReturnObj(Object retObj) throws IOException {
58 // Send back return value
59 byte[] retObjBytes = IoTRMIUtil.getObjectBytes(retObj);
60 rmiServer.sendBytes(retObjBytes);
65 * getMethodBytes() waits for method transmission in bytes
67 public void getMethodBytes() throws IOException {
69 // Receive method info
70 methodBytes = rmiServer.receiveBytes(methodBytes);
75 * getSignature() gets method signature from bytes
77 public String getSignature() {
79 // Get method Id bytes
80 byte[] methodIdBytes = new byte[IoTRMIUtil.METHOD_ID_LEN];
81 System.arraycopy(methodBytes, 0, methodIdBytes, 0, IoTRMIUtil.METHOD_ID_LEN);
83 int methodId = IoTRMIUtil.byteArrayToInt(methodIdBytes);
84 // Get method signature from the Map
85 return mapHash2Sign.get(methodId);
90 * getMethodParams() gets method params based on byte array received
92 * Basically this is the format of a method in bytes:
93 * 1) 32-bit value of method ID (hash code)
94 * 2) m parameters with n-bit value each (m x n-bit)
95 * For the parameters that don't have definite length,
96 * we need to extract the length from a preceding 32-bit
97 * field in front of it.
99 * For primitive objects:
100 * | 32-bit method ID | m-bit actual data (fixed length) |
102 * For string, arrays, and non-primitive objects:
103 * | 32-bit method ID | 32-bit length | n-bit actual data | ...
106 public Object[] getMethodParams(Class<?>[] arrCls, Class<?>[] arrGenKeyCls, Class<?>[] arrGenValCls) {
108 // Byte scanning position
109 int pos = IoTRMIUtil.METHOD_ID_LEN;
110 Object[] paramObj = new Object[arrCls.length];
111 for (int i=0; i < arrCls.length; i++) {
113 String paramType = arrCls[i].getSimpleName();
114 int paramSize = rmiUtil.getTypeSize(paramType);
115 // Get the 32-bit field in the byte array to get the actual
116 // length (this is a param with indefinite length)
117 if (paramSize == -1) {
118 byte[] bytPrmLen = new byte[IoTRMIUtil.PARAM_LEN];
119 System.arraycopy(methodBytes, pos, bytPrmLen, 0, IoTRMIUtil.PARAM_LEN);
120 pos = pos + IoTRMIUtil.PARAM_LEN;
121 paramSize = IoTRMIUtil.byteArrayToInt(bytPrmLen);
123 byte[] paramBytes = new byte[paramSize];
124 System.arraycopy(methodBytes, pos, paramBytes, 0, paramSize);
125 pos = pos + paramSize;
126 paramObj[i] = IoTRMIUtil.getParamObject(arrCls[i], arrGenKeyCls[i],
127 arrGenValCls[i], paramBytes);
135 * getMethodIds() gets methods identifiers (hash code) and store them in the Map
137 private void getMethodIds(String[] methodSign) {
139 for (String sign : methodSign) {
140 byte[] hashCode = IoTRMIUtil.getHashCodeBytes(sign);
141 int methodId = IoTRMIUtil.byteArrayToInt(hashCode);
142 mapHash2Sign.put(methodId, sign);