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