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