bf5d9dcf3e44d012b640172b588ab272cd653485
[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                 try {
56                         rmiClient.sendBytes(methodBytes);
57                 } catch (IOException ex) {
58                         ex.printStackTrace();
59                         throw new Error("IoTRMICall: Error when sending bytes - rmiClient.sendBytes()");
60                 }
61                 // Receive return value and return it to caller
62                 Object retObj = null;
63                 if (retType != void.class) {
64                         byte[] retObjBytes = null;
65                         try {
66                                 retObjBytes = rmiClient.receiveBytes(retObjBytes);
67                         } catch (IOException ex) {
68                                 ex.printStackTrace();
69                                 throw new Error("IoTRMICall: Error when receiving bytes - rmiClient.receiveBytes()");
70                         }
71                         retObj = IoTRMIUtil.getParamObject(retType, retGenTypeVal, retObjBytes);
72                 }
73                 return retObj;
74         }
75
76
77         /**
78          * methodToBytes() returns byte representation of a method
79          */
80         public byte[] methodToBytes(int objectId, int methId, Class<?>[] paramCls, Object[] paramObj) {
81
82                 // Initialized to the length of method ID
83                 int methodLen = IoTRMIUtil.OBJECT_ID_LEN;
84                 byte[] objId = IoTRMIUtil.intToByteArray(objectId);
85                 // Get method ID in bytes
86                 byte[] methodId = IoTRMIUtil.intToByteArray(methId);
87                 // Get byte arrays and calculate method bytes length
88                 int numbParam = paramObj.length;
89                 methodLen = methodLen + IoTRMIUtil.METHOD_ID_LEN;
90                 byte[][] objBytesArr = new byte[numbParam][];
91                 for (int i = 0; i < numbParam; i++) {
92                         // Get byte arrays for the objects
93                         objBytesArr[i] = IoTRMIUtil.getObjectBytes(paramObj[i]);
94                         String clsName = paramCls[i].getSimpleName();
95                         int paramLen = rmiUtil.getTypeSize(clsName);
96                         if (paramLen == -1) {           // indefinite length - store the length first
97                                 methodLen = methodLen + IoTRMIUtil.PARAM_LEN;
98                         }
99                         methodLen = methodLen + objBytesArr[i].length;
100                 }
101                 // Construct method in byte array
102                 byte[] method = new byte[methodLen];
103                 int pos = 0;
104                 System.arraycopy(objId, 0, method, 0, IoTRMIUtil.METHOD_ID_LEN);
105                 pos = pos + IoTRMIUtil.OBJECT_ID_LEN;
106                 System.arraycopy(methodId, 0, method, pos, IoTRMIUtil.METHOD_ID_LEN);
107                 pos = pos + IoTRMIUtil.METHOD_ID_LEN;
108                 // Second iteration for copying bytes
109                 for (int i = 0; i < numbParam; i++) {
110
111                         String clsName = paramCls[i].getSimpleName();
112                         int paramLen = rmiUtil.getTypeSize(clsName);
113                         if (paramLen == -1) {           // indefinite length
114                                 paramLen = objBytesArr[i].length;
115                                 byte[] paramLenBytes = IoTRMIUtil.intToByteArray(paramLen);
116                                 System.arraycopy(paramLenBytes, 0, method, pos, IoTRMIUtil.PARAM_LEN);
117                                 pos = pos + IoTRMIUtil.PARAM_LEN;
118                         }               
119                         System.arraycopy(objBytesArr[i], 0, method, pos, paramLen);
120                         pos = pos + paramLen;
121                 }
122
123                 return method;
124         }
125
126
127         /**
128          * remoteCall() calls a method remotely by passing in parameters and getting a return Object
129          */
130         public synchronized Object[] getStructObjects(Class<?>[] retType, Class<?>[] retGenTypeVal) {
131
132                 // Receive return value and return it to caller
133                 Object[] retObj = null;
134                 byte[] retObjBytes = null;
135                 try {
136                         retObjBytes = rmiClient.receiveBytes(retObjBytes);
137                 } catch (IOException ex) {
138                         ex.printStackTrace();
139                         throw new Error("IoTRMICall: Error when receiving bytes - rmiClient.receiveBytes()");
140                 }
141                 retObj = getReturnObjects(retObjBytes, retType, retGenTypeVal);
142
143                 return retObj;
144         }
145
146
147         public Object[] getReturnObjects(byte[] retBytes, Class<?>[] arrCls, Class<?>[] arrGenValCls) {
148
149                 // Byte scanning position
150                 int pos = 0;
151                 Object[] retObj = new Object[arrCls.length];
152                 for (int i=0; i < arrCls.length; i++) {
153
154                         String retType = arrCls[i].getSimpleName();
155                         int retSize = rmiUtil.getTypeSize(retType);
156                         // Get the 32-bit field in the byte array to get the actual
157                         //              length (this is a param with indefinite length)
158                         if (retSize == -1) {
159                                 byte[] bytRetLen = new byte[IoTRMIUtil.RETURN_LEN];
160                                 System.arraycopy(retBytes, pos, bytRetLen, 0, IoTRMIUtil.RETURN_LEN);
161                                 pos = pos + IoTRMIUtil.RETURN_LEN;
162                                 retSize = IoTRMIUtil.byteArrayToInt(bytRetLen);
163                         }
164                         byte[] retObjBytes = new byte[retSize];
165                         System.arraycopy(retBytes, pos, retObjBytes, 0, retSize);
166                         pos = pos + retSize;
167                         retObj[i] = IoTRMIUtil.getParamObject(arrCls[i], arrGenValCls[i], retObjBytes);
168                 }
169
170                 return retObj;
171         }
172
173
174         public static void main(String[] args) throws Exception {
175
176                 String[] test = { "123", "456", "789" };
177                 byte[] b = IoTRMIUtil.getObjectBytes(test);
178
179                 Boolean[] test2 = new Boolean[] { true, false, false };
180                 byte[] b2 = IoTRMIUtil.getObjectBytes(test2);
181
182                 System.out.println(Arrays.toString(b));
183                 System.out.println(Arrays.toString(b2));
184
185                 String[] c = (String[]) IoTRMIUtil.getParamObjectArray(String[].class, b);
186                 System.out.println(Arrays.toString(c));
187
188                 Boolean[] c2 = (Boolean[]) IoTRMIUtil.getParamObjectArray(Boolean[].class, b2);
189                 System.out.println(Arrays.toString(c2));
190
191                 IoTRMICall rmiCall = new IoTRMICall(1234, "localhost", 0);
192                 byte[] retObjBytes = { 0, 0, 4, -46, 0, 0, 0, 10, 116, 101, 115, 116, 115, 116, 114, 105, 110, 103, 0, 0, 21, 56 };
193                 //Class<?>[] retCls = new Class<?>[] { int.class, String.class, int.class };
194                 Object[] retObj = rmiCall.getReturnObjects(retObjBytes, new Class<?>[] { int.class, String.class, int.class },
195                         new Class<?>[] { null, null, null });
196                 System.out.println("Ret object 1: " + retObj[0]);
197                 System.out.println("Ret object 2: " + retObj[1]);
198                 System.out.println("Ret object 3: " + retObj[2]);
199
200                 // List
201                 /*List<Long> list = new ArrayList<Long>();
202                 list.add(12345678l);
203                 list.add(23455432l);
204                 list.add(34566543l);
205
206                 byte[] objBytes = IoTRMIUtil.getObjectBytes(list);
207                 System.out.println(Arrays.toString(objBytes));
208                 Object obj = IoTRMIUtil.getParamObject(List.class, null, Long.class, objBytes);
209
210                 @SuppressWarnings("unchecked")
211                 List<Long> listStr = (List<Long>) obj;
212                 System.out.println("List: " + listStr.toString());*/
213
214                 //@SuppressWarnings("unchecked")
215                 //List<Long> listStr = (List<Long>) obj;
216                 //System.out.println("List: " + listStr.toString());
217
218         }
219 }