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