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