5d257722772b03d9480bb67df92e36967755b6b0
[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 Set<Integer> hsAllPorts;
71         private Map<Integer, Integer> hmAdditionalPort;
72         private int iNumOfObjects;
73         private int iNumOfHosts;
74         private boolean bVerbose;
75
76         // TODO: THIS IS HACKING FOR IOTSEC
77         // Replace random
78         private int comPortCount = 10000;
79         private int rmiRegCount = 20000;
80         private int rmiStubCount = 30000;
81         private int additionalCount = 40000;
82
83         /**
84          * CommunicationHandler class constants
85          */
86         private final int INT_MAX_PORT = 65535;
87         private final int INT_MIN_PORT = 10000;
88
89         /**
90          * Empty constructor
91          */
92         public CommunicationHandler(boolean _bVerbose) {
93
94                 random = new Random();
95                 listActiveControllerObj = new ArrayList<String>();
96                 listFieldObjectID = new ArrayList<String>();
97                 listObjCrtInfo = new ArrayList<ObjectCreationInfo>();
98                 listArrFieldValues = new ArrayList<Object[]>();
99                 listArrFieldClasses = new ArrayList<Class[]>();
100                 hmActiveObj = new HashMap<String, Integer>();
101                 hmHostAdd = new HashMap<Integer, String>();
102                 hmHostList = new HashMap<String, ArrayList<String>>();
103                 hmComPort = new HashMap<Integer, Integer>();
104                 hmRMIRegPort = new HashMap<Integer, Integer>();
105                 hmRMIStubPort = new HashMap<Integer, Integer>();
106                 hsDevicePort = new HashSet<Integer>();
107                 hsAllPorts = new HashSet<Integer>();
108                 hmAdditionalPort = new HashMap<Integer, Integer>();
109                 iNumOfObjects = 0;
110                 iNumOfHosts = 0;
111                 bVerbose = _bVerbose;
112                 RuntimeOutput.print("CommunicationHandler: Creating a new CommunicationHandler object!", bVerbose);
113         }
114         
115         /**
116          * Method clearCommunicationHandler()
117          * <p>
118          * Clear the data structure
119          *
120          * @return  void
121          */
122         public void clearCommunicationHandler() {
123
124                 listActiveControllerObj.clear();
125                 listFieldObjectID.clear();
126                 listObjCrtInfo.clear();
127                 listArrFieldValues.clear();
128                 listArrFieldClasses.clear();
129                 hmActiveObj.clear();
130                 hmHostAdd.clear();
131                 hmHostList.clear();
132                 hmComPort.clear();
133                 hmRMIRegPort.clear();
134                 hmRMIStubPort.clear();
135                 hsDevicePort.clear();
136                 hmAdditionalPort.clear();
137                 iNumOfObjects = 0;
138                 iNumOfHosts = 0;
139                 RuntimeOutput.print("CommunicationHandler: Clearing CommunicationHandler object's data structure!", bVerbose);
140     }
141
142         /**
143          * Method addPortConnection()
144          * <p>
145          * Add a new connection then generate new in-port and out-port numbers
146          *
147          * @param   sHAddress                   String host address
148          * @param   sAObject                    String active object name
149          * @return  void
150          */
151         public void addPortConnection(String sHAddress, String sAObject) {
152
153                 // Increment counter first before we add objects as we start from 0
154                 // Objects are named uniquely so we record this and match with the host
155                 // Hostname occurrence can be repetitive as there can be more than
156                 // one host on one compute node
157
158                 // Add a new object in the list of objects
159                 hmActiveObj.put(sAObject, iNumOfObjects);
160
161                 // Check host existence in our data structure
162                 // Add a new host and a new object
163                 if(hmHostList.containsKey(sHAddress) == false) {
164                         iNumOfHosts++;
165                         hmHostList.put(sHAddress, new ArrayList<String>());
166                 }
167                 hmHostList.get(sHAddress).add(sAObject);
168
169                 // Map object to host
170                 hmHostAdd.put(iNumOfObjects, sHAddress);
171
172                 int iComPort = 0;
173                 do {
174                         iComPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
175                         //System.out.println("DEBUG: Assigning comPort: " + comPortCount);
176                         //iComPort = comPortCount++;
177                         // Check port existence in HashMap
178                 } while (portIsAvailable(iComPort) == false);
179                 hmComPort.put(iNumOfObjects, iComPort);
180                 // hsAllPorts tracks all the existing and used port numbers
181                 hsAllPorts.add(iComPort);
182
183                 int iRMIRegPort = 0;
184                 do {
185                         iRMIRegPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
186                         //System.out.println("DEBUG: Assigning regPort: " + rmiRegCount);
187                         //iRMIRegPort = rmiRegCount++;
188                         // Check port existence in HashMap
189                 } while (portIsAvailable(iRMIRegPort) == false);
190                 hmRMIRegPort.put(iNumOfObjects, iRMIRegPort);
191                 hsAllPorts.add(iRMIRegPort);
192
193                 int iRMIStubPort = 0;
194                 do {
195                         iRMIStubPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
196                         //System.out.println("DEBUG: Assigning stubPort: " + rmiStubCount);
197                         //iRMIStubPort = rmiStubCount++;
198                         // Check port existence in HashMap
199                 } while (portIsAvailable(iRMIStubPort) == false);
200                 hmRMIStubPort.put(iNumOfObjects, iRMIStubPort);
201                 hsAllPorts.add(iRMIStubPort);
202
203                 iNumOfObjects++;
204         }
205
206         /**
207          * A private method to add a new active controller object
208          *
209          * @params  strFieldObjectID                    String field object ID
210          * @params  strObjName                                  String object name
211          * @params  strObjClassName                     String object class name
212          * @params  strObjClassInterfaceName    String object class interface name
213          * @params  strIoTSlaveObjectHostAdd    String IoTSlave host address
214          * @params  arrFieldValues                              Array of field values
215          * @params  arrFieldClasses                             Array of field classes
216          * @return  void
217          */
218         public void addActiveControllerObject(String strFieldObjectID, String strObjName, String strObjClassName,
219                 String strObjClassInterfaceName, String strObjStubClsIntfaceName, String strIoTSlaveObjectHostAdd, Object[] arrFieldValues, 
220                 Class[] arrFieldClasses) {
221
222                 listActiveControllerObj.add(strObjName);
223                 listFieldObjectID.add(strFieldObjectID);
224                 listArrFieldValues.add(arrFieldValues);
225                 listArrFieldClasses.add(arrFieldClasses);
226                 ObjectCreationInfo objCrtInfo = new ObjectCreationInfo(strIoTSlaveObjectHostAdd, strObjName,
227                         strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName);
228                 listObjCrtInfo.add(objCrtInfo);
229         }
230
231         /**
232          * Method addDevicePort()
233          * <p>
234          * Add a port that is used by a device when communicating with its driver
235          * This port will be taken into account when checking for port availability
236          *
237          * @param   iDevPort  Device port number
238          * @return  void
239          */
240         public void addDevicePort(int iDevPort) {
241
242                 hsDevicePort.add(iDevPort);
243                 // Track this port number
244         hsAllPorts.add(iDevPort);
245         }
246
247         /**
248          * Method addAdditionalPort()
249          * <p>
250          * Add a new port for new connections for any objects in the program.
251          * This newly generated port number will be recorded.
252          *
253          * @return  int         One new port
254          */
255         public int addAdditionalPort(String sAObject) {
256
257                 hmActiveObj.put(sAObject, iNumOfObjects);
258
259                 int iAdditionalPort = 0;
260                 do {
261                         iAdditionalPort = random.nextInt(INT_MAX_PORT - INT_MIN_PORT + 1) + INT_MIN_PORT;
262                         //System.out.println("DEBUG: Assigning additionalPort: " + additionalCount);
263                         //iAdditionalPort = additionalCount++;
264                         // Check port existence in HashMap
265                 } while (portIsAvailable(iAdditionalPort) == false);
266                 hmAdditionalPort.put(iNumOfObjects, iAdditionalPort);
267                 // Track this port number
268                 hsAllPorts.add(iAdditionalPort);
269
270                 iNumOfObjects++;
271
272                 return iAdditionalPort;
273         }
274
275         /**
276          * Method portIsAvailable()
277          * <p>
278          * Checks the availability of the newly generated port.
279          * If port number has been used in any of the lists then
280          * it is not available
281          *
282          * @param   iPortNumber  Device port number
283          * @return  boolean
284          */
285         public boolean portIsAvailable(int iPortNumber) {
286
287                 if (hmComPort.containsValue(iPortNumber) == true) {
288                         return false;
289                 } else if (hmRMIRegPort.containsValue(iPortNumber) == true) {
290                         return false;
291                 } else if (hmRMIStubPort.containsValue(iPortNumber) == true) {
292                         return false;
293                 } else if (hmAdditionalPort.containsValue(iPortNumber) == true) {
294                         return false;
295                 } else if (hsDevicePort.contains(iPortNumber) == true) {
296                         return false;
297                 } else {
298                         return true;
299                 }
300                 //if (hsAllPorts.contains(iPortNumber)) {
301                 //    return false;
302                 //} else {
303                 //    return true;
304                 //}
305         }
306
307         /**
308          * Method getNumOfObjects()
309          *
310          * @return  int
311          */
312         public int getNumOfObjects() {
313
314                 return iNumOfObjects;
315
316         }
317
318         /**
319          * Method getNumOfHosts()
320          *
321          * @return  int
322          */
323         public int getNumOfHosts() {
324
325                 return iNumOfHosts;
326
327         }
328
329         /**
330          * Method objectExists()
331          *
332          * @param   sObjName  String object name
333          * @return  boolean
334          */
335         public boolean objectExists(String sObjName) {
336
337                 return hmActiveObj.containsKey(sObjName);
338
339         }
340
341         /**
342          * Method hostExists()
343          *
344          * @param   sHostName  String host name
345          * @return  boolean
346          */
347         public boolean hostExists(String sHostName) {
348
349                 return hmHostList.containsKey(sHostName);
350
351         }
352
353         /**
354          * Method getHostAddress()
355          * <p>
356          * User finds HostAddress using Object name
357          *
358          * @param   sAObject  String active object name
359          * @return  String
360          */
361         public String getHostAddress(String sAObject) {
362
363                 return hmHostAdd.get(hmActiveObj.get(sAObject));
364
365         }
366
367         /**
368          * Method getHosts()
369          * <p>
370          * User gets the set of hostnames
371          *
372          * @return  String
373          */
374         public Set<String> getHosts() {
375
376                 return hmHostList.keySet();
377
378         }
379
380         /**
381          * Method getComPort()
382          * <p>
383          * User finds In-Port number using Object name
384          *
385          * @param   sAObject  String active object name
386          * @return  Integer
387          */
388         public Integer getComPort(String sAObject) {
389
390                 return hmComPort.get(hmActiveObj.get(sAObject));
391         }
392
393         /**
394          * Method getAdditionalPort()
395          * <p>
396          * User finds a port number using Object name
397          *
398          * @param   sAObject  String active object name
399          * @return  Integer
400          */
401         public Integer getAdditionalPort(String sAObject) {
402
403                 return hmAdditionalPort.get(hmActiveObj.get(sAObject));
404         }
405
406         /**
407          * Method getRMIRegPort()
408          * <p>
409          * User finds Out-Port number using Object name
410          *
411          * @param   sAObject  String active object name
412          * @return  Integer
413          */
414         public Integer getRMIRegPort(String sAObject) {
415
416                 return hmRMIRegPort.get(hmActiveObj.get(sAObject));
417
418         }
419
420         /**
421          * Method getRMIStubPort()
422          * <p>
423          * User finds Out-Port number using Object name
424          *
425          * @param   sAObject  String active object name
426          * @return  Integer
427          */
428         public Integer getRMIStubPort(String sAObject) {
429
430                 return hmRMIStubPort.get(hmActiveObj.get(sAObject));
431
432         }
433
434         /**
435          * Method getFieldObjectID()
436          * <p>
437          * User finds field object ID using Object name
438          *
439          * @param   sAObject  String active object name
440          * @return  String
441          */
442         public String getFieldObjectID(String sAObject) {
443
444                 return listFieldObjectID.get(listActiveControllerObj.indexOf(sAObject));
445
446         }
447
448         /**
449          * Method getObjectCreationInfo()
450          * <p>
451          * User finds ObjectCreationInfo using Object name
452          *
453          * @param   sAObject  String active object name
454          * @return  ObjectCreationInfo
455          */
456         public ObjectCreationInfo getObjectCreationInfo(String sAObject) {
457
458                 return listObjCrtInfo.get(listActiveControllerObj.indexOf(sAObject));
459
460         }
461
462         /**
463          * Method getArrayFieldClasses()
464          * <p>
465          * User finds array of field classes using Object name
466          *
467          * @param   sAObject  String active object name
468          * @return  Class[]
469          */
470         public Class[] getArrayFieldClasses(String sAObject) {
471
472                 return listArrFieldClasses.get(listActiveControllerObj.indexOf(sAObject));
473
474         }
475
476         /**
477          * Method getArrayFieldValues()
478          * <p>
479          * User finds array of field values using Object name
480          *
481          * @param   sAObject  String active object name
482          * @return  Object[]
483          */
484         public Object[] getArrayFieldValues(String sAObject) {
485
486                 return listArrFieldValues.get(listActiveControllerObj.indexOf(sAObject));
487
488         }
489
490         /**
491          * Method getActiveControllerObjectList()
492          *
493          * @return  List<String>
494          */
495         public List<String> getActiveControllerObjectList() {
496
497                 return listActiveControllerObj;
498
499         }
500
501         /**
502          * Method printLists()
503          *
504          * @return  void
505          */
506         public void printLists() {
507
508                 // Iterate on HostAddress
509                 for(String s : hmHostList.keySet()) {
510
511                         for(String str : hmHostList.get(s)) {
512
513                                 int iIndex = hmActiveObj.get(str);
514                                 RuntimeOutput.print("Active Object: " + str, bVerbose);
515                                 RuntimeOutput.print("Communication Port: " + hmComPort.get(iIndex), bVerbose);
516                                 RuntimeOutput.print("RMI Registry Port: " + hmRMIRegPort.get(iIndex), bVerbose);
517                                 RuntimeOutput.print("RMI Stub Port: " + hmRMIStubPort.get(iIndex), bVerbose);
518                                 RuntimeOutput.print("\n", bVerbose);
519                         }
520                 }
521
522                 for(int iPort : hsDevicePort) {
523                         RuntimeOutput.print("Device Port: " + iPort, bVerbose);
524                 }
525                 RuntimeOutput.print("\n", bVerbose);
526         }
527 }