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