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