15db69022eeaf98d0c04adcac6f2d1c8847ea8c0
[iot2.git] / iotjava / iotruntime / master / CommunicationHandler.java
1 package iotruntime.master;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.HashSet;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Random;
9 import java.util.Set;
10
11 /** Class CommunicationHandler is a class that maintains
12  *  a data structure that preserves a collection of host name,
13  *  port numbers, and objects that are running
14  *  +-----------------+----+--------+------------------+--------------+----------------+
15  *  | HOST-ADDRESS    | ...|IN-PORT | RMIREGISTRY-PORT | RMISTUB-PORT | ACTIVE OBJECTS |
16  *  +-----------------+----+--------+------------------+--------------+----------------+
17  *  | XXX.XXX.XXX.XXX |    | XXXXX  | XXXXX            | XXXXX        | XXXXXXXXXXXXXX |
18  *  |                 |    | XXXXX  | XXXXX            | XXXXX        | XXXXXXXXXXXXXX |
19  *  |                 |    | XXXXX  | XXXXX            | XXXXX        | XXXXXXXXXXXXXX |
20  *  |                 | ...| ...    | ...              | ...          | ...            |
21  *  +-----------------+----+--------+------------------+--------------+----------------+
22  *  In this case we use ACTIVE OBJECTS names as the key
23  *  So ACTIVE OBJECTS maps to numbers and these numbers map to each other
24  *  entry in hashmaps (HostAddress can be repetitive)
25  *  e.g. ACTIVE OBJECTS ProximitySensorPS0 - 0
26  *                      ProximitySensorPS1 - 1
27  *                      TempSensorTS1      - 2
28  *                      ...
29  *       IN-PORT / RMIREGISTRY-PORT / RMISTUB-PORT / HOST-ADDRESS: 0 - XXXXX
30  *                                                                 1 - XXXXX
31  *                                                                 2 - XXXXX
32  *  +-------------+
33  *  | DEVICE-PORT |
34  *  +-------------+
35  *  | XXXXX       |
36  *  | XXXXX       |
37  *  | XXXXX       |
38  *  | ...         |
39  *  +-------------+
40  *  We add a Set structure to handle all the other ports that are used by devices
41  *  when communicating with their respective drivers
42  *
43  * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
44  * @version     1.0
45  * @since       2016-01-07
46  */
47 public final class CommunicationHandler {
48
49         /**
50          * CommunicationHandler class properties
51          * <p>
52          * Random, host name, port number, active objects
53          * HostAdd is the key to the table so we use it
54          * as a key to elements
55          * HostList gives a mapping from hostname to list of objects
56          */
57         private Random random;
58         private List<String> listActiveControllerObj;
59         private List<String> listFieldObjectID;
60         private List<ObjectCreationInfo> listObjCrtInfo;
61         private List<Object[]> listArrFieldValues;
62         private List<Class[]> listArrFieldClasses;
63         private Map<String, Integer> hmActiveObj;
64         private Map<Integer, String> hmHostAdd;
65         private Map<String, ArrayList<String> > hmHostList;
66         private Map<Integer, Integer> hmComPort;
67         private Map<Integer, Integer> hmRMIRegPort;
68         private Map<Integer, Integer> hmRMIStubPort;
69         private Set<Integer> hsDevicePort;
70         private Map<Integer, Integer> hmAdditionalPort;
71         private int iNumOfObjects;
72         private int iNumOfHosts;
73         private boolean bVerbose;
74
75         /**
76          * CommunicationHandler class constants
77          */
78         private final int INT_MAX_PORT = 65535;
79         private final int INT_MIN_PORT = 10000;
80
81         /**
82          * Empty constructor
83          */
84         public CommunicationHandler(boolean _bVerbose) {
85
86                 random = new Random();
87                 listActiveControllerObj = new ArrayList<String>();
88                 listFieldObjectID = new ArrayList<String>();
89                 listObjCrtInfo = new ArrayList<ObjectCreationInfo>();
90                 listArrFieldValues = new ArrayList<Object[]>();
91                 listArrFieldClasses = new ArrayList<Class[]>();
92                 hmActiveObj = new HashMap<String, Integer>();
93                 hmHostAdd = new HashMap<Integer, String>();
94                 hmHostList = new HashMap<String, ArrayList<String>>();
95                 hmComPort = new HashMap<Integer, Integer>();
96                 hmRMIRegPort = new HashMap<Integer, Integer>();
97                 hmRMIStubPort = new HashMap<Integer, Integer>();
98                 hsDevicePort = new HashSet<Integer>();
99                 hmAdditionalPort = new HashMap<Integer, Integer>();
100                 iNumOfObjects = 0;
101                 iNumOfHosts = 0;
102                 bVerbose = _bVerbose;
103                 RuntimeOutput.print("CommunicationHandler: Creating a new CommunicationHandler object!", bVerbose);
104         }
105
106         /**
107          * Method addPortConnection()
108          * <p>
109          * Add a new connection then generate new in-port and out-port numbers
110          *
111          * @param   sHAddress                   String host address
112          * @param   sAObject                    String active object name
113          * @return  void
114          */
115         public void addPortConnection(String sHAddress, String sAObject) {
116
117                 // Increment counter first before we add objects as we start from 0
118                 // Objects are named uniquely so we record this and match with the host
119                 // Hostname occurrence can be repetitive as there can be more than
120                 // one host on one compute node
121
122                 // Add a new object in the list of objects
123                 hmActiveObj.put(sAObject, iNumOfObjects);
124
125                 // Check host existence in our data structure
126                 // Add a new host and a new object
127                 if(hmHostList.containsKey(sHAddress) == false) {
128                         iNumOfHosts++;
129                         hmHostList.put(sHAddress, new ArrayList<String>());
130                 }
131                 hmHostList.get(sHAddress).add(sAObject);
132
133                 // Map object to host
134                 hmHostAdd.put(iNumOfObjects, sHAddress);
135
136                 int iComPort = 0;
137                 do {
138                         iComPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
139                         // Check port existence in HashMap
140                 } while (portIsAvailable(iComPort) == false);
141                 hmComPort.put(iNumOfObjects, iComPort);
142
143                 int iRMIRegPort = 0;
144                 do {
145                         iRMIRegPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
146                         // Check port existence in HashMap
147                 } while (portIsAvailable(iRMIRegPort) == false);
148                 hmRMIRegPort.put(iNumOfObjects, iRMIRegPort);
149
150                 int iRMIStubPort = 0;
151                 do {
152                         iRMIStubPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
153                         // Check port existence in HashMap
154                 } while (portIsAvailable(iRMIStubPort) == false);
155                 hmRMIStubPort.put(iNumOfObjects, iRMIStubPort);
156
157                 iNumOfObjects++;
158         }
159
160         /**
161          * A private method to add a new active controller object
162          *
163          * @params  strFieldObjectID                    String field object ID
164          * @params  strObjName                                  String object name
165          * @params  strObjClassName                     String object class name
166          * @params  strObjClassInterfaceName    String object class interface name
167          * @params  strIoTSlaveObjectHostAdd    String IoTSlave host address
168          * @params  arrFieldValues                              Array of field values
169          * @params  arrFieldClasses                             Array of field classes
170          * @return  void
171          */
172         public void addActiveControllerObject(String strFieldObjectID, String strObjName, String strObjClassName,
173                 String strObjClassInterfaceName, String strObjStubClsIntfaceName, String strIoTSlaveObjectHostAdd, Object[] arrFieldValues, 
174                 Class[] arrFieldClasses) {
175
176                 listActiveControllerObj.add(strObjName);
177                 listFieldObjectID.add(strFieldObjectID);
178                 listArrFieldValues.add(arrFieldValues);
179                 listArrFieldClasses.add(arrFieldClasses);
180                 ObjectCreationInfo objCrtInfo = new ObjectCreationInfo(strIoTSlaveObjectHostAdd, strObjName,
181                         strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName);
182                 listObjCrtInfo.add(objCrtInfo);
183         }
184
185         /**
186          * Method addDevicePort()
187          * <p>
188          * Add a port that is used by a device when communicating with its driver
189          * This port will be taken into account when checking for port availability
190          *
191          * @param   iDevPort  Device port number
192          * @return  void
193          */
194         public void addDevicePort(int iDevPort) {
195
196                 hsDevicePort.add(iDevPort);
197
198         }
199
200         /**
201          * Method addAdditionalPort()
202          * <p>
203          * Add a new port for new connections for any objects in the program.
204          * This newly generated port number will be recorded.
205          *
206          * @return  int         One new port
207          */
208         public int addAdditionalPort(String sAObject) {
209
210                 hmActiveObj.put(sAObject, iNumOfObjects);
211
212                 int iAdditionalPort = 0;
213                 do {
214                         iAdditionalPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
215                         // Check port existence in HashMap
216                 } while (portIsAvailable(iAdditionalPort) == false);
217                 hmAdditionalPort.put(iNumOfObjects, iAdditionalPort);
218
219                 iNumOfObjects++;
220
221                 return iAdditionalPort;
222         }
223
224         /**
225          * Method portIsAvailable()
226          * <p>
227          * Checks the availability of the newly generated port.
228          * If port number has been used in any of the lists then
229          * it is not available
230          *
231          * @param   iPortNumber  Device port number
232          * @return  boolean
233          */
234         public boolean portIsAvailable(int iPortNumber) {
235
236                 if (hmComPort.containsValue(iPortNumber) == true) {
237                         return false;
238                 } else if (hmRMIRegPort.containsValue(iPortNumber) == true) {
239                         return false;
240                 } else if (hmRMIStubPort.containsValue(iPortNumber) == true) {
241                         return false;
242                 } else if (hmAdditionalPort.containsValue(iPortNumber) == true) {
243                         return false;
244                 } else if (hsDevicePort.contains(iPortNumber) == true) {
245                         return false;
246                 } else {
247                         return true;
248                 }
249         }
250
251         /**
252          * Method getNumOfObjects()
253          *
254          * @return  int
255          */
256         public int getNumOfObjects() {
257
258                 return iNumOfObjects;
259
260         }
261
262         /**
263          * Method getNumOfHosts()
264          *
265          * @return  int
266          */
267         public int getNumOfHosts() {
268
269                 return iNumOfHosts;
270
271         }
272
273         /**
274          * Method objectExists()
275          *
276          * @param   sObjName  String object name
277          * @return  boolean
278          */
279         public boolean objectExists(String sObjName) {
280
281                 return hmActiveObj.containsKey(sObjName);
282
283         }
284
285         /**
286          * Method hostExists()
287          *
288          * @param   sHostName  String host name
289          * @return  boolean
290          */
291         public boolean hostExists(String sHostName) {
292
293                 return hmHostList.containsKey(sHostName);
294
295         }
296
297         /**
298          * Method getHostAddress()
299          * <p>
300          * User finds HostAddress using Object name
301          *
302          * @param   sAObject  String active object name
303          * @return  String
304          */
305         public String getHostAddress(String sAObject) {
306
307                 return hmHostAdd.get(hmActiveObj.get(sAObject));
308
309         }
310
311         /**
312          * Method getHosts()
313          * <p>
314          * User gets the set of hostnames
315          *
316          * @return  String
317          */
318         public Set<String> getHosts() {
319
320                 return hmHostList.keySet();
321
322         }
323
324         /**
325          * Method getComPort()
326          * <p>
327          * User finds In-Port number using Object name
328          *
329          * @param   sAObject  String active object name
330          * @return  Integer
331          */
332         public Integer getComPort(String sAObject) {
333
334                 return hmComPort.get(hmActiveObj.get(sAObject));
335         }
336
337         /**
338          * Method getAdditionalPort()
339          * <p>
340          * User finds a port number using Object name
341          *
342          * @param   sAObject  String active object name
343          * @return  Integer
344          */
345         public Integer getAdditionalPort(String sAObject) {
346
347                 return hmAdditionalPort.get(hmActiveObj.get(sAObject));
348         }
349
350         /**
351          * Method getRMIRegPort()
352          * <p>
353          * User finds Out-Port number using Object name
354          *
355          * @param   sAObject  String active object name
356          * @return  Integer
357          */
358         public Integer getRMIRegPort(String sAObject) {
359
360                 return hmRMIRegPort.get(hmActiveObj.get(sAObject));
361
362         }
363
364         /**
365          * Method getRMIStubPort()
366          * <p>
367          * User finds Out-Port number using Object name
368          *
369          * @param   sAObject  String active object name
370          * @return  Integer
371          */
372         public Integer getRMIStubPort(String sAObject) {
373
374                 return hmRMIStubPort.get(hmActiveObj.get(sAObject));
375
376         }
377
378         /**
379          * Method getFieldObjectID()
380          * <p>
381          * User finds field object ID using Object name
382          *
383          * @param   sAObject  String active object name
384          * @return  String
385          */
386         public String getFieldObjectID(String sAObject) {
387
388                 return listFieldObjectID.get(listActiveControllerObj.indexOf(sAObject));
389
390         }
391
392         /**
393          * Method getObjectCreationInfo()
394          * <p>
395          * User finds ObjectCreationInfo using Object name
396          *
397          * @param   sAObject  String active object name
398          * @return  ObjectCreationInfo
399          */
400         public ObjectCreationInfo getObjectCreationInfo(String sAObject) {
401
402                 return listObjCrtInfo.get(listActiveControllerObj.indexOf(sAObject));
403
404         }
405
406         /**
407          * Method getArrayFieldClasses()
408          * <p>
409          * User finds array of field classes using Object name
410          *
411          * @param   sAObject  String active object name
412          * @return  Class[]
413          */
414         public Class[] getArrayFieldClasses(String sAObject) {
415
416                 return listArrFieldClasses.get(listActiveControllerObj.indexOf(sAObject));
417
418         }
419
420         /**
421          * Method getArrayFieldValues()
422          * <p>
423          * User finds array of field values using Object name
424          *
425          * @param   sAObject  String active object name
426          * @return  Object[]
427          */
428         public Object[] getArrayFieldValues(String sAObject) {
429
430                 return listArrFieldValues.get(listActiveControllerObj.indexOf(sAObject));
431
432         }
433
434         /**
435          * Method getActiveControllerObjectList()
436          *
437          * @return  List<String>
438          */
439         public List<String> getActiveControllerObjectList() {
440
441                 return listActiveControllerObj;
442
443         }
444
445         /**
446          * Method printLists()
447          *
448          * @return  void
449          */
450         public void printLists() {
451
452                 // Iterate on HostAddress
453                 for(String s : hmHostList.keySet()) {
454
455                         for(String str : hmHostList.get(s)) {
456
457                                 int iIndex = hmActiveObj.get(str);
458                                 RuntimeOutput.print("Active Object: " + str, bVerbose);
459                                 RuntimeOutput.print("Communication Port: " + hmComPort.get(iIndex), bVerbose);
460                                 RuntimeOutput.print("RMI Registry Port: " + hmRMIRegPort.get(iIndex), bVerbose);
461                                 RuntimeOutput.print("RMI Stub Port: " + hmRMIStubPort.get(iIndex), bVerbose);
462                                 RuntimeOutput.print("\n", bVerbose);
463                         }
464                 }
465
466                 for(int iPort : hsDevicePort) {
467                         RuntimeOutput.print("Device Port: " + iPort, bVerbose);
468                 }
469                 RuntimeOutput.print("\n", bVerbose);
470         }
471 }