Adjustments in stubs and skeletons for callback in callback; using different ports...
[iot2.git] / iotjava / iotrmi / Java / IoTRMICall.java
1 package iotrmi.Java;
2
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;
8 import java.util.List;
9 import java.util.Map;
10 import java.lang.reflect.Method;
11
12 import java.util.HashSet;
13 import java.util.Set;
14
15
16 /** Class IoTRMICall is a class that serves method calls on stub.
17  *  <p>
18  *  A stub will use an object of this class to send the method
19  *  information, e.g. object identifier, method identifier, and
20  *  parameters.
21  *
22  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
23  * @version     1.0
24  * @since       2016-10-04
25  */
26 public class IoTRMICall {
27
28
29         /**
30          * Class Properties
31          */
32         private IoTRMIUtil rmiUtil;
33         private IoTSocketClient rmiClient;
34         //private List<String> listMethodId;    // Map from method ID to signature
35
36
37         /**
38          * Constructors
39          */
40         public IoTRMICall(int _port, String _address, int _rev) throws IOException {
41
42                 rmiUtil = new IoTRMIUtil();
43                 rmiClient = new IoTSocketClient(_port, _address, _rev);
44         }
45
46
47         /**
48          * remoteCall() calls a method remotely by passing in parameters and getting a return Object
49          */
50         public synchronized Object remoteCall(int objectId, int methodId, Class<?> retType, 
51                         Class<?> retGenTypeVal, Class<?>[] paramCls, Object[] paramObj) {
52
53                 // Send method info
54                 byte[] methodBytes = methodToBytes(objectId, methodId, paramCls, paramObj);
55                 //System.out.println("Method RMICall: " + Arrays.toString(methodBytes));
56                 try {
57                         rmiClient.sendBytes(methodBytes);
58                         //System.out.println("Sent bytes RMICall!!!");
59                 } catch (IOException ex) {
60                         ex.printStackTrace();
61                         throw new Error("IoTRMICall: Error when sending bytes - rmiClient.sendBytes()");
62                 }
63                 // Receive return value and return it to caller
64                 Object retObj = null;
65                 if (retType != void.class) {
66                         byte[] retObjBytes = null;
67                         try {
68                                 retObjBytes = rmiClient.receiveBytes(retObjBytes);
69                         } catch (IOException ex) {
70                                 ex.printStackTrace();
71                                 throw new Error("IoTRMICall: Error when receiving bytes - rmiClient.receiveBytes()");
72                         }
73                         retObj = IoTRMIUtil.getParamObject(retType, retGenTypeVal, retObjBytes);
74                 }
75                 return retObj;
76         }
77
78
79         /**
80          * methodToBytes() returns byte representation of a method
81          */
82         public byte[] methodToBytes(int objectId, int methId, Class<?>[] paramCls, Object[] paramObj) {
83
84                 // Initialized to the length of method ID
85                 int methodLen = IoTRMIUtil.OBJECT_ID_LEN;
86                 byte[] objId = IoTRMIUtil.intToByteArray(objectId);
87                 // Get method ID in bytes
88                 byte[] methodId = IoTRMIUtil.intToByteArray(methId);
89                 // Get byte arrays and calculate method bytes length
90                 int numbParam = paramObj.length;
91                 methodLen = methodLen + IoTRMIUtil.METHOD_ID_LEN;
92                 byte[][] objBytesArr = new byte[numbParam][];
93                 for (int i = 0; i < numbParam; i++) {
94                         // Get byte arrays for the objects
95                         objBytesArr[i] = IoTRMIUtil.getObjectBytes(paramObj[i]);
96                         String clsName = paramCls[i].getSimpleName();
97                         int paramLen = rmiUtil.getTypeSize(clsName);
98                         if (paramLen == -1) {           // indefinite length - store the length first
99                                 methodLen = methodLen + IoTRMIUtil.PARAM_LEN;
100                         }
101                         methodLen = methodLen + objBytesArr[i].length;
102                 }
103                 // Construct method in byte array
104                 byte[] method = new byte[methodLen];
105                 int pos = 0;
106                 System.arraycopy(objId, 0, method, 0, IoTRMIUtil.METHOD_ID_LEN);
107                 pos = pos + IoTRMIUtil.OBJECT_ID_LEN;
108                 System.arraycopy(methodId, 0, method, pos, IoTRMIUtil.METHOD_ID_LEN);
109                 pos = pos + IoTRMIUtil.METHOD_ID_LEN;
110                 // Second iteration for copying bytes
111                 for (int i = 0; i < numbParam; i++) {
112
113                         String clsName = paramCls[i].getSimpleName();
114                         int paramLen = rmiUtil.getTypeSize(clsName);
115                         if (paramLen == -1) {           // indefinite length
116                                 paramLen = objBytesArr[i].length;
117                                 byte[] paramLenBytes = IoTRMIUtil.intToByteArray(paramLen);
118                                 System.arraycopy(paramLenBytes, 0, method, pos, IoTRMIUtil.PARAM_LEN);
119                                 pos = pos + IoTRMIUtil.PARAM_LEN;
120                         }               
121                         System.arraycopy(objBytesArr[i], 0, method, pos, paramLen);
122                         pos = pos + paramLen;
123                 }
124
125                 return method;
126         }
127
128
129         /**
130          * remoteCall() calls a method remotely by passing in parameters and getting a return Object
131          */
132         public synchronized Object[] getStructObjects(Class<?>[] retType, Class<?>[] retGenTypeVal) {
133
134                 // Receive return value and return it to caller
135                 Object[] retObj = null;
136                 byte[] retObjBytes = null;
137                 try {
138                         retObjBytes = rmiClient.receiveBytes(retObjBytes);
139                 } catch (IOException ex) {
140                         ex.printStackTrace();
141                         throw new Error("IoTRMICall: Error when receiving bytes - rmiClient.receiveBytes()");
142                 }
143                 retObj = getReturnObjects(retObjBytes, retType, retGenTypeVal);
144
145                 return retObj;
146         }
147
148
149         public Object[] getReturnObjects(byte[] retBytes, Class<?>[] arrCls, Class<?>[] arrGenValCls) {
150
151                 // Byte scanning position
152                 int pos = 0;
153                 Object[] retObj = new Object[arrCls.length];
154                 for (int i=0; i < arrCls.length; i++) {
155
156                         String retType = arrCls[i].getSimpleName();
157                         int retSize = rmiUtil.getTypeSize(retType);
158                         // Get the 32-bit field in the byte array to get the actual
159                         //              length (this is a param with indefinite length)
160                         if (retSize == -1) {
161                                 byte[] bytRetLen = new byte[IoTRMIUtil.RETURN_LEN];
162                                 System.arraycopy(retBytes, pos, bytRetLen, 0, IoTRMIUtil.RETURN_LEN);
163                                 pos = pos + IoTRMIUtil.RETURN_LEN;
164                                 retSize = IoTRMIUtil.byteArrayToInt(bytRetLen);
165                         }
166                         byte[] retObjBytes = new byte[retSize];
167                         System.arraycopy(retBytes, pos, retObjBytes, 0, retSize);
168                         pos = pos + retSize;
169                         retObj[i] = IoTRMIUtil.getParamObject(arrCls[i], arrGenValCls[i], retObjBytes);
170                 }
171
172                 return retObj;
173         }
174 }