Modifying master for Tomoyo process jailing; Adding basic policies for Tomoyo environ...
[iot2.git] / iotjava / iotruntime / master / IoTMaster.java
1 package iotruntime.master;
2
3 import iotruntime.*;
4 import iotruntime.slave.IoTAddress;
5 import iotruntime.slave.IoTDeviceAddress;
6 import iotruntime.messages.*;
7
8 // ASM packages
9 import org.objectweb.asm.ClassReader;
10 import org.objectweb.asm.ClassWriter;
11 import org.objectweb.asm.ClassVisitor;
12
13 // Java packages
14 import java.io.*;
15 import java.util.*;
16 import java.io.BufferedReader;
17 import java.io.InputStream;
18 import java.io.InputStreamReader;
19 import java.io.File;
20 import java.io.FileInputStream;
21 import java.io.FileOutputStream;
22 import java.io.OutputStream;
23 import java.io.ObjectInputStream;
24 import java.io.ObjectOutputStream;
25 import java.io.IOException;
26 import java.lang.ClassNotFoundException;
27 import java.lang.Class;
28 import java.lang.reflect.*;
29 import java.net.Socket;
30 import java.net.ServerSocket;
31 import java.nio.ByteBuffer;
32 import java.util.*;
33 import static java.lang.Math.toIntExact;
34
35 /** Class IoTMaster is responsible to use ClassRuntimeInstrumenterMaster
36  *  to instrument the controller/device bytecode and starts multiple
37  *  IoTSlave running on different JVM's in a distributed fashion.
38  *
39  * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
40  * @version     1.0
41  * @since       2016-06-16
42  */
43 public class IoTMaster {
44
45         /**
46          * IoTMaster class properties
47          * <p>
48          * CommunicationHandler maintains the data structure for hostnames and ports
49          * LoadBalancer assigns a job onto a host based on certain metrics
50          */
51         private CommunicationHandler commHan;
52         private LoadBalancer lbIoT;
53         private RouterConfig routerConfig;
54         private ObjectInitHandler objInitHand;
55         private ObjectAddressInitHandler objAddInitHand;
56         private String[] strObjectNames;
57         // Now this can be either ClassRuntimeInstrumenterMaster or CRuntimeInstrumenterMaster
58         private Map<String,Object> mapClassNameToCrim;
59
60         /**
61          * These properties hold information of a certain object
62          * at a certain time
63          */
64         private String strObjName;
65         private String strObjClassName;
66         private String strObjClassInterfaceName;
67         private String strObjStubClsIntfaceName;
68         private String strIoTMasterHostAdd;
69         private String strIoTSlaveControllerHostAdd;
70         private String strIoTSlaveObjectHostAdd;
71         private Class[] arrFieldClasses;
72         private Object[] arrFieldValues;
73         private Socket filesocket;
74
75         /**
76          * For connection with C++ IoTSlave
77          */
78         private ServerSocket serverSocketCpp;
79         private Socket socketCpp;
80         private BufferedInputStream inputCpp;
81         private BufferedOutputStream outputCpp;
82
83         // Constants that are to be extracted from config file
84         private static String STR_MASTER_MAC_ADD;
85         private static String STR_IOT_CODE_PATH;
86         private static String STR_CONT_PATH;
87         private static String STR_RUNTIME_DIR;
88         private static String STR_SLAVE_DIR;
89         private static String STR_CLS_PATH;
90         private static String STR_RMI_PATH;
91         private static String STR_RMI_HOSTNAME;
92         private static String STR_LOG_FILE_PATH;
93         private static String STR_USERNAME;
94         private static String STR_ROUTER_ADD;
95         private static String STR_MONITORING_HOST;
96         private static String STR_ZB_GATEWAY_ADDRESS;
97         private static String STR_ZB_GATEWAY_PORT;
98         private static String STR_ZB_IOTMASTER_PORT;
99         private static String STR_JVM_INIT_HEAP_SIZE;
100         private static String STR_JVM_MAX_HEAP_SIZE;
101         private static String STR_LANGUAGE_CONTROLLER;
102         private static String STR_SKEL_CLASS_SUFFIX;
103         private static String STR_STUB_CLASS_SUFFIX;
104         private static boolean BOOL_VERBOSE;
105
106         /**
107          * IoTMaster class constants
108          * <p>
109          * Name constants - not to be configured by users
110          */
111         private static final String STR_IOT_MASTER_NAME = "IoTMaster";
112         private static final String STR_CFG_FILE_EXT = ".config";
113         private static final String STR_CLS_FILE_EXT = ".class";
114         private static final String STR_JAR_FILE_EXT = ".jar";
115         private static final String STR_SHELL_FILE_EXT = ".sh";
116         private static final String STR_SO_FILE_EXT = ".so";
117         private static final String STR_ZIP_FILE_EXT = ".zip";
118         private static final String STR_TCP_PROTOCOL = "tcp";
119         private static final String STR_UDP_PROTOCOL = "udp";
120         private static final String STR_TCPGW_PROTOCOL = "tcpgw";
121         private static final String STR_NO_PROTOCOL = "nopro";
122         private static final String STR_SELF_MAC_ADD = "00:00:00:00:00:00";
123         private static final String STR_INTERFACE_CLS_CFG = "INTERFACE_CLASS";
124         private static final String STR_INT_STUB_CLS_CFG = "INTERFACE_STUB_CLASS";
125         private static final String STR_FILE_TRF_CFG = "ADDITIONAL_ZIP_FILE";
126         private static final String STR_LANGUAGE = "LANGUAGE";
127         private static final String STR_YES = "Yes";
128         private static final String STR_NO = "No";
129         private static final String STR_JAVA = "Java";
130         private static final String STR_CPP = "C++";
131         private static final String STR_SSH = "ssh";
132         private static final String STR_SCP = "scp";
133         private static final String STR_IOTSLAVE_CPP = "./IoTSlave.o";
134         private static final String STR_SHELL_HEADER = "#!/bin/sh";
135         private static final String STR_JAVA_PATH = "/usr/bin/java";
136
137         private static int INT_SIZE = 4;        // send length in the size of integer (4 bytes)
138
139         /**
140          * Runtime class name constants - not to be configured by users
141          */
142         private static final String STR_REL_INSTRUMENTER_CLS = "iotruntime.master.RelationInstrumenter";
143         private static final String STR_SET_INSTRUMENTER_CLS = "iotruntime.master.SetInstrumenter";
144         private static final String STR_IOT_SLAVE_CLS = "iotruntime.slave.IoTSlave";
145         private static final String STR_IOT_DEV_ADD_CLS = "IoTDeviceAddress";
146         private static final String STR_IOT_ZB_ADD_CLS = "IoTZigbeeAddress";
147         private static final String STR_IOT_ADD_CLS = "IoTAddress";
148         
149         /**
150          * Class constructor
151          *
152          */
153         public IoTMaster(String[] argObjNms) {
154
155                 commHan = null;
156                 lbIoT = null;
157                 routerConfig = null;
158                 objInitHand = null;
159                 objAddInitHand = null;
160                 strObjectNames = argObjNms;
161                 strObjName = null;
162                 strObjClassName = null;
163                 strObjClassInterfaceName = null;
164                 strObjStubClsIntfaceName = null;
165                 strIoTMasterHostAdd = null;
166                 strIoTSlaveControllerHostAdd = null;
167                 strIoTSlaveObjectHostAdd = null;
168                 arrFieldClasses = null;
169                 arrFieldValues = null;
170                 filesocket = null;
171                 mapClassNameToCrim = null;
172                 // Connection with C++ IoTSlave
173                 serverSocketCpp = null;
174                 socketCpp = null;
175                 inputCpp = null;
176                 outputCpp = null;
177
178                 STR_MASTER_MAC_ADD = null;
179                 STR_IOT_CODE_PATH = null;
180                 STR_CONT_PATH = null;
181                 STR_RUNTIME_DIR = null;
182                 STR_SLAVE_DIR = null;
183                 STR_CLS_PATH = null;
184                 STR_RMI_PATH = null;
185                 STR_RMI_HOSTNAME = null;
186                 STR_LOG_FILE_PATH = null;
187                 STR_USERNAME = null;
188                 STR_ROUTER_ADD = null;
189                 STR_MONITORING_HOST = null;
190                 STR_ZB_GATEWAY_ADDRESS = null;
191                 STR_ZB_GATEWAY_PORT = null;
192                 STR_ZB_IOTMASTER_PORT = null;
193                 STR_JVM_INIT_HEAP_SIZE = null;
194                 STR_JVM_MAX_HEAP_SIZE = null;
195                 STR_LANGUAGE_CONTROLLER = null;
196                 BOOL_VERBOSE = false;
197         }
198
199         /**
200          * A method to initialize CommunicationHandler, LoadBalancer, RouterConfig and ObjectInitHandler
201          *
202          * @return void
203          */
204         private void initLiveDataStructure() {
205
206                 commHan = new CommunicationHandler(BOOL_VERBOSE);
207                 lbIoT = new LoadBalancer(BOOL_VERBOSE);
208                 lbIoT.setupLoadBalancer();
209                 routerConfig = new RouterConfig();
210                 routerConfig.getAddressList(STR_ROUTER_ADD);
211                 objInitHand = new ObjectInitHandler(BOOL_VERBOSE);
212                 objAddInitHand = new ObjectAddressInitHandler(BOOL_VERBOSE);
213                 mapClassNameToCrim = new HashMap<String,Object>();
214         }
215
216         /**
217          * getPrintWriter() gets a new PrintWriter for a new object
218          *
219          * @param   strObjectName       String object name
220          * @return  PrintWriter
221          */
222         private PrintWriter getPrintWriter(String strObjectName) {
223
224                 FileWriter fw = null;
225                 try {
226                         fw = new FileWriter(strObjectName);
227                 } catch (IOException ex) {
228                         ex.printStackTrace();
229                 }
230                 PrintWriter printWriter = new PrintWriter(new BufferedWriter(fw));
231                 return printWriter;
232         }
233
234         /**
235          * A method to initialize constants from config file
236          *
237          * @return void
238          */
239         private void parseIoTMasterConfigFile() {
240                 // Parse configuration file
241                 Properties prop = new Properties();
242                 String strCfgFileName = STR_IOT_MASTER_NAME + STR_CFG_FILE_EXT;
243                 File file = new File(strCfgFileName);
244                 FileInputStream fis = null;
245                 try {
246                         fis = new FileInputStream(file);
247                         prop.load(fis);
248                         fis.close();
249                 } catch (IOException ex) {
250                         System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
251                         ex.printStackTrace();
252                 }
253                 // Initialize constants from config file
254                 STR_MASTER_MAC_ADD = prop.getProperty("MAC_ADDRESS");
255                 STR_IOT_CODE_PATH = prop.getProperty("IOT_CODE_PATH");
256                 STR_CONT_PATH = prop.getProperty("CONTROLLERS_CODE_PATH");
257                 STR_RUNTIME_DIR = prop.getProperty("RUNTIME_DIR");
258                 STR_SLAVE_DIR = prop.getProperty("SLAVE_DIR");
259                 STR_CLS_PATH = prop.getProperty("CLASS_PATH");
260                 STR_RMI_PATH = prop.getProperty("RMI_PATH");
261                 STR_RMI_HOSTNAME = prop.getProperty("RMI_HOSTNAME");
262                 STR_LOG_FILE_PATH = prop.getProperty("LOG_FILE_PATH");
263                 STR_USERNAME = prop.getProperty("USERNAME");
264                 STR_ROUTER_ADD = prop.getProperty("ROUTER_ADD");
265                 STR_MONITORING_HOST = prop.getProperty("MONITORING_HOST");
266                 STR_ZB_GATEWAY_ADDRESS = prop.getProperty("ZIGBEE_GATEWAY_ADDRESS");
267                 STR_ZB_GATEWAY_PORT = prop.getProperty("ZIGBEE_GATEWAY_PORT");
268                 STR_ZB_IOTMASTER_PORT = prop.getProperty("ZIGBEE_IOTMASTER_PORT");
269                 STR_JVM_INIT_HEAP_SIZE = prop.getProperty("JVM_INIT_HEAP_SIZE");
270                 STR_JVM_MAX_HEAP_SIZE = prop.getProperty("JVM_MAX_HEAP_SIZE");
271                 STR_SKEL_CLASS_SUFFIX = prop.getProperty("SKEL_CLASS_SUFFIX");
272                 STR_STUB_CLASS_SUFFIX = prop.getProperty("STUB_CLASS_SUFFIX");
273                 if(prop.getProperty("VERBOSE").equals(STR_YES)) {
274                         BOOL_VERBOSE = true;
275                 }
276
277                 RuntimeOutput.print("IoTMaster: Extracting information from config file: " + strCfgFileName, BOOL_VERBOSE);
278                 RuntimeOutput.print("STR_MASTER_MAC_ADD=" + STR_MASTER_MAC_ADD, BOOL_VERBOSE);
279                 RuntimeOutput.print("STR_IOT_CODE_PATH=" + STR_IOT_CODE_PATH, BOOL_VERBOSE);
280                 RuntimeOutput.print("STR_CONT_PATH=" + STR_CONT_PATH, BOOL_VERBOSE);
281                 RuntimeOutput.print("STR_RUNTIME_DIR=" + STR_RUNTIME_DIR, BOOL_VERBOSE);
282                 RuntimeOutput.print("STR_SLAVE_DIR=" + STR_SLAVE_DIR, BOOL_VERBOSE);
283                 RuntimeOutput.print("STR_CLS_PATH=" + STR_CLS_PATH, BOOL_VERBOSE);
284                 RuntimeOutput.print("STR_RMI_PATH=" + STR_RMI_PATH, BOOL_VERBOSE);
285                 RuntimeOutput.print("STR_RMI_HOSTNAME=" + STR_RMI_HOSTNAME, BOOL_VERBOSE);
286                 RuntimeOutput.print("STR_LOG_FILE_PATH=" + STR_LOG_FILE_PATH, BOOL_VERBOSE);
287                 RuntimeOutput.print("STR_USERNAME=" + STR_USERNAME, BOOL_VERBOSE);
288                 RuntimeOutput.print("STR_ROUTER_ADD=" + STR_ROUTER_ADD, BOOL_VERBOSE);
289                 RuntimeOutput.print("STR_MONITORING_HOST=" + STR_MONITORING_HOST, BOOL_VERBOSE);
290                 RuntimeOutput.print("STR_ZB_GATEWAY_ADDRESS=" + STR_ZB_GATEWAY_ADDRESS, BOOL_VERBOSE);
291                 RuntimeOutput.print("STR_ZB_GATEWAY_PORT=" + STR_ZB_GATEWAY_PORT, BOOL_VERBOSE);
292                 RuntimeOutput.print("STR_ZB_IOTMASTER_PORT=" + STR_ZB_IOTMASTER_PORT, BOOL_VERBOSE);
293                 RuntimeOutput.print("STR_JVM_INIT_HEAP_SIZE=" + STR_JVM_INIT_HEAP_SIZE, BOOL_VERBOSE);
294                 RuntimeOutput.print("STR_JVM_MAX_HEAP_SIZE=" + STR_JVM_MAX_HEAP_SIZE, BOOL_VERBOSE);
295                 RuntimeOutput.print("STR_SKEL_CLASS_SUFFIX=" + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
296                 RuntimeOutput.print("STR_STUB_CLASS_SUFFIX=" + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
297                 RuntimeOutput.print("BOOL_VERBOSE=" + BOOL_VERBOSE, BOOL_VERBOSE);
298                 RuntimeOutput.print("IoTMaster: Information extracted successfully!", BOOL_VERBOSE);
299         }
300
301         /**
302          * A method to parse information from a config file
303          *
304          * @param       strCfgFileName  Config file name
305          * @param       strCfgField             Config file field name
306          * @return      String
307          */
308         private String parseConfigFile(String strCfgFileName, String strCfgField) {
309                 // Parse configuration file
310                 Properties prop = new Properties();
311                 File file = new File(strCfgFileName);
312                 FileInputStream fis = null;
313                 try {
314                         fis = new FileInputStream(file);
315                         prop.load(fis);
316                         fis.close();
317                 } catch (IOException ex) {
318                         System.out.println("IoTMaster: Error reading config file: " + strCfgFileName);
319                         ex.printStackTrace();
320                 }
321                 System.out.println("IoTMaster: Reading " + strCfgField +
322                         " from config file: " + strCfgFileName + " with value: " + 
323                         prop.getProperty(strCfgField, null));
324                 // NULL is returned if the property isn't found
325                 return prop.getProperty(strCfgField, null);
326         }
327
328         /**
329          * A method to send files from IoTMaster
330          *
331          * @param  filesocket File socket object
332          * @param  sFileName  File name
333          * @param  lFLength   File length
334          * @return            void
335          */
336         private void sendFile(Socket filesocket, String sFileName, long lFLength) throws IOException {
337
338                 File file = new File(sFileName);
339                 byte[] bytFile = new byte[toIntExact(lFLength)];
340                 InputStream inFileStream = new FileInputStream(file);
341
342                 OutputStream outFileStream = filesocket.getOutputStream();
343                 int iCount;
344                 while ((iCount = inFileStream.read(bytFile)) > 0) {
345                         outFileStream.write(bytFile, 0, iCount);
346                 }
347                 filesocket.close();
348                 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
349         }
350
351         /**
352          * A method to create a thread
353          *
354          * @param  sSSHCmd    SSH command
355          * @return            void
356          */
357         private void createThread(String sSSHCmd) throws IOException {
358
359                 // Start a new thread to start a new JVM
360                 new Thread() {
361                         Runtime runtime = Runtime.getRuntime();
362                         Process process = runtime.exec(sSSHCmd);
363                 }.start();
364                 RuntimeOutput.print("Executing: " + sSSHCmd, BOOL_VERBOSE);
365         }
366
367         /**
368          * A method to send command from master and receive reply from slave
369          *
370          * @params  msgSend     Message object
371          * @params  strPurpose  String that prints purpose message
372          * @params  inStream    Input stream
373          * @params  outStream   Output stream
374          * @return  void
375          */
376         private void commMasterToSlave(Message msgSend, String strPurpose,
377                 InputStream _inStream, OutputStream _outStream)  
378                         throws IOException, ClassNotFoundException {
379
380                 // Send message/command from master
381                 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
382                 outStream.writeObject(msgSend);
383                 RuntimeOutput.print("IoTMaster: Send message: " + strPurpose, BOOL_VERBOSE);
384
385                 // Get reply from slave as acknowledgment
386                 ObjectInputStream inStream = (ObjectInputStream) _inStream;
387                 Message msgReply = (Message) inStream.readObject();
388                 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
389         }
390
391         /**
392          * A private method to instrument IoTSet device
393          *
394          * @params  strFieldIdentifier        String field name + object ID
395          * @params  strFieldName              String field name
396          * @params  strIoTSlaveObjectHostAdd  String slave host address
397          * @params  inStream                  ObjectInputStream communication
398          * @params  inStream                  ObjectOutputStream communication
399          * @params  strLanguage                           String language
400          * @return  void
401          */
402         private void instrumentIoTSetDevice(String strFieldIdentifier, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
403                 InputStream inStream, OutputStream outStream, String strLanguage)  
404                         throws IOException, ClassNotFoundException, InterruptedException {
405
406                 // Get information from the set
407                 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
408                 // Create a new IoTSet
409                 if(strLanguage.equals(STR_JAVA)) {
410                         Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
411                         commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTDeviceAddress!", inStream, outStream);
412                 } else
413                         createNewIoTSetCpp(strFieldName, outStream, inStream);
414                 int iRows = listObject.size();
415                 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
416                 // Transfer the address
417                 for(int iRow=0; iRow<iRows; iRow++) {
418                         arrFieldValues = listObject.get(iRow);
419                         // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
420                         String strDeviceAddress = null;
421                         String strDeviceAddressKey = null;
422                         if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
423                                 strDeviceAddress = strIoTSlaveObjectHostAdd;
424                                 strDeviceAddressKey = strObjName + "-" + strIoTSlaveObjectHostAdd;
425                         } else {
426                                 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
427                                 strDeviceAddressKey = strObjName + "-" + strDeviceAddress;
428                         }
429                         int iDestDeviceDriverPort = (int) arrFieldValues[1];
430                         String strProtocol = (String) arrFieldValues[2];
431                         // Check for wildcard feature                   
432                         boolean bSrcPortWildCard = false;
433                         boolean bDstPortWildCard = false;
434                         if (arrFieldValues.length > 3) {
435                                 bSrcPortWildCard = (boolean) arrFieldValues[3];
436                                 bDstPortWildCard = (boolean) arrFieldValues[4];
437                         }
438                         // Add the port connection into communication handler - if it's not assigned yet
439                         if (commHan.getComPort(strDeviceAddressKey) == null) {
440                                 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddressKey);
441                         }
442
443                         // TODO: DEBUG!!!
444                         System.out.println("\n\n DEBUG: InstrumentSetDevice: Object Name: " + strObjName);
445                         System.out.println("DEBUG: InstrumentSetDevice: Port number: " + commHan.getComPort(strDeviceAddressKey));
446                         System.out.println("DEBUG: InstrumentSetDevice: Device address: " + strDeviceAddressKey + "\n\n");
447
448                         // Send address one by one
449                         if(strLanguage.equals(STR_JAVA)) {
450                                 Message msgGetIoTSetObj = null;
451                                 if (bDstPortWildCard) {
452                                         String strUniqueDev = strDeviceAddressKey + ":" + iRow;
453                                         msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
454                                                 strDeviceAddress, commHan.getAdditionalPort(strUniqueDev), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard);
455                                 } else
456                                         msgGetIoTSetObj = new MessageGetDeviceObject(IoTCommCode.GET_DEVICE_IOTSET_OBJECT,
457                                                 strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort, bSrcPortWildCard, bDstPortWildCard);
458                                 commMasterToSlave(msgGetIoTSetObj, "Get IoTSet objects!", inStream, outStream);
459                         } else
460                                 getDeviceIoTSetObjectCpp(outStream, inStream, strDeviceAddress, commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort, 
461                                         bSrcPortWildCard, bDstPortWildCard);
462                 }
463                 // Reinitialize IoTSet on device object
464                 if(strLanguage.equals(STR_JAVA))
465                         commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream);
466                 else
467                         reinitializeIoTSetFieldCpp(outStream, inStream);
468         }
469
470
471         /**
472          * A private method to instrument IoTSet Zigbee device
473          *
474          * @params  Map.Entry<String,Object>  Entry of map IoTSet instrumentation
475          * @params  strFieldName              String field name
476          * @params  strIoTSlaveObjectHostAdd  String slave host address
477          * @params  inStream                  ObjectInputStream communication
478          * @params  inStream                  ObjectOutputStream communication
479          * @params  strLanguage                           String language
480          * @return  void
481          */
482         private void instrumentIoTSetZBDevice(Map.Entry<String,Object> map, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
483                 InputStream inStream, OutputStream outStream, String strLanguage)  
484                         throws IOException, ClassNotFoundException, InterruptedException {
485
486                 // Get information from the set
487                 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
488                 // Create a new IoTSet
489                 if(strLanguage.equals(STR_JAVA)) {
490                         Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
491                         commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTZigbeeAddress!", inStream, outStream);
492                 } else  // TODO: will need to implement IoTSet Zigbee for C++ later
493                         ;
494                 // Prepare ZigbeeConfig
495                 String strZigbeeGWAddress = routerConfig.getIPFromMACAddress(STR_ZB_GATEWAY_ADDRESS);
496                 String strZigbeeGWAddressKey = strObjName + "-" + strZigbeeGWAddress;
497                 int iZigbeeGWPort = Integer.parseInt(STR_ZB_GATEWAY_PORT);
498                 int iZigbeeIoTMasterPort = Integer.parseInt(STR_ZB_IOTMASTER_PORT);
499                 commHan.addDevicePort(iZigbeeIoTMasterPort);
500                 ZigbeeConfig zbConfig = new ZigbeeConfig(strZigbeeGWAddress, iZigbeeGWPort, iZigbeeIoTMasterPort, 
501                         BOOL_VERBOSE);
502                 // Add the port connection into communication handler - if it's not assigned yet
503                 if (commHan.getComPort(strZigbeeGWAddressKey) == null) {
504                         commHan.addPortConnection(strIoTSlaveObjectHostAdd, strZigbeeGWAddressKey);
505                 }               
506                 int iRows = setInstrumenter.numberOfRows();
507                 RuntimeOutput.print("IoTMaster: Number of rows for IoTZigbeeAddress: " + iRows, BOOL_VERBOSE);
508
509                 // TODO: DEBUG!!!
510                 System.out.println("\n\n DEBUG: InstrumentZigbeeDevice: Object Name: " + strObjName);
511                 System.out.println("DEBUG: InstrumentZigbeeDevice: Port number: " + commHan.getComPort(strZigbeeGWAddressKey));
512                 System.out.println("DEBUG: InstrumentZigbeeDevice: Device address: " + strZigbeeGWAddress + "\n\n");
513
514                 // Transfer the address
515                 for(int iRow=0; iRow<iRows; iRow++) {
516                         arrFieldValues = setInstrumenter.fieldValues(iRow);
517                         // Get device address
518                         String strZBDevAddress = (String) arrFieldValues[0];
519                         // Send policy to Zigbee gateway - TODO: Need to clear policy first?
520                         zbConfig.setPolicy(strIoTSlaveObjectHostAdd, commHan.getComPort(strZigbeeGWAddressKey), strZBDevAddress);
521                         // Send address one by one
522                         if(strLanguage.equals(STR_JAVA)) {
523                                 Message msgGetIoTSetZBObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ZB_DEV_IOTSET_OBJECT, strZBDevAddress);
524                                 commMasterToSlave(msgGetIoTSetZBObj, "Get IoTSet objects!", inStream, outStream);
525                         } else  // TODO: Implement IoTSet Zigbee for C++
526                                 ;
527                 }
528                 zbConfig.closeConnection();
529                 // Reinitialize IoTSet on device object
530                 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream);
531         }
532
533         
534         /**
535          * A private method to instrument IoTSet of addresses
536          *
537          * @params  strFieldIdentifier        String field name + object ID
538          * @params  strFieldName              String field name
539          * @params  inStream                  ObjectInputStream communication
540          * @params  inStream                  ObjectOutputStream communication
541          * @params  strLanguage                           String language
542          * @return  void
543          */
544         private void instrumentIoTSetAddress(String strFieldIdentifier, String strFieldName,
545                 InputStream inStream, OutputStream outStream, String strLanguage)  
546                         throws IOException, ClassNotFoundException, InterruptedException {
547
548                 // Get information from the set
549                 List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
550                 // Create a new IoTSet
551                 if(strLanguage.equals(STR_JAVA)) {
552                         Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
553                         commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTAddress!", inStream, outStream);
554                 } else
555                         ;
556                 int iRows = listObject.size();
557                 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
558                 // Transfer the address
559                 for(int iRow=0; iRow<iRows; iRow++) {
560                         arrFieldValues = listObject.get(iRow);
561                         // Get device address
562                         String strAddress = (String) arrFieldValues[0];
563                         // Send address one by one
564                         if(strLanguage.equals(STR_JAVA)) {
565                                 Message msgGetIoTSetAddObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ADD_IOTSET_OBJECT, strAddress);
566                                 commMasterToSlave(msgGetIoTSetAddObj, "Get IoTSet objects!", inStream, outStream);
567                         } else  // TODO: Implement IoTSet Address for C++
568                                 ;
569                 }
570                 // Reinitialize IoTSet on device object
571                 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
572                                                                                         "Reinitialize IoTSet fields!", inStream, outStream);
573         }
574
575
576         /**
577          * A private method to instrument an object on a specific machine and setting up policies
578          *
579          * @params  strFieldObjectID              String field object ID
580          * @params  strLanguage                           String language
581          * @return  void
582          */
583         private void instrumentObject(String strFieldObjectID, String strLanguage) throws IOException {
584
585                 // Extract the interface name for RMI
586                 // e.g. ProximitySensorInterface, TempSensorInterface, etc.
587                 
588                 String strObjCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
589                 strObjClassInterfaceName = parseConfigFile(strObjCfgFile, STR_INTERFACE_CLS_CFG);
590                 strObjStubClsIntfaceName = parseConfigFile(strObjCfgFile, STR_INT_STUB_CLS_CFG);
591                 // Create an object name, e.g. ProximitySensorImplPS1
592                 strObjName = strObjClassName + strFieldObjectID;
593                 // Check first if host exists
594                 if(commHan.objectExists(strObjName)) {
595                         // If this object exists already ...
596                         // Re-read IoTSlave object hostname for further reference
597                         strIoTSlaveObjectHostAdd = commHan.getHostAddress(strObjName);
598                         RuntimeOutput.print("IoTMaster: Object with name: " + strObjName + " has existed!", BOOL_VERBOSE);
599                 } else {
600                         // If this is a new object ... then create one
601                         // Get host address for IoTSlave from LoadBalancer
602                         //strIoTSlaveObjectHostAdd = lbIoT.selectHost();
603                         strIoTSlaveObjectHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
604                         if (strIoTSlaveControllerHostAdd == null)
605                                 throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
606                         RuntimeOutput.print("IoTMaster: Object name: " + strObjName, BOOL_VERBOSE);
607                         // Add port connection and get port numbers
608                         // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
609                         commHan.addPortConnection(strIoTSlaveObjectHostAdd, strObjName);
610                         commHan.addActiveControllerObject(strFieldObjectID, strObjName, strObjClassName, strObjClassInterfaceName, 
611                                 strObjStubClsIntfaceName, strIoTSlaveObjectHostAdd, arrFieldValues, arrFieldClasses);
612                         // ROUTING POLICY: IoTMaster and device/controller object
613                         // Master-slave communication
614                         routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
615                                 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
616                         // ROUTING POLICY: Send the same routing policy to both the hosts
617                         routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
618                                 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
619                         routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTMasterHostAdd,
620                                 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjName));
621                         // Need to accommodate callback functions here - open ports for TCP
622                         routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd,
623                                 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
624                         routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd,
625                                 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
626                         routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd,
627                                 strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
628                         // Instrument the IoTSet declarations inside the class file
629                         instrumentObjectIoTSet(strFieldObjectID, strLanguage);
630                 }
631                 // Send routing policy to router for controller object
632                 // ROUTING POLICY: RMI communication - RMI registry and stub ports
633                 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
634                         STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
635                 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
636                         STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
637                 // Send the same set of routing policies to compute nodes
638                 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
639                         STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
640                 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
641                         STR_TCP_PROTOCOL, commHan.getRMIRegPort(strObjName));
642                 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
643                         STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
644                 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
645                         STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
646         }
647
648
649         /**
650          * A private method to set router policies for IoTDeviceAddress objects
651          *
652          * @params  strFieldIdentifier        String field name + object ID
653          * @params  Map.Entry<String,Object>  Entry of map IoTSet instrumentation
654          * @params  strIoTSlaveObjectHostAdd  String slave host address
655          * @return  void
656          */
657         private void setRouterPolicyIoTSetDevice(String strFieldIdentifier, Map.Entry<String,Object> map, 
658                 String strIoTSlaveObjectHostAdd) {
659
660                 // Get information from the set
661                 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
662                 int iRows = setInstrumenter.numberOfRows();
663                 RuntimeOutput.print("IoTMaster: Number of rows for IoTDeviceAddress: " + iRows, BOOL_VERBOSE);
664                 // Transfer the address
665                 for(int iRow=0; iRow<iRows; iRow++) {
666                         arrFieldValues = setInstrumenter.fieldValues(iRow);
667                         objAddInitHand.addField(strFieldIdentifier, arrFieldValues);    // Save this for object instantiation
668                         // Get device address - if 00:00:00:00:00:00 that means it needs the driver object address (self)
669                         String strDeviceAddress = null;
670                         String strDeviceAddressKey = null;
671                         if (arrFieldValues[0].equals(STR_SELF_MAC_ADD)) {
672                                 strDeviceAddress = strIoTSlaveObjectHostAdd;
673                                 strDeviceAddressKey = strObjName + "-" + strIoTSlaveObjectHostAdd;
674                         } else {        // Concatenate object name and IP address to give unique key - for a case where there is one device for multiple drivers
675                                 strDeviceAddress = routerConfig.getIPFromMACAddress((String) arrFieldValues[0]);
676                                 strDeviceAddressKey = strObjName + "-" + strDeviceAddress;
677                         }
678                         int iDestDeviceDriverPort = (int) arrFieldValues[1];
679                         String strProtocol = (String) arrFieldValues[2];
680                         // Add the port connection into communication handler - if it's not assigned yet
681                         if (commHan.getComPort(strDeviceAddressKey) == null)
682                                 commHan.addPortConnection(strIoTSlaveObjectHostAdd, strDeviceAddressKey);
683                         boolean bDstPortWildCard = false;
684                         // Recognize this and allocate different ports for it
685                         if (arrFieldValues.length > 3) {
686                                 bDstPortWildCard = (boolean) arrFieldValues[4];
687                                 if (bDstPortWildCard) { // This needs a unique source port
688                                         String strUniqueDev = strDeviceAddressKey + ":" + iRow; 
689                                         commHan.addAdditionalPort(strUniqueDev);
690                                 }
691                         }
692
693                         // TODO: DEBUG!!!
694                         System.out.println("\n\n DEBUG: InstrumentPolicySetDevice: Object Name: " + strObjName);
695                         System.out.println("DEBUG: InstrumentPolicySetDevice: Port number: " + commHan.getComPort(strDeviceAddressKey));
696                         System.out.println("DEBUG: InstrumentPolicySetDevice: Device address: " + strDeviceAddressKey + "\n\n");
697
698                         // Send routing policy to router for device drivers and devices
699                         // ROUTING POLICY: RMI communication - RMI registry and stub ports
700                         if((iDestDeviceDriverPort == -1) && (!strProtocol.equals(STR_NO_PROTOCOL))) {
701                                 // Port number -1 means that we don't set the policy strictly to port number level
702                                 // "nopro" = no protocol specified for just TCP or just UDP (can be both used as well)
703                                 // ROUTING POLICY: Device driver and device
704                                 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol);
705                                 // ROUTING POLICY: Send to the compute node where the device driver is
706                                 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol);
707                         } else if((iDestDeviceDriverPort == -1) && (strProtocol.equals(STR_NO_PROTOCOL))) {
708                                 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
709                                 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
710                         } else if(strProtocol.equals(STR_TCPGW_PROTOCOL)) {
711                                 // This is a TCP protocol that connects, e.g. a phone to our runtime system
712                                 // that provides a gateway access (accessed through destination port number)
713                                 commHan.addDevicePort(iDestDeviceDriverPort);
714                                 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort);
715                                 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort);
716                                 routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
717                                 routerConfig.configureHostHTTPPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
718                         } else {
719                                 // Other port numbers...
720                                 commHan.addDevicePort(iDestDeviceDriverPort);
721                                 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol, 
722                                         commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
723                                 routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol, 
724                                         commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
725                         }
726                 }
727         }
728
729         /**
730          * A private method to set router policies for IoTAddress objects
731          *
732          * @params  strFieldIdentifier        String field name + object ID
733          * @params  Map.Entry<String,Object>  Entry of map IoTSet instrumentation
734          * @params  strHostAddress            String host address
735          * @return  void
736          */
737         private void setRouterPolicyIoTSetAddress(String strFieldIdentifier, Map.Entry<String,Object> map, 
738                 String strHostAddress) {
739
740                 // Get information from the set
741                 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
742                 int iRows = setInstrumenter.numberOfRows();
743                 RuntimeOutput.print("IoTMaster: Number of rows for IoTAddress: " + iRows, BOOL_VERBOSE);
744                 // Transfer the address
745                 for(int iRow=0; iRow<iRows; iRow++) {
746                         arrFieldValues = setInstrumenter.fieldValues(iRow);
747                         objAddInitHand.addField(strFieldIdentifier, arrFieldValues);    // Save this for object instantiation
748                         // Get device address
749                         String strAddress = (String) arrFieldValues[0];
750                         // Setting up router policies for HTTP/HTTPs
751                         routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strHostAddress, strAddress);
752                         routerConfig.configureHostHTTPPolicies(strHostAddress, strHostAddress, strAddress);
753                 }
754         }
755
756         /**
757          * A private method to instrument an object's IoTSet and IoTRelation field to up policies
758          * <p>
759          * Mostly the IoTSet fields would contain IoTDeviceAddress objects
760          *
761          * @params  strFieldObjectID    String field object ID
762          * @params  strLanguage                 String language
763          * @return  void
764          */
765         private void instrumentObjectIoTSet(String strFieldObjectID, String strLanguage) throws IOException {
766
767                 // If this is a new object ... then create one
768                 // Instrument the class source code and look for IoTSet for device addresses
769                 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
770                 HashMap<String,Object> hmObjectFieldObjects = null;
771                 if(strLanguage.equals(STR_JAVA)) {
772                         String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CLS_FILE_EXT;
773                         FileInputStream fis = new FileInputStream(strObjectClassNamePath);
774                         ClassReader cr = new ClassReader(fis);
775                         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
776                         // We need Object ID to instrument IoTDeviceAddress
777                         ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, strFieldObjectID, BOOL_VERBOSE);
778                         cr.accept(crim, 0);
779                         fis.close();
780                         mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
781                         hmObjectFieldObjects = crim.getFieldObjects();
782                 } else {        // For C++
783                         String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
784                         CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strObjectClassNamePath, strFieldObjectID, BOOL_VERBOSE);
785                         mapClassNameToCrim.put(strObjClassName + strFieldObjectID, crim);
786                         hmObjectFieldObjects = crim.getFieldObjects();
787                 }
788                 // Get the object and the class names
789                 // Build objects for IoTSet and IoTRelation fields in the device object classes
790                 RuntimeOutput.print("IoTMaster: Going to instrument for " + strObjClassName + " with objectID " + 
791                         strFieldObjectID, BOOL_VERBOSE);
792                 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
793                         RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
794                         // Iterate over HashMap and choose between processing
795                         String strFieldName = map.getKey();
796                         String strClassName = map.getValue().getClass().getName();
797                         String strFieldIdentifier = strFieldName + strFieldObjectID;
798                         if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
799                                 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
800                                 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) { 
801                                 // Instrument the normal IoTDeviceAddress
802                                         setRouterPolicyIoTSetDevice(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
803                                 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) { 
804                                 // Instrument the IoTAddress
805                                         setRouterPolicyIoTSetAddress(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
806                                 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) { 
807                                 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
808                                         RuntimeOutput.print("IoTMaster: IoTZigbeeAddress found! No router policy is set here..", 
809                                                 BOOL_VERBOSE);
810                                 } else {
811                                         String strErrMsg = "IoTMaster: Device driver object" +
812                                                                                 " can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
813                                                                                 " or IoTSet<IoTZigbeeAddress>!";
814                                         throw new Error(strErrMsg);
815                                 }
816                         } else {
817                                 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
818                                 throw new Error(strErrMsg);
819                         }
820                 }
821         }
822
823
824         /**
825          * A private method to send files to a Java slave driver
826          *
827          * @params  serverSocket                                ServerSocket
828          * @params  _inStream                                   InputStream
829          * @params  _outStream                                  OutputStream
830          * @params  strObjName                                  String
831          * @params  strObjClassName                             String
832          * @params  strObjClassInterfaceName    String
833          * @params  strObjStubClsIntfaceName    String
834          * @params  strIoTSlaveObjectHostAdd    String
835          * @params  strFieldObjectID                    String
836          * @params  arrFieldValues                              Object[]
837          * @params  arrFieldClasses                             Class[]
838          * @return  void
839          */
840         private void sendFileToJavaSlaveDriver(ServerSocket serverSocket, InputStream _inStream, OutputStream _outStream,
841                 String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
842                 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses) 
843                         throws IOException, ClassNotFoundException {
844
845                 ObjectInputStream inStream = (ObjectInputStream) _inStream;
846                 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
847                 // Create message to transfer file first
848                 String sFileName = strObjClassName + STR_JAR_FILE_EXT;
849                 String sPath = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
850                 File file = new File(sPath);
851                 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, sFileName, file.length()),
852                         "Sending file!", inStream, outStream);
853                 // Send file - JAR file for object creation
854                 sendFile(serverSocket.accept(), sPath, file.length());
855                 Message msgReply = (Message) inStream.readObject();
856                 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
857                 // Pack object information to create object on a IoTSlave
858                 Message msgObjIoTSlave = new MessageCreateObject(IoTCommCode.CREATE_OBJECT, strIoTSlaveObjectHostAdd,
859                         strObjClassName, strObjName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName), 
860                         commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses);
861                 // Send message
862                 commMasterToSlave(msgObjIoTSlave, "Sending object information", inStream, outStream);
863         }
864
865
866         /**
867          * A private method to send files to a Java slave driver
868          *
869          * @return  void
870          */
871         private void sendFileToCppSlaveDriver(String strObjClassName, String strIoTSlaveObjectHostAdd) 
872                         throws IOException, ClassNotFoundException {
873
874                 // Create message to transfer file first
875                 String sFileName = strObjClassName + STR_ZIP_FILE_EXT;
876                 String sFile = STR_IOT_CODE_PATH + strObjClassName + "/" + sFileName;
877                 String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + ":" + STR_SLAVE_DIR;
878                 runCommand(strCmdSend);
879                 RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
880                 // Unzip file
881                 String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " +
882                                         STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
883                 runCommand(strCmdUnzip);
884                 RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
885
886         }
887
888
889         /**
890          * Construct command line for Java IoTSlave
891          *
892          * @return       String
893          */
894         /*private String getCmdJavaDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
895
896                 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " sudo java " +
897                         STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_RMI_HOSTNAME +
898                         strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
899                         commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " +
900                         commHan.getRMIStubPort(strObjName) + " >& " + STR_LOG_FILE_PATH + strObjName + ".log &";
901         }*/
902         private String getCmdJavaDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
903
904                 // Create an Shell executable
905                 String strJavaCommand = STR_SHELL_HEADER + "\nexec " + STR_JAVA_PATH + " " + STR_CLS_PATH + " " + STR_RMI_PATH + " " + 
906                         STR_RMI_HOSTNAME + strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
907                         commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " +
908                         commHan.getRMIStubPort(strObjName) + " > " + STR_LOG_FILE_PATH + strObjName + ".log &";
909                 String shellFile = "./" + strObjName + STR_SHELL_FILE_EXT;
910                 createWrapperShellScript(strJavaCommand, shellFile);
911                 // Send the file to the compute node
912                 String strCmdSend = "scp " + shellFile + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + ":" + STR_RUNTIME_DIR;
913                 runCommand(strCmdSend);
914                 System.out.println("IoTMaster: Sending shell file: " + strCmdSend);
915                 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " " + shellFile;
916         }
917
918
919         /**
920          * Construct command line for C++ IoTSlave
921          *
922          * @return       String
923          */
924         private String getCmdCppDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
925
926                 return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " +
927                                         STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " +
928                                         commHan.getComPort(strObjName) + " " + strObjName;
929         }
930
931
932         /**
933          * createWrapperShellScript() gets a wrapper shell script
934          *
935          * @param   strCommand          String command
936          * @param   strObjectName       String object name
937          * @return  PrintWriter
938          */
939         private void createWrapperShellScript(String strCommand, String strFileName) {
940
941                 PrintWriter printWriter = getPrintWriter(strFileName);
942                 printWriter.println(strCommand);
943                 printWriter.close();
944                 runCommand("chmod 755 " + strFileName);
945         }
946
947
948         /**
949          * A private method to create an object on a specific machine
950          *
951          * @params  strObjName                                  String object name
952          * @params  strObjClassName                     String object class name
953          * @params  strObjClassInterfaceName    String object class interface name
954          * @params  strIoTSlaveObjectHostAdd    String IoTSlave host address
955          * @params  strFieldObjectID                    String field object ID
956          * @params  arrFieldValues                              Array of field values
957          * @params  arrFieldClasses                             Array of field classes
958          * @return  void
959          */
960         private void createObject(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strObjStubClsIntfaceName,
961                 String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses) 
962                 throws IOException, FileNotFoundException, ClassNotFoundException, InterruptedException {
963
964                 // Read config file
965                 String sCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
966                 String strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE + "_" + strObjName);
967                 if(strLanguageDriver == null)   // Read just the field LANGUAGE if the first read is null
968                         strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE);
969                 if(strLanguageDriver == null) // Check nullness for the second time - report if it is still null
970                         throw new Error("IoTMaster: Language specification missing in config file: " + sCfgFile);
971                 // PROFILING
972                 long start = 0;
973                 long result = 0;
974                 // PROFILING
975                 start = System.currentTimeMillis();
976
977                 // Construct ssh command line
978                 // e.g. ssh rtrimana@dw-2.eecs.uci.edu cd <path>;
979                 //      java -cp $CLASSPATH:./*.jar
980                 //           -Djava.rmi.server.codebase=file:./*.jar
981                 //           iotruntime.IoTSlave dw-1.eecs.uci.edu 46151 23829 42874 &
982                 // The In-Port for IoTMaster is the Out-Port for IoTSlave and vice versa
983                 String strSSHCommand = null;
984                 if(strLanguageDriver.equals(STR_JAVA))
985                         strSSHCommand = getCmdJavaDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
986                 else if(strLanguageDriver.equals(STR_CPP))
987                         strSSHCommand = getCmdCppDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
988                 else
989                         throw new Error("IoTMaster: Language specification not recognized: " + strLanguageDriver);
990                 RuntimeOutput.print("IoTMaster: Language for " + strObjName + " is " + strLanguageDriver, BOOL_VERBOSE);
991
992                 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
993                 // Start a new thread to start a new JVM
994                 createThread(strSSHCommand);
995                 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjName));
996                 Socket socket = serverSocket.accept();
997                 //InputStream inStream = new ObjectInputStream(socket.getInputStream());
998                 //OutputStream outStream = new ObjectOutputStream(socket.getOutputStream());
999                 InputStream inStream = null;
1000                 OutputStream outStream = null;
1001                 if(strLanguageDriver.equals(STR_JAVA)) {
1002                         inStream = new ObjectInputStream(socket.getInputStream());
1003                         outStream = new ObjectOutputStream(socket.getOutputStream());
1004                 } else {        // At this point the language is certainly C++, otherwise would've complained above
1005                         inStream = new BufferedInputStream(socket.getInputStream());
1006                         outStream = new BufferedOutputStream(socket.getOutputStream());
1007                         recvAck(inStream);
1008                 }
1009
1010                 // PROFILING
1011                 result = System.currentTimeMillis()-start;
1012                 System.out.println("\n\n ==> Time needed to start JVM for " + strObjName + ": " + result + "\n\n");
1013
1014                 // PROFILING
1015                 start = System.currentTimeMillis();
1016
1017                 if(strLanguageDriver.equals(STR_JAVA)) {
1018                         sendFileToJavaSlaveDriver(serverSocket, inStream, outStream, strObjName, 
1019                                 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
1020                                 strIoTSlaveObjectHostAdd, strFieldObjectID, arrFieldValues, arrFieldClasses);
1021                 } else {
1022                         sendFileToCppSlaveDriver(strObjClassName, strIoTSlaveObjectHostAdd);
1023                         createObjectCpp(strObjName, strObjClassName, strObjClassInterfaceName, strIoTSlaveObjectHostAdd,
1024                         commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName), arrFieldValues, arrFieldClasses,
1025                         outStream, inStream);
1026                 }
1027
1028                 // PROFILING
1029                 result = System.currentTimeMillis()-start;
1030                 System.out.println("\n\n ==> Time needed to send JAR file for " + strObjName + ": " + result + "\n\n");
1031
1032                 // PROFILING
1033                 start = System.currentTimeMillis();
1034
1035                 // Instrument the class source code and look for IoTSet for device addresses
1036                 // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
1037                 RuntimeOutput.print("IoTMaster: Instantiating for " + strObjClassName + " with objectID " + strFieldObjectID, BOOL_VERBOSE);
1038                 // Get the object and the class names
1039                 // Build objects for IoTSet and IoTRelation fields in the device object classes
1040                 Object crimObj = mapClassNameToCrim.get(strObjClassName + strFieldObjectID);
1041                 HashMap<String,Object> hmObjectFieldObjects = null;
1042                 if (crimObj instanceof ClassRuntimeInstrumenterMaster) {
1043                         ClassRuntimeInstrumenterMaster crim = (ClassRuntimeInstrumenterMaster) crimObj;
1044                         hmObjectFieldObjects = crim.getFieldObjects();
1045                 } else if (crimObj instanceof CRuntimeInstrumenterMaster) {
1046                         CRuntimeInstrumenterMaster crim = (CRuntimeInstrumenterMaster) crimObj;
1047                         hmObjectFieldObjects = crim.getFieldObjects();
1048                 }
1049                 for(Map.Entry<String,Object> map : hmObjectFieldObjects.entrySet()) {
1050                         RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
1051                         // Iterate over HashMap and choose between processing
1052                         String strFieldName = map.getKey();
1053                         String strClassName = map.getValue().getClass().getName();
1054                         String strFieldIdentifier = strFieldName + strFieldObjectID;
1055                         if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
1056                                 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1057                                 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) { 
1058                                 // Instrument the normal IoTDeviceAddress
1059                                         synchronized(this) {
1060                                                 instrumentIoTSetDevice(strFieldIdentifier, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
1061                                         }
1062                                 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) { 
1063                                 // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
1064                                         synchronized(this) {
1065                                                 instrumentIoTSetZBDevice(map, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
1066                                         }
1067                                 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) { 
1068                                 // Instrument the IoTAddress
1069                                         synchronized(this) {
1070                                                 instrumentIoTSetAddress(strFieldIdentifier, strFieldName, inStream, outStream, strLanguageDriver);
1071                                         }
1072                                 } else {
1073                                         String strErrMsg = "IoTMaster: Device driver object can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
1074                                                                                 " or IoTSet<IoTZigbeeAddress>!";
1075                                         throw new Error(strErrMsg);
1076                                 }
1077                         } else {
1078                                 String strErrMsg = "IoTMaster: Device driver object can only have IoTSet for addresses!";
1079                                 throw new Error(strErrMsg);
1080                         }
1081                 }
1082                 // End the session
1083                 // TODO: Change this later
1084                 if(strLanguageDriver.equals(STR_JAVA)) {
1085                         ObjectOutputStream oStream = (ObjectOutputStream) outStream;
1086                         oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
1087                 } else {        // C++ side for now will be running continuously because it's an infinite loop (not in a separate thread)
1088                         createDriverObjectCpp(outStream, inStream);
1089                         //endSessionCpp(outStream);
1090                 }
1091
1092                 // PROFILING
1093                 result = System.currentTimeMillis()-start;
1094                 System.out.println("\n\n ==> Time needed to create object " + strObjName + " and instrument IoTDeviceAddress: " + result + "\n\n");
1095
1096                 // Closing streams
1097                 outStream.close();
1098                 inStream.close();
1099                 socket.close();
1100                 serverSocket.close();
1101         }
1102
1103
1104         /**
1105          * A private method to create controller objects
1106          *
1107          * @return  void
1108          */
1109         private void createDriverObjects() throws InterruptedException {
1110
1111                 // Create a list of threads
1112                 List<Thread> threads = new ArrayList<Thread>();
1113                 // Get the list of active controller objects and loop it
1114                 List<String> listActiveControllerObject = commHan.getActiveControllerObjectList();
1115                 for(String strObjName : listActiveControllerObject) {
1116
1117                         ObjectCreationInfo objCrtInfo = commHan.getObjectCreationInfo(strObjName);
1118                         Thread objectThread = new Thread(new Runnable() {
1119                                 public void run() {
1120                                         synchronized(this) {
1121                                                 try {
1122                                                         createObject(strObjName, objCrtInfo.getObjectClassName(), objCrtInfo.getObjectClassInterfaceName(),
1123                                                                 objCrtInfo.getObjectStubClassInterfaceName(), objCrtInfo.getIoTSlaveObjectHostAdd(), 
1124                                                                 commHan.getFieldObjectID(strObjName), commHan.getArrayFieldValues(strObjName), 
1125                                                                 commHan.getArrayFieldClasses(strObjName));
1126                                                 } catch (IOException                    | 
1127                                                                  ClassNotFoundException |
1128                                                                  InterruptedException ex) {
1129                                                         ex.printStackTrace();
1130                                                 }
1131                                         }
1132                                 }
1133                         });
1134                         threads.add(objectThread);
1135                         objectThread.start();
1136                 }
1137                 // Join all threads
1138                 for (Thread thread : threads) {
1139                         try {
1140                                 thread.join();
1141                         } catch (InterruptedException ex) {
1142                                 ex.printStackTrace();
1143                         }
1144                 }
1145         }       
1146
1147
1148         /**
1149          * A private method to instrument IoTSet
1150          *
1151          * @params  Map.Entry<String,Object>  Entry of map IoTSet instrumentation
1152          * @params  strFieldName              String field name
1153          * @params  strLanguage                           String language
1154          * @return  void
1155          */
1156         private void instrumentIoTSet(Map.Entry<String,Object> map, String strFieldName, String strLanguage) 
1157                 throws IOException, ClassNotFoundException, InterruptedException {
1158                                 
1159                 // Get information from the set
1160                 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
1161                 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTSET);
1162
1163                 int iRows = setInstrumenter.numberOfRows();
1164                 for(int iRow=0; iRow<iRows; iRow++) {
1165                         // Get field classes and values
1166                         arrFieldClasses = setInstrumenter.fieldClasses(iRow);
1167                         arrFieldValues = setInstrumenter.fieldValues(iRow);
1168                         // Get object ID and class name
1169                         String strObjID = setInstrumenter.fieldObjectID(iRow);
1170                         strObjClassName = setInstrumenter.fieldEntryType(strObjID);
1171                         // Call the method to create an object
1172                         instrumentObject(strObjID, strLanguage);
1173                         objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1174                                 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName), 
1175                                 commHan.getRMIStubPort(strObjName));
1176                 }
1177         }
1178
1179
1180         /**
1181          * A private method to instrument IoTRelation
1182          *
1183          * @params  Map.Entry<String,Object>  Entry of map IoTRelation instrumentation
1184          * @params  strFieldName              String field name
1185          * @params  strLanguage                           String language
1186          * @return  void
1187          */
1188         private void instrumentIoTRelation(Map.Entry<String,Object> map, String strFieldName, String strLanguage) 
1189                 throws IOException, ClassNotFoundException, InterruptedException {
1190
1191                         // Get information from the set
1192                 RelationInstrumenter relationInstrumenter = (RelationInstrumenter) map.getValue();
1193                 int iRows = relationInstrumenter.numberOfRows();
1194                 objInitHand.addField(strFieldName, IoTCommCode.CREATE_NEW_IOTRELATION);
1195
1196                 for(int iRow=0; iRow<iRows; iRow++) {
1197                         // Operate on the first set first
1198                         arrFieldClasses = relationInstrumenter.firstFieldClasses(iRow);
1199                         arrFieldValues = relationInstrumenter.firstFieldValues(iRow);
1200                         String strObjID = relationInstrumenter.firstFieldObjectID(iRow);
1201                         strObjClassName = relationInstrumenter.firstEntryFieldType(strObjID);
1202                         // Call the method to create an object
1203                         instrumentObject(strObjID, strLanguage);
1204                         // Get the first object controller host address
1205                         String strFirstIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
1206                         objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1207                                 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, 
1208                                 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
1209                         // Operate on the second set
1210                         arrFieldClasses = relationInstrumenter.secondFieldClasses(iRow);
1211                         arrFieldValues = relationInstrumenter.secondFieldValues(iRow);
1212                         strObjID = relationInstrumenter.secondFieldObjectID(iRow);
1213                         strObjClassName = relationInstrumenter.secondEntryFieldType(strObjID);
1214                         // Call the method to create an object
1215                         instrumentObject(strObjID, strLanguage);
1216                         // Get the second object controller host address
1217                         String strSecondIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
1218                         objInitHand.addSecondObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
1219                                 strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, 
1220                                 commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
1221                         // ROUTING POLICY: first and second controller objects in IoTRelation
1222                         routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strFirstIoTSlaveObjectHostAdd,
1223                                 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1224                         // ROUTING POLICY: Send the same routing policy to both the hosts
1225                         routerConfig.configureHostMainPolicies(strFirstIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
1226                                 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1227                         routerConfig.configureHostMainPolicies(strSecondIoTSlaveObjectHostAdd, strFirstIoTSlaveObjectHostAdd,
1228                                 strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
1229                 }
1230         }
1231
1232         /**
1233          * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
1234          *
1235          * @params  inStream                  ObjectInputStream communication
1236          * @params  outStream                 ObjectOutputStream communication
1237          * @return      void
1238          */
1239         private void initializeSetsAndRelationsJava(InputStream inStream, OutputStream outStream)  
1240                 throws IOException, ClassNotFoundException {
1241                 // Get list of fields
1242                 List<String> strFields = objInitHand.getListOfFields();
1243                 // Iterate on HostAddress
1244                 for(String str : strFields) {
1245                         IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
1246                         if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
1247                                 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
1248                                 Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, str);
1249                                 commMasterToSlave(msgCrtIoTSet, "Create new IoTSet!", inStream, outStream);
1250                                 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1251                                 for (ObjectInitInfo objInitInfo : listObject) {
1252                                         // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
1253                                         commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(),
1254                                                 objInitInfo.getObjectName(), objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), 
1255                                                 objInitInfo.getObjectStubClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()), 
1256                                                 "Get IoTSet object!", inStream, outStream);
1257
1258                                 }
1259                                 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
1260                                 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD),
1261                                         "Renitialize IoTSet field!", inStream, outStream);
1262                         } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
1263                                 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
1264                                 Message msgCrtIoTRel = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTRELATION, str);
1265                                 commMasterToSlave(msgCrtIoTRel, "Create new IoTRelation!", inStream, outStream);
1266                                 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1267                                 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
1268                                 Iterator it = listSecondObject.iterator();
1269                                 for (ObjectInitInfo objInitInfo : listObject) {
1270                                         // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
1271                                         commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT, 
1272                                                 objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), objInitInfo.getObjectClassName(),
1273                                                 objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1274                                                 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()), 
1275                                                 "Get IoTRelation first object!", inStream, outStream);
1276                                         ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
1277                                         // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
1278                                         commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT,
1279                                                 objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), objSecObj.getObjectClassName(),
1280                                                 objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
1281                                                 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort()), 
1282                                                 "Get IoTRelation second object!", inStream, outStream);
1283                                 }
1284                                 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
1285                                 commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD),
1286                                         "Renitialize IoTRelation field!", inStream, outStream);
1287                         }
1288                 }
1289         }
1290
1291         /**
1292          * A method to reinitialize IoTSet and IoTRelation in the code based on ObjectInitHandler information
1293          *
1294          * @params  inStream                  ObjectInputStream communication
1295          * @params  outStream                 ObjectOutputStream communication
1296          * @return      void
1297          */
1298         private void initializeSetsAndRelationsCpp(InputStream inStream, OutputStream outStream)  
1299                 throws IOException, ClassNotFoundException {
1300                 // Get list of fields
1301                 List<String> strFields = objInitHand.getListOfFields();
1302                 // Iterate on HostAddress
1303                 for(String str : strFields) {
1304                         IoTCommCode iotcommMsg = objInitHand.getFieldMessage(str);
1305                         if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTSET) {
1306                                 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTSET
1307                                 createNewIoTSetCpp(str, outStream, inStream);
1308                                 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1309                                 for (ObjectInitInfo objInitInfo : listObject) {
1310                                         // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
1311                                         getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), 
1312                                                 objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1313                                                 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream);
1314                                 }
1315                                 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
1316                                 reinitializeIoTSetFieldCpp(outStream, inStream);
1317                         } else if (iotcommMsg == IoTCommCode.CREATE_NEW_IOTRELATION) {
1318                                 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO CREATE IOTRELATION
1319                                 // TODO: createNewIoTRelation needs to be created here!
1320                                 createNewIoTRelationCpp(str, outStream, inStream);
1321                                 List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
1322                                 List<ObjectInitInfo> listSecondObject = objInitHand.getSecondObjectInitInfo(str);
1323                                 Iterator it = listSecondObject.iterator();
1324                                 for (ObjectInitInfo objInitInfo : listObject) {
1325                                         // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
1326                                         getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), 
1327                                                 objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
1328                                                 objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream);
1329                                         ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
1330                                         // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
1331                                         getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT, objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), 
1332                                                 objSecObj.getObjectClassName(), objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
1333                                                 objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort(), outStream, inStream);
1334                                 }
1335                                 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
1336                                 reinitializeIoTRelationFieldCpp(outStream, inStream);
1337                         }
1338                 }
1339         }
1340
1341         /**
1342          * A method to set router basic policies at once
1343          *
1344          * @param       strRouter String router name
1345          * @return      void
1346          */
1347         private void setRouterBasicPolicies(String strRouter) {
1348
1349                 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1350                 routerConfig.configureRouterICMPPolicies(strRouter, strMonitorHost);
1351                 routerConfig.configureRouterDHCPPolicies(strRouter);
1352                 routerConfig.configureRouterDNSPolicies(strRouter);
1353                 routerConfig.configureRouterSSHPolicies(strRouter, strMonitorHost);
1354                 routerConfig.configureRejectPolicies(strRouter);
1355         }
1356
1357         /**
1358          * A method to set host basic policies at once
1359          *
1360          * @param       strHost String host name
1361          * @return      void
1362          */
1363         private void setHostBasicPolicies(String strHost) {
1364
1365                 String strMonitorHost = routerConfig.getIPFromMACAddress(STR_MONITORING_HOST);
1366                 routerConfig.configureHostDHCPPolicies(strHost);
1367                 routerConfig.configureHostDNSPolicies(strHost);
1368                 if (strHost.equals(strMonitorHost)) {
1369                 // Check if this is the monitoring host
1370                         routerConfig.configureHostICMPPolicies(strHost);
1371                         routerConfig.configureHostSSHPolicies(strHost);
1372                 } else {
1373                         routerConfig.configureHostICMPPolicies(strHost, strMonitorHost);
1374                         routerConfig.configureHostSSHPolicies(strHost, strMonitorHost);
1375                 }
1376                 // Apply SQL allowance policies to master host
1377                 if (strHost.equals(strIoTMasterHostAdd)) {
1378                         routerConfig.configureHostSQLPolicies(strHost);
1379                 }
1380                 routerConfig.configureRejectPolicies(strHost);
1381         }
1382
1383         /**
1384          * A method to create a thread for policy deployment
1385          *
1386          * @param  strRouterAddress             String router address to configure
1387          * @param  setHostAddresses             Set of strings for host addresses to configure
1388          * @return                              void
1389          */
1390         private void createPolicyThreads(String strRouterAddress, Set<String> setHostAddresses) throws IOException {
1391
1392                 // Create a list of threads
1393                 List<Thread> threads = new ArrayList<Thread>();
1394                 // Start threads for hosts
1395                 for(String strAddress : setHostAddresses) {
1396                         Thread policyThread = new Thread(new Runnable() {
1397                                 public void run() {
1398                                         synchronized(this) {
1399                                                 routerConfig.sendHostPolicies(strAddress);
1400                                         }
1401                                 }
1402                         });
1403                         threads.add(policyThread);
1404                         policyThread.start();
1405                         RuntimeOutput.print("Deploying policies for: " + strAddress, BOOL_VERBOSE);
1406                 }
1407                 // A thread for router
1408                 Thread policyThread = new Thread(new Runnable() {
1409                         public void run() {
1410                                 synchronized(this) {
1411                                         routerConfig.sendRouterPolicies(strRouterAddress);
1412                                 }
1413                         }
1414                 });
1415                 threads.add(policyThread);
1416                 policyThread.start();
1417                 RuntimeOutput.print("Deploying policies on router: " + strRouterAddress, BOOL_VERBOSE);         
1418                 // Join all threads
1419                 for (Thread thread : threads) {
1420                         try {
1421                                 thread.join();
1422                         } catch (InterruptedException ex) {
1423                                 ex.printStackTrace();
1424                         }
1425                 }
1426         }
1427
1428
1429         /**
1430          * A method to send files to Java IoTSlave
1431          *
1432          * @params  strObjControllerName      String
1433          * @params  serverSocket              ServerSocket
1434          * @params  inStream                  ObjectInputStream communication
1435          * @params  outStream                 ObjectOutputStream communication
1436          * @return       void
1437          */     
1438         private void sendFileToJavaSlave(String strObjControllerName, ServerSocket serverSocket, 
1439                         InputStream _inStream, OutputStream _outStream) throws IOException, ClassNotFoundException {
1440
1441                 ObjectInputStream inStream = (ObjectInputStream) _inStream;
1442                 ObjectOutputStream outStream = (ObjectOutputStream) _outStream;
1443                 // Send .jar file
1444                 String strControllerJarName = strObjControllerName + STR_JAR_FILE_EXT;
1445                 String strControllerJarNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1446                         strControllerJarName;
1447                 File file = new File(strControllerJarNamePath);
1448                 commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerJarName, file.length()),
1449                         "Sending file!", inStream, outStream);
1450                 // Send file - Class file for object creation
1451                 sendFile(serverSocket.accept(), strControllerJarNamePath, file.length());
1452                 Message msgReply = (Message) inStream.readObject();
1453                 RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1454                 // Send .zip file if additional zip file is specified
1455                 String strObjCfgFile = strObjControllerName + STR_CFG_FILE_EXT;
1456                 String strObjCfgFilePath = STR_CONT_PATH + strObjControllerName + "/" + strObjCfgFile;
1457                 String strAdditionalFile = parseConfigFile(strObjCfgFilePath, STR_FILE_TRF_CFG);
1458                 if (strAdditionalFile.equals(STR_YES)) {
1459                         String strControllerCmpName = strObjControllerName + STR_ZIP_FILE_EXT;
1460                         String strControllerCmpNamePath = STR_CONT_PATH + strObjControllerName + "/" +
1461                                 strControllerCmpName;
1462                         file = new File(strControllerCmpNamePath);
1463                         commMasterToSlave(new MessageSendFile(IoTCommCode.TRANSFER_FILE, strControllerCmpName, file.length()),
1464                                 "Sending file!", inStream, outStream);
1465                         // Send file - Class file for object creation
1466                         sendFile(serverSocket.accept(), strControllerCmpNamePath, file.length());
1467                         msgReply = (Message) inStream.readObject();
1468                         RuntimeOutput.print("IoTMaster: Reply message: " + msgReply.getMessage(), BOOL_VERBOSE);
1469                 }
1470         }
1471
1472
1473         /**
1474          * A method to send files to C++ IoTSlave
1475          *
1476          * @return       void
1477          * TODO: Need to look into this (as of now, file transferred retains the "data" format, 
1478          * hence it is unreadable from outside world
1479          */
1480         private void sendFileToCppSlave(String sFilePath, String sFileName, Socket fileSocket, 
1481                         InputStream inStream, OutputStream outStream) throws IOException {
1482
1483                 sendCommCode(IoTCommCode.TRANSFER_FILE, outStream, inStream);
1484                 // Send file name
1485                 sendString(sFileName, outStream); recvAck(inStream);
1486                 File file = new File(sFilePath + sFileName);
1487                 int iFileLen = toIntExact(file.length());
1488                 RuntimeOutput.print("IoTMaster: Sending file " + sFileName + " with length " + iFileLen + " bytes...", BOOL_VERBOSE);
1489                 // Send file length
1490                 sendInteger(iFileLen, outStream); recvAck(inStream);
1491                 RuntimeOutput.print("IoTMaster: Sent file size!", BOOL_VERBOSE);
1492                 byte[] bytFile = new byte[iFileLen];
1493                 InputStream inFileStream = new FileInputStream(file);
1494                 RuntimeOutput.print("IoTMaster: Opened file!", BOOL_VERBOSE);
1495
1496                 OutputStream outFileStream = fileSocket.getOutputStream();
1497                 RuntimeOutput.print("IoTMaster: Got output stream!", BOOL_VERBOSE);
1498                 int iCount;
1499                 while ((iCount = inFileStream.read(bytFile)) > 0) {
1500                         outFileStream.write(bytFile, 0, iCount);
1501                 }
1502                 RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
1503                 recvAck(inStream);
1504         }
1505
1506
1507         /**
1508          * A method to send files to C++ IoTSlave (now master using Process() to start 
1509          * file transfer using scp)
1510          *
1511          * @return       void
1512          */
1513         private void sendFileToCppSlave(String sFilePath, String sFileName) throws IOException {
1514
1515                 // Construct shell command to transfer file     
1516                 String sFile = sFilePath + sFileName;
1517                 String strCmdSend = STR_SCP + " " + sFile + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + ":" + STR_SLAVE_DIR;
1518                 runCommand(strCmdSend);
1519                 RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
1520                 // Unzip file
1521                 String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1522                                         STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
1523                 runCommand(strCmdUnzip);
1524                 RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
1525         }
1526
1527
1528         /**
1529          * runCommand() method runs shell command
1530          *
1531          * @param   strCommand  String that contains command line
1532          * @return  void
1533          */
1534         private void runCommand(String strCommand) {
1535
1536                 try {
1537                         Runtime runtime = Runtime.getRuntime();
1538                         Process process = runtime.exec(strCommand);
1539                         process.waitFor();
1540                 } catch (IOException ex) {
1541                         System.out.println("RouterConfig: IOException: " + ex.getMessage());
1542                         ex.printStackTrace();
1543                 } catch (InterruptedException ex) {
1544                         System.out.println("RouterConfig: InterruptException: " + ex.getMessage());
1545                         ex.printStackTrace();
1546                 }
1547         }
1548
1549
1550         /**
1551          * Construct command line for Java IoTSlave
1552          *
1553          * @return       String
1554          */
1555         /*private String getCmdJavaIoTSlave(String strObjControllerName) {
1556
1557                 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1558                                         STR_RUNTIME_DIR + " sudo java " + STR_JVM_INIT_HEAP_SIZE + " " + 
1559                                         STR_JVM_MAX_HEAP_SIZE + " " + STR_CLS_PATH + " " +
1560                                         STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
1561                                         commHan.getComPort(strObjControllerName) + " " +
1562                                         commHan.getRMIRegPort(strObjControllerName) + " " +
1563                                         commHan.getRMIStubPort(strObjControllerName) + " >& " +
1564                                         STR_LOG_FILE_PATH + strObjControllerName + ".log &";
1565         }*/
1566         private String getCmdJavaIoTSlave(String strObjControllerName) {
1567
1568                 // Create an Shell executable
1569                 String strJavaCommand = STR_SHELL_HEADER + "\nexec " + STR_JAVA_PATH + " " + STR_JVM_INIT_HEAP_SIZE + " " + 
1570                                         STR_JVM_MAX_HEAP_SIZE + " " + STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " + 
1571                                         strIoTMasterHostAdd + " " + commHan.getComPort(strObjControllerName) + " " +
1572                                         commHan.getRMIRegPort(strObjControllerName) + " " + commHan.getRMIStubPort(strObjControllerName) + 
1573                                         " > " + STR_LOG_FILE_PATH + strObjControllerName + ".log &";
1574                 String shellFile = "./" + strObjControllerName + STR_SHELL_FILE_EXT;
1575                 createWrapperShellScript(strJavaCommand, shellFile);
1576                 // Send the file to the compute node
1577                 String strCmdSend = "scp " + shellFile + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + ":" + STR_RUNTIME_DIR;
1578                 runCommand(strCmdSend);
1579                 System.out.println("IoTMaster: Sending main controller shell file: " + strCmdSend);
1580                 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " + STR_RUNTIME_DIR + " " + shellFile;
1581         }
1582
1583
1584         /**
1585          * Construct command line for C++ IoTSlave
1586          *
1587          * @return       String
1588          */
1589         private String getCmdCppIoTSlave(String strObjControllerName) {
1590
1591                 return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
1592                                         STR_SLAVE_DIR + " sudo " + STR_IOTSLAVE_CPP + " " + strIoTMasterHostAdd + " " +
1593                                         commHan.getComPort(strObjControllerName) + " " + strObjControllerName;
1594         }
1595
1596
1597         /**
1598          * sendInteger() sends an integer in bytes
1599          */
1600         public void sendInteger(int intSend, OutputStream outStream) throws IOException {
1601
1602                 BufferedOutputStream output = (BufferedOutputStream) outStream;
1603                 // Transform integer into bytes
1604                 ByteBuffer bb = ByteBuffer.allocate(INT_SIZE);
1605                 bb.putInt(intSend);
1606                 // Send the byte array
1607                 output.write(bb.array(), 0, INT_SIZE);
1608                 output.flush();
1609         }
1610
1611
1612         /**
1613          * recvInteger() receives integer in bytes
1614          */
1615         public int recvInteger(InputStream inStream) throws IOException {
1616
1617                 BufferedInputStream input = (BufferedInputStream) inStream;
1618                 // Wait until input is available
1619                 while(input.available() == 0);
1620                 // Read integer - 4 bytes
1621                 byte[] recvInt = new byte[INT_SIZE];
1622                 input.read(recvInt, 0, INT_SIZE);
1623                 int retVal = ByteBuffer.wrap(recvInt).getInt();
1624
1625                 return retVal;
1626         }
1627
1628
1629         /**
1630          * recvString() receives String in bytes
1631          */
1632         public String recvString(InputStream inStream) throws IOException {
1633
1634                 BufferedInputStream input = (BufferedInputStream) inStream;
1635                 int strLen = recvInteger(inStream);
1636                 // Wait until input is available
1637                 while(input.available() == 0);
1638                 // Read String per strLen
1639                 byte[] recvStr = new byte[strLen];
1640                 input.read(recvStr, 0, strLen);
1641                 String retVal = new String(recvStr);
1642
1643                 return retVal;
1644         }
1645
1646
1647         /**
1648          * sendString() sends a String in bytes
1649          */
1650         public void sendString(String strSend, OutputStream outStream) throws IOException {
1651
1652                 BufferedOutputStream output = (BufferedOutputStream) outStream;
1653                 // Transform String into bytes
1654                 byte[] strSendBytes = strSend.getBytes();
1655                 int strLen = strSend.length();
1656                 // Send the string length first
1657                 sendInteger(strLen, outStream);
1658                 // Send the byte array
1659                 output.write(strSendBytes, 0, strLen);
1660                 output.flush();
1661         }
1662
1663
1664         /**
1665          * Convert integer to enum
1666          */
1667         public IoTCommCode getCode(int intCode) throws IOException {
1668
1669                 IoTCommCode[] commCode = IoTCommCode.values();
1670                 IoTCommCode retCode = commCode[intCode];
1671                 return retCode;
1672
1673         }
1674
1675
1676         /**
1677          * Receive ACK
1678          */
1679         public synchronized boolean recvAck(InputStream inStream) throws IOException {
1680
1681                 int intAck = recvInteger(inStream);
1682                 IoTCommCode codeAck = getCode(intAck);
1683                 if (codeAck == IoTCommCode.ACKNOWLEDGED)
1684                         return true;
1685                 return false;
1686
1687         }
1688
1689
1690         /**
1691          * Send END
1692          */
1693         public void sendEndTransfer(OutputStream outStream) throws IOException {
1694
1695                 int endCode = IoTCommCode.END_TRANSFER.ordinal();
1696                 sendInteger(endCode, outStream);
1697         }
1698
1699
1700         /**
1701          * Send communication code to C++
1702          */
1703         public void sendCommCode(IoTCommCode inpCommCode, OutputStream outStream, InputStream inStream) throws IOException {
1704
1705
1706                 IoTCommCode commCode = inpCommCode;
1707                 int intCode = commCode.ordinal();
1708                 // TODO: delete this later
1709                 System.out.println("DEBUG: Sending " + commCode + " with ordinal: " + intCode);
1710                 sendInteger(intCode, outStream); recvAck(inStream);
1711         }
1712
1713
1714         /**
1715          * Create a main controller object for C++
1716          */
1717         public void createMainObjectCpp(String strObjControllerName, OutputStream outStream, InputStream inStream) throws IOException {
1718
1719                 sendCommCode(IoTCommCode.CREATE_MAIN_OBJECT, outStream, inStream);
1720                 String strMainObjName = strObjControllerName;
1721                 sendString(strMainObjName, outStream); recvAck(inStream);
1722                 RuntimeOutput.print("IoTMaster: Create a main object: " + strMainObjName, BOOL_VERBOSE);
1723         }
1724
1725
1726         /**
1727          * A helper function that converts Class into String
1728          *
1729          * @param  strDataType  String MySQL data type
1730          * @return              Class
1731          */
1732         public String getClassConverted(Class<?> cls) {
1733
1734                 if (cls == String.class) {
1735                         return "string";
1736                 } else if (cls == int.class) {
1737                         return "int";
1738                 } else {
1739                         return null;
1740                 }
1741         }
1742
1743
1744         /**
1745          * A helper function that converts Object into String for transfer to C++ slave
1746          *
1747          * @param  obj           Object to be converted
1748          * @param  strClassType  String Java Class type
1749          * @return               Object
1750          */
1751         public String getObjectConverted(Object obj) {
1752
1753                 if (obj instanceof String) {
1754                         return (String) obj;
1755                 } else if (obj instanceof Integer) {
1756                         return Integer.toString((Integer) obj);
1757                 } else {
1758                         return null;
1759                 }
1760         }
1761
1762
1763         /**
1764          * Create a driver object for C++
1765          */
1766         public void createObjectCpp(String strObjName, String strObjClassName, String strObjClassInterfaceName, String strIoTSlaveObjectHostAdd, 
1767                 Integer iRMIRegistryPort, Integer iRMIStubPort, Object[] arrFieldValues, Class[] arrFieldClasses, 
1768                 OutputStream outStream, InputStream inStream) throws IOException {
1769
1770                 sendCommCode(IoTCommCode.CREATE_OBJECT, outStream, inStream);
1771                 RuntimeOutput.print("IoTMaster: Send request to create a driver object... ", BOOL_VERBOSE);
1772                 RuntimeOutput.print("IoTMaster: Driver object name: " + strObjName, BOOL_VERBOSE);
1773                 sendString(strObjName, outStream); recvAck(inStream);
1774                 RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjClassName, BOOL_VERBOSE);
1775                 sendString(strObjClassName, outStream); recvAck(inStream);
1776                 RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjClassInterfaceName, BOOL_VERBOSE);
1777                 sendString(strObjStubClsIntfaceName, outStream); recvAck(inStream);
1778                 RuntimeOutput.print("IoTMaster: Driver object skeleton class name: " + strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
1779                 sendString(strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, outStream); recvAck(inStream);
1780                 RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
1781                 sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
1782                 RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
1783                 sendInteger(iRMIStubPort, outStream); recvAck(inStream);
1784                 int numOfArgs = arrFieldValues.length;
1785                 RuntimeOutput.print("IoTMaster: Send constructor arguments! Number of arguments: " + numOfArgs, BOOL_VERBOSE);
1786                 sendInteger(numOfArgs, outStream); recvAck(inStream);
1787                 for(Object obj : arrFieldValues) {
1788                         String str = getObjectConverted(obj);
1789                         sendString(str, outStream); recvAck(inStream);
1790                 }
1791                 RuntimeOutput.print("IoTMaster: Send constructor argument classes!", BOOL_VERBOSE);
1792                 for(Class cls : arrFieldClasses) {
1793                         String str = getClassConverted(cls);
1794                         sendString(str, outStream); recvAck(inStream);
1795                 }
1796         }
1797
1798
1799         /**
1800          * Create new IoTSet for C++
1801          */
1802         public void createNewIoTSetCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
1803
1804                 sendCommCode(IoTCommCode.CREATE_NEW_IOTSET, outStream, inStream);
1805                 RuntimeOutput.print("IoTMaster: Creating new IoTSet...", BOOL_VERBOSE);
1806                 RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
1807                 sendString(strObjFieldName, outStream); recvAck(inStream);
1808         }
1809
1810
1811         /**
1812          * Create new IoTRelation for C++
1813          */
1814         public void createNewIoTRelationCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
1815
1816                 sendCommCode(IoTCommCode.CREATE_NEW_IOTRELATION, outStream, inStream);
1817                 RuntimeOutput.print("IoTMaster: Creating new IoTRelation...", BOOL_VERBOSE);
1818                 RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
1819                 sendString(strObjFieldName, outStream); recvAck(inStream);
1820         }
1821
1822
1823         /**
1824          * Get a IoTDeviceAddress object for C++
1825          */
1826         public void getDeviceIoTSetObjectCpp(OutputStream outStream, InputStream inStream,
1827                         String strDeviceAddress, int iSourcePort, int iDestPort, boolean bSourceWildCard, boolean bDestWildCard) throws IOException {
1828
1829                 sendCommCode(IoTCommCode.GET_DEVICE_IOTSET_OBJECT, outStream, inStream);
1830                 RuntimeOutput.print("IoTMaster: Getting IoTDeviceAddress...", BOOL_VERBOSE);
1831                 sendString(strDeviceAddress, outStream); recvAck(inStream);
1832                 sendInteger(iSourcePort, outStream); recvAck(inStream);
1833                 sendInteger(iDestPort, outStream); recvAck(inStream);
1834                 int iSourceWildCard = (bSourceWildCard ? 1 : 0);
1835                 sendInteger(iSourceWildCard, outStream); recvAck(inStream);
1836                 int iDestWildCard = (bDestWildCard ? 1 : 0);
1837                 sendInteger(iDestWildCard, outStream); recvAck(inStream);
1838                 RuntimeOutput.print("IoTMaster: Send device address: " + strDeviceAddress, BOOL_VERBOSE);
1839         }
1840
1841
1842         /**
1843          * Get a IoTSet content object for C++
1844          */
1845         public void getIoTSetRelationObjectCpp(IoTCommCode iotCommCode, String strIoTSlaveHostAddress, String strObjectName, String strObjectClassName, 
1846                         String strObjectClassInterfaceName, String strObjectStubClassInterfaceName, int iRMIRegistryPort, int iRMIStubPort, 
1847                         OutputStream outStream, InputStream inStream) throws IOException {
1848
1849                 sendCommCode(iotCommCode, outStream, inStream);
1850                 RuntimeOutput.print("IoTMaster: Getting IoTSet object content...", BOOL_VERBOSE);
1851                 // Send info
1852                 RuntimeOutput.print("IoTMaster: Send host address: " + strIoTSlaveHostAddress, BOOL_VERBOSE);
1853                 sendString(strIoTSlaveHostAddress, outStream); recvAck(inStream);
1854                 RuntimeOutput.print("IoTMaster: Driver object name: " + strObjectName, BOOL_VERBOSE);
1855                 sendString(strObjectName, outStream); recvAck(inStream);
1856                 RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjectClassName, BOOL_VERBOSE);
1857                 sendString(strObjectClassName, outStream); recvAck(inStream);
1858                 RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjectClassInterfaceName, BOOL_VERBOSE);
1859                 sendString(strObjectClassInterfaceName, outStream); recvAck(inStream);
1860                 RuntimeOutput.print("IoTMaster: Driver object stub class name: " + strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
1861                 sendString(strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, outStream); recvAck(inStream);
1862                 RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
1863                 sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
1864                 RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
1865                 sendInteger(iRMIStubPort, outStream); recvAck(inStream);
1866         }
1867
1868
1869         /**
1870          * Reinitialize IoTRelation field for C++
1871          */
1872         private void reinitializeIoTRelationFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
1873
1874                 RuntimeOutput.print("IoTMaster: About to Reinitialize IoTRelation field!", BOOL_VERBOSE);
1875                 sendCommCode(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD, outStream, inStream);
1876                 RuntimeOutput.print("IoTMaster: Reinitialize IoTRelation field!", BOOL_VERBOSE);
1877         }
1878
1879
1880         /**
1881          * Reinitialize IoTSet field for C++
1882          */
1883         private void reinitializeIoTSetFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
1884
1885                 RuntimeOutput.print("IoTMaster: About to Reinitialize IoTSet field!", BOOL_VERBOSE);
1886                 sendCommCode(IoTCommCode.REINITIALIZE_IOTSET_FIELD, outStream, inStream);
1887                 RuntimeOutput.print("IoTMaster: Reinitialize IoTSet field!", BOOL_VERBOSE);
1888         }
1889
1890
1891         /**
1892          * Create driver object for C++
1893          */
1894         private void createDriverObjectCpp(OutputStream outStream, InputStream inStream) throws IOException {
1895
1896                 sendCommCode(IoTCommCode.CREATE_DRIVER_OBJECT, outStream, inStream);
1897                 RuntimeOutput.print("IoTMaster: Send command to create driver object!", BOOL_VERBOSE);
1898         }
1899
1900
1901         /**
1902          * Invoke init() for C++
1903          */
1904         private void invokeInitMethodCpp(OutputStream outStream, InputStream inStream) throws IOException {
1905
1906                 sendCommCode(IoTCommCode.INVOKE_INIT_METHOD, outStream, inStream);
1907                 RuntimeOutput.print("IoTMaster: Invoke init method!", BOOL_VERBOSE);
1908         }
1909
1910
1911         /**
1912          * End session for C++
1913          */
1914         public void endSessionCpp(OutputStream outStream) throws IOException {
1915
1916                 // Send message to end session
1917                 IoTCommCode endSessionCode = IoTCommCode.END_SESSION;
1918                 int intCode = endSessionCode.ordinal();
1919                 sendInteger(intCode, outStream);
1920                 //RuntimeOutput.print("IoTMaster: Send request to create a main object: " + strObjName, BOOL_VERBOSE);
1921                 RuntimeOutput.print("IoTMaster: Send request to end session!", BOOL_VERBOSE);
1922         }
1923
1924
1925         /**
1926          * A method to assign objects to multiple JVMs, including
1927          * the controller/device object that uses other objects
1928          * in IoTSet and IoTRelation
1929          *
1930          * @return       void
1931          */
1932         private void createObjects() {
1933
1934                 // PROFILING
1935                 long start = 0;
1936                 long result = 0;
1937
1938                 try {
1939                         // Extract hostname for this IoTMaster from MySQL DB
1940                         strIoTMasterHostAdd = routerConfig.getIPFromMACAddress(STR_MASTER_MAC_ADD);
1941                         // Loop as we can still find controller/device classes
1942                         for(int i=0; i<strObjectNames.length; i++) {
1943                                 // PROFILING
1944                                 start = System.currentTimeMillis();
1945
1946                                 // Assign a new list of PrintWriter objects
1947                                 routerConfig.renewPrintWriter();
1948                                 // Get controller names one by one
1949                                 String strObjControllerName = strObjectNames[i];
1950                                 // Use LoadBalancer to assign a host address
1951                                 //strIoTSlaveControllerHostAdd = lbIoT.selectHost();
1952                                 strIoTSlaveControllerHostAdd = routerConfig.getIPFromMACAddress(lbIoT.selectHost());
1953                                 if (strIoTSlaveControllerHostAdd == null)
1954                                         throw new Error("IoTMaster: Could not translate MAC to IP address! Please check the router's /tmp/dhcp.leases!");
1955                                 // == START INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
1956                                 // Add port connection and get port numbers
1957                                 // Naming for objects ProximitySensor becomes ProximitySensor0, ProximitySensor1, etc.
1958                                 commHan.addPortConnection(strIoTSlaveControllerHostAdd, strObjControllerName);
1959                                 // ROUTING POLICY: IoTMaster and main controller object
1960                                 routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strIoTMasterHostAdd,
1961                                         strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1962                                 // ROUTING POLICY: Send the same routing policy to both the hosts
1963                                 routerConfig.configureHostMainPolicies(strIoTMasterHostAdd, strIoTMasterHostAdd,
1964                                         strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1965                                 routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTMasterHostAdd,
1966                                         strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
1967                                 // Read config file
1968                                 String strControllerCfg = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT;
1969                                 STR_LANGUAGE_CONTROLLER = parseConfigFile(strControllerCfg, STR_LANGUAGE);
1970                                 if(STR_LANGUAGE_CONTROLLER == null)
1971                                         throw new Error("IoTMaster: Language specification missing in config file: " + strControllerCfg);
1972                                 // Construct ssh command line and create a controller thread for e.g. AcmeProximity
1973                                 String strSSHCommand = null;
1974                                 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
1975                                         strSSHCommand = getCmdJavaIoTSlave(strObjControllerName);
1976                                 else if(STR_LANGUAGE_CONTROLLER.equals(STR_CPP))
1977                                         strSSHCommand = getCmdCppIoTSlave(strObjControllerName);
1978                                 else
1979                                         throw new Error("IoTMaster: Language specification not recognized: " + STR_LANGUAGE_CONTROLLER);
1980                                 RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
1981                                 createThread(strSSHCommand);
1982                                 // Wait for connection
1983                                 // Create a new socket for communication
1984                                 ServerSocket serverSocket = new ServerSocket(commHan.getComPort(strObjControllerName));
1985                                 Socket socket = serverSocket.accept();
1986                                 InputStream inStream = null;
1987                                 OutputStream outStream = null;
1988                                 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
1989                                         inStream = new ObjectInputStream(socket.getInputStream());
1990                                         outStream = new ObjectOutputStream(socket.getOutputStream());
1991                                 } else {        // At this point the language is certainly C++, otherwise would've complained above
1992                                         inStream = new BufferedInputStream(socket.getInputStream());
1993                                         outStream = new BufferedOutputStream(socket.getOutputStream());
1994                                         recvAck(inStream);
1995                                 }
1996                                 RuntimeOutput.print("IoTMaster: Communication established!", BOOL_VERBOSE);
1997
1998                                 // PROFILING
1999                                 result = System.currentTimeMillis()-start;
2000                                 System.out.println("\n\n ==> From start until after SSH for main controller: " + result);
2001                                 // PROFILING
2002                                 start = System.currentTimeMillis();
2003
2004                                 // Send files for every controller class
2005                                 // e.g. AcmeProximity.jar and AcmeProximity.zip
2006                                 String strControllerClassName = strObjControllerName + STR_CLS_FILE_EXT;
2007                                 String strControllerClassNamePath = STR_CONT_PATH + strObjControllerName + "/" +
2008                                         strControllerClassName;
2009
2010                                 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2011                                         sendFileToJavaSlave(strObjControllerName, serverSocket, inStream, outStream);
2012                                         // Create main controller/device object
2013                                         commMasterToSlave(new MessageCreateMainObject(IoTCommCode.CREATE_MAIN_OBJECT, strObjControllerName),
2014                                                 "Create main object!", inStream, outStream);
2015                                 } else {
2016                                         String strControllerZipFile = strObjControllerName + STR_ZIP_FILE_EXT;
2017                                         String strControllerFilePath = STR_CONT_PATH + strObjControllerName + "/";
2018                                         sendFileToCppSlave(strControllerFilePath, strControllerZipFile);
2019                                         createMainObjectCpp(strObjControllerName, outStream, inStream);
2020                                 }
2021
2022                                 // PROFILING
2023                                 result = System.currentTimeMillis()-start;
2024                                 System.out.println("\n\n ==> From IoTSlave start until main controller object is created: " + result);
2025                                 System.out.println(" ==> Including file transfer times!\n\n");
2026                                 // PROFILING
2027                                 start = System.currentTimeMillis();
2028
2029                                 // == END INITIALIZING CONTROLLER/DEVICE IOTSLAVE ==
2030                                 // Instrumenting one file
2031                                 RuntimeOutput.print("IoTMaster: Opening class file: " + strControllerClassName, BOOL_VERBOSE);
2032                                 RuntimeOutput.print("IoTMaster: Class file path: " + strControllerClassNamePath, BOOL_VERBOSE);
2033                                 HashMap<String,Object> hmControllerFieldObjects = null;
2034                                 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2035                                         FileInputStream fis = new FileInputStream(strControllerClassNamePath);
2036                                         ClassReader cr = new ClassReader(fis);
2037                                         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
2038                                         ClassRuntimeInstrumenterMaster crim = new ClassRuntimeInstrumenterMaster(cw, null, BOOL_VERBOSE);
2039                                         cr.accept(crim, 0);
2040                                         fis.close();
2041                                         hmControllerFieldObjects = crim.getFieldObjects();
2042                                 } else {
2043                                         String strControllerConfigFile = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT;
2044                                         CRuntimeInstrumenterMaster crim = new CRuntimeInstrumenterMaster(strControllerConfigFile, null, BOOL_VERBOSE);
2045                                         hmControllerFieldObjects = crim.getFieldObjects();
2046                                 }
2047                                 // Get the object and the class names
2048                                 // Build objects for IoTSet and IoTRelation fields in the controller/device classes
2049                                 //HashMap<String,Object> hmControllerFieldObjects = crim.getFieldObjects();
2050                                 for(Map.Entry<String,Object> map : hmControllerFieldObjects.entrySet()) {
2051                                         RuntimeOutput.print("IoTMaster: Object name: " + map.getValue().getClass().getName(), BOOL_VERBOSE);
2052                                         // Iterate over HashMap and choose between processing
2053                                         // SetInstrumenter vs. RelationInstrumenter
2054                                         String strFieldName = map.getKey();
2055                                         String strClassName = map.getValue().getClass().getName();
2056                                         if(strClassName.equals(STR_SET_INSTRUMENTER_CLS)) {
2057                                                 SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
2058                                                 if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) { 
2059                                                         String strErrMsg = "IoTMaster: Controller object" +
2060                                                                 " cannot have IoTSet<IoTDeviceAddress>!";
2061                                                         throw new Error(strErrMsg);
2062                                                 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) { 
2063                                                         String strErrMsg = "IoTMaster: Controller object" +
2064                                                                 " cannot have IoTSet<ZigbeeAddress>!";
2065                                                         throw new Error(strErrMsg);
2066                                                 } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) { 
2067                                                 // Instrument the IoTAddress
2068                                                         setRouterPolicyIoTSetAddress(strFieldName, map, strIoTSlaveControllerHostAdd);
2069                                                         instrumentIoTSetAddress(strFieldName, strFieldName, inStream, outStream, STR_LANGUAGE_CONTROLLER);
2070                                                 } else {
2071                                                 // Any other cases
2072                                                         instrumentIoTSet(map, strFieldName, STR_LANGUAGE_CONTROLLER);
2073                                                 }
2074                                         } else if (strClassName.equals(STR_REL_INSTRUMENTER_CLS)) {
2075                                                 instrumentIoTRelation(map, strFieldName, STR_LANGUAGE_CONTROLLER);
2076                                         }
2077                                 }
2078                                 // PROFILING
2079                                 result = System.currentTimeMillis()-start;
2080                                 System.out.println("\n\n ==> Time needed to instrument device driver objects: " + result + "\n\n");
2081                                 System.out.println(" ==> #Objects: " + commHan.getActiveControllerObjectList().size() + "\n\n");
2082
2083                                 // PROFILING
2084                                 start = System.currentTimeMillis();
2085
2086                                 // ROUTING POLICY: Deploy basic policies if this is the last controller
2087                                 if (i == strObjectNames.length-1) {
2088                                         // ROUTING POLICY: implement basic policies to reject all other irrelevant traffics
2089                                         for(String s: commHan.getHosts()) {
2090                                                 setHostBasicPolicies(s);
2091                                         }
2092                                         // We retain all the basic policies for router, 
2093                                         // but we delete the initial allowance policies for internal all TCP and UDP communications
2094                                         setRouterBasicPolicies(STR_ROUTER_ADD);
2095                                 }
2096                                 // Close access to policy files and deploy policies
2097                                 routerConfig.close();
2098                                 // Deploy the policy
2099                                 HashSet<String> setAddresses = new HashSet<String>(commHan.getHosts());
2100                                 setAddresses.add(strIoTMasterHostAdd);
2101                                 createPolicyThreads(STR_ROUTER_ADD, setAddresses);
2102
2103                                 // PROFILING
2104                                 result = System.currentTimeMillis()-start;
2105                                 System.out.println("\n\n ==> Time needed to send policy files and deploy them : " + result + "\n\n");
2106
2107                                 // PROFILING
2108                                 start = System.currentTimeMillis();
2109
2110                                 // Separating object creations and Set/Relation initializations
2111                                 createDriverObjects();
2112
2113                                 // PROFILING
2114                                 result = System.currentTimeMillis()-start;
2115                                 System.out.println("\n\n ==> Time needed to instantiate objects: " + result + "\n\n");
2116                                 // PROFILING
2117                                 start = System.currentTimeMillis();
2118
2119                                 // Sets and relations initializations
2120                                 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2121                                         initializeSetsAndRelationsJava(inStream, outStream);
2122                                 else
2123                                         initializeSetsAndRelationsCpp(inStream, outStream);;
2124
2125                                 // PROFILING
2126                                 result = System.currentTimeMillis()-start;
2127                                 System.out.println("\n\n ==> Time needed to initialize sets and relations: " + result + "\n\n");
2128
2129                                 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
2130                                         // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO EXECUTE INIT METHOD
2131                                         commMasterToSlave(new MessageSimple(IoTCommCode.INVOKE_INIT_METHOD), "Invoke init() method!", inStream, outStream);
2132                                 else
2133                                         invokeInitMethodCpp(outStream, inStream);
2134                                 // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO END PROCESS
2135                                 if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
2136                                         ObjectOutputStream oStream = (ObjectOutputStream) outStream;
2137                                         oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
2138                                 } else  // C++ side will wait until the program finishes, it's not generating a separate thread for now
2139                                         //endSessionCpp(outStream);
2140                                 outStream.close();
2141                                 inStream.close();
2142                                 socket.close();
2143                                 serverSocket.close();
2144                                 commHan.printLists();
2145                                 lbIoT.printHostInfo();
2146                         }
2147
2148                 } catch (IOException          |
2149                                  InterruptedException |
2150                                  ClassNotFoundException ex) {
2151                         System.out.println("IoTMaster: Exception: "
2152                                 + ex.getMessage());
2153                         ex.printStackTrace();
2154                 }
2155         }
2156
2157         public static void main(String args[]) {
2158
2159                 // Detect the available controller/device classes
2160                 // Input args[] should be used to list the controllers/devices
2161                 // e.g. java IoTMaster AcmeProximity AcmeThermostat AcmeVentController
2162                 IoTMaster iotMaster = new IoTMaster(args);
2163                 // Read config file
2164                 iotMaster.parseIoTMasterConfigFile();
2165                 // Initialize CommunicationHandler, LoadBalancer, and RouterConfig
2166                 iotMaster.initLiveDataStructure();
2167                 // Create objects
2168                 iotMaster.createObjects();
2169         }
2170 }