Adding config file for sharing.
[iot2.git] / iotjava / iotpolicy / IoTCompiler.java
index 0a8e5dd0f2e125f2d173af297aa2c4e352d0660e..027ea07670c77433c6e030ff6f984f26893de84c 100644 (file)
@@ -49,6 +49,7 @@ public class IoTCompiler {
        private Map<String,DeclarationHandler> mapIntDeclHand;
        private Map<String,Map<String,Set<String>>> mapInt2NewInts;
        private Map<String,String> mapInt2NewIntName;
+       private Map<String,List<String>> mapInt2Drv;
        // Data structure to store our types (primitives and non-primitives) for compilation
        private Map<String,String> mapPrimitives;
        private Map<String,String> mapNonPrimitivesJava;
@@ -61,13 +62,22 @@ public class IoTCompiler {
        private String subdir;
        private Map<String,Integer> mapPortCount;       // Counter for ports
        private static int portCount = 0;
+       private static int countObjId = 1;                      // Always increment object Id for a new stub/skeleton
        private String mainClass;
+       private String controllerClass;
 
 
        /**
         * Class constants
         */
        private final static String OUTPUT_DIRECTORY = "output_files";
+       private final static String INTERFACES_DIRECTORY = "interfaces";
+       private final static String VIRTUALS_DIRECTORY = "virtuals";
+       private final static String DRIVERS_DIRECTORY = "drivers";
+       private final static String CONTROLLER_DIRECTORY = "controller";
+       private final static String CODE_PREFIX = "iotcode";
+       private final static String INTERFACE_PACKAGE = "iotcode.interfaces";
+
 
        private enum ParamCategory {
 
@@ -88,6 +98,7 @@ public class IoTCompiler {
                mapIntDeclHand = new HashMap<String,DeclarationHandler>();
                mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
                mapInt2NewIntName = new HashMap<String,String>();
+               mapInt2Drv = new HashMap<String,List<String>>();
                mapIntfaceObjId = new HashMap<String,Integer>();
                mapNewIntfaceObjId = new HashMap<String,Integer>();
                mapPrimitives = new HashMap<String,String>();
@@ -101,6 +112,29 @@ public class IoTCompiler {
                dir = OUTPUT_DIRECTORY;
                subdir = null;
                mainClass = null;
+               controllerClass = null;
+       }
+
+
+       /**
+        * setDriverClass() sets the name of the driver class.
+        */
+       public void setDriverClass(String intface, String driverClass) {
+               
+               List<String> drvList = mapInt2Drv.get(intface);
+               if(drvList == null)
+                       drvList = new ArrayList<String>();
+               drvList.add(driverClass);
+               mapInt2Drv.put(intface, drvList);
+       }
+       
+       
+       /**
+        * setControllerClass() sets the name of the controller class.
+        */
+       public void setControllerClass(String _controllerClass) {
+               
+               controllerClass = _controllerClass;
        }
 
 
@@ -143,7 +177,18 @@ public class IoTCompiler {
                mapIntfacePTH.put(origInt, ptHandler);
                mapIntDeclHand.put(origInt, decHandler);
                // Set object Id counter to 0 for each interface
-               mapIntfaceObjId.put(origInt, new Integer(0));
+               mapIntfaceObjId.put(origInt, countObjId++);
+       }
+       
+       
+       /**
+        * setObjectId() updates the object Id. This option is useful
+        * when the stub/skeleton are also used in other apps, so that
+        * we can set a single object Id for the stub/skeleton.
+        */
+       private void setObjectId(String intface, String objectId) {
+
+               mapIntfaceObjId.put(intface, Integer.parseInt(objectId));
        }
 
 
@@ -258,6 +303,7 @@ public class IoTCompiler {
 
                // Create a new directory
                createDirectory(dir);
+               String path = createDirectories(dir, INTERFACES_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
                        // Get the right EnumDecl
                        DeclarationHandler decHandler = mapIntDeclHand.get(intface);
@@ -266,8 +312,9 @@ public class IoTCompiler {
                        // Iterate over enum declarations
                        for (String enType : enumTypes) {
                                // Open a new file to write into
-                               FileWriter fw = new FileWriter(dir + "/" + enType + ".java");
+                               FileWriter fw = new FileWriter(path + "/" + enType + ".java");
                                pw = new PrintWriter(new BufferedWriter(fw));
+                               println("package " + INTERFACE_PACKAGE + ";\n");
                                println("public enum " + enType + " {");
                                List<String> enumMembers = enumDecl.getMembers(enType);
                                for (int i = 0; i < enumMembers.size(); i++) {
@@ -295,6 +342,7 @@ public class IoTCompiler {
 
                // Create a new directory
                createDirectory(dir);
+               String path = createDirectories(dir, INTERFACES_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
                        // Get the right StructDecl
                        DeclarationHandler decHandler = mapIntDeclHand.get(intface);
@@ -303,8 +351,9 @@ public class IoTCompiler {
                        // Iterate over enum declarations
                        for (String stType : structTypes) {
                                // Open a new file to write into
-                               FileWriter fw = new FileWriter(dir + "/" + stType + ".java");
+                               FileWriter fw = new FileWriter(path + "/" + stType + ".java");
                                pw = new PrintWriter(new BufferedWriter(fw));
+                               println("package " + INTERFACE_PACKAGE + ";\n");
                                println("public class " + stType + " {");
                                List<String> structMemberTypes = structDecl.getMemberTypes(stType);
                                List<String> structMembers = structDecl.getMembers(stType);
@@ -334,9 +383,10 @@ public class IoTCompiler {
 
                // Create a new directory
                createDirectory(dir);
+               String path = createDirectories(dir, INTERFACES_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
                        // Open a new file to write into
-                       FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
+                       FileWriter fw = new FileWriter(path + "/" + intface + ".java");
                        pw = new PrintWriter(new BufferedWriter(fw));
                        // Pass in set of methods and get import classes
                        DeclarationHandler decHandler = mapIntDeclHand.get(intface);
@@ -345,6 +395,7 @@ public class IoTCompiler {
                        Set<String> importClasses = getImportClasses(methods, intDecl);
                        List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
                        List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
+                       println("package " + INTERFACE_PACKAGE + ";\n");
                        printImportStatements(allImportClasses);
                        // Write interface header
                        println("");
@@ -363,9 +414,9 @@ public class IoTCompiler {
         */
        private void updateIntfaceObjIdMap(String intface, String newIntface) {
 
+               // We are assuming that we only generate one stub per one skeleton at this point @Feb 2017
                Integer objId = mapIntfaceObjId.get(intface);
                mapNewIntfaceObjId.put(newIntface, objId);
-               mapIntfaceObjId.put(intface, objId++);
        }
 
 
@@ -376,6 +427,7 @@ public class IoTCompiler {
 
                // Create a new directory
                String path = createDirectories(dir, subdir);
+               path = createDirectories(dir + "/" + subdir, INTERFACES_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
 
                        Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
@@ -392,6 +444,7 @@ public class IoTCompiler {
                                Set<String> importClasses = getImportClasses(methods, intDecl);
                                List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
                                List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
+                       println("package " + INTERFACE_PACKAGE + ";\n");
                                printImportStatements(allImportClasses);
                                // Write interface header
                                println("");
@@ -416,8 +469,6 @@ public class IoTCompiler {
                for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
                        String newIntface = intMeth.getKey();
                        int newObjectId = getNewIntfaceObjectId(newIntface);
-                       println("private final static int object" + newObjectId + "Id = " + 
-                               newObjectId + ";\t//" + newIntface);
                        Set<String> methodIds = intMeth.getValue();
                        print("private static Integer[] object" + newObjectId + "Permission = { ");
                        int i = 0;
@@ -479,7 +530,12 @@ public class IoTCompiler {
        private void writeConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
 
                println("public " + newStubClass + "(int _localPortSend, int _localPortRecv, int _portSend, int _portRecv, String _skeletonAddress, int _rev) throws Exception {");
+               println("if (_localPortSend != 0 && _localPortRecv != 0) {");
                println("rmiComm = new IoTRMICommClient(_localPortSend, _localPortRecv, _portSend, _portRecv, _skeletonAddress, _rev);");
+               println("} else");
+               println("{");
+               println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev);");
+               println("}");
                // Register the AtomicBoolean variables
                for (String method : methods) {
                        // Generate AtomicBooleans for methods that have return values
@@ -515,42 +571,6 @@ public class IoTCompiler {
        }
 
 
-       /**
-        * HELPER: writeJavaMethodCallbackPermission() writes permission checks in stub for callbacks
-        */
-       private void writeJavaMethodCallbackPermission(String intface) {
-
-               println("int methodId = IoTRMIObject.getMethodId(method);");
-               // Get all the different stubs
-               Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
-               for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
-                       String newIntface = intMeth.getKey();
-                       int newObjectId = getNewIntfaceObjectId(newIntface);
-                       println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
-                       println("throw new Error(\"Callback object for " + intface + " is not allowed to access method: \" + methodId);");
-                       println("}");
-               }
-       }
-
-
-       /**
-        * HELPER: writeJavaInitCallbackPermission() writes the permission for callback
-        */
-       private void writeJavaInitCallbackPermission(String intface, InterfaceDecl intDecl, boolean callbackExist) {
-
-               if (callbackExist) {
-                       String method = "___initCallBack()";
-                       int methodNumId = intDecl.getHelperMethodNumId(method);
-                       Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
-                       for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
-                               String newIntface = intMeth.getKey();
-                               int newObjectId = getNewIntfaceObjectId(newIntface);
-                               println("set" + newObjectId + "Allowed.add(" + methodNumId + ");");
-                       }
-               }
-       }
-
-
        /**
         * HELPER: getPortCount() gets port count for different stubs and skeletons
         */
@@ -753,7 +773,7 @@ public class IoTCompiler {
        /**
         * HELPER: writeStructParamClassJavaStub() writes parameters if struct is present
         */
-       private void writeStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes, String callbackType) {
+       private void writeStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
 
                print("int paramLen = ");
                writeLengthStructParamClassJavaStub(methParams, methPrmTypes);
@@ -769,15 +789,8 @@ public class IoTCompiler {
                        if (isStructClass(simpleType)) {
                                writeStructMembersJavaStub(simpleType, paramType, param);
                        } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
-                               println("paramCls[pos] = int.class;");
-                               print("paramObj[pos++] = ");
-                               if (isArray(methParams.get(i)))
-                                       print(getSimpleIdentifier(methParams.get(i)) + ".length");
-                               else if (isList(methPrmTypes.get(i)))
-                                       print(getSimpleIdentifier(methParams.get(i)) + ".size()");
-                               else
-                                       print("new Integer(1)");
-                               println(";");
+                               println("paramCls[pos] = int[].class;");
+                               println("paramObj[pos++] = objIdSent" + i + ";");
                        } else {
                                String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
                                println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
@@ -861,7 +874,6 @@ public class IoTCompiler {
                                println("retClsVal[retPos++] = null;");
                        }
                }
-               //println("Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);");
                // Handle the actual returned struct
                writeWaitForReturnValueJava(method, intDecl, "Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);");
                if (isArray(retType)) {                 // An array
@@ -896,7 +908,7 @@ public class IoTCompiler {
         * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
         */
        private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
-                       List<String> methPrmTypes, String method, String callbackType) {
+                       List<String> methPrmTypes, String method, Set<String> callbackType) {
 
                checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method);
                println("int methodId = " + intDecl.getMethodNumId(method) + ";");
@@ -927,7 +939,7 @@ public class IoTCompiler {
                        for (int i = 0; i < methParams.size(); i++) {
                                String paramType = methPrmTypes.get(i);
                                if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
-                                       print("objIdSent");
+                                       print("objIdSent" + i);
                                } else
                                        print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
                                // Check if this is the last element (don't print a comma)
@@ -976,6 +988,24 @@ public class IoTCompiler {
        }
 
 
+       /**
+        * HELPER: checkCallbackType() checks the callback type
+        */
+       private boolean checkCallbackType(String paramType, Set<String> callbackType) {
+
+               String prmType = returnGenericCallbackType(paramType);
+               if (callbackType == null)       // If there is no callbackType it means not a callback method
+                       return false;
+               else {
+                       for (String type : callbackType) {
+                               if (type.equals(prmType))
+                                       return true;    // Check callbackType one by one
+                       }
+                       return false;
+               }
+       }
+
+
        /**
         * HELPER: checkCallbackType() checks the callback type
         */
@@ -997,17 +1027,17 @@ public class IoTCompiler {
                println("if (!IoTRMIUtil.mapSkel.containsKey(" + paramIdent + ")) {");
                println("int newObjIdSent = rmiComm.getObjectIdCounter();");
                if (isMultipleCallbacks)
-                       println("objIdSent[i++] = newObjIdSent;");
+                       println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
                else
-                       println("objIdSent[0] = newObjIdSent;");
+                       println("objIdSent" + counter + "[0] = newObjIdSent;");
                println("rmiComm.decrementObjectIdCounter();");
                println(callbackType + "_Skeleton skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
-               println("IoTRMIUtil.mapSkel.put(" + paramIdent + ", skel0);");
+               println("IoTRMIUtil.mapSkel.put(" + paramIdent + ", skel" + counter + ");");
                println("IoTRMIUtil.mapSkelId.put(" + paramIdent + ", newObjIdSent);");
                println("Thread thread = new Thread() {");
                println("public void run() {");
                println("try {");
-               println("skel0.___waitRequestInvokeMethod();");
+               println("skel" + counter + ".___waitRequestInvokeMethod();");
                println("} catch (Exception ex) {");
                println("ex.printStackTrace();");
                println("throw new Error(\"Exception when trying to run ___waitRequestInvokeMethod() for " + 
@@ -1022,9 +1052,9 @@ public class IoTCompiler {
                println("{");
                println("int newObjIdSent = IoTRMIUtil.mapSkelId.get(" + paramIdent + ");");
                if (isMultipleCallbacks)
-                       println("objIdSent[i++] = newObjIdSent;");
+                       println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
                else
-                       println("objIdSent[0] = newObjIdSent;");
+                       println("objIdSent" + counter + "[0] = newObjIdSent;");
                println("}");
        }
 
@@ -1033,13 +1063,13 @@ public class IoTCompiler {
         * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class
         */
        private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
-                       List<String> methPrmTypes, String method, String callbackType) {
+                       List<String> methPrmTypes, String method, Set<String> callbackType) {
 
                // Determine callback object counter type (List vs. single variable)
-               print("int[] objIdSent = ");
                for (int i = 0; i < methParams.size(); i++) {
                        String paramType = methPrmTypes.get(i);
                        if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
+                               print("int[] objIdSent" + i + " = ");
                                String param = methParams.get(i);
                                if (isArray(methParams.get(i)))
                                        println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".length];");
@@ -1056,11 +1086,11 @@ public class IoTCompiler {
                        if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
                                String param = methParams.get(i);
                                if (isArrayOrList(paramType, param)) {  // Generate loop
-                                       println("int i = 0;");
+                                       println("int cnt" + i + " = 0;");
                                        println("for (" + getGenericType(paramType) + " cb : " + getSimpleIdentifier(param) + ") {");
-                                       writeCallbackInstantiationMethodBodyJavaStub("cb", callbackType, i, true);
+                                       writeCallbackInstantiationMethodBodyJavaStub("cb", returnGenericCallbackType(paramType), i, true);
                                } else
-                                       writeCallbackInstantiationMethodBodyJavaStub(getSimpleIdentifier(param), callbackType, i, false);
+                                       writeCallbackInstantiationMethodBodyJavaStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i, false);
                                if (isArrayOrList(paramType, param))
                                        println("}");
                        }
@@ -1085,14 +1115,16 @@ public class IoTCompiler {
                        print("public " + intDecl.getMethodType(method) + " " +
                                intDecl.getMethodId(method) + "(");
                        boolean isCallbackMethod = false;
-                       String callbackType = null;
+                       //String callbackType = null;
+                       Set<String> callbackType = new HashSet<String>();
                        for (int i = 0; i < methParams.size(); i++) {
 
                                String paramType = returnGenericCallbackType(methPrmTypes.get(i));
                                // Check if this has callback object
                                if (callbackClasses.contains(paramType)) {
                                        isCallbackMethod = true;
-                                       callbackType = paramType;       
+                                       //callbackType = paramType;
+                                       callbackType.add(paramType);
                                        // Even if there're 2 callback arguments, we expect them to be of the same interface
                                }
                                print(methPrmTypes.get(i) + " " + methParams.get(i));
@@ -1105,7 +1137,6 @@ public class IoTCompiler {
                        // Now, write the body of stub!
                        if (isCallbackMethod)
                                writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
-                       //else
                        writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
                        println("}\n");
                }
@@ -1130,38 +1161,55 @@ public class IoTCompiler {
                String path = createDirectories(dir, subdir);
                for (String intface : mapIntfacePTH.keySet()) {
 
-                       Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
-                       for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
-
-                               // Open a new file to write into
-                               String newIntface = intMeth.getKey();
-                               String newStubClass = newIntface + "_Stub";
-                               FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
-                               pw = new PrintWriter(new BufferedWriter(fw));
-                               DeclarationHandler decHandler = mapIntDeclHand.get(intface);
-                               InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
-                               // Pass in set of methods and get import classes
-                               Set<String> methods = intMeth.getValue();
-                               Set<String> importClasses = getImportClasses(methods, intDecl);
-                               List<String> stdImportClasses = getStandardJavaImportClasses();
-                               List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
-                               printImportStatements(allImportClasses); println("");
-                               // Find out if there are callback objects
-                               Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
-                               boolean callbackExist = !callbackClasses.isEmpty();
-                               // Write class header
-                               println("public class " + newStubClass + " implements " + newIntface + " {\n");
-                               // Write properties
-                               writePropertiesJavaStub(intface, intMeth.getValue(), intDecl);
-                               // Write constructor
-                               writeConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
-                               // Write callback constructor (used if this stub is treated as a callback stub)
-                               writeCallbackConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
-                               // Write methods
-                               writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass);
-                               println("}");
-                               pw.close();
-                               System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
+                       // Check if there is more than 1 class that uses the same interface
+                       List<String> drvList = mapInt2Drv.get(intface);
+                       for(int i = 0; i < drvList.size(); i++) {
+
+                               String driverClass = drvList.get(i);
+                               Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+                               for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+
+                                       // Open a new file to write into
+                                       String newIntface = intMeth.getKey();
+                                       String newStubClass = newIntface + "_Stub";
+                                       String packageClass = null;
+                                       // Check if this interface is a callback class
+                                       if(isCallbackClass(intface)) {
+                                               packageClass = CODE_PREFIX + "." + driverClass;
+                                               path = createDirectories(dir + "/" + subdir + "/" + DRIVERS_DIRECTORY, driverClass);
+                                       } else {
+                                               packageClass = controllerClass;
+                                               path = createDirectories(dir + "/" + subdir + "/" + CONTROLLER_DIRECTORY, controllerClass);
+                                       }
+                                       FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
+                                       pw = new PrintWriter(new BufferedWriter(fw));
+                                       DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                                       InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                                       // Pass in set of methods and get import classes
+                                       Set<String> methods = intMeth.getValue();
+                                       Set<String> importClasses = getImportClasses(methods, intDecl);
+                                       List<String> stdImportClasses = getStandardJavaImportClasses();
+                                       List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
+                                       // Find out if there are callback objects
+                                       Set<String> callbackClasses = getCallbackClasses(methods, intDecl);                     
+                                       boolean callbackExist = !callbackClasses.isEmpty();
+                                       println("package " + packageClass + ";\n");
+                                       printImportStatements(allImportClasses); 
+                                       println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
+                                       // Write class header
+                                       println("public class " + newStubClass + " implements " + newIntface + " {\n");
+                                       // Write properties
+                                       writePropertiesJavaStub(intface, intMeth.getValue(), intDecl);
+                                       // Write constructor
+                                       writeConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
+                                       // Write callback constructor (used if this stub is treated as a callback stub)
+                                       writeCallbackConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
+                                       // Write methods
+                                       writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass);
+                                       println("}");
+                                       pw.close();
+                                       System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
+                               }
                        }
                }
        }
@@ -1173,7 +1221,8 @@ public class IoTCompiler {
        private void writePropertiesJavaSkeleton(String intface, InterfaceDecl intDecl) {
 
                println("private " + intface + " mainObj;");
-               println("private int objectId = 0;");
+               Integer objId = mapIntfaceObjId.get(intface);
+               println("private int objectId = " + objId + ";");
                println("// Communications and synchronizations");
                println("private IoTRMIComm rmiComm;");
                println("private AtomicBoolean didAlreadyInitWaitInvoke;");
@@ -1227,7 +1276,6 @@ public class IoTCompiler {
                println("rmiComm = new IoTRMICommServer(_portSend, _portRecv);");
                // Generate permission control initialization
                writeConstructorJavaPermission(intface);
-               //writeJavaInitCallbackPermission(intface, intDecl, callbackExist);
                writeStructPermissionJavaSkeleton(methods, intDecl, intface);
                println("IoTRMIUtil.mapSkel.put(_mainObj, this);");
                println("IoTRMIUtil.mapSkelId.put(_mainObj, objectId);");
@@ -1294,8 +1342,7 @@ public class IoTCompiler {
        /**
         * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class
         */
-       private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, 
-                       boolean callbackSkeleton, String intface) {
+       private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
 
                for (String method : methods) {
 
@@ -1303,16 +1350,10 @@ public class IoTCompiler {
                        List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
                        String methodId = intDecl.getMethodId(method);
                        print("public " + intDecl.getMethodType(method) + " " + methodId + "(");
-                       boolean isCallbackMethod = false;
-                       String callbackType = null;
                        for (int i = 0; i < methParams.size(); i++) {
 
                                String origParamType = methPrmTypes.get(i);
                                String paramType = checkAndGetParamClass(origParamType);
-                               if (callbackClasses.contains(origParamType)) { // Check if this has callback object
-                                       isCallbackMethod = true;
-                                       callbackType = origParamType;   
-                               }
                                print(paramType + " " + methParams.get(i));
                                // Check if this is the last element (don't print a comma)
                                if (i != methParams.size() - 1) {
@@ -1330,18 +1371,17 @@ public class IoTCompiler {
        /**
         * HELPER: writeCallbackInstantiationJavaStubGeneration() writes the instantiation of callback stubs
         */
-       private void writeCallbackInstantiationJavaStubGeneration(String exchParamType) {
+       private void writeCallbackInstantiationJavaStubGeneration(String exchParamType, int counter) {
 
-               //println("int objIdRecv = (int[]) paramObj[0];");
-               println(exchParamType + " newStub = null;");
-               println("if(!IoTRMIUtil.mapStub.containsKey(objIdRecv)) {");
-               println("newStub = new " + exchParamType + "_Stub(rmiComm, objIdRecv);");
-               println("IoTRMIUtil.mapStub.put(objIdRecv, newStub);");
-               println("rmiComm.setObjectIdCounter(objIdRecv);");
+               println(exchParamType + " newStub" + counter + " = null;");
+               println("if(!IoTRMIUtil.mapStub.containsKey(objIdRecv" + counter + ")) {");
+               println("newStub" + counter + " = new " + exchParamType + "_Stub(rmiComm, objIdRecv" + counter + ");");
+               println("IoTRMIUtil.mapStub.put(objIdRecv" + counter + ", newStub" + counter + ");");
+               println("rmiComm.setObjectIdCounter(objIdRecv" + counter + ");");
                println("rmiComm.decrementObjectIdCounter();");
                println("}");
                println("else {");
-               println("newStub = (" + exchParamType + "_Stub) IoTRMIUtil.mapStub.get(objIdRecv);");
+               println("newStub" + counter + " = (" + exchParamType + "_Stub) IoTRMIUtil.mapStub.get(objIdRecv" + counter + ");");
                println("}");
        }
 
@@ -1350,7 +1390,7 @@ public class IoTCompiler {
         * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part
         */
        private Map<Integer,String> writeCallbackJavaStubGeneration(List<String> methParams, List<String> methPrmTypes, 
-                       String callbackType, boolean isStructMethod) {
+                       Set<String> callbackType, boolean isStructMethod) {
 
                Map<Integer,String> mapStubParam = new HashMap<Integer,String>();
                String offsetPfx = "";
@@ -1371,8 +1411,8 @@ public class IoTCompiler {
                                        println("int numStubs" + i + " = stubIdArray" + i + ".length;");
                                        println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();");
                                } else {
-                                       println("int objIdRecv = stubIdArray" + i + "[0];");
-                                       writeCallbackInstantiationJavaStubGeneration(exchParamType);
+                                       println("int objIdRecv" + i + " = stubIdArray" + i + "[0];");
+                                       writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
                                }
                        }
                        // Generate a loop if needed
@@ -1380,18 +1420,18 @@ public class IoTCompiler {
                                String exchParamType = checkAndGetParamClass(getGenericType(paramType));
                                if (isArray(param)) {
                                        println("for (int i = 0; i < numStubs" + i + "; i++) {");
-                                       println("int objIdRecv = stubIdArray" + i + "[i];");
-                                       writeCallbackInstantiationJavaStubGeneration(exchParamType);
-                                       println("stub" + i + "[i] = newStub;");
+                                       println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
+                                       writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
+                                       println("stub" + i + "[i] = newStub" + i + ";");
                                        println("}");
                                } else if (isList(paramType)) {
                                        println("for (int i = 0; i < numStubs" + i + "; i++) {");
-                                       println("int objIdRecv = stubIdArray" + i + "[i];");
-                                       writeCallbackInstantiationJavaStubGeneration(exchParamType);
-                                       println("stub" + i + ".add(newStub);");
+                                       println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
+                                       writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
+                                       println("stub" + i + ".add(newStub" + i + ");");
                                        println("}");
                                } else
-                                       println(exchParamType + " stub" + i + " = newStub;");
+                                       println(exchParamType + " stub" + i + " = newStub" + i + ";");
                                mapStubParam.put(i, "stub" + i);        // List of all stub parameters
                        }
                }
@@ -1675,7 +1715,7 @@ public class IoTCompiler {
         * HELPER: writeMethodHelperReturnJavaSkeleton() writes return statement part in skeleton
         */
        private void writeMethodHelperReturnJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
-                       List<String> methPrmTypes, String method, boolean isCallbackMethod, String callbackType,
+                       List<String> methPrmTypes, String method, boolean isCallbackMethod, Set<String> callbackType,
                        boolean isStructMethod) {
 
                checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes, isStructMethod);
@@ -1743,7 +1783,7 @@ public class IoTCompiler {
 
                // Generate array of parameter objects
                boolean isCallbackMethod = false;
-               String callbackType = null;
+               Set<String> callbackType = new HashSet<String>();
                println("byte[] localMethodBytes = methodBytes;");
                println("rmiComm.setGetMethodBytes();");
                print("int paramLen = ");
@@ -1763,7 +1803,8 @@ public class IoTCompiler {
                                String prmType = returnGenericCallbackType(methPrmTypes.get(i));
                                if (callbackClasses.contains(prmType)) {
                                        isCallbackMethod = true;
-                                       callbackType = prmType;
+                                       //callbackType = prmType;
+                                       callbackType.add(prmType);
                                        println("paramCls[pos] = int[].class;");
                                        println("paramClsGen[pos++] = null;");
                                } else {        // Generate normal classes if it's not a callback object
@@ -1793,7 +1834,7 @@ public class IoTCompiler {
 
                // Generate array of parameter objects
                boolean isCallbackMethod = false;
-               String callbackType = null;
+               Set<String> callbackType = new HashSet<String>();
                println("byte[] localMethodBytes = methodBytes;");
                println("rmiComm.setGetMethodBytes();");
                print("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { ");
@@ -1802,7 +1843,7 @@ public class IoTCompiler {
                        String paramType = returnGenericCallbackType(methPrmTypes.get(i));
                        if (callbackClasses.contains(paramType)) {
                                isCallbackMethod = true;
-                               callbackType = paramType;
+                               callbackType.add(paramType);
                                print("int[].class");
                        } else {        // Generate normal classes if it's not a callback object
                                String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
@@ -1811,7 +1852,6 @@ public class IoTCompiler {
                        if (i != methParams.size() - 1)
                                print(", ");
                }
-               //println(" }, ");
                // Generate generic class if it's a generic type.. null otherwise
                print(" }, new Class<?>[] { ");
                for (int i = 0; i < methParams.size(); i++) {
@@ -2253,41 +2293,59 @@ public class IoTCompiler {
                // Create a new directory
                String path = createDirectories(dir, subdir);
                for (String intface : mapIntfacePTH.keySet()) {
-                       // Open a new file to write into
-                       String newSkelClass = intface + "_Skeleton";
-                       FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
-                       pw = new PrintWriter(new BufferedWriter(fw));
-                       // Pass in set of methods and get import classes
-                       DeclarationHandler decHandler = mapIntDeclHand.get(intface);
-                       InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
-                       List<String> methods = intDecl.getMethods();
-                       Set<String> importClasses = getImportClasses(methods, intDecl);
-                       List<String> stdImportClasses = getStandardJavaImportClasses();
-                       List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
-                       printImportStatements(allImportClasses);
-                       // Find out if there are callback objects
-                       Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
-                       boolean callbackExist = !callbackClasses.isEmpty();
-                       // Write class header
-                       println("");
-                       println("public class " + newSkelClass  + " implements " + intface + " {\n");
-                       // Write properties
-                       writePropertiesJavaSkeleton(intface, intDecl);
-                       // Write constructor
-                       writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
-                       // Write constructor that is called when this object is a callback object
-                       writeCallbackConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
-                       // Write function to return didAlreadyInitWaitInvoke
-                       writeReturnDidAlreadyInitWaitInvoke();
-                       // Write methods
-                       writeMethodJavaSkeleton(methods, intDecl, callbackClasses, false, intface);
-                       // Write method helper
-                       writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
-                       // Write waitRequestInvokeMethod() - main loop
-                       writeJavaWaitRequestInvokeMethod(methods, intDecl, intface);
-                       println("}");
-                       pw.close();
-                       System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
+               
+                       // Check if there is more than 1 class that uses the same interface
+                       List<String> drvList = mapInt2Drv.get(intface);
+                       for(int i = 0; i < drvList.size(); i++) {
+
+                               // Get driver class
+                               String driverClass = drvList.get(i);
+                               // Open a new file to write into
+                               String newSkelClass = intface + "_Skeleton";
+                               String packageClass = null;
+                               // Check if this interface is a callback class
+                               if(isCallbackClass(intface)) {
+                                       packageClass = controllerClass;
+                                       path = createDirectories(dir + "/" + subdir + "/" + CONTROLLER_DIRECTORY, controllerClass);
+                               } else {
+                                       packageClass = CODE_PREFIX + "." + driverClass;
+                                       path = createDirectories(dir + "/" + subdir + "/" + DRIVERS_DIRECTORY, driverClass);
+                               }
+                               FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
+                               pw = new PrintWriter(new BufferedWriter(fw));
+                               // Pass in set of methods and get import classes
+                               DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                               InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                               List<String> methods = intDecl.getMethods();
+                               Set<String> importClasses = getImportClasses(methods, intDecl);
+                               List<String> stdImportClasses = getStandardJavaImportClasses();
+                               List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
+                               // Find out if there are callback objects
+                               Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
+                               boolean callbackExist = !callbackClasses.isEmpty();
+                               println("package " + packageClass + ";\n");
+                               printImportStatements(allImportClasses);
+                               println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
+                               // Write class header
+                               println("public class " + newSkelClass  + " implements " + intface + " {\n");
+                               // Write properties
+                               writePropertiesJavaSkeleton(intface, intDecl);
+                               // Write constructor
+                               writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
+                               // Write constructor that is called when this object is a callback object
+                               writeCallbackConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
+                               // Write function to return didAlreadyInitWaitInvoke
+                               writeReturnDidAlreadyInitWaitInvoke();
+                               // Write methods
+                               writeMethodJavaSkeleton(methods, intDecl);
+                               // Write method helper
+                               writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
+                               // Write waitRequestInvokeMethod() - main loop
+                               writeJavaWaitRequestInvokeMethod(methods, intDecl, intface);
+                               println("}");
+                               pw.close();
+                               System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
+                       }
                }
        }
 
@@ -2363,6 +2421,7 @@ public class IoTCompiler {
 
                // Create a new directory
                createDirectory(dir);
+               String path = createDirectories(dir, VIRTUALS_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
                        // Get the right StructDecl
                        DeclarationHandler decHandler = mapIntDeclHand.get(intface);
@@ -2371,7 +2430,7 @@ public class IoTCompiler {
                        // Iterate over enum declarations
                        for (String enType : enumTypes) {
                                // Open a new file to write into
-                               FileWriter fw = new FileWriter(dir + "/" + enType + ".hpp");
+                               FileWriter fw = new FileWriter(path + "/" + enType + ".hpp");
                                pw = new PrintWriter(new BufferedWriter(fw));
                                // Write file headers
                                println("#ifndef _" + enType.toUpperCase() + "_HPP__");
@@ -2404,6 +2463,7 @@ public class IoTCompiler {
 
                // Create a new directory
                createDirectory(dir);
+               String path = createDirectories(dir, VIRTUALS_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
                        // Get the right StructDecl
                        DeclarationHandler decHandler = mapIntDeclHand.get(intface);
@@ -2412,7 +2472,7 @@ public class IoTCompiler {
                        // Iterate over enum declarations
                        for (String stType : structTypes) {
                                // Open a new file to write into
-                               FileWriter fw = new FileWriter(dir + "/" + stType + ".hpp");
+                               FileWriter fw = new FileWriter(path + "/" + stType + ".hpp");
                                pw = new PrintWriter(new BufferedWriter(fw));
                                // Write file headers
                                println("#ifndef _" + stType.toUpperCase() + "_HPP__");
@@ -2450,9 +2510,10 @@ public class IoTCompiler {
 
                // Create a new directory
                createDirectory(dir);
+               String path = createDirectories(dir, VIRTUALS_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
                        // Open a new file to write into
-                       FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
+                       FileWriter fw = new FileWriter(path + "/" + intface + ".hpp");
                        pw = new PrintWriter(new BufferedWriter(fw));
                        // Write file headers
                        println("#ifndef _" + intface.toUpperCase() + "_HPP__");
@@ -2516,6 +2577,7 @@ public class IoTCompiler {
 
                // Create a new directory
                String path = createDirectories(dir, subdir);
+               path = createDirectories(dir + "/" + subdir, VIRTUALS_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
 
                        Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
@@ -2556,7 +2618,7 @@ public class IoTCompiler {
        /**
         * HELPER: writeMethodDeclCplusStub() writes the method declarations of the stub
         */
-       private void writeMethodDeclCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
+       private void writeMethodDeclCplusStub(Collection<String> methods, InterfaceDecl intDecl) {
 
                for (String method : methods) {
 
@@ -2564,17 +2626,9 @@ public class IoTCompiler {
                        List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
                        print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
                                intDecl.getMethodId(method) + "(");
-                       boolean isCallbackMethod = false;
-                       String callbackType = null;
                        for (int i = 0; i < methParams.size(); i++) {
 
                                String paramType = returnGenericCallbackType(methPrmTypes.get(i));
-                               // Check if this has callback object
-                               if (callbackClasses.contains(paramType)) {
-                                       isCallbackMethod = true;
-                                       callbackType = paramType;       
-                                       // Even if there're 2 callback arguments, we expect them to be of the same interface
-                               }
                                String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
                                String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
                                print(methParamComplete);
@@ -2604,14 +2658,15 @@ public class IoTCompiler {
                        print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " + newStubClass + "::" +
                                intDecl.getMethodId(method) + "(");
                        boolean isCallbackMethod = false;
-                       String callbackType = null;
+                       Set<String> callbackType = new HashSet<String>();
                        for (int i = 0; i < methParams.size(); i++) {
 
                                String paramType = returnGenericCallbackType(methPrmTypes.get(i));
                                // Check if this has callback object
                                if (callbackClasses.contains(paramType)) {
                                        isCallbackMethod = true;
-                                       callbackType = paramType;       
+                                       //callbackType = paramType;
+                                       callbackType.add(paramType);
                                        // Even if there're 2 callback arguments, we expect them to be of the same interface
                                }
                                String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
@@ -2638,23 +2693,23 @@ public class IoTCompiler {
         */
        private void writeCallbackInstantiationMethodBodyCplusStub(String paramIdent, String callbackType, int counter) {
 
-               println("auto it = IoTRMIUtil::mapSkel->find(" + paramIdent + ");");
-               println("if (it == IoTRMIUtil::mapSkel->end()) {");
+               println("auto it" + counter + " = IoTRMIUtil::mapSkel->find(" + paramIdent + ");");
+               println("if (it" + counter + " == IoTRMIUtil::mapSkel->end()) {");
                println("int newObjIdSent = rmiComm->getObjectIdCounter();");
-               println("objIdSent.push_back(newObjIdSent);");
+               println("objIdSent" + counter + ".push_back(newObjIdSent);");
                println("rmiComm->decrementObjectIdCounter();");
                println(callbackType + "_Skeleton* skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
-               println("vecCallbackObj.push_back(skel0);");
-               println("IoTRMIUtil::mapSkel->insert(make_pair(" + paramIdent + ", skel0));");
+               println("IoTRMIUtil::mapSkel->insert(make_pair(" + paramIdent + ", skel" + counter + "));");
                println("IoTRMIUtil::mapSkelId->insert(make_pair(" + paramIdent + ", newObjIdSent));");
-               println("thread th0 (&" + callbackType + "_Skeleton::___waitRequestInvokeMethod, std::ref(skel0), std::ref(skel0));");
-               println("th0.detach();");
+               println("thread th" + counter + " (&" + callbackType + "_Skeleton::___waitRequestInvokeMethod, skel" + counter + 
+                       ", skel" + counter +");");
+               println("th" + counter + ".detach();");
                println("while(!skel" + counter + "->didInitWaitInvoke());");
                println("}");
                println("else");
                println("{");
                println("auto itId = IoTRMIUtil::mapSkelId->find(" + paramIdent + ");");
-               println("objIdSent.push_back(itId->second);");
+               println("objIdSent" + counter + ".push_back(itId->second);");
                println("}");
        }
 
@@ -2663,28 +2718,27 @@ public class IoTCompiler {
         * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class
         */
        private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
-                       List<String> methPrmTypes, String method, String callbackType) {
+                       List<String> methPrmTypes, String method, Set<String> callbackType) {
 
                // Check if this is single object, array, or list of objects
                boolean isArrayOrList = false;
                String callbackParam = null;
-               println("vector<int> objIdSent;");
                for (int i = 0; i < methParams.size(); i++) {
-
                        String paramType = methPrmTypes.get(i);
                        if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
+                               println("vector<int> objIdSent" + i + ";");
                                String param = methParams.get(i);
                                if (isArrayOrList(paramType, param)) {  // Generate loop                                
                                        println("for (" + getGenericType(paramType) + "* cb : " + getSimpleIdentifier(param) + ") {");
-                                       writeCallbackInstantiationMethodBodyCplusStub("cb", callbackType, i);
+                                       writeCallbackInstantiationMethodBodyCplusStub("cb", returnGenericCallbackType(paramType), i);
                                        isArrayOrList = true;
                                        callbackParam = getSimpleIdentifier(param);
                                } else {
-                                       writeCallbackInstantiationMethodBodyCplusStub(getSimpleIdentifier(param), callbackType, i);
+                                       writeCallbackInstantiationMethodBodyCplusStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i);
                                }
                                if (isArrayOrList)
                                        println("}");
-                               println("vector<int> ___paramCB" + i + " = objIdSent;");
+                               println("vector<int> ___paramCB" + i + " = objIdSent" + i + ";");
                        }
                }
        }
@@ -2772,7 +2826,6 @@ public class IoTCompiler {
                                        println("1;");
                                }
                                println("void* paramObjStruct" + i + "[] = { &structLen" + i + " };");
-                               //println("void* retStructLen" + i + " = NULL;");
                                println("rmiComm->remoteCall(objectId, methodIdStruct" + i + 
                                                ", paramClsStruct" + i + ", paramObjStruct" + i + 
                                                ", numParam" + i + ");\n");
@@ -2843,7 +2896,7 @@ public class IoTCompiler {
        /**
         * HELPER: writeStructParamClassCplusStub() writes member parameters of struct
         */
-       private void writeStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes, String callbackType) {
+       private void writeStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
 
                print("int numParam = ");
                writeLengthStructParamClassCplusStub(methParams, methPrmTypes);
@@ -2952,7 +3005,6 @@ public class IoTCompiler {
                                println("retObj[retPos++] = &retParam" + i + ";");
                        }
                }
-               //println("rmiComm->getStructObjects(retCls, numRet, retObj);");
                writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getStructObjects(retCls, numRet, retObj);");
                if (isArrayOrList(retType, retType)) {  // An array or list
                        println("vector<" + simpleType + "> structRet(retLen);");
@@ -2980,7 +3032,7 @@ public class IoTCompiler {
         * HELPER: writeStdMethodBodyCplusStub() writes the standard method body in the stub class
         */
        private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
-                       List<String> methPrmTypes, String method, String callbackType, boolean isCallbackMethod) {
+                       List<String> methPrmTypes, String method, Set<String> callbackType, boolean isCallbackMethod) {
 
                checkAndWriteStructSetupCplusStub(methParams, methPrmTypes, intDecl, method);
                println("int methodId = " + intDecl.getMethodNumId(method) + ";");
@@ -3059,7 +3111,6 @@ public class IoTCompiler {
                for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
                        String newIntface = intMeth.getKey();
                        int newObjectId = getNewIntfaceObjectId(newIntface);
-                       println("int objectId = " + newObjectId + ";");
                        println("static set<int> set" + newObjectId + "Allowed;");
                }
        }       
@@ -3074,13 +3125,6 @@ public class IoTCompiler {
                // Get the object Id
                Integer objId = mapIntfaceObjId.get(intface);
                println("int objectId = " + objId + ";");
-               if (callbackExist) {
-               // We assume that each class only has one callback interface for now
-                       Iterator it = callbackClasses.iterator();
-                       String callbackType = (String) it.next();
-                       println("// Callback properties");
-                       println("vector<" + callbackType + "*> vecCallbackObj;");
-               }
                println("// Synchronization variables");
                for (String method : methods) {
                        // Generate AtomicBooleans for methods that have return values
@@ -3149,39 +3193,11 @@ public class IoTCompiler {
                println("delete rmiComm;");
                println("rmiComm = NULL;");
                println("}");
-               if (callbackExist) {
-               // We assume that each class only has one callback interface for now
-                       Iterator it = callbackClasses.iterator();
-                       String callbackType = (String) it.next();
-                       println("for(" + callbackType + "* cb : vecCallbackObj) {");
-                       println("delete cb;");
-                       println("cb = NULL;");
-                       println("}");
-               }
                println("}");
                println("");
        }
 
 
-       /**
-        * HELPER: writeCplusMethodCallbackPermission() writes permission checks in stub for callbacks
-        */
-       private void writeCplusMethodCallbackPermission(String intface) {
-
-               println("int methodId = IoTRMIObject::getMethodId(method);");
-               // Get all the different stubs
-               Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
-               for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
-                       String newIntface = intMeth.getKey();
-                       int newObjectId = getNewIntfaceObjectId(newIntface);
-                       println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
-                       println("cerr << \"Callback object for " + intface + " is not allowed to access method: \" << methodId;");
-                       println("return;");
-                       println("}");
-               }
-       }
-
-
        /**
         * generateCPlusStubClassesHpp() generate stubs based on the methods list in C++ (.hpp file)
         */
@@ -3191,45 +3207,56 @@ public class IoTCompiler {
                String path = createDirectories(dir, subdir);
                for (String intface : mapIntfacePTH.keySet()) {
 
-                       Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
-                       for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
-                               // Open a new file to write into
-                               String newIntface = intMeth.getKey();
-                               String newStubClass = newIntface + "_Stub";
-                               FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
-                               pw = new PrintWriter(new BufferedWriter(fw));
-                               // Write file headers
-                               println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
-                               println("#define _" + newStubClass.toUpperCase() + "_HPP__");
-                               println("#include <iostream>");
-                               // Find out if there are callback objects
-                               Set<String> methods = intMeth.getValue();
-                               DeclarationHandler decHandler = mapIntDeclHand.get(intface);
-                               InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
-                               Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
-                               boolean callbackExist = !callbackClasses.isEmpty();
-                               println("#include <thread>");
-                               println("#include <mutex>");
-                               List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
-                               printIncludeStatements(stdIncludeClasses); println("");
-                               println("#include \"" + newIntface + ".hpp\""); println("");            
-                               println("using namespace std;"); println("");
-                               println("class " + newStubClass + " : public " + newIntface); println("{");
-                               println("private:\n");
-                               writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses, methods, intDecl);
-                               println("public:\n");
-                               // Add default constructor and destructor
-                               println(newStubClass + "();");
-                               // Declarations
-                               println(newStubClass + "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult);");
-                               println(newStubClass + "(IoTRMIComm* _rmiComm, int _objectId);");
-                               println("~" + newStubClass + "();");
-                               // Write methods
-                               writeMethodDeclCplusStub(methods, intDecl, callbackClasses, newStubClass);
-                               print("}"); println(";");
-                               println("#endif");
-                               pw.close();
-                               System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
+                       // Check if there is more than 1 class that uses the same interface
+                       List<String> drvList = mapInt2Drv.get(intface);
+                       for(int i = 0; i < drvList.size(); i++) {
+
+                               String driverClass = drvList.get(i);
+                               Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+                               for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+                                       // Open a new file to write into
+                                       String newIntface = intMeth.getKey();
+                                       String newStubClass = newIntface + "_Stub";
+                                       // Check if this interface is a callback class
+                                       if(isCallbackClass(intface))
+                                               path = createDirectories(dir + "/" + subdir + "/" + DRIVERS_DIRECTORY, driverClass);
+                                       else
+                                               path = createDirectories(dir + "/" + subdir + "/" + CONTROLLER_DIRECTORY, controllerClass);
+                                       FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
+                                       pw = new PrintWriter(new BufferedWriter(fw));
+                                       // Write file headers
+                                       println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
+                                       println("#define _" + newStubClass.toUpperCase() + "_HPP__");
+                                       println("#include <iostream>");
+                                       // Find out if there are callback objects
+                                       Set<String> methods = intMeth.getValue();
+                                       DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                                       InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                                       Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
+                                       boolean callbackExist = !callbackClasses.isEmpty();
+                                       println("#include <thread>");
+                                       println("#include <mutex>");
+                                       List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
+                                       printIncludeStatements(stdIncludeClasses); println("");
+                                       println("#include \"" + newIntface + ".hpp\""); println("");            
+                                       println("using namespace std;"); println("");
+                                       println("class " + newStubClass + " : public " + newIntface); println("{");
+                                       println("private:\n");
+                                       writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses, methods, intDecl);
+                                       println("public:\n");
+                                       // Add default constructor and destructor
+                                       println(newStubClass + "();");
+                                       // Declarations
+                                       println(newStubClass + "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult);");
+                                       println(newStubClass + "(IoTRMIComm* _rmiComm, int _objectId);");
+                                       println("~" + newStubClass + "();");
+                                       // Write methods
+                                       writeMethodDeclCplusStub(methods, intDecl);
+                                       print("}"); println(";");
+                                       println("#endif");
+                                       pw.close();
+                                       System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
+                               }
                        }
                }
        }
@@ -3249,11 +3276,8 @@ public class IoTCompiler {
                println(newStubClass + "* obj = (" + newStubClass + "*) t;");
                println("delete obj;");
                println("}\n");
-               //println("extern \"C\" void init" + newStubClass + "(void* t) {");
-               //println(newStubClass + "* obj = (" + newStubClass + "*) t;");
-               //println("obj->init();");
-               //println("while(true);");
-               //println("}\n");
+               println("extern \"C\" void init" + newStubClass + "(void* t) {");
+               println("}\n");
        }
 
 
@@ -3266,46 +3290,56 @@ public class IoTCompiler {
                String path = createDirectories(dir, subdir);
                for (String intface : mapIntfacePTH.keySet()) {
 
-                       Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
-                       for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
-                               // Open a new file to write into
-                               String newIntface = intMeth.getKey();
-                               String newStubClass = newIntface + "_Stub";
-                               FileWriter fw = new FileWriter(path + "/" + newStubClass + ".cpp");
-                               pw = new PrintWriter(new BufferedWriter(fw));
-                               // Write file headers
-                               println("#include <iostream>");
-                               // Find out if there are callback objects
-                               Set<String> methods = intMeth.getValue();
-                               DeclarationHandler decHandler = mapIntDeclHand.get(intface);
-                               InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
-                               Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
-                               boolean callbackExist = !callbackClasses.isEmpty();
-                               println("#include \"" + newStubClass + ".hpp\""); println("");
-                               for(String str: callbackClasses) {
-                                       if (intface.equals(mainClass))
-                                               println("#include \"" + str + "_Skeleton.cpp\"\n");
+                       // Check if there is more than 1 class that uses the same interface
+                       List<String> drvList = mapInt2Drv.get(intface);
+                       for(int i = 0; i < drvList.size(); i++) {
+
+                               String driverClass = drvList.get(i);
+                               Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+                               for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+                                       // Open a new file to write into
+                                       String newIntface = intMeth.getKey();
+                                       String newStubClass = newIntface + "_Stub";
+                                       // Check if this interface is a callback class
+                                       if(isCallbackClass(intface))
+                                               path = createDirectories(dir + "/" + subdir + "/" + DRIVERS_DIRECTORY, driverClass);
                                        else
-                                               println("#include \"" + str + "_Skeleton.hpp\"\n");
-                               }
-                               println("using namespace std;"); println("");
-                               // Add default constructor and destructor
-                               //println(newStubClass + "() { }"); println("");
-                               writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
-                               writeCallbackConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
-                               writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
-                               // Write methods
-                               writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass);
-                               // Write external functions for .so file
-                               writeStubExternalCFunctions(newStubClass);
-                               // TODO: Remove this later
-                               if (intface.equals(mainClass)) {
-                                       println("int main() {");
-                                       println("return 0;");
-                                       println("}");
+                                               path = createDirectories(dir + "/" + subdir + "/" + CONTROLLER_DIRECTORY, controllerClass);
+                                       FileWriter fw = new FileWriter(path + "/" + newStubClass + ".cpp");
+                                       pw = new PrintWriter(new BufferedWriter(fw));
+                                       // Write file headers
+                                       println("#include <iostream>");
+                                       // Find out if there are callback objects
+                                       Set<String> methods = intMeth.getValue();
+                                       DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                                       InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                                       Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
+                                       boolean callbackExist = !callbackClasses.isEmpty();
+                                       println("#include \"" + newStubClass + ".hpp\""); println("");
+                                       for(String str: callbackClasses) {
+                                               if (intface.equals(mainClass))
+                                                       println("#include \"" + str + "_Skeleton.cpp\"\n");
+                                               else
+                                                       println("#include \"" + str + "_Skeleton.hpp\"\n");
+                                       }
+                                       println("using namespace std;"); println("");
+                                       // Add default constructor and destructor
+                                       writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
+                                       writeCallbackConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
+                                       writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
+                                       // Write methods
+                                       writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass);
+                                       // Write external functions for .so file
+                                       writeStubExternalCFunctions(newStubClass);
+                                       // TODO: Remove this later
+                                       if (intface.equals(mainClass)) {
+                                               println("int main() {");
+                                               println("return 0;");
+                                               println("}");
+                                       }
+                                       pw.close();
+                                       System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".cpp...");
                                }
-                               pw.close();
-                               System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".cpp...");
                        }
                }
        }
@@ -3317,17 +3351,11 @@ public class IoTCompiler {
        private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
 
                println(intface + " *mainObj;");
-               // Callback
-               if (callbackExist) {
-                       Iterator it = callbackClasses.iterator();
-                       String callbackType = (String) it.next();
-                       String exchangeType = checkAndGetParamClass(callbackType);
-                       println("// Callback properties");
-                       println("vector<" + exchangeType + "*> vecCallbackObj;");
-               }
                println("IoTRMIComm *rmiComm;");
                println("char* methodBytes;");
                println("int methodLen;");
+               Integer objId = mapIntfaceObjId.get(intface);
+               println("int objectId = " + objId + ";");
                // Keep track of object Ids of all stubs registered to this interface
                writePropertiesCplusPermission(intface);
                println("// Synchronization variables");
@@ -3450,16 +3478,6 @@ public class IoTCompiler {
                println("delete rmiComm;");
                println("rmiComm = NULL;");
                println("}");
-               if (callbackExist) {
-               // We assume that each class only has one callback interface for now
-                       Iterator it = callbackClasses.iterator();
-                       String callbackType = (String) it.next();
-                       String exchangeType = checkAndGetParamClass(callbackType);
-                       println("for(" + exchangeType + "* cb : vecCallbackObj) {");
-                       println("delete cb;");
-                       println("cb = NULL;");
-                       println("}");
-               }
                println("}");
                println("");
        }
@@ -3525,8 +3543,7 @@ public class IoTCompiler {
        /**
         * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class
         */
-       private void writeMethodCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, 
-                       Set<String> callbackClasses, boolean callbackSkeleton, String intface, String newSkelClass) {
+       private void writeMethodCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String newSkelClass) {
 
                for (String method : methods) {
 
@@ -3535,15 +3552,9 @@ public class IoTCompiler {
                        String methodId = intDecl.getMethodId(method);
                        String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
                        print(methodType + " " + newSkelClass + "::" + methodId + "(");
-                       boolean isCallbackMethod = false;
-                       String callbackType = null;
                        for (int i = 0; i < methParams.size(); i++) {
 
                                String origParamType = methPrmTypes.get(i);
-                               if (callbackClasses.contains(origParamType)) { // Check if this has callback object
-                                       isCallbackMethod = true;
-                                       callbackType = origParamType;   
-                               }
                                String paramType = checkAndGetParamClass(methPrmTypes.get(i));
                                String methPrmType = checkAndGetCplusType(paramType);
                                String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
@@ -3564,14 +3575,12 @@ public class IoTCompiler {
        /**
         * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable
         */
-       private void writeCallbackCplusNumStubs(List<String> methParams, List<String> methPrmTypes, String callbackType) {
+       private void writeCallbackCplusNumStubs(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
 
                for (int i = 0; i < methParams.size(); i++) {
                        String paramType = methPrmTypes.get(i);
                        String param = methParams.get(i);
-                       //if (callbackType.equals(paramType)) {
                        if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
-                               //println("int numStubs" + i + " = 0;");
                                println("vector<int> numStubIdArray" + i + ";");
                }
        }
@@ -3580,20 +3589,18 @@ public class IoTCompiler {
        /**
         * HELPER: writeCallbackInstantiationCplusStubGeneration() writes the instantiation of callback stubs
         */
-       private void writeCallbackInstantiationCplusStubGeneration(String exchParamType) {
+       private void writeCallbackInstantiationCplusStubGeneration(String exchParamType, int counter) {
 
-               //println("int objIdRecv = (int[]) paramObj[0];");
-               println(exchParamType + "* newStub = NULL;");
-               println("auto it = IoTRMIUtil::mapStub->find(objIdRecv);");
-               println("if (it == IoTRMIUtil::mapStub->end()) {");
-               println("newStub = new " + exchParamType + "_Stub(rmiComm, objIdRecv);");
-               println("IoTRMIUtil::mapStub->insert(make_pair(objIdRecv, newStub));");
-               println("rmiComm->setObjectIdCounter(objIdRecv);");
+               println(exchParamType + "* newStub" + counter + " = NULL;");
+               println("auto it" + counter + " = IoTRMIUtil::mapStub->find(objIdRecv" + counter + ");");
+               println("if (it" + counter + " == IoTRMIUtil::mapStub->end()) {");
+               println("newStub" + counter + " = new " + exchParamType + "_Stub(rmiComm, objIdRecv" + counter + ");");
+               println("IoTRMIUtil::mapStub->insert(make_pair(objIdRecv" + counter + ", newStub" + counter + "));");
+               println("rmiComm->setObjectIdCounter(objIdRecv" + counter + ");");
                println("rmiComm->decrementObjectIdCounter();");
-               println("skel->vecCallbackObj.push_back(newStub);");
                println("}");
                println("else {");
-               println("newStub = (" + exchParamType + "_Stub*) it->second;");
+               println("newStub" + counter + " = (" + exchParamType + "_Stub*) it" + counter + "->second;");
                println("}");
        }
 
@@ -3601,7 +3608,7 @@ public class IoTCompiler {
        /**
         * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part
         */
-       private void writeCallbackCplusStubGeneration(List<String> methParams, List<String> methPrmTypes, String callbackType) {
+       private void writeCallbackCplusStubGeneration(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
 
                // Iterate over callback objects
                for (int i = 0; i < methParams.size(); i++) {
@@ -3613,14 +3620,14 @@ public class IoTCompiler {
                                if (isArrayOrList(paramType, param)) {
                                        println("vector<" + exchParamType + "*> stub" + i + ";");
                                        println("for (int i = 0; i < numStubIdArray" + i + ".size(); i++) {");
-                                       println("int objIdRecv = numStubIdArray" + i + "[i];");
-                                       writeCallbackInstantiationCplusStubGeneration(exchParamType);
-                                       println("stub" + i + ".push_back(newStub);");
+                                       println("int objIdRecv" + i + " = numStubIdArray" + i + "[i];");
+                                       writeCallbackInstantiationCplusStubGeneration(exchParamType, i);
+                                       println("stub" + i + ".push_back(newStub" + i + ");");
                                        println("}");
                                } else {
-                                       println("int objIdRecv = numStubIdArray" + i + "[0];");
-                                       writeCallbackInstantiationCplusStubGeneration(exchParamType);
-                                       println(exchParamType + "* stub" + i + " = newStub;");
+                                       println("int objIdRecv" + i + " = numStubIdArray" + i + "[0];");
+                                       writeCallbackInstantiationCplusStubGeneration(exchParamType, i);
+                                       println(exchParamType + "* stub" + i + " = newStub" + i + ";");
                                }
                        }
                }
@@ -3710,7 +3717,7 @@ public class IoTCompiler {
         * HELPER: writeMethodHelperReturnCplusSkeleton() writes the return statement part in skeleton
         */
        private void writeMethodHelperReturnCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
-                       List<String> methPrmTypes, String method, boolean isCallbackMethod, String callbackType,
+                       List<String> methPrmTypes, String method, boolean isCallbackMethod, Set<String> callbackType,
                        String methodId, Set<String> callbackClasses) {
 
                println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
@@ -3756,13 +3763,13 @@ public class IoTCompiler {
 
                // Generate array of parameter types
                boolean isCallbackMethod = false;
-               String callbackType = null;
+               Set<String> callbackType = new HashSet<String>();
                print("string paramCls[] = { ");
                for (int i = 0; i < methParams.size(); i++) {
                        String paramType = returnGenericCallbackType(methPrmTypes.get(i));
                        if (callbackClasses.contains(paramType)) {
                                isCallbackMethod = true;
-                               callbackType = paramType;
+                               callbackType.add(paramType);
                                print("\"int*\"");
                        } else {        // Generate normal classes if it's not a callback object
                                String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
@@ -3950,7 +3957,7 @@ public class IoTCompiler {
 
                // Generate array of parameter objects
                boolean isCallbackMethod = false;
-               String callbackType = null;
+               Set<String> callbackType = new HashSet<String>();
                print("int numParam = ");
                writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
                println(";");
@@ -3968,8 +3975,7 @@ public class IoTCompiler {
                                String prmType = returnGenericCallbackType(methPrmTypes.get(i));
                                if (callbackClasses.contains(prmType)) {
                                        isCallbackMethod = true;
-                                       callbackType = prmType;
-                                       //println("int numStubs" + i + " = 0;");
+                                       callbackType.add(prmType);
                                        println("vector<int> numStubIdArray" + i + ";");
                                        println("paramCls[pos] = \"int*\";");
                                        println("paramObj[pos++] = &numStubIdArray" + i + ";");
@@ -3999,8 +4005,7 @@ public class IoTCompiler {
        /**
         * HELPER: writeMethodHelperDeclCplusSkeleton() writes the method helper declarations of the skeleton class
         */
-       private void writeMethodHelperDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, 
-                       Set<String> callbackClasses, String newSkelClass) {
+       private void writeMethodHelperDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String newSkelClass) {
 
                // Use this set to handle two same methodIds
                Set<String> uniqueMethodIds = new HashSet<String>();
@@ -4283,7 +4288,7 @@ public class IoTCompiler {
                                helperMethod = helperMethod + methodNumId;
                        else
                                uniqueMethodIds.add(methodId);
-                       print(helperMethod + ", std::ref(skel), ");
+                       print(helperMethod + ", skel, ");
                        boolean structExists = writeInputCountVarStructCplusSkeleton(method, intDecl);
                        if (structExists)
                                print(", ");
@@ -4309,49 +4314,62 @@ public class IoTCompiler {
                // Create a new directory
                String path = createDirectories(dir, subdir);
                for (String intface : mapIntfacePTH.keySet()) {
-                       // Open a new file to write into
-                       String newSkelClass = intface + "_Skeleton";
-                       FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
-                       pw = new PrintWriter(new BufferedWriter(fw));
-                       // Write file headers
-                       println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
-                       println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
-                       println("#include <iostream>");
-                       println("#include \"" + intface + ".hpp\"\n");
-                       // Pass in set of methods and get import classes
-                       DeclarationHandler decHandler = mapIntDeclHand.get(intface);
-                       InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
-                       List<String> methods = intDecl.getMethods();
-                       List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
-                       printIncludeStatements(stdIncludeClasses); println("");
-                       println("using namespace std;\n");
-                       // Find out if there are callback objects
-                       Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
-                       boolean callbackExist = !callbackClasses.isEmpty();
-                       // Write class header
-                       println("class " + newSkelClass + " : public " + intface); println("{");
-                       println("private:\n");
-                       // Write properties
-                       writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses);
-                       println("public:\n");
-                       // Write constructors
-                       println(newSkelClass + "();");
-                       println(newSkelClass + "(" + intface + "*_mainObj, int _portSend, int _portRecv);");
-                       println(newSkelClass + "(" + intface + "*_mainObj, IoTRMIComm *rmiComm, int _objectId);");
-                       // Write deconstructor
-                       println("~" + newSkelClass + "();");
-                       // Write method declarations
-                       println("bool didInitWaitInvoke();");
-                       writeMethodDeclCplusSkeleton(methods, intDecl, callbackClasses);
-                       // Write method helper declarations
-                       writeMethodHelperDeclCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass);
-                       // Write waitRequestInvokeMethod() declaration - main loop
-                       println("void ___waitRequestInvokeMethod(" + newSkelClass + "* skel);");
-                       println("};");
-                       writePermissionInitializationCplus(intface, newSkelClass, intDecl);
-                       println("#endif");
-                       pw.close();
-                       System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
+               
+                       // Check if there is more than 1 class that uses the same interface
+                       List<String> drvList = mapInt2Drv.get(intface);
+                       for(int i = 0; i < drvList.size(); i++) {
+
+                               // Open a new file to write into
+                               String newSkelClass = intface + "_Skeleton";
+                               // Get driver class
+                               String driverClass = drvList.get(i);
+                               // Check if this interface is a callback class
+                               if(isCallbackClass(intface))
+                                       path = createDirectories(dir + "/" + subdir + "/" + CONTROLLER_DIRECTORY, controllerClass);
+                               else
+                                       path = createDirectories(dir + "/" + subdir + "/" + DRIVERS_DIRECTORY, driverClass);
+                               FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
+                               pw = new PrintWriter(new BufferedWriter(fw));
+                               // Write file headers
+                               println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
+                               println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
+                               println("#include <iostream>");
+                               println("#include \"" + intface + ".hpp\"\n");
+                               // Pass in set of methods and get import classes
+                               DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                               InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                               List<String> methods = intDecl.getMethods();
+                               List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
+                               printIncludeStatements(stdIncludeClasses); println("");
+                               println("using namespace std;\n");
+                               // Find out if there are callback objects
+                               Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
+                               boolean callbackExist = !callbackClasses.isEmpty();
+                               // Write class header
+                               println("class " + newSkelClass + " : public " + intface); println("{");
+                               println("private:\n");
+                               // Write properties
+                               writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses);
+                               println("public:\n");
+                               // Write constructors
+                               println(newSkelClass + "();");
+                               println(newSkelClass + "(" + intface + "*_mainObj, int _portSend, int _portRecv);");
+                               println(newSkelClass + "(" + intface + "*_mainObj, IoTRMIComm *rmiComm, int _objectId);");
+                               // Write deconstructor
+                               println("~" + newSkelClass + "();");
+                               // Write method declarations
+                               println("bool didInitWaitInvoke();");
+                               writeMethodDeclCplusSkeleton(methods, intDecl, callbackClasses);
+                               // Write method helper declarations
+                               writeMethodHelperDeclCplusSkeleton(methods, intDecl, newSkelClass);
+                               // Write waitRequestInvokeMethod() declaration - main loop
+                               println("void ___waitRequestInvokeMethod(" + newSkelClass + "* skel);");
+                               println("};");
+                               writePermissionInitializationCplus(intface, newSkelClass, intDecl);
+                               println("#endif");
+                               pw.close();
+                               System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
+                       }
                }
        }
 
@@ -4373,17 +4391,14 @@ public class IoTCompiler {
 
                println("extern \"C\" void* create" + newSkelClass + "(void** params) {");
                println("// Args: *_mainObj, int _portSend, int _portRecv");
-               println("return new " + newSkelClass + "((" + intface + "*) params[0], *((int*) params[0]), *((int*) params[1]));");
+               println("return new " + newSkelClass + "((" + intface + "*) params[0], *((int*) params[1]), *((int*) params[2]));");
                println("}\n");
                println("extern \"C\" void destroy" + newSkelClass + "(void* t) {");
                println(newSkelClass + "* obj = (" + newSkelClass + "*) t;");
                println("delete obj;");
                println("}\n");
-               //println("extern \"C\" void init" + newSkelClass + "(void* t) {");
-               //println(newSkelClass + "* obj = (" + newSkelClass + "*) t;");
-               //println("obj->init();");
-               //println("while(true);");
-               //println("}\n");
+               println("extern \"C\" void init" + newSkelClass + "(void* t) {");
+               println("}\n");
        }
 
 
@@ -4395,51 +4410,64 @@ public class IoTCompiler {
                // Create a new directory
                String path = createDirectories(dir, subdir);
                for (String intface : mapIntfacePTH.keySet()) {
-                       // Open a new file to write into
-                       String newSkelClass = intface + "_Skeleton";
-                       FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".cpp");
-                       pw = new PrintWriter(new BufferedWriter(fw));
-                       // Write file headers
-                       println("#include <iostream>");
-                       println("#include \"" + newSkelClass + ".hpp\"\n");
-                       // Pass in set of methods and get import classes
-                       DeclarationHandler decHandler = mapIntDeclHand.get(intface);
-                       InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
-                       List<String> methods = intDecl.getMethods();
-                       // Find out if there are callback objects
-                       Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
-                       boolean callbackExist = !callbackClasses.isEmpty();
-                       for(String str: callbackClasses) {
-                               if (intface.equals(mainClass))
-                                       println("#include \"" + getStubInterface(str) + "_Stub.cpp\"\n");
+
+                       // Check if there is more than 1 class that uses the same interface
+                       List<String> drvList = mapInt2Drv.get(intface);
+                       for(int i = 0; i < drvList.size(); i++) {
+
+                               // Open a new file to write into
+                               String newSkelClass = intface + "_Skeleton";
+                               // Get driver class
+                               String driverClass = drvList.get(i);
+                               // Check if this interface is a callback class
+                               if(isCallbackClass(intface))
+                                       path = createDirectories(dir + "/" + subdir + "/" + CONTROLLER_DIRECTORY, controllerClass);
                                else
-                                       println("#include \"" + getStubInterface(str) + "_Stub.hpp\"\n");
-                       }
-                       println("using namespace std;\n");
-                       // Write constructor
-                       writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
-                       // Write callback constructor
-                       writeCallbackConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
-                       // Write deconstructor
-                       writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses);
-                       // Write didInitWaitInvoke() to return bool
-                       writeReturnDidAlreadyInitWaitInvoke(newSkelClass);
-                       // Write methods
-                       writeMethodCplusSkeleton(methods, intDecl, callbackClasses, false, intface, newSkelClass);
-                       // Write method helper
-                       writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass);
-                       // Write waitRequestInvokeMethod() - main loop
-                       writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface, newSkelClass);
-                       // Write external functions for .so file
-                       writeSkelExternalCFunctions(newSkelClass, intface);
-                       // TODO: Remove this later
-                       if (intface.equals(mainClass)) {
-                               println("int main() {");
-                               println("return 0;");
-                               println("}");
+                                       path = createDirectories(dir + "/" + subdir + "/" + DRIVERS_DIRECTORY, driverClass);
+                               FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".cpp");
+                               pw = new PrintWriter(new BufferedWriter(fw));
+                               // Write file headers
+                               println("#include <iostream>");
+                               println("#include \"" + newSkelClass + ".hpp\"\n");
+                               // Pass in set of methods and get import classes
+                               DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                               InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                               List<String> methods = intDecl.getMethods();
+                               // Find out if there are callback objects
+                               Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
+                               boolean callbackExist = !callbackClasses.isEmpty();
+                               for(String str: callbackClasses) {
+                                       if (intface.equals(mainClass))
+                                               println("#include \"" + getStubInterface(str) + "_Stub.cpp\"\n");
+                                       else
+                                               println("#include \"" + getStubInterface(str) + "_Stub.hpp\"\n");
+                               }
+                               println("using namespace std;\n");
+                               // Write constructor
+                               writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
+                               // Write callback constructor
+                               writeCallbackConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
+                               // Write deconstructor
+                               writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses);
+                               // Write didInitWaitInvoke() to return bool
+                               writeReturnDidAlreadyInitWaitInvoke(newSkelClass);
+                               // Write methods
+                               writeMethodCplusSkeleton(methods, intDecl, newSkelClass);
+                               // Write method helper
+                               writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass);
+                               // Write waitRequestInvokeMethod() - main loop
+                               writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface, newSkelClass);
+                               // Write external functions for .so file
+                               writeSkelExternalCFunctions(newSkelClass, intface);
+                               // TODO: Remove this later
+                               if (intface.equals(mainClass)) {
+                                       println("int main() {");
+                                       println("return 0;");
+                                       println("}");
+                               }
+                               pw.close();
+                               System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".cpp...");
                        }
-                       pw.close();
-                       System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".cpp...");
                }
        }
 
@@ -4489,7 +4517,7 @@ public class IoTCompiler {
        public static void printUsage() {
 
                System.out.println();
-               System.out.println("Sentinel interface and stub compiler version 1.0");
+               System.out.println("Vigilia interface and stub compiler version 1.0");
                System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
                System.out.println("All rights reserved.");
                System.out.println("Usage:");
@@ -4499,8 +4527,14 @@ public class IoTCompiler {
                System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
                System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
                System.out.println("Options:");
-               System.out.println("\t-java\t<directory>\tGenerate Java stub files");
-               System.out.println("\t-cplus\t<directory>\tGenerate C++ stub files");
+               System.out.println("\t-cont\t<controller-class>\tSpecify controller class name");
+               System.out.println("\t-drv\t<driver-class>\t\tSpecify driver class name");
+               System.out.println("\t\t(place this option right after a pair of .pol and .req files)");
+               System.out.println("\t-objid\t<object-id>\t\tSpecify object Id for stub/skeleton used in multiple apps");
+               System.out.println("\t\t(place this option right after -drv option)");
+               System.out.println("\t-cplus\t<directory>\t\tGenerate C++ stub files");
+               System.out.println("\t-java\t<directory>\t\tGenerate Java stub files\n");
+               System.out.println("\t\tNote: The options -cont and -drv have to be defined before -cplus and -java");
                System.out.println();
        }
 
@@ -4637,14 +4671,8 @@ public class IoTCompiler {
        // Basically the compiler needs to parse the policy (and requires) files for callback class first
        private int getNewIntfaceObjectId(String newIntface) {
 
-//             if (!mapNewIntfaceObjId.containsKey(newIntface)) {
-//                     throw new Error("IoTCompiler: Need to parse policy and requires files for callback class first! " +
-//                                                     "Please place the two files for callback class in front...\n");
-//                     return -1;
-//             } else {
-                       int retObjId = mapNewIntfaceObjId.get(newIntface);
-                       return retObjId;
-//             }
+               int retObjId = mapNewIntfaceObjId.get(newIntface);      
+               return retObjId;
        }
 
 
@@ -4734,8 +4762,6 @@ public class IoTCompiler {
                // Add the standard list first
                importClasses.add("<vector>");
                importClasses.add("<set>");
-               //importClasses.add("\"IoTRMICall.hpp\"");
-               //importClasses.add("\"IoTRMIObject.hpp\"");
                importClasses.add("\"IoTRMIComm.hpp\"");
                importClasses.add("\"IoTRMICommClient.hpp\"");
                importClasses.add("\"IoTRMICommServer.hpp\"");
@@ -4984,6 +5010,45 @@ public class IoTCompiler {
                }
                return callbackClasses;
        }
+       
+
+       // Check if this is a callback class
+       private boolean isCallbackClass(String className) {
+
+               Set<String> intfaceSet = mapIntDeclHand.keySet();
+               for(String intface : intfaceSet) {
+
+                       DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                       InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                       Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+                       for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+                               Set<String> methods = intMeth.getValue();
+                               for (String method : methods) {
+
+                                       List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+                                       List<String> methParams = intDecl.getMethodParams(method);
+                                       for (int i = 0; i < methPrmTypes.size(); i++) {
+
+                                               String type = methPrmTypes.get(i);
+                                               if (getParamCategory(type) == ParamCategory.USERDEFINED) {
+                                                       // Final check to see if this is the searched class
+                                                       if (type.equals(className))
+                                                               return true;
+                                               } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
+                                               // Can be a List<...> of callback objects ...
+                                                       String genericType = getTypeOfGeneric(type)[0];
+                                                       if (getParamCategory(type) == ParamCategory.USERDEFINED) {
+                                                               if (type.equals(className))
+                                                                       return true;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return false;
+       }
 
 
        // Print import statements into file
@@ -5288,32 +5353,53 @@ public class IoTCompiler {
        public static void main(String[] args) throws Exception {
 
                // If there is no argument or just "--help" or "-h", then invoke printUsage()
-               if ((args[0].equals("-help") ||
+               if ((args.length == 0        ||
+                        args[0].equals("-help") ||
                         args[0].equals("--help")||
-                        args[0].equals("-h"))   ||
-                       (args.length == 0)) {
+                        args[0].equals("-h"))) {
 
                        IoTCompiler.printUsage();
 
                } else if (args.length > 1) {
 
                        IoTCompiler comp = new IoTCompiler();
-                       int i = 0;                              
+                       int i = 0;
+                       boolean controllerDefined = false;
                        do {
-                               // Parse main policy file
-                               ParseNode pnPol = IoTCompiler.parseFile(args[i]);
-                               // Parse "requires" policy file
-                               ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
-                               // Get interface name
-                               String intface = ParseTreeHandler.getOrigIntface(pnPol);
-                               comp.setDataStructures(intface, pnPol, pnReq);
-                               comp.getMethodsForIntface(intface);
+                               if (!controllerDefined && args[i].equals("-cont")) {
+                                       comp.setControllerClass(args[i+1]);
+                                       controllerDefined = true;
+                                       i = i + 2;
+                               }
+                           // Parse main policy file
+                           ParseNode pnPol = IoTCompiler.parseFile(args[i]);
+                           // Parse "requires" policy file
+                           ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
+                           // Get interface name
+                           String intface = ParseTreeHandler.getOrigIntface(pnPol);
+                           comp.setDataStructures(intface, pnPol, pnReq);
+                           comp.getMethodsForIntface(intface);
                                i = i + 2;
+                               // Driver name
+                               if (args[i].equals("-drv")) {
+                                       comp.setDriverClass(intface, args[i+1]);
+                                       i = i + 2;
+                               } else
+                                       throw new Error("IoTCompiler: ERROR - driver class name is needed for the interface: " + intface + "\n");
+                               // Object ID (for a stub/skeleton pair that is also used in other applications)
+                               if (args[i].equals("-objid")) {
+                                       comp.setObjectId(intface, args[i+1]);
+                                       i = i + 2;
+                               }
+
                        // 1) Check if this is the last option before "-java" or "-cplus"
-                       // 2) Check if this is really the last option (no "-java" or "-cplus")
+                       // 2) Check if this is really the last option
                        } while(!args[i].equals("-java") &&
                                        !args[i].equals("-cplus") &&
                                        (i < args.length));
+                       // Controller class name needs to be defined at least once
+                       if (!controllerDefined)
+                               throw new Error("IoTCompiler: ERROR - controller class name has not been specified!\n");
 
                        // Generate everything if we don't see "-java" or "-cplus"
                        if (i == args.length) {
@@ -5329,10 +5415,8 @@ public class IoTCompiler {
                                comp.generateCPlusInterfaces();
                                comp.generateCPlusStubClassesHpp();
                                comp.generateCPlusStubClassesCpp();
-                               //comp.generateCPlusCallbackStubClasses();
                                comp.generateCplusSkeletonClassHpp();
                                comp.generateCplusSkeletonClassCpp();
-                               //comp.generateCplusCallbackSkeletonClass();
                        } else {
                        // Check other options
                                while(i < args.length) {
@@ -5360,10 +5444,8 @@ public class IoTCompiler {
                                                        comp.generateCPlusInterfaces();
                                                        comp.generateCPlusStubClassesHpp();
                                                        comp.generateCPlusStubClassesCpp();
-                                                       //comp.generateCPlusCallbackStubClasses();
                                                        comp.generateCplusSkeletonClassHpp();
                                                        comp.generateCplusSkeletonClassCpp();
-                                                       //comp.generateCplusCallbackSkeletonClass();
                                                }
                                        }
                                        i = i + 2;
@@ -5378,3 +5460,4 @@ public class IoTCompiler {
 }
 
 
+