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