X-Git-Url: http://plrg.eecs.uci.edu/git/?p=iot2.git;a=blobdiff_plain;f=iotjava%2Fiotpolicy%2FIoTCompiler.java;h=027ea07670c77433c6e030ff6f984f26893de84c;hp=66287f93a79b4fc58d5813757128ff71f2ef71d0;hb=HEAD;hpb=47a251f41e05f47b4bc19c236ab9441cef5ed42c diff --git a/iotjava/iotpolicy/IoTCompiler.java b/iotjava/iotpolicy/IoTCompiler.java index 66287f9..027ea07 100644 --- a/iotjava/iotpolicy/IoTCompiler.java +++ b/iotjava/iotpolicy/IoTCompiler.java @@ -49,6 +49,7 @@ public class IoTCompiler { private Map mapIntDeclHand; private Map>> mapInt2NewInts; private Map mapInt2NewIntName; + private Map> mapInt2Drv; // Data structure to store our types (primitives and non-primitives) for compilation private Map mapPrimitives; private Map mapNonPrimitivesJava; @@ -61,12 +62,22 @@ public class IoTCompiler { private String subdir; private Map 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 { @@ -87,6 +98,7 @@ public class IoTCompiler { mapIntDeclHand = new HashMap(); mapInt2NewInts = new HashMap>>(); mapInt2NewIntName = new HashMap(); + mapInt2Drv = new HashMap>(); mapIntfaceObjId = new HashMap(); mapNewIntfaceObjId = new HashMap(); mapPrimitives = new HashMap(); @@ -99,6 +111,30 @@ public class IoTCompiler { pw = null; 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 drvList = mapInt2Drv.get(intface); + if(drvList == null) + drvList = new ArrayList(); + drvList.add(driverClass); + mapInt2Drv.put(intface, drvList); + } + + + /** + * setControllerClass() sets the name of the controller class. + */ + public void setControllerClass(String _controllerClass) { + + controllerClass = _controllerClass; } @@ -141,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)); } @@ -185,11 +232,17 @@ public class IoTCompiler { // Map new interface method name to the original interface // TODO: perhaps need to check in the future if we have more than 1 stub interface for one original interface mapInt2NewIntName.put(origInt, strInt); + if (mainClass == null) // Take the first class as the main class (whichever is placed first in the order of compilation files) + mainClass = origInt; } // Map the map of interface-methods to the original interface mapInt2NewInts.put(origInt, mapNewIntMethods); } + +/*================ + * Java generation + *================/ /** * HELPER: writeMethodJavaLocalInterface() writes the method of the local interface @@ -250,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); @@ -258,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 enumMembers = enumDecl.getMembers(enType); for (int i = 0; i < enumMembers.size(); i++) { @@ -287,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); @@ -295,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 structMemberTypes = structDecl.getMemberTypes(stType); List structMembers = structDecl.getMembers(stType); @@ -326,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); @@ -337,6 +395,7 @@ public class IoTCompiler { Set importClasses = getImportClasses(methods, intDecl); List stdImportClasses = getStandardJavaIntfaceImportClasses(); List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); + println("package " + INTERFACE_PACKAGE + ";\n"); printImportStatements(allImportClasses); // Write interface header println(""); @@ -355,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++); } @@ -368,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> mapNewIntMethods = mapInt2NewInts.get(intface); @@ -384,6 +444,7 @@ public class IoTCompiler { Set importClasses = getImportClasses(methods, intDecl); List stdImportClasses = getStandardJavaIntfaceImportClasses(); List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); + println("package " + INTERFACE_PACKAGE + ";\n"); printImportStatements(allImportClasses); // Write interface header println(""); @@ -408,8 +469,6 @@ public class IoTCompiler { for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { String newIntface = intMeth.getKey(); int newObjectId = getNewIntfaceObjectId(newIntface); - println("private final static int object" + newObjectId + "Id = " + - newObjectId + ";\t//" + newIntface); Set methodIds = intMeth.getValue(); print("private static Integer[] object" + newObjectId + "Permission = { "); int i = 0; @@ -431,28 +490,21 @@ public class IoTCompiler { /** * HELPER: writePropertiesJavaStub() writes the properties of the stub class */ - private void writePropertiesJavaStub(String intface, String newIntface, boolean callbackExist, Set callbackClasses) { + private void writePropertiesJavaStub(String intface, Set methods, InterfaceDecl intDecl) { - println("private IoTRMICall rmiCall;"); - println("private String callbackAddress;"); - println("private int[] ports;\n"); // Get the object Id Integer objId = mapIntfaceObjId.get(intface); - println("private final static int objectId = " + objId + ";"); - //mapNewIntfaceObjId.put(newIntface, objId); - //mapIntfaceObjId.put(intface, 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("private IoTRMIObject rmiObj;"); - println("List<" + callbackType + "> listCallbackObj;"); - println("private static int objIdCnt = 0;"); - // Generate permission stuff for callback stubs - DeclarationHandler decHandler = mapIntDeclHand.get(callbackType); - InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType); - writePropertiesJavaPermission(callbackType, intDecl); + println("private int objectId = " + objId + ";"); + println("private IoTRMIComm rmiComm;"); + // Write the list of AtomicBoolean variables + println("// Synchronization variables"); + for (String method : methods) { + // Generate AtomicBooleans for methods that have return values + String returnType = intDecl.getMethodType(method); + int methodNumId = intDecl.getMethodNumId(method); + if (!returnType.equals("void")) { + println("private AtomicBoolean retValueReceived" + methodNumId + " = new AtomicBoolean(false);"); + } } println("\n"); } @@ -475,59 +527,47 @@ public class IoTCompiler { /** * HELPER: writeConstructorJavaStub() writes the constructor of the stub class */ - private void writeConstructorJavaStub(String intface, String newStubClass, boolean callbackExist, Set callbackClasses) { - - println("public " + newStubClass + "(int _port, String _skeletonAddress, String _callbackAddress, int _rev, int[] _ports) throws Exception {"); - println("callbackAddress = _callbackAddress;"); - println("ports = _ports;"); - println("rmiCall = new IoTRMICall(_port, _skeletonAddress, _rev);"); - if (callbackExist) { - Iterator it = callbackClasses.iterator(); - String callbackType = (String) it.next(); - writeConstructorJavaPermission(callbackType); - println("listCallbackObj = new ArrayList<" + callbackType + ">();"); - DeclarationHandler decHandler = mapIntDeclHand.get(callbackType); - InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType); - writeJavaInitCallbackPermission(callbackType, intDecl, callbackExist); - println("___initCallBack();"); - } - println("}\n"); - } - - - /** - * HELPER: writeJavaMethodCallbackPermission() writes permission checks in stub for callbacks - */ - private void writeJavaMethodCallbackPermission(String intface) { + private void writeConstructorJavaStub(String intface, String newStubClass, Set methods, InterfaceDecl intDecl) { - println("int methodId = IoTRMIObject.getMethodId(method);"); - // Get all the different stubs - Map> mapNewIntMethods = mapInt2NewInts.get(intface); - for (Map.Entry> 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("}"); + 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 + String returnType = intDecl.getMethodType(method); + int methodNumId = intDecl.getMethodNumId(method); + if (!returnType.equals("void")) { + println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");"); + } } + println("IoTRMIUtil.mapStub.put(objectId, this);"); + println("}\n"); } /** - * HELPER: writeJavaInitCallbackPermission() writes the permission for callback + * HELPER: writeCallbackConstructorJavaStub() writes the callback constructor of the stub class */ - private void writeJavaInitCallbackPermission(String intface, InterfaceDecl intDecl, boolean callbackExist) { + private void writeCallbackConstructorJavaStub(String intface, String newStubClass, Set methods, InterfaceDecl intDecl) { - if (callbackExist) { - String method = "___initCallBack()"; - int methodNumId = intDecl.getHelperMethodNumId(method); - Map> mapNewIntMethods = mapInt2NewInts.get(intface); - for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { - String newIntface = intMeth.getKey(); - int newObjectId = getNewIntfaceObjectId(newIntface); - println("set" + newObjectId + "Allowed.add(" + methodNumId + ");"); + println("public " + newStubClass + "(IoTRMIComm _rmiComm, int _objectId) throws Exception {"); + println("rmiComm = _rmiComm;"); + println("objectId = _objectId;"); + // Register the AtomicBoolean variables + for (String method : methods) { + // Generate AtomicBooleans for methods that have return values + String returnType = intDecl.getMethodType(method); + int methodNumId = intDecl.getMethodNumId(method); + if (!returnType.equals("void")) { + println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");"); } } + println("}\n"); } @@ -542,50 +582,6 @@ public class IoTCompiler { } - /** - * HELPER: writeInitCallbackJavaStub() writes callback initialization in stub - */ - private void writeInitCallbackJavaStub(String intface, InterfaceDecl intDecl, String newStubClass) { - - println("public void ___initCallBack() {"); - // Generate main thread for callbacks - println("Thread thread = new Thread() {"); - println("public void run() {"); - println("try {"); - int port = getPortCount(newStubClass); - println("rmiObj = new IoTRMIObject(ports[" + port + "]);"); - println("while (true) {"); - println("byte[] method = rmiObj.getMethodBytes();"); - println("int objId = IoTRMIObject.getObjectId(method);"); - println(intface + "_CallbackSkeleton skel = (" + intface + "_CallbackSkeleton) listCallbackObj.get(objId);"); - println("if (skel != null) {"); - writeJavaMethodCallbackPermission(intface); - println("skel.invokeMethod(rmiObj);"); - print("}"); - println(" else {"); - println("throw new Error(\"" + intface + ": Object with Id \" + objId + \" not found!\");"); - println("}"); - println("}"); - print("}"); - println(" catch (Exception ex) {"); - println("ex.printStackTrace();"); - println("throw new Error(\"Error instantiating class " + intface + "_CallbackSkeleton!\");"); - println("}"); - println("}"); - println("};"); - println("thread.start();\n"); - // Generate info sending part - String method = "___initCallBack()"; - int methodNumId = intDecl.getHelperMethodNumId(method); - println("int methodId = " + methodNumId + ";"); - println("Class retType = void.class;"); - println("Class[] paramCls = new Class[] { int[].class, String.class, int.class };"); - println("Object[] paramObj = new Object[] { ports, callbackAddress, 0 };"); - println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); - println("}\n"); - } - - /** * HELPER: checkAndWriteEnumTypeJavaStub() writes the enum type (convert from enum to int) */ @@ -622,8 +618,10 @@ public class IoTCompiler { /** * HELPER: checkAndWriteEnumRetTypeJavaStub() writes the enum return type (convert from enum to int) */ - private void checkAndWriteEnumRetTypeJavaStub(String retType) { + private void checkAndWriteEnumRetTypeJavaStub(String retType, String method, InterfaceDecl intDecl) { + // Write the wait-for-return-value part + writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);"); // Strips off array "[]" for return type String pureType = getSimpleArrayType(getGenericType(retType)); // Take the inner type of generic @@ -670,7 +668,6 @@ public class IoTCompiler { int methodNumId = intDecl.getMethodNumId(method); String helperMethod = methodNumId + "struct" + i; println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";"); - println("Class retTypeStruct" + i + " = void.class;"); println("Class[] paramClsStruct" + i + " = new Class[] { int.class };"); if (isArray(param)) { // An array println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".length };"); @@ -679,9 +676,8 @@ public class IoTCompiler { } else { // Just one element println("Object[] paramObjStruct" + i + " = new Object[] { new Integer(1) };"); } - println("rmiCall.remoteCall(objectId, methodIdStruct" + i + - ", retTypeStruct" + i + ", null, paramClsStruct" + i + - ", paramObjStruct" + i + ");\n"); + println("rmiComm.remoteCall(objectId, methodIdStruct" + i + + ", paramClsStruct" + i + ", paramObjStruct" + i + ");\n"); } } } @@ -777,7 +773,7 @@ public class IoTCompiler { /** * HELPER: writeStructParamClassJavaStub() writes parameters if struct is present */ - private void writeStructParamClassJavaStub(List methParams, List methPrmTypes, String callbackType) { + private void writeStructParamClassJavaStub(List methParams, List methPrmTypes, Set callbackType) { print("int paramLen = "); writeLengthStructParamClassJavaStub(methParams, methPrmTypes); @@ -793,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;"); @@ -830,7 +819,7 @@ public class IoTCompiler { for (int i = 0; i < members.size(); i++) { String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); print("structRet[i]." + getSimpleIdentifier(members.get(i))); - println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];"); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];"); } println("}"); } else if (isList(retType)) { // A list @@ -838,7 +827,7 @@ public class IoTCompiler { for (int i = 0; i < members.size(); i++) { String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); print("structRetMem." + getSimpleIdentifier(members.get(i))); - println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];"); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];"); } println("structRet.add(structRetMem);"); println("}"); @@ -846,7 +835,7 @@ public class IoTCompiler { for (int i = 0; i < members.size(); i++) { String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); print("structRet." + getSimpleIdentifier(members.get(i))); - println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];"); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];"); } } println("return structRet;"); @@ -856,12 +845,12 @@ public class IoTCompiler { /** * HELPER: writeStructReturnJavaStub() writes parameters if struct is present for return statement */ - private void writeStructReturnJavaStub(String simpleType, String retType) { + private void writeStructReturnJavaStub(String simpleType, String retType, String method, InterfaceDecl intDecl) { - // Handle the returned struct!!! - println("Object retLenObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); + // Handle the returned struct size + writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);"); // Minimum retLen is 1 if this is a single struct object - println("int retLen = (int) retLenObj;"); + println("int retLen = (int) retObj;"); int numMem = getNumOfMembers(simpleType); println("Class[] retCls = new Class[" + numMem + "*retLen];"); println("Class[] retClsVal = new Class[" + numMem + "*retLen];"); @@ -885,7 +874,8 @@ public class IoTCompiler { println("retClsVal[retPos++] = null;"); } } - println("Object[] retObj = rmiCall.getStructObjects(retCls, retClsVal);"); + // Handle the actual returned struct + writeWaitForReturnValueJava(method, intDecl, "Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);"); if (isArray(retType)) { // An array println(simpleType + "[] structRet = new " + simpleType + "[retLen];"); println("for(int i = 0; i < retLen; i++) {"); @@ -900,11 +890,25 @@ public class IoTCompiler { } + /** + * HELPER: writeWaitForReturnValueJava() writes the synchronization part for return values + */ + private void writeWaitForReturnValueJava(String method, InterfaceDecl intDecl, String getReturnValue) { + + println("// Waiting for return value"); + int methodNumId = intDecl.getMethodNumId(method); + println("while (!retValueReceived" + methodNumId + ".get());"); + println(getReturnValue); + println("retValueReceived" + methodNumId + ".set(false);"); + println("rmiComm.setGetReturnBytes();\n"); + } + + /** * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class */ private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List methParams, - List methPrmTypes, String method, String callbackType) { + List methPrmTypes, String method, Set callbackType) { checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method); println("int methodId = " + intDecl.getMethodNumId(method) + ";"); @@ -919,7 +923,7 @@ public class IoTCompiler { for (int i = 0; i < methParams.size(); i++) { String prmType = methPrmTypes.get(i); if (checkCallbackType(prmType, callbackType)) { // Check if this has callback object - print("int.class"); + print("int[].class"); } else { // Generate normal classes if it's not a callback object String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); print(getSimpleType(getEnumType(paramType)) + ".class"); @@ -935,13 +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 - //if (isArray(methPrmTypes.get(i), methParams.get(i))) - 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)"); + 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) @@ -951,26 +949,26 @@ public class IoTCompiler { } println(" };"); } + // Send method call first and wait for return value separately + println("rmiComm.remoteCall(objectId, methodId, paramCls, paramObj);"); // Check if this is "void" - if (retType.equals("void")) { - println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); - } else { // We do have a return value + if (!retType.equals("void")) { // We do have a return value // Generate array of parameter types if (isStructClass(getGenericType(getSimpleArrayType(retType)))) { - writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType); + writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl); } else { // This is an enum type if (getParamCategory(getGenericType(getSimpleArrayType(retType))) == ParamCategory.ENUM) { - println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); - checkAndWriteEnumRetTypeJavaStub(retType); + //println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); + checkAndWriteEnumRetTypeJavaStub(retType, method, intDecl); } else if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) { // Check if the return value NONPRIMITIVES String retGenValType = getGenericType(retType); println("Class retGenValType = " + retGenValType + ".class;"); - println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, retGenValType, paramCls, paramObj);"); + writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, retGenValType);"); println("return (" + retType + ")retObj;"); } else { - println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); + writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);"); println("return (" + retType + ")retObj;"); } } @@ -990,6 +988,24 @@ public class IoTCompiler { } + /** + * HELPER: checkCallbackType() checks the callback type + */ + private boolean checkCallbackType(String paramType, Set 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 */ @@ -1003,12 +1019,66 @@ public class IoTCompiler { } + /** + * HELPER: writeCallbackInstantiationMethodBodyJavaStub() writes the callback object instantiation in the method of the stub class + */ + private void writeCallbackInstantiationMethodBodyJavaStub(String paramIdent, String callbackType, int counter, boolean isMultipleCallbacks) { + + println("if (!IoTRMIUtil.mapSkel.containsKey(" + paramIdent + ")) {"); + println("int newObjIdSent = rmiComm.getObjectIdCounter();"); + if (isMultipleCallbacks) + println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;"); + else + println("objIdSent" + counter + "[0] = newObjIdSent;"); + println("rmiComm.decrementObjectIdCounter();"); + println(callbackType + "_Skeleton skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);"); + 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("skel" + counter + ".___waitRequestInvokeMethod();"); + println("} catch (Exception ex) {"); + println("ex.printStackTrace();"); + println("throw new Error(\"Exception when trying to run ___waitRequestInvokeMethod() for " + + callbackType + "_Skeleton!\");"); + println("}"); + println("}"); + println("};"); + println("thread.start();"); + println("while(!skel" + counter + ".didAlreadyInitWaitInvoke());"); + println("}"); + println("else"); + println("{"); + println("int newObjIdSent = IoTRMIUtil.mapSkelId.get(" + paramIdent + ");"); + if (isMultipleCallbacks) + println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;"); + else + println("objIdSent" + counter + "[0] = newObjIdSent;"); + println("}"); + } + + /** * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class */ private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List methParams, - List methPrmTypes, String method, String callbackType) { + List methPrmTypes, String method, Set callbackType) { + // Determine callback object counter type (List vs. single variable) + 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];"); + else if (isList(methPrmTypes.get(i))) + println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".size()];"); + else + println("new int[1];"); + } + } println("try {"); // Check if this is single object, array, or list of objects for (int i = 0; i < methParams.size(); i++) { @@ -1016,12 +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 cnt" + i + " = 0;"); println("for (" + getGenericType(paramType) + " cb : " + getSimpleIdentifier(param) + ") {"); - println(callbackType + "_CallbackSkeleton skel" + i + " = new " + callbackType + "_CallbackSkeleton(cb, callbackAddress, objIdCnt++);"); + writeCallbackInstantiationMethodBodyJavaStub("cb", returnGenericCallbackType(paramType), i, true); } else - println(callbackType + "_CallbackSkeleton skel" + i + " = new " + callbackType + "_CallbackSkeleton(" + - getSimpleIdentifier(param) + ", callbackAddress, objIdCnt++);"); - println("listCallbackObj.add(skel" + i + ");"); + writeCallbackInstantiationMethodBodyJavaStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i, false); if (isArrayOrList(paramType, param)) println("}"); } @@ -1039,7 +1108,6 @@ public class IoTCompiler { */ private void writeMethodJavaStub(Collection methods, InterfaceDecl intDecl, Set callbackClasses, String newStubClass) { - boolean isDefined = false; for (String method : methods) { List methParams = intDecl.getMethodParams(method); @@ -1047,14 +1115,16 @@ public class IoTCompiler { print("public " + intDecl.getMethodType(method) + " " + intDecl.getMethodId(method) + "("); boolean isCallbackMethod = false; - String callbackType = null; + //String callbackType = null; + Set callbackType = new HashSet(); 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)); @@ -1067,14 +1137,8 @@ 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"); - // Write the init callback helper method - if (isCallbackMethod && !isDefined) { - writeInitCallbackJavaStub(callbackType, intDecl, newStubClass); - isDefined = true; - } } } @@ -1097,137 +1161,55 @@ public class IoTCompiler { String path = createDirectories(dir, subdir); for (String intface : mapIntfacePTH.keySet()) { - Map> mapNewIntMethods = mapInt2NewInts.get(intface); - for (Map.Entry> 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 methods = intMeth.getValue(); - Set importClasses = getImportClasses(methods, intDecl); - List stdImportClasses = getStandardJavaImportClasses(); - List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); - printImportStatements(allImportClasses); println(""); - // Find out if there are callback objects - Set callbackClasses = getCallbackClasses(methods, intDecl); - boolean callbackExist = !callbackClasses.isEmpty(); - // Write class header - println("public class " + newStubClass + " implements " + newIntface + " {\n"); - // Write properties - writePropertiesJavaStub(intface, newIntface, callbackExist, callbackClasses); - // Write constructor - writeConstructorJavaStub(intface, newStubClass, callbackExist, callbackClasses); - // Write methods - writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass); - println("}"); - pw.close(); - System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java..."); - } - } - } - - - /** - * HELPER: writePropertiesJavaCallbackStub() writes the properties of the callback stub class - */ - private void writePropertiesJavaCallbackStub(String intface, String newIntface, boolean callbackExist, Set callbackClasses) { - - println("private IoTRMICall rmiCall;"); - println("private String callbackAddress;"); - println("private int[] ports;\n"); - // Get the object Id - println("private int objectId = 0;"); - 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("private IoTRMIObject rmiObj;"); - println("List<" + callbackType + "> listCallbackObj;"); - println("private static int objIdCnt = 0;"); - // Generate permission stuff for callback stubs - DeclarationHandler decHandler = mapIntDeclHand.get(callbackType); - InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType); - writePropertiesJavaPermission(callbackType, intDecl); - } - println("\n"); - } - - - /** - * HELPER: writeConstructorJavaCallbackStub() writes the constructor of the callback stub class - */ - private void writeConstructorJavaCallbackStub(String intface, String newStubClass, boolean callbackExist, Set callbackClasses) { - - // TODO: If we want callback in callback, then we need to add address and port initializations - println("public " + newStubClass + "(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {"); - println("callbackAddress = _callbackAddress;"); - println("objectId = _objectId;"); - println("rmiCall = _rmiCall;"); - println("ports = _ports;"); - if (callbackExist) { - Iterator it = callbackClasses.iterator(); - String callbackType = (String) it.next(); - writeConstructorJavaPermission(callbackType); - println("listCallbackObj = new ArrayList<" + callbackType + ">();"); - DeclarationHandler decHandler = mapIntDeclHand.get(callbackType); - InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType); - writeJavaInitCallbackPermission(callbackType, intDecl, callbackExist); - println("___initCallBack();"); - } - println("}\n"); - } - - - /** - * generateJavaCallbackStubClasses() generate callback stubs based on the methods list in Java - *

- * Callback stubs gets the IoTRMICall objects from outside of the class as contructor input - * because all these stubs are populated by the class that takes in this object as a callback - * object. In such a class, we only use one socket, hence one IoTRMICall, for all callback objects. - */ - public void generateJavaCallbackStubClasses() throws IOException { - - // Create a new directory - String path = createDirectories(dir, subdir); - for (String intface : mapIntfacePTH.keySet()) { - - Map> mapNewIntMethods = mapInt2NewInts.get(intface); - for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { - - // Open a new file to write into - String newIntface = intMeth.getKey(); - String newStubClass = newIntface + "_CallbackStub"; - 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 methods = intMeth.getValue(); - Set importClasses = getImportClasses(methods, intDecl); - List stdImportClasses = getStandardJavaImportClasses(); - List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); - printImportStatements(allImportClasses); println(""); - // Find out if there are callback objects - Set callbackClasses = getCallbackClasses(methods, intDecl); - boolean callbackExist = !callbackClasses.isEmpty(); - // Write class header - println("public class " + newStubClass + " implements " + newIntface + " {\n"); - // Write properties - writePropertiesJavaCallbackStub(intface, newIntface, callbackExist, callbackClasses); - // Write constructor - writeConstructorJavaCallbackStub(intface, newStubClass, callbackExist, callbackClasses); - // Write methods - // TODO: perhaps need to generate callback for callback - writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass); - println("}"); - pw.close(); - System.out.println("IoTCompiler: Generated callback stub class " + newStubClass + ".java..."); + // Check if there is more than 1 class that uses the same interface + List drvList = mapInt2Drv.get(intface); + for(int i = 0; i < drvList.size(); i++) { + + String driverClass = drvList.get(i); + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> 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 methods = intMeth.getValue(); + Set importClasses = getImportClasses(methods, intDecl); + List stdImportClasses = getStandardJavaImportClasses(); + List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); + // Find out if there are callback objects + Set 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..."); + } } } } @@ -1236,18 +1218,17 @@ public class IoTCompiler { /** * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class */ - private void writePropertiesJavaSkeleton(String intface, boolean callbackExist, InterfaceDecl intDecl) { + private void writePropertiesJavaSkeleton(String intface, InterfaceDecl intDecl) { println("private " + intface + " mainObj;"); - //println("private int ports;"); - println("private IoTRMIObject rmiObj;\n"); - println("private String callbackAddress;"); - // Callback - if (callbackExist) { - println("private static int objIdCnt = 0;"); - println("private IoTRMICall rmiCall;"); - println("private int[] ports;\n"); - } + Integer objId = mapIntfaceObjId.get(intface); + println("private int objectId = " + objId + ";"); + println("// Communications and synchronizations"); + println("private IoTRMIComm rmiComm;"); + println("private AtomicBoolean didAlreadyInitWaitInvoke;"); + println("private AtomicBoolean methodReceived;"); + println("private byte[] methodBytes = null;"); + println("// Permissions"); writePropertiesJavaPermission(intface, intDecl); println("\n"); } @@ -1287,17 +1268,52 @@ public class IoTCompiler { /** * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class */ - private void writeConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, Collection methods, boolean callbackExist) { + private void writeConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, + Collection methods, boolean callbackExist) { - println("public " + newSkelClass + "(" + intface + " _mainObj, String _callbackAddress, int _port) throws Exception {"); + println("public " + newSkelClass + "(" + intface + " _mainObj, int _portSend, int _portRecv) throws Exception {"); println("mainObj = _mainObj;"); - println("callbackAddress = _callbackAddress;"); - println("rmiObj = new IoTRMIObject(_port);"); + 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);"); + println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);"); + println("methodReceived = new AtomicBoolean(false);"); + println("rmiComm.registerSkeleton(objectId, methodReceived);"); + println("Thread thread1 = new Thread() {"); + println("public void run() {"); + println("try {"); println("___waitRequestInvokeMethod();"); + println("}"); + println("catch (Exception ex)"); + println("{"); + println("ex.printStackTrace();"); + println("}"); + println("}"); + println("};"); + println("thread1.start();"); + println("}\n"); + } + + + /** + * HELPER: writeCallbackConstructorJavaSkeleton() writes the constructor of the skeleton class + */ + private void writeCallbackConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, + Collection methods, boolean callbackExist) { + + println("public " + newSkelClass + "(" + intface + " _mainObj, IoTRMIComm _rmiComm, int _objectId) throws Exception {"); + println("mainObj = _mainObj;"); + println("rmiComm = _rmiComm;"); + println("objectId = _objectId;"); + // Generate permission control initialization + writeConstructorJavaPermission(intface); + writeStructPermissionJavaSkeleton(methods, intDecl, intface); + println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);"); + println("methodReceived = new AtomicBoolean(false);"); + println("rmiComm.registerSkeleton(objectId, methodReceived);"); println("}\n"); } @@ -1323,53 +1339,21 @@ public class IoTCompiler { } - /** - * HELPER: writeInitCallbackJavaSkeleton() writes the init callback method for skeleton class - */ - private void writeInitCallbackJavaSkeleton(boolean callbackSkeleton, String intface) { - - // This is a callback skeleton generation - if (callbackSkeleton) - println("public void ___regCB(IoTRMIObject rmiObj) throws IOException {"); - else - println("public void ___regCB() throws IOException {"); - print("Object[] paramObj = rmiObj.getMethodParams(new Class[] { int[].class, String.class, int.class },"); - println("new Class[] { null, null, null });"); - println("ports = (int[]) paramObj[0];"); - String stubInt = null; - if (callbackSkeleton) - stubInt = getStubInterface(intface) + "_CallbackStub"; - else - stubInt = getStubInterface(intface) + "_Stub"; - int port = getPortCount(stubInt); - println("rmiCall = new IoTRMICall(ports[" + port + "], (String) paramObj[1], (int) paramObj[2]);"); - println("}\n"); - } - - /** * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class */ - private void writeMethodJavaSkeleton(Collection methods, InterfaceDecl intDecl, Set callbackClasses, - boolean callbackSkeleton, String intface) { + private void writeMethodJavaSkeleton(Collection methods, InterfaceDecl intDecl) { - boolean isDefined = false; for (String method : methods) { List methParams = intDecl.getMethodParams(method); List 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) { @@ -1380,19 +1364,33 @@ public class IoTCompiler { // Now, write the body of skeleton! writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method)); println("}\n"); - if (isCallbackMethod && !isDefined) { // Make sure that this function is only defined once! - writeInitCallbackJavaSkeleton(callbackSkeleton, intface); - isDefined = true; - } } } + /** + * HELPER: writeCallbackInstantiationJavaStubGeneration() writes the instantiation of callback stubs + */ + private void writeCallbackInstantiationJavaStubGeneration(String exchParamType, int counter) { + + 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" + counter + " = (" + exchParamType + "_Stub) IoTRMIUtil.mapStub.get(objIdRecv" + counter + ");"); + println("}"); + } + + /** * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part */ private Map writeCallbackJavaStubGeneration(List methParams, List methPrmTypes, - String callbackType, boolean isStructMethod) { + Set callbackType, boolean isStructMethod) { Map mapStubParam = new HashMap(); String offsetPfx = ""; @@ -1405,31 +1403,35 @@ public class IoTCompiler { if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object String exchParamType = checkAndGetParamClass(getGenericType(paramType)); // Print array if this is array or list if this is a list of callback objects - if (isArray(param)) { - println("int numStubs" + i + " = (int) paramObj[" + offsetPfx + i + "];"); + println("int[] stubIdArray" + i + " = (int[]) paramObj[" + offsetPfx + i + "];"); + if (isArray(param)) { + println("int numStubs" + i + " = stubIdArray" + i + ".length;"); println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];"); } else if (isList(paramType)) { - println("int numStubs" + i + " = (int) paramObj[" + offsetPfx + i + "];"); + println("int numStubs" + i + " = stubIdArray" + i + ".length;"); println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();"); } else { - println(exchParamType + " stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);"); - println("objIdCnt++;"); + println("int objIdRecv" + i + " = stubIdArray" + i + "[0];"); + writeCallbackInstantiationJavaStubGeneration(exchParamType, i); } } // Generate a loop if needed if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object String exchParamType = checkAndGetParamClass(getGenericType(paramType)); if (isArray(param)) { - println("for (int objId = 0; objId < numStubs" + i + "; objId++) {"); - println("stub" + i + "[objId] = new " + exchParamType + "_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);"); - println("objIdCnt++;"); + println("for (int i = 0; i < numStubs" + i + "; i++) {"); + println("int objIdRecv" + i + " = stubIdArray" + i + "[i];"); + writeCallbackInstantiationJavaStubGeneration(exchParamType, i); + println("stub" + i + "[i] = newStub" + i + ";"); println("}"); } else if (isList(paramType)) { - println("for (int objId = 0; objId < numStubs" + i + "; objId++) {"); - println("stub" + i + ".add(new " + exchParamType + "_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports));"); - println("objIdCnt++;"); + println("for (int i = 0; i < numStubs" + i + "; i++) {"); + println("int objIdRecv" + i + " = stubIdArray" + i + "[i];"); + writeCallbackInstantiationJavaStubGeneration(exchParamType, i); + println("stub" + i + ".add(newStub" + i + ");"); println("}"); - } + } else + println(exchParamType + " stub" + i + " = newStub" + i + ";"); mapStubParam.put(i, "stub" + i); // List of all stub parameters } } @@ -1667,7 +1669,7 @@ public class IoTCompiler { else // Just single struct object println("int retLen = 1;"); println("Object retLenObj = retLen;"); - println("rmiObj.sendReturnObj(retLenObj);"); + println("rmiComm.sendReturnObj(retLenObj, localMethodBytes);"); int numMem = getNumOfMembers(simpleType); println("Class[] retCls = new Class[" + numMem + "*retLen];"); println("Object[] retObj = new Object[" + numMem + "*retLen];"); @@ -1713,7 +1715,7 @@ public class IoTCompiler { * HELPER: writeMethodHelperReturnJavaSkeleton() writes return statement part in skeleton */ private void writeMethodHelperReturnJavaSkeleton(InterfaceDecl intDecl, List methParams, - List methPrmTypes, String method, boolean isCallbackMethod, String callbackType, + List methPrmTypes, String method, boolean isCallbackMethod, Set callbackType, boolean isStructMethod) { checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes, isStructMethod); @@ -1756,12 +1758,12 @@ public class IoTCompiler { if (!retType.equals("void")) { if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type checkAndWriteEnumRetConvJavaSkeleton(retType); - println("rmiObj.sendReturnObj(retObj);"); + println("rmiComm.sendReturnObj(retObj, localMethodBytes);"); } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type writeStructReturnJavaSkeleton(getSimpleArrayType(getGenericType(retType)), retType); - println("rmiObj.sendReturnObj(retCls, retObj);"); + println("rmiComm.sendReturnObj(retCls, retObj, localMethodBytes);"); } else - println("rmiObj.sendReturnObj(retObj);"); + println("rmiComm.sendReturnObj(retObj, localMethodBytes);"); } if (isCallbackMethod) { // Catch exception if this is callback print("}"); @@ -1781,7 +1783,9 @@ public class IoTCompiler { // Generate array of parameter objects boolean isCallbackMethod = false; - String callbackType = null; + Set callbackType = new HashSet(); + println("byte[] localMethodBytes = methodBytes;"); + println("rmiComm.setGetMethodBytes();"); print("int paramLen = "); writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl); println(";"); @@ -1799,8 +1803,9 @@ public class IoTCompiler { String prmType = returnGenericCallbackType(methPrmTypes.get(i)); if (callbackClasses.contains(prmType)) { isCallbackMethod = true; - callbackType = prmType; - println("paramCls[pos] = int.class;"); + //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 String paramTypeOth = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); @@ -1814,7 +1819,7 @@ public class IoTCompiler { } } } - println("Object[] paramObj = rmiObj.getMethodParams(paramCls, paramClsGen);"); + println("Object[] paramObj = rmiComm.getMethodParams(paramCls, paramClsGen, localMethodBytes);"); writeStructMembersInitJavaSkeleton(intDecl, methParams, methPrmTypes, method); // Write the return value part writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, true); @@ -1829,15 +1834,17 @@ public class IoTCompiler { // Generate array of parameter objects boolean isCallbackMethod = false; - String callbackType = null; - print("Object[] paramObj = rmiObj.getMethodParams(new Class[] { "); + Set callbackType = new HashSet(); + println("byte[] localMethodBytes = methodBytes;"); + println("rmiComm.setGetMethodBytes();"); + print("Object[] paramObj = rmiComm.getMethodParams(new Class[] { "); for (int i = 0; i < methParams.size(); i++) { String paramType = returnGenericCallbackType(methPrmTypes.get(i)); if (callbackClasses.contains(paramType)) { isCallbackMethod = true; - callbackType = paramType; - print("int.class"); + 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)); print(getSimpleType(getEnumType(prmType)) + ".class"); @@ -1845,9 +1852,8 @@ public class IoTCompiler { if (i != methParams.size() - 1) print(", "); } - println(" }, "); // Generate generic class if it's a generic type.. null otherwise - print("new Class[] { "); + print(" }, new Class[] { "); for (int i = 0; i < methParams.size(); i++) { String prmType = methPrmTypes.get(i); if ((getParamCategory(prmType) == ParamCategory.NONPRIMITIVES) && @@ -1859,7 +1865,7 @@ public class IoTCompiler { if (i != methParams.size() - 1) print(", "); } - println(" });"); + println(" }, localMethodBytes);"); // Write the return value part writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, false); } @@ -1953,7 +1959,9 @@ public class IoTCompiler { String helperMethod = methodNumId + "struct" + i; println(helperMethod + "() {"); // Now, write the helper body of skeleton! - println("Object[] paramObj = rmiObj.getMethodParams(new Class[] { int.class }, new Class[] { null });"); + println("byte[] localMethodBytes = methodBytes;"); + println("rmiComm.setGetMethodBytes();"); + println("Object[] paramObj = rmiComm.getMethodParams(new Class[] { int.class }, new Class[] { null }, localMethodBytes);"); println("return (int) paramObj[0];"); println("}\n"); } @@ -1984,7 +1992,7 @@ public class IoTCompiler { String helperMethod = methodNumId + "struct" + i; println(helperMethod + "(IoTRMIObject rmiObj) {"); // Now, write the helper body of skeleton! - println("Object[] paramObj = rmiObj.getMethodParams(new Class[] { int.class }, new Class[] { null });"); + println("Object[] paramObj = rmiComm.getMethodParams(new Class[] { int.class }, new Class[] { null });"); println("return (int) paramObj[0];"); println("}\n"); } @@ -2016,11 +2024,39 @@ public class IoTCompiler { } } - + /** - * HELPER: writeInputCountVarStructSkeleton() writes input counter variable of struct for skeleton + * HELPER: writeInputCountVarStructJavaSkeleton() writes input counter variable of struct for skeleton */ - private boolean writeInputCountVarStructSkeleton(String method, InterfaceDecl intDecl) { + private boolean writeInputCountVarStructJavaSkeleton(String method, InterfaceDecl intDecl) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + boolean structExist = false; + boolean begin = true; + // Check for params with structs + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + structExist = true; + if (!begin) + print(", "); + else + begin = false; + int methodNumId = intDecl.getMethodNumId(method); + print("struct" + methodNumId + "Size" + i + "Final"); + } + } + return structExist; + } + + + /** + * HELPER: writeInputCountVarStructCplusSkeleton() writes input counter variable of struct for skeleton + */ + private boolean writeInputCountVarStructCplusSkeleton(String method, InterfaceDecl intDecl) { List methParams = intDecl.getMethodParams(method); List methPrmTypes = intDecl.getMethodParamTypes(method); @@ -2046,9 +2082,9 @@ public class IoTCompiler { /** - * HELPER: writeMethodCallStructSkeleton() writes method call for wait invoke in skeleton + * HELPER: writeMethodCallStructJavaSkeleton() writes method call for wait invoke in skeleton */ - private void writeMethodCallStructSkeleton(Collection methods, InterfaceDecl intDecl) { + private void writeMethodCallStructJavaSkeleton(Collection methods, InterfaceDecl intDecl) { // Use this set to handle two same methodIds for (String method : methods) { @@ -2074,6 +2110,35 @@ public class IoTCompiler { } + /** + * HELPER: writeMethodCallStructCplusSkeleton() writes method call for wait invoke in skeleton + */ + private void writeMethodCallStructCplusSkeleton(Collection methods, InterfaceDecl intDecl) { + + // Use this set to handle two same methodIds + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + // Check for params with structs + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + int methodNumId = intDecl.getMethodNumId(method); + print("case "); + String helperMethod = methodNumId + "struct" + i; + String tempVar = "struct" + methodNumId + "Size" + i; + print(intDecl.getHelperMethodNumId(helperMethod) + ": "); + print(tempVar + " = ___"); + println(helperMethod + "(skel); break;"); + } + } + } + } + + /** * HELPER: writeMethodCallStructCallbackSkeleton() writes method call for wait invoke in skeleton */ @@ -2113,32 +2178,62 @@ public class IoTCompiler { for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { String newIntface = intMeth.getKey(); int newObjectId = getNewIntfaceObjectId(newIntface); - println("if (_objectId == object" + newObjectId + "Id) {"); + println("if (_objectId == objectId) {"); println("if (!set" + newObjectId + "Allowed.contains(methodId)) {"); println("throw new Error(\"Object with object Id: \" + _objectId + \" is not allowed to access method: \" + methodId);"); println("}"); println("}"); println("else {"); - println("throw new Error(\"Object Id: \" + _objectId + \" not recognized!\");"); + println("continue;"); println("}"); } } + /** + * HELPER: writeFinalInputCountVarStructSkeleton() writes the final version of input counter variable of struct for skeleton + */ + private boolean writeFinalInputCountVarStructSkeleton(String method, InterfaceDecl intDecl) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + boolean structExist = false; + boolean begin = true; + // Check for params with structs + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + structExist = true; + int methodNumId = intDecl.getMethodNumId(method); + println("final int struct" + methodNumId + "Size" + i + + "Final = struct" + methodNumId + "Size" + i + ";"); + } + } + return structExist; + } + + /** * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class */ - private void writeJavaWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, boolean callbackExist, String intface) { + private void writeJavaWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, String intface) { // Use this set to handle two same methodIds Set uniqueMethodIds = new HashSet(); - println("private void ___waitRequestInvokeMethod() throws IOException {"); + println("public void ___waitRequestInvokeMethod() throws IOException {"); // Write variables here if we have callbacks or enums or structs writeCountVarStructSkeleton(methods, intDecl); + println("didAlreadyInitWaitInvoke.compareAndSet(false, true);"); println("while (true) {"); - println("rmiObj.getMethodBytes();"); - println("int _objectId = rmiObj.getObjectId();"); - println("int methodId = rmiObj.getMethodId();"); + println("if (!methodReceived.get()) {"); + println("continue;"); + println("}"); + println("methodBytes = rmiComm.getMethodBytes();"); + println("methodReceived.set(false);"); + println("int _objectId = IoTRMIComm.getObjectId(methodBytes);"); + println("int methodId = IoTRMIComm.getMethodId(methodBytes);"); // Generate permission check writeJavaMethodPermission(intface); println("switch (methodId) {"); @@ -2146,23 +2241,31 @@ public class IoTCompiler { for (String method : methods) { String methodId = intDecl.getMethodId(method); int methodNumId = intDecl.getMethodNumId(method); - print("case " + methodNumId + ": ___"); + println("case " + methodNumId + ":"); + // Check for stuct counters + writeFinalInputCountVarStructSkeleton(method, intDecl); + println("new Thread() {"); + println("public void run() {"); + println("try {"); + print("___"); String helperMethod = methodId; if (uniqueMethodIds.contains(methodId)) helperMethod = helperMethod + methodNumId; else uniqueMethodIds.add(methodId); print(helperMethod + "("); - writeInputCountVarStructSkeleton(method, intDecl); - println("); break;"); + writeInputCountVarStructJavaSkeleton(method, intDecl); + println(");"); + println("}"); + println("catch (Exception ex) {"); + println("ex.printStackTrace();"); + println("}"); + println("}"); + println("}.start();"); + println("break;"); } String method = "___initCallBack()"; - // Print case -9999 (callback handler) if callback exists - if (callbackExist) { - int methodId = intDecl.getHelperMethodNumId(method); - println("case " + methodId + ": ___regCB(); break;"); - } - writeMethodCallStructSkeleton(methods, intDecl); + writeMethodCallStructJavaSkeleton(methods, intDecl); println("default: "); println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");"); println("}"); @@ -2172,233 +2275,86 @@ public class IoTCompiler { /** - * generateJavaSkeletonClass() generate skeletons based on the methods list in Java - */ - public void generateJavaSkeletonClass() throws IOException { - - // 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 methods = intDecl.getMethods(); - Set importClasses = getImportClasses(methods, intDecl); - List stdImportClasses = getStandardJavaImportClasses(); - List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); - printImportStatements(allImportClasses); - // Find out if there are callback objects - Set callbackClasses = getCallbackClasses(methods, intDecl); - boolean callbackExist = !callbackClasses.isEmpty(); - // Write class header - println(""); - println("public class " + newSkelClass + " implements " + intface + " {\n"); - // Write properties - writePropertiesJavaSkeleton(intface, callbackExist, intDecl); - // Write constructor - writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist); - // Write methods - writeMethodJavaSkeleton(methods, intDecl, callbackClasses, false, intface); - // Write method helper - writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses); - // Write waitRequestInvokeMethod() - main loop - writeJavaWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface); - println("}"); - pw.close(); - System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java..."); - } - } - - - /** - * HELPER: writePropertiesJavaCallbackSkeleton() writes the properties of the callback skeleton class - */ - private void writePropertiesJavaCallbackSkeleton(String intface, boolean callbackExist) { - - println("private " + intface + " mainObj;"); - // For callback skeletons, this is its own object Id - println("private int objectId = 0;"); - println("private String callbackAddress;"); - // Callback - if (callbackExist) { - - println("private static int objIdCnt = 0;"); - println("private IoTRMICall rmiCall;"); - println("private int[] ports;\n"); - } - println("\n"); - } - - - /** - * HELPER: writeConstructorJavaCallbackSkeleton() writes the constructor of the skeleton class - */ - private void writeConstructorJavaCallbackSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, Collection methods) { - - println("public " + newSkelClass + "(" + intface + " _mainObj, String _callbackAddress, int _objectId) throws Exception {"); - println("callbackAddress = _callbackAddress;"); - println("mainObj = _mainObj;"); - println("objectId = _objectId;"); - println("}\n"); - } - - - /** - * HELPER: writeMethodHelperJavaCallbackSkeleton() writes the method helper of the callback skeleton class - */ - private void writeMethodHelperJavaCallbackSkeleton(Collection methods, InterfaceDecl intDecl, Set callbackClasses) { - - // Use this set to handle two same methodIds - Set uniqueMethodIds = new HashSet(); - for (String method : methods) { - - List methParams = intDecl.getMethodParams(method); - List methPrmTypes = intDecl.getMethodParamTypes(method); - if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently - String methodId = intDecl.getMethodId(method); - print("public void ___"); - String helperMethod = methodId; - if (uniqueMethodIds.contains(methodId)) - helperMethod = helperMethod + intDecl.getMethodNumId(method); - else - uniqueMethodIds.add(methodId); - String retType = intDecl.getMethodType(method); - print(helperMethod + "("); - boolean begin = true; - for (int i = 0; i < methParams.size(); i++) { // Print size variables - String paramType = methPrmTypes.get(i); - String param = methParams.get(i); - String simpleType = getGenericType(paramType); - if (isStructClass(simpleType)) { - if (!begin) // Generate comma for not the beginning variable - print(", "); - else - begin = false; - int methodNumId = intDecl.getMethodNumId(method); - print("int struct" + methodNumId + "Size" + i); - } - } - // Check if this is "void" - if (retType.equals("void")) - println(", IoTRMIObject rmiObj) {"); - else - println(", IoTRMIObject rmiObj) throws IOException {"); - writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses); - println("}\n"); - } else { - String methodId = intDecl.getMethodId(method); - print("public void ___"); - String helperMethod = methodId; - if (uniqueMethodIds.contains(methodId)) - helperMethod = helperMethod + intDecl.getMethodNumId(method); - else - uniqueMethodIds.add(methodId); - // Check if this is "void" - String retType = intDecl.getMethodType(method); - if (retType.equals("void")) - println(helperMethod + "(IoTRMIObject rmiObj) {"); - else - println(helperMethod + "(IoTRMIObject rmiObj) throws IOException {"); - // Now, write the helper body of skeleton! - writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses); - println("}\n"); - } - } - // Write method helper for structs - writeMethodHelperStructSetupJavaCallbackSkeleton(methods, intDecl); - } - - - /** - * HELPER: writeJavaCallbackWaitRequestInvokeMethod() writes the request invoke method of the callback skeleton class + * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke */ - private void writeJavaCallbackWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, boolean callbackExist) { + private void writeReturnDidAlreadyInitWaitInvoke() { - // Use this set to handle two same methodIds - Set uniqueMethodIds = new HashSet(); - println("public void invokeMethod(IoTRMIObject rmiObj) throws IOException {"); - // Write variables here if we have callbacks or enums or structs - writeCountVarStructSkeleton(methods, intDecl); - // Write variables here if we have callbacks or enums or structs - println("int methodId = rmiObj.getMethodId();"); - // TODO: code the permission check here! - println("switch (methodId) {"); - // Print methods and method Ids - for (String method : methods) { - String methodId = intDecl.getMethodId(method); - int methodNumId = intDecl.getMethodNumId(method); - print("case " + methodNumId + ": ___"); - String helperMethod = methodId; - if (uniqueMethodIds.contains(methodId)) - helperMethod = helperMethod + methodNumId; - else - uniqueMethodIds.add(methodId); - print(helperMethod + "("); - if (writeInputCountVarStructSkeleton(method, intDecl)) - println(", rmiObj); break;"); - else - println("rmiObj); break;"); - } - String method = "___initCallBack()"; - // Print case -9999 (callback handler) if callback exists - if (callbackExist) { - int methodId = intDecl.getHelperMethodNumId(method); - println("case " + methodId + ": ___regCB(rmiObj); break;"); - } - writeMethodCallStructCallbackSkeleton(methods, intDecl); - println("default: "); - println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");"); - println("}"); + println("public boolean didAlreadyInitWaitInvoke() {"); + println("return didAlreadyInitWaitInvoke.get();"); println("}\n"); } /** - * generateJavaCallbackSkeletonClass() generate callback skeletons based on the methods list in Java + * generateJavaSkeletonClass() generate skeletons based on the methods list in Java */ - public void generateJavaCallbackSkeletonClass() throws IOException { + public void generateJavaSkeletonClass() throws IOException { // Create a new directory String path = createDirectories(dir, subdir); for (String intface : mapIntfacePTH.keySet()) { - // Open a new file to write into - String newSkelClass = intface + "_CallbackSkeleton"; - 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 methods = intDecl.getMethods(); - Set importClasses = getImportClasses(methods, intDecl); - List stdImportClasses = getStandardJavaImportClasses(); - List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); - printImportStatements(allImportClasses); - // Find out if there are callback objects - Set callbackClasses = getCallbackClasses(methods, intDecl); - boolean callbackExist = !callbackClasses.isEmpty(); - // Write class header - println(""); - println("public class " + newSkelClass + " implements " + intface + " {\n"); - // Write properties - writePropertiesJavaCallbackSkeleton(intface, callbackExist); - // Write constructor - writeConstructorJavaCallbackSkeleton(newSkelClass, intface, intDecl, methods); - // Write methods - writeMethodJavaSkeleton(methods, intDecl, callbackClasses, true, intface); - // Write method helper - writeMethodHelperJavaCallbackSkeleton(methods, intDecl, callbackClasses); - // Write waitRequestInvokeMethod() - main loop - writeJavaCallbackWaitRequestInvokeMethod(methods, intDecl, callbackExist); - println("}"); - pw.close(); - System.out.println("IoTCompiler: Generated callback skeleton class " + newSkelClass + ".java..."); + + // Check if there is more than 1 class that uses the same interface + List 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 methods = intDecl.getMethods(); + Set importClasses = getImportClasses(methods, intDecl); + List stdImportClasses = getStandardJavaImportClasses(); + List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); + // Find out if there are callback objects + Set 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..."); + } } } + +/*================================================================================ + * + * C++ generation + * + *================================================================================/ /** * HELPER: writeMethodCplusLocalInterface() writes the method of the local interface @@ -2465,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); @@ -2473,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__"); @@ -2506,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); @@ -2514,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__"); @@ -2552,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__"); @@ -2567,7 +2526,9 @@ public class IoTCompiler { Set includeClasses = getIncludeClasses(methods, intDecl, intface, true); printIncludeStatements(includeClasses); println(""); println("using namespace std;\n"); - //writeStructCplus(structDecl); + Set callbackClasses = getCallbackClasses(methods, intDecl); + if (!intface.equals(mainClass)) // Forward declare if not main class + writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, true); println("class " + intface); println("{"); println("public:"); // Write methods @@ -2580,6 +2541,33 @@ public class IoTCompiler { } + /** + * HELPER: writeMethodCplusInterfaceForwardDecl() writes the forward declaration of the interface + */ + private void writeMethodCplusInterfaceForwardDecl(Collection methods, InterfaceDecl intDecl, Set callbackClasses, boolean needNewIntface) { + + Set isDefined = new HashSet(); + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + for (int i = 0; i < methParams.size(); i++) { + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); + // Check if this has callback object + if (callbackClasses.contains(paramType)) { + if (!isDefined.contains(paramType)) { + if (needNewIntface) + println("class " + getStubInterface(paramType) + ";\n"); + else + println("class " + paramType + ";\n"); + isDefined.add(paramType); + } + } + } + } + } + + /** * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++ *

@@ -2589,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> mapNewIntMethods = mapInt2NewInts.get(intface); @@ -2608,10 +2597,10 @@ public class IoTCompiler { // Pass in set of methods and get import classes Set methods = intMeth.getValue(); Set includeClasses = getIncludeClasses(methods, intDecl, intface, false); - List stdIncludeClasses = getStandardCplusIncludeClasses(); - List allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses); - printIncludeStatements(allIncludeClasses); println(""); + printIncludeStatements(includeClasses); println(""); println("using namespace std;\n"); + Set callbackClasses = getCallbackClasses(methods, intDecl); + writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, false); println("class " + newIntface); println("{"); println("public:"); @@ -2626,27 +2615,58 @@ public class IoTCompiler { } + /** + * HELPER: writeMethodDeclCplusStub() writes the method declarations of the stub + */ + private void writeMethodDeclCplusStub(Collection methods, InterfaceDecl intDecl) { + + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " + + intDecl.getMethodId(method) + "("); + for (int i = 0; i < methParams.size(); i++) { + + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); + String methPrmType = checkAndGetCplusType(methPrmTypes.get(i)); + String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i)); + print(methParamComplete); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } + } + println(");"); + } + } + + /** * HELPER: writeMethodCplusStub() writes the methods of the stub */ private void writeMethodCplusStub(Collection methods, InterfaceDecl intDecl, Set callbackClasses, String newStubClass) { - boolean isDefined = false; for (String method : methods) { List methParams = intDecl.getMethodParams(method); List methPrmTypes = intDecl.getMethodParamTypes(method); - print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " + + // Print the mutex lock first + int methodNumId = intDecl.getMethodNumId(method); + String mutexVar = "mtx" + newStubClass + "MethodExec" + methodNumId; + println("mutex " + mutexVar + ";"); + print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " + newStubClass + "::" + intDecl.getMethodId(method) + "("); boolean isCallbackMethod = false; - String callbackType = null; + Set callbackType = new HashSet(); 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)); @@ -2658,50 +2678,67 @@ public class IoTCompiler { } } println(") { "); + println("lock_guard guard(" + mutexVar + ");"); if (isCallbackMethod) writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType); writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType, isCallbackMethod); println("}\n"); - // Write the init callback helper method - if (isCallbackMethod && !isDefined) { - writeInitCallbackCplusStub(callbackType, intDecl, newStubClass); - writeInitCallbackSendInfoCplusStub(intDecl); - isDefined = true; - } + } } + /** + * HELPER: writeCallbackInstantiationMethodBodyCplusStub() writes the callback object instantiation in the method of the stub class + */ + private void writeCallbackInstantiationMethodBodyCplusStub(String paramIdent, String callbackType, int counter) { + + println("auto it" + counter + " = IoTRMIUtil::mapSkel->find(" + paramIdent + ");"); + println("if (it" + counter + " == IoTRMIUtil::mapSkel->end()) {"); + println("int newObjIdSent = rmiComm->getObjectIdCounter();"); + println("objIdSent" + counter + ".push_back(newObjIdSent);"); + println("rmiComm->decrementObjectIdCounter();"); + println(callbackType + "_Skeleton* skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);"); + println("IoTRMIUtil::mapSkel->insert(make_pair(" + paramIdent + ", skel" + counter + "));"); + println("IoTRMIUtil::mapSkelId->insert(make_pair(" + paramIdent + ", newObjIdSent));"); + 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" + counter + ".push_back(itId->second);"); + println("}"); + } + + /** * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class */ private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List methParams, - List methPrmTypes, String method, String callbackType) { + List methPrmTypes, String method, Set callbackType) { // Check if this is single object, array, or list of objects boolean isArrayOrList = false; String callbackParam = null; 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 objIdSent" + i + ";"); String param = methParams.get(i); - if (isArrayOrList(paramType, param)) { // Generate loop + if (isArrayOrList(paramType, param)) { // Generate loop println("for (" + getGenericType(paramType) + "* cb : " + getSimpleIdentifier(param) + ") {"); - println(callbackType + "_CallbackSkeleton* skel" + i + " = new " + callbackType + "_CallbackSkeleton(cb, callbackAddress, objIdCnt++);"); + writeCallbackInstantiationMethodBodyCplusStub("cb", returnGenericCallbackType(paramType), i); isArrayOrList = true; callbackParam = getSimpleIdentifier(param); - } else - println(callbackType + "_CallbackSkeleton* skel" + i + " = new " + callbackType + "_CallbackSkeleton(" + - getSimpleIdentifier(param) + ", callbackAddress, objIdCnt++);"); - println("vecCallbackObj.push_back(skel" + i + ");"); + } else { + writeCallbackInstantiationMethodBodyCplusStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i); + } if (isArrayOrList) println("}"); - print("int ___paramCB" + i + " = "); - if (isArrayOrList) - println(callbackParam + ".size();"); - else - println("1;"); + println("vector ___paramCB" + i + " = objIdSent" + i + ";"); } } } @@ -2736,7 +2773,7 @@ public class IoTCompiler { /** * HELPER: checkAndWriteEnumRetTypeCplusStub() writes the enum return type (convert from enum to int) */ - private void checkAndWriteEnumRetTypeCplusStub(String retType) { + private void checkAndWriteEnumRetTypeCplusStub(String retType, String method, InterfaceDecl intDecl) { // Strips off array "[]" for return type String pureType = getSimpleArrayType(getGenericType(retType)); @@ -2747,7 +2784,8 @@ public class IoTCompiler { // Check if this is enum type println("vector retEnumInt;"); println("void* retObj = &retEnumInt;"); - println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);"); + println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);"); + writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);"); if (isArrayOrList(retType, retType)) { // An array or vector println("int retLen = retEnumInt.size();"); println("vector<" + pureType + "> retVal(retLen);"); @@ -2779,7 +2817,7 @@ public class IoTCompiler { int methodNumId = intDecl.getMethodNumId(method); String helperMethod = methodNumId + "struct" + i; println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";"); - println("string retTypeStruct" + i + " = \"void\";"); + //println("string retTypeStruct" + i + " = \"void\";"); println("string paramClsStruct" + i + "[] = { \"int\" };"); print("int structLen" + i + " = "); if (isArrayOrList(paramType, param)) { // An array @@ -2788,10 +2826,9 @@ public class IoTCompiler { println("1;"); } println("void* paramObjStruct" + i + "[] = { &structLen" + i + " };"); - println("void* retStructLen" + i + " = NULL;"); - println("rmiCall->remoteCall(objectId, methodIdStruct" + i + - ", retTypeStruct" + i + ", paramClsStruct" + i + ", paramObjStruct" + i + - ", numParam" + i + ", retStructLen" + i + ");\n"); + println("rmiComm->remoteCall(objectId, methodIdStruct" + i + + ", paramClsStruct" + i + ", paramObjStruct" + i + + ", numParam" + i + ");\n"); } } } @@ -2859,7 +2896,7 @@ public class IoTCompiler { /** * HELPER: writeStructParamClassCplusStub() writes member parameters of struct */ - private void writeStructParamClassCplusStub(List methParams, List methPrmTypes, String callbackType) { + private void writeStructParamClassCplusStub(List methParams, List methPrmTypes, Set callbackType) { print("int numParam = "); writeLengthStructParamClassCplusStub(methParams, methPrmTypes); @@ -2922,13 +2959,14 @@ public class IoTCompiler { /** * HELPER: writeStructReturnCplusStub() writes member parameters of struct for return statement */ - private void writeStructReturnCplusStub(String simpleType, String retType) { + private void writeStructReturnCplusStub(String simpleType, String retType, String method, InterfaceDecl intDecl) { // Minimum retLen is 1 if this is a single struct object println("int retLen = 0;"); println("void* retLenObj = { &retLen };"); // Handle the returned struct!!! - println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retLenObj);"); + println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);"); + writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retLenObj);"); int numMem = getNumOfMembers(simpleType); println("int numRet = " + numMem + "*retLen;"); println("string retCls[numRet];"); @@ -2967,7 +3005,7 @@ public class IoTCompiler { println("retObj[retPos++] = &retParam" + i + ";"); } } - println("rmiCall->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);"); } else @@ -2976,11 +3014,25 @@ public class IoTCompiler { } + /** + * HELPER: writeWaitForReturnValueCplus() writes the synchronization part for return values + */ + private void writeWaitForReturnValueCplus(String method, InterfaceDecl intDecl, String getReturnValue) { + + println("// Waiting for return value"); + int methodNumId = intDecl.getMethodNumId(method); + println("while (!retValueReceived" + methodNumId + ");"); + println(getReturnValue); + println("retValueReceived" + methodNumId + " = false;"); + println("didGetReturnBytes.exchange(true);\n"); + } + + /** * HELPER: writeStdMethodBodyCplusStub() writes the standard method body in the stub class */ private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List methParams, - List methPrmTypes, String method, String callbackType, boolean isCallbackMethod) { + List methPrmTypes, String method, Set callbackType, boolean isCallbackMethod) { checkAndWriteStructSetupCplusStub(methParams, methPrmTypes, intDecl, method); println("int methodId = " + intDecl.getMethodNumId(method) + ";"); @@ -2996,7 +3048,7 @@ public class IoTCompiler { for (int i = 0; i < methParams.size(); i++) { String paramType = returnGenericCallbackType(methPrmTypes.get(i)); if (checkCallbackType(paramType, callbackType)) { - print("\"int\""); + print("\"int*\""); } else { String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i)); print("\"" + paramTypeC + "\""); @@ -3024,16 +3076,15 @@ public class IoTCompiler { } // Check if this is "void" if (retType.equals("void")) { - println("void* retObj = NULL;"); - println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);"); + println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);"); } else { // We do have a return value // Generate array of parameter types if (isStructClass(getGenericType(getSimpleArrayType(retType)))) { - writeStructReturnCplusStub(getGenericType(getSimpleArrayType(retType)), retType); + writeStructReturnCplusStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl); } else { // Check if the return value NONPRIMITIVES if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { - checkAndWriteEnumRetTypeCplusStub(retType); + checkAndWriteEnumRetTypeCplusStub(retType, method, intDecl); } else { //if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) if (isArrayOrList(retType,retType)) @@ -3042,7 +3093,8 @@ public class IoTCompiler { println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";"); } println("void* retObj = &retVal;"); - println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);"); + println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);"); + writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);"); println("return retVal;"); } } @@ -3051,7 +3103,7 @@ public class IoTCompiler { /** - * HELPER: writePropertiesCplusStub() writes the properties of the stub class + * HELPER: writePropertiesCplusPermission() writes the properties of the stub class */ private void writePropertiesCplusPermission(String intface) { @@ -3059,7 +3111,6 @@ public class IoTCompiler { for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { String newIntface = intMeth.getKey(); int newObjectId = getNewIntfaceObjectId(newIntface); - println("const static int object" + newObjectId + "Id = " + newObjectId + ";\t//" + newIntface); println("static set set" + newObjectId + "Allowed;"); } } @@ -3067,24 +3118,21 @@ public class IoTCompiler { /** * HELPER: writePropertiesCplusStub() writes the properties of the stub class */ - private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist, Set callbackClasses) { + private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist, + Set callbackClasses, Set methods, InterfaceDecl intDecl) { - println("IoTRMICall *rmiCall;"); - println("string callbackAddress;"); - println("vector ports;\n"); + println("IoTRMIComm *rmiComm;"); // Get the object Id Integer objId = mapIntfaceObjId.get(intface); - println("const static 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("IoTRMIObject *rmiObj;"); - println("vector<" + callbackType + "*> vecCallbackObj;"); - println("static int objIdCnt;"); - // Generate permission stuff for callback stubs - writePropertiesCplusPermission(callbackType); + println("int objectId = " + objId + ";"); + println("// Synchronization variables"); + for (String method : methods) { + // Generate AtomicBooleans for methods that have return values + String returnType = intDecl.getMethodType(method); + int methodNumId = intDecl.getMethodNumId(method); + if (!returnType.equals("void")) { + println("bool retValueReceived" + methodNumId + " = false;"); + } } println("\n"); } @@ -3093,302 +3141,205 @@ public class IoTCompiler { /** * HELPER: writeConstructorCplusStub() writes the constructor of the stub class */ - private void writeConstructorCplusStub(String newStubClass, boolean callbackExist, Set callbackClasses) { - - println(newStubClass + - "(int _port, const char* _skeletonAddress, string _callbackAddress, int _rev, bool* _bResult, vector _ports) {"); - println("callbackAddress = _callbackAddress;"); - println("ports = _ports;"); - println("rmiCall = new IoTRMICall(_port, _skeletonAddress, _rev, _bResult);"); - if (callbackExist) { - Iterator it = callbackClasses.iterator(); - String callbackType = (String) it.next(); - DeclarationHandler decHandler = mapIntDeclHand.get(callbackType); - InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType); - writeCplusInitCallbackPermission(callbackType, intDecl, callbackExist); - println("thread th1 (&" + newStubClass + "::___initCallBack, this);"); - println("th1.detach();"); - println("___regCB();"); - } - println("}\n"); - } - - - /** - * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class - */ - private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set callbackClasses) { - - println("~" + newStubClass + "() {"); - println("if (rmiCall != NULL) {"); - println("delete rmiCall;"); - println("rmiCall = NULL;"); - println("}"); - if (callbackExist) { - // We assume that each class only has one callback interface for now - println("if (rmiObj != NULL) {"); - println("delete rmiObj;"); - println("rmiObj = NULL;"); - println("}"); - 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) { + private void writeConstructorCplusStub(String newStubClass, boolean callbackExist, + Set callbackClasses, Set methods, InterfaceDecl intDecl) { - println("int methodId = IoTRMIObject::getMethodId(method);"); - // Get all the different stubs - Map> mapNewIntMethods = mapInt2NewInts.get(intface); - for (Map.Entry> 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("}"); + println(newStubClass + "::" + newStubClass + + "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult) {"); + println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev, _bResult);"); + // Register the AtomicBoolean variables + for (String method : methods) { + // Generate AtomicBooleans for methods that have return values + String returnType = intDecl.getMethodType(method); + int methodNumId = intDecl.getMethodNumId(method); + if (!returnType.equals("void")) { + println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");"); + } } - } - - - /** - * HELPER: writeInitCallbackCplusStub() writes the initialization of callback - */ - private void writeInitCallbackCplusStub(String intface, InterfaceDecl intDecl, String newStubClass) { - - println("void ___initCallBack() {"); - println("bool bResult = false;"); - int port = getPortCount(newStubClass); - println("rmiObj = new IoTRMIObject(ports[" + port + "], &bResult);"); - println("while (true) {"); - println("char* method = rmiObj->getMethodBytes();"); - //writeCplusMethodCallbackPermission(intface); - println("int objId = IoTRMIObject::getObjectId(method);"); - println("if (objId < vecCallbackObj.size()) { // Check if still within range"); - println(intface + "_CallbackSkeleton* skel = dynamic_cast<" + intface + - "_CallbackSkeleton*> (vecCallbackObj.at(objId));"); - writeCplusMethodCallbackPermission(intface); - println("skel->invokeMethod(rmiObj);"); - print("}"); - println(" else {"); - println("cerr << \"Illegal object Id: \" << to_string(objId);"); - // TODO: perhaps need to change this into "throw" to make it cleaner (allow stack unfolding) - println("return;"); - println("}"); - println("}"); + println("IoTRMIUtil::mapStub->insert(make_pair(objectId, this));"); println("}\n"); } /** - * HELPER: writeCplusInitCallbackPermission() writes the permission for callback + * HELPER: writeCallbackConstructorCplusStub() writes the callback constructor of the stub class */ - private void writeCplusInitCallbackPermission(String intface, InterfaceDecl intDecl, boolean callbackExist) { + private void writeCallbackConstructorCplusStub(String newStubClass, boolean callbackExist, + Set callbackClasses, Set methods, InterfaceDecl intDecl) { - if (callbackExist) { - String method = "___initCallBack()"; - int methodNumId = intDecl.getHelperMethodNumId(method); - Map> mapNewIntMethods = mapInt2NewInts.get(intface); - for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { - String newIntface = intMeth.getKey(); - int newObjectId = getNewIntfaceObjectId(newIntface); - println("set" + newObjectId + "Allowed.insert(" + methodNumId + ");"); + println(newStubClass + "::" + newStubClass + "(IoTRMIComm* _rmiComm, int _objectId) {"); + println("rmiComm = _rmiComm;"); + println("objectId = _objectId;"); + // Register the AtomicBoolean variables + for (String method : methods) { + // Generate AtomicBooleans for methods that have return values + String returnType = intDecl.getMethodType(method); + int methodNumId = intDecl.getMethodNumId(method); + if (!returnType.equals("void")) { + println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");"); } } + println("}\n"); } /** - * HELPER: writeInitCallbackSendInfoCplusStub() writes the initialization (send info part) of callback + * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class */ - private void writeInitCallbackSendInfoCplusStub(InterfaceDecl intDecl) { + private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set callbackClasses) { - // Generate info sending part - println("void ___regCB() {"); - println("int numParam = 3;"); - String method = "___initCallBack()"; - int methodNumId = intDecl.getHelperMethodNumId(method); - println("int methodId = " + methodNumId + ";"); - println("string retType = \"void\";"); - println("string paramCls[] = { \"int*\", \"String\", \"int\" };"); - println("int rev = 0;"); - println("void* paramObj[] = { &ports, &callbackAddress, &rev };"); - println("void* retObj = NULL;"); - println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);"); - println("}\n"); + println(newStubClass + "::~" + newStubClass + "() {"); + println("if (rmiComm != NULL) {"); + println("delete rmiComm;"); + println("rmiComm = NULL;"); + println("}"); + println("}"); + println(""); } /** - * generateCPlusStubClasses() generate stubs based on the methods list in C++ + * generateCPlusStubClassesHpp() generate stubs based on the methods list in C++ (.hpp file) */ - public void generateCPlusStubClasses() throws IOException { + public void generateCPlusStubClassesHpp() throws IOException { // Create a new directory String path = createDirectories(dir, subdir); for (String intface : mapIntfacePTH.keySet()) { - Map> mapNewIntMethods = mapInt2NewInts.get(intface); - for (Map.Entry> 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 "); - // Find out if there are callback objects - Set methods = intMeth.getValue(); - DeclarationHandler decHandler = mapIntDeclHand.get(intface); - InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); - Set callbackClasses = getCallbackClasses(methods, intDecl); - boolean callbackExist = !callbackClasses.isEmpty(); - if (callbackExist) // Need thread library if this has callback + // Check if there is more than 1 class that uses the same interface + List drvList = mapInt2Drv.get(intface); + for(int i = 0; i < drvList.size(); i++) { + + String driverClass = drvList.get(i); + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> 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 "); + // Find out if there are callback objects + Set methods = intMeth.getValue(); + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + Set callbackClasses = getCallbackClasses(methods, intDecl); + boolean callbackExist = !callbackClasses.isEmpty(); println("#include "); - println("#include \"" + newIntface + ".hpp\""); println(""); - println("using namespace std;"); println(""); - println("class " + newStubClass + " : public " + newIntface); println("{"); - println("private:\n"); - writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses); - println("public:\n"); - // Add default constructor and destructor - println(newStubClass + "() { }"); println(""); - writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses); - writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses); - // Write methods - writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass); - print("}"); println(";"); - if (callbackExist) { - Iterator it = callbackClasses.iterator(); - String callbackType = (String) it.next(); - // Generate permission stuff for callback stubs - DeclarationHandler decHandlerCallback = mapIntDeclHand.get(callbackType); - InterfaceDecl intDeclCallback = (InterfaceDecl) decHandlerCallback.getInterfaceDecl(callbackType); - writePermissionInitializationCplus(callbackType, newStubClass, intDeclCallback); + println("#include "); + List 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..."); } - writeObjectIdCountInitializationCplus(newStubClass, callbackExist); - println("#endif"); - pw.close(); - System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp..."); } } } /** - * HELPER: writePropertiesCplusCallbackStub() writes the properties of the stub class - */ - private void writePropertiesCplusCallbackStub(String intface, String newIntface, boolean callbackExist, Set callbackClasses) { - - println("IoTRMICall *rmiCall;"); - // Get the object Id - println("int objectId;"); - println("vector ports;\n"); - println("string callbackAddress;"); - 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("IoTRMIObject *rmiObj;"); - println("vector<" + callbackType + "*> vecCallbackObj;"); - println("static int objIdCnt;"); - // TODO: Need to initialize address and ports if we want to have callback-in-callback - writePropertiesCplusPermission(callbackType); - } - println("\n"); - } - - - /** - * HELPER: writeConstructorCplusCallbackStub() writes the constructor of the stub class + * writeStubExternalCFunctions() generate external functions for .so file */ - private void writeConstructorCplusCallbackStub(String newStubClass, boolean callbackExist, Set callbackClasses) { + public void writeStubExternalCFunctions(String newStubClass) throws IOException { - println(newStubClass + "(IoTRMICall* _rmiCall, string _callbackAddress, int _objectId, vector _ports) {"); - println("objectId = _objectId;"); - println("callbackAddress = _callbackAddress;"); - println("rmiCall = _rmiCall;"); - println("ports = _ports;"); - if (callbackExist) { - Iterator it = callbackClasses.iterator(); - String callbackType = (String) it.next(); - DeclarationHandler decHandler = mapIntDeclHand.get(callbackType); - InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType); - writeCplusInitCallbackPermission(callbackType, intDecl, callbackExist); - println("thread th1 (&" + newStubClass + "::___initCallBack, this);"); - println("th1.detach();"); - println("___regCB();"); - } + println("extern \"C\" void* create" + newStubClass + "(void** params) {"); + println("// Args: int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult"); + println("return new " + newStubClass + "(*((int*) params[0]), *((int*) params[1]), ((string*) params[2])->c_str(), " + + "*((int*) params[3]), (bool*) params[4]);"); + println("}\n"); + println("extern \"C\" void destroy" + newStubClass + "(void* t) {"); + println(newStubClass + "* obj = (" + newStubClass + "*) t;"); + println("delete obj;"); + println("}\n"); + println("extern \"C\" void init" + newStubClass + "(void* t) {"); println("}\n"); } /** - * generateCPlusCallbackStubClasses() generate callback stubs based on the methods list in C++ + * generateCPlusStubClassesCpp() generate stubs based on the methods list in C++ (.cpp file) */ - public void generateCPlusCallbackStubClasses() throws IOException { + public void generateCPlusStubClassesCpp() throws IOException { // Create a new directory String path = createDirectories(dir, subdir); for (String intface : mapIntfacePTH.keySet()) { - Map> mapNewIntMethods = mapInt2NewInts.get(intface); - for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { - // Open a new file to write into - String newIntface = intMeth.getKey(); - String newStubClass = newIntface + "_CallbackStub"; - FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp"); - pw = new PrintWriter(new BufferedWriter(fw)); - // Find out if there are callback objects - Set methods = intMeth.getValue(); - DeclarationHandler decHandler = mapIntDeclHand.get(intface); - InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); - Set callbackClasses = getCallbackClasses(methods, intDecl); - boolean callbackExist = !callbackClasses.isEmpty(); - // Write file headers - println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__"); - println("#define _" + newStubClass.toUpperCase() + "_HPP__"); - println("#include "); - if (callbackExist) - println("#include "); - println("#include \"" + newIntface + ".hpp\""); println(""); - println("using namespace std;"); println(""); - println("class " + newStubClass + " : public " + newIntface); println("{"); - println("private:\n"); - writePropertiesCplusCallbackStub(intface, newIntface, callbackExist, callbackClasses); - println("public:\n"); - // Add default constructor and destructor - println(newStubClass + "() { }"); println(""); - writeConstructorCplusCallbackStub(newStubClass, callbackExist, callbackClasses); - writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses); - // Write methods - writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass); - println("};"); - if (callbackExist) { - Iterator it = callbackClasses.iterator(); - String callbackType = (String) it.next(); - // Generate permission stuff for callback stubs - DeclarationHandler decHandlerCallback = mapIntDeclHand.get(callbackType); - InterfaceDecl intDeclCallback = (InterfaceDecl) decHandlerCallback.getInterfaceDecl(callbackType); - writePermissionInitializationCplus(callbackType, newStubClass, intDeclCallback); + // Check if there is more than 1 class that uses the same interface + List drvList = mapInt2Drv.get(intface); + for(int i = 0; i < drvList.size(); i++) { + + String driverClass = drvList.get(i); + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> 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 + ".cpp"); + pw = new PrintWriter(new BufferedWriter(fw)); + // Write file headers + println("#include "); + // Find out if there are callback objects + Set methods = intMeth.getValue(); + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + Set 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..."); } - writeObjectIdCountInitializationCplus(newStubClass, callbackExist); - println("#endif"); - pw.close(); - System.out.println("IoTCompiler: Generated callback stub class " + newIntface + ".hpp..."); } } } @@ -3400,21 +3351,16 @@ public class IoTCompiler { private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set callbackClasses) { println(intface + " *mainObj;"); - println("vector ports;"); - println("string callbackAddress;"); - // Callback - if (callbackExist) { - Iterator it = callbackClasses.iterator(); - String callbackType = (String) it.next(); - String exchangeType = checkAndGetParamClass(callbackType); - println("// Callback properties"); - println("static int objIdCnt;"); - println("vector<" + exchangeType + "*> vecCallbackObj;"); - println("IoTRMICall *rmiCall;"); - } - println("IoTRMIObject *rmiObj;\n"); + 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"); + println("bool methodReceived = false;"); + println("bool didAlreadyInitWaitInvoke = false;"); println("\n"); } @@ -3492,14 +3438,32 @@ public class IoTCompiler { */ private void writeConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection methods) { - println(newSkelClass + "(" + intface + " *_mainObj, string _callbackAddress, int _port) {"); + println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, int _portSend, int _portRecv) {"); println("bool _bResult = false;"); println("mainObj = _mainObj;"); - println("callbackAddress = _callbackAddress;"); - println("rmiObj = new IoTRMIObject(_port, &_bResult);"); - writeCplusInitCallbackPermission(intface, intDecl, callbackExist); + println("rmiComm = new IoTRMICommServer(_portSend, _portRecv, &_bResult);"); + println("IoTRMIUtil::mapSkel->insert(make_pair(_mainObj, this));"); + println("IoTRMIUtil::mapSkelId->insert(make_pair(_mainObj, objectId));"); + println("rmiComm->registerSkeleton(objectId, &methodReceived);"); + writeStructPermissionCplusSkeleton(methods, intDecl, intface); + println("thread th1 (&" + newSkelClass + "::___waitRequestInvokeMethod, this, this);"); + println("th1.join();"); + println("}\n"); + } + + + /** + * HELPER: writeCallbackConstructorCplusSkeleton() writes the callback constructor of the skeleton class + */ + private void writeCallbackConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection methods) { + + println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, IoTRMIComm *_rmiComm, int _objectId) {"); + println("bool _bResult = false;"); + println("mainObj = _mainObj;"); + println("rmiComm = _rmiComm;"); + println("objectId = _objectId;"); + println("rmiComm->registerSkeleton(objectId, &methodReceived);"); writeStructPermissionCplusSkeleton(methods, intDecl, intface); - println("___waitRequestInvokeMethod();"); println("}\n"); } @@ -3509,25 +3473,11 @@ public class IoTCompiler { */ private void writeDeconstructorCplusSkeleton(String newSkelClass, boolean callbackExist, Set callbackClasses) { - println("~" + newSkelClass + "() {"); - println("if (rmiObj != NULL) {"); - println("delete rmiObj;"); - println("rmiObj = NULL;"); + println(newSkelClass + "::~" + newSkelClass + "() {"); + println("if (rmiComm != NULL) {"); + println("delete rmiComm;"); + println("rmiComm = NULL;"); println("}"); - if (callbackExist) { - // We assume that each class only has one callback interface for now - println("if (rmiCall != NULL) {"); - println("delete rmiCall;"); - println("rmiCall = NULL;"); - println("}"); - 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(""); } @@ -3555,41 +3505,11 @@ public class IoTCompiler { /** - * HELPER: writeInitCallbackCplusSkeleton() writes the init callback method for skeleton class - */ - private void writeInitCallbackCplusSkeleton(boolean callbackSkeleton, String intface) { - - // This is a callback skeleton generation - if (callbackSkeleton) - println("void ___regCB(IoTRMIObject* rmiObj) {"); - else - println("void ___regCB() {"); - println("int numParam = 3;"); - println("vector param1;"); - println("string param2 = \"\";"); - println("int param3 = 0;"); - println("string paramCls[] = { \"int*\", \"String\", \"int\" };"); - println("void* paramObj[] = { ¶m1, ¶m2, ¶m3 };"); - println("rmiObj->getMethodParams(paramCls, numParam, paramObj);"); - println("bool bResult = false;"); - String stubInt = null; - if (callbackSkeleton) - stubInt = getStubInterface(intface) + "_CallbackStub"; - else - stubInt = getStubInterface(intface) + "_Stub"; - int port = getPortCount(stubInt); - println("rmiCall = new IoTRMICall(param1[" + port + "], param2.c_str(), param3, &bResult);"); - println("}\n"); - } - - - /** - * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class + * HELPER: writeMethodDeclCplusSkeleton() writes the method declaration of the skeleton class */ - private void writeMethodCplusSkeleton(Collection methods, InterfaceDecl intDecl, - Set callbackClasses, boolean callbackSkeleton, String intface) { + private void writeMethodDeclCplusSkeleton(Collection methods, InterfaceDecl intDecl, + Set callbackClasses) { - boolean isDefined = false; for (String method : methods) { List methParams = intDecl.getMethodParams(method); @@ -3615,14 +3535,39 @@ public class IoTCompiler { print(", "); } } + println(");"); + } + } + + + /** + * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class + */ + private void writeMethodCplusSkeleton(Collection methods, InterfaceDecl intDecl, String newSkelClass) { + + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + String methodId = intDecl.getMethodId(method); + String methodType = checkAndGetCplusType(intDecl.getMethodType(method)); + print(methodType + " " + newSkelClass + "::" + methodId + "("); + for (int i = 0; i < methParams.size(); i++) { + + String origParamType = methPrmTypes.get(i); + String paramType = checkAndGetParamClass(methPrmTypes.get(i)); + String methPrmType = checkAndGetCplusType(paramType); + String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i)); + print(methParamComplete); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } + } println(") {"); // Now, write the body of skeleton! writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method)); println("}\n"); - if (isCallbackMethod && !isDefined) { - writeInitCallbackCplusSkeleton(callbackSkeleton, intface); - isDefined = true; - } } } @@ -3630,22 +3575,40 @@ public class IoTCompiler { /** * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable */ - private void writeCallbackCplusNumStubs(List methParams, List methPrmTypes, String callbackType) { + private void writeCallbackCplusNumStubs(List methParams, List methPrmTypes, Set 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 numStubIdArray" + i + ";"); } } + /** + * HELPER: writeCallbackInstantiationCplusStubGeneration() writes the instantiation of callback stubs + */ + private void writeCallbackInstantiationCplusStubGeneration(String exchParamType, int counter) { + + 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("}"); + println("else {"); + println("newStub" + counter + " = (" + exchParamType + "_Stub*) it" + counter + "->second;"); + println("}"); + } + + /** * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part */ - private void writeCallbackCplusStubGeneration(List methParams, List methPrmTypes, String callbackType) { + private void writeCallbackCplusStubGeneration(List methParams, List methPrmTypes, Set callbackType) { // Iterate over callback objects for (int i = 0; i < methParams.size(); i++) { @@ -3656,16 +3619,15 @@ public class IoTCompiler { String exchParamType = checkAndGetParamClass(getGenericType(paramType)); if (isArrayOrList(paramType, param)) { println("vector<" + exchParamType + "*> stub" + i + ";"); - println("for (int objId = 0; objId < numStubs" + i + "; objId++) {"); - println(exchParamType + "* cb" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);"); - println("stub" + i + ".push_back(cb" + i + ");"); - println("vecCallbackObj.push_back(cb" + i + ");"); - println("objIdCnt++;"); + println("for (int i = 0; i < numStubIdArray" + i + ".size(); i++) {"); + println("int objIdRecv" + i + " = numStubIdArray" + i + "[i];"); + writeCallbackInstantiationCplusStubGeneration(exchParamType, i); + println("stub" + i + ".push_back(newStub" + i + ");"); println("}"); } else { - println(exchParamType + "* stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);"); - println("vecCallbackObj.push_back(stub" + i + ");"); - println("objIdCnt++;"); + println("int objIdRecv" + i + " = numStubIdArray" + i + "[0];"); + writeCallbackInstantiationCplusStubGeneration(exchParamType, i); + println(exchParamType + "* stub" + i + " = newStub" + i + ";"); } } } @@ -3755,10 +3717,10 @@ public class IoTCompiler { * HELPER: writeMethodHelperReturnCplusSkeleton() writes the return statement part in skeleton */ private void writeMethodHelperReturnCplusSkeleton(InterfaceDecl intDecl, List methParams, - List methPrmTypes, String method, boolean isCallbackMethod, String callbackType, + List methPrmTypes, String method, boolean isCallbackMethod, Set callbackType, String methodId, Set callbackClasses) { - println("rmiObj->getMethodParams(paramCls, numParam, paramObj);"); + println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);"); if (isCallbackMethod) writeCallbackCplusStubGeneration(methParams, methPrmTypes, callbackType); checkAndWriteEnumTypeCplusSkeleton(methParams, methPrmTypes); @@ -3786,9 +3748,9 @@ public class IoTCompiler { println("void* retObj = &retVal;"); String retTypeC = checkAndGetCplusType(retType); if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type - println("rmiObj->sendReturnObj(retObj, retCls, numRetObj);"); + println("rmiComm->sendReturnObj(retObj, retCls, numRetObj, localMethodBytes);"); else - println("rmiObj->sendReturnObj(retObj, \"" + checkAndGetCplusRetClsType(getEnumType(retType)) + "\");"); + println("rmiComm->sendReturnObj(retObj, \"" + checkAndGetCplusRetClsType(getEnumType(retType)) + "\", localMethodBytes);"); } } @@ -3801,14 +3763,14 @@ public class IoTCompiler { // Generate array of parameter types boolean isCallbackMethod = false; - String callbackType = null; + Set callbackType = new HashSet(); 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; - print("\"int\""); + 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)); print("\"" + paramTypeC + "\""); @@ -3841,7 +3803,7 @@ public class IoTCompiler { for (int i = 0; i < methParams.size(); i++) { String paramType = returnGenericCallbackType(methPrmTypes.get(i)); if (callbackClasses.contains(paramType)) - print("&numStubs" + i); + print("&numStubIdArray" + i); else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type print("¶mEnumInt" + i); else @@ -3954,7 +3916,7 @@ public class IoTCompiler { else // Just single struct object println("int retLen = 1;"); println("void* retLenObj = &retLen;"); - println("rmiObj->sendReturnObj(retLenObj, \"int\");"); + println("rmiComm->sendReturnObj(retLenObj, \"int\", localMethodBytes);"); int numMem = getNumOfMembers(simpleType); println("int numRetObj = " + numMem + "*retLen;"); println("string retCls[numRetObj];"); @@ -3995,7 +3957,7 @@ public class IoTCompiler { // Generate array of parameter objects boolean isCallbackMethod = false; - String callbackType = null; + Set callbackType = new HashSet(); print("int numParam = "); writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl); println(";"); @@ -4013,10 +3975,10 @@ public class IoTCompiler { String prmType = returnGenericCallbackType(methPrmTypes.get(i)); if (callbackClasses.contains(prmType)) { isCallbackMethod = true; - callbackType = prmType; - println("int numStubs" + i + " = 0;"); - println("paramCls[pos] = \"int\";"); - println("paramObj[pos++] = &numStubs" + i + ";"); + callbackType.add(prmType); + println("vector numStubIdArray" + i + ";"); + println("paramCls[pos] = \"int*\";"); + println("paramObj[pos++] = &numStubIdArray" + i + ";"); } else { // Generate normal classes if it's not a callback object String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i)); if (isEnumClass(getGenericType(paramTypeC))) { // Check if this is enum type @@ -4034,16 +3996,109 @@ public class IoTCompiler { } } } - // Write the return value part - writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, - callbackType, methodId, callbackClasses); + // Write the return value part + writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, + callbackType, methodId, callbackClasses); + } + + + /** + * HELPER: writeMethodHelperDeclCplusSkeleton() writes the method helper declarations of the skeleton class + */ + private void writeMethodHelperDeclCplusSkeleton(Collection methods, InterfaceDecl intDecl, String newSkelClass) { + + // Use this set to handle two same methodIds + Set uniqueMethodIds = new HashSet(); + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently + String methodId = intDecl.getMethodId(method); + print("void ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + intDecl.getMethodNumId(method); + else + uniqueMethodIds.add(methodId); + String retType = intDecl.getMethodType(method); + print(helperMethod + "("); + boolean begin = true; + for (int i = 0; i < methParams.size(); i++) { // Print size variables + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + if (!begin) // Generate comma for not the beginning variable + print(", "); + else + begin = false; + int methodNumId = intDecl.getMethodNumId(method); + print("int struct" + methodNumId + "Size" + i); + } + } + println(", " + newSkelClass + "* skel);"); + } else { + String methodId = intDecl.getMethodId(method); + print("void ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + intDecl.getMethodNumId(method); + else + uniqueMethodIds.add(methodId); + // Check if this is "void" + String retType = intDecl.getMethodType(method); + println(helperMethod + "(" + newSkelClass + "* skel);"); + } + } + // Write method helper for structs + writeMethodHelperStructDeclSetupCplusSkeleton(methods, intDecl, newSkelClass); + } + + + /** + * HELPER: writeMethodHelperStructDeclSetupCplusSkeleton() writes the struct method helper declaration in skeleton class + */ + private void writeMethodHelperStructDeclSetupCplusSkeleton(Collection methods, + InterfaceDecl intDecl, String newSkelClass) { + + // Use this set to handle two same methodIds + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + // Check for params with structs + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + int methodNumId = intDecl.getMethodNumId(method); + print("int ___"); + String helperMethod = methodNumId + "struct" + i; + println(helperMethod + "(" + newSkelClass + "* skel);"); + } + } + } + } + + + /** + * HELPER: writeMethodBytesCopy() writes the methodBytes copy part in C++ skeleton + */ + private void writeMethodBytesCopy() { + + println("char* localMethodBytes = new char[methodLen];"); + println("memcpy(localMethodBytes, skel->methodBytes, methodLen);"); + println("didGetMethodBytes.exchange(true);"); } /** * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class */ - private void writeMethodHelperCplusSkeleton(Collection methods, InterfaceDecl intDecl, Set callbackClasses) { + private void writeMethodHelperCplusSkeleton(Collection methods, InterfaceDecl intDecl, + Set callbackClasses, String newSkelClass) { // Use this set to handle two same methodIds Set uniqueMethodIds = new HashSet(); @@ -4053,7 +4108,7 @@ public class IoTCompiler { List methPrmTypes = intDecl.getMethodParamTypes(method); if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently String methodId = intDecl.getMethodId(method); - print("void ___"); + print("void " + newSkelClass + "::___"); String helperMethod = methodId; if (uniqueMethodIds.contains(methodId)) helperMethod = helperMethod + intDecl.getMethodNumId(method); @@ -4075,12 +4130,14 @@ public class IoTCompiler { print("int struct" + methodNumId + "Size" + i); } } - println(") {"); + println(", " + newSkelClass + "* skel) {"); + writeMethodBytesCopy(); writeMethodHelperStructCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses); + println("delete[] localMethodBytes;"); println("}\n"); } else { String methodId = intDecl.getMethodId(method); - print("void ___"); + print("void " + newSkelClass + "::___"); String helperMethod = methodId; if (uniqueMethodIds.contains(methodId)) helperMethod = helperMethod + intDecl.getMethodNumId(method); @@ -4088,14 +4145,16 @@ public class IoTCompiler { uniqueMethodIds.add(methodId); // Check if this is "void" String retType = intDecl.getMethodType(method); - println(helperMethod + "() {"); + println(helperMethod + "(" + newSkelClass + "* skel) {"); + writeMethodBytesCopy(); // Now, write the helper body of skeleton! writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses); + println("delete[] localMethodBytes;"); println("}\n"); } } // Write method helper for structs - writeMethodHelperStructSetupCplusSkeleton(methods, intDecl); + writeMethodHelperStructSetupCplusSkeleton(methods, intDecl, newSkelClass); } @@ -4103,7 +4162,7 @@ public class IoTCompiler { * HELPER: writeMethodHelperStructSetupCplusSkeleton() writes the method helper of struct in skeleton class */ private void writeMethodHelperStructSetupCplusSkeleton(Collection methods, - InterfaceDecl intDecl) { + InterfaceDecl intDecl, String newSkelClass) { // Use this set to handle two same methodIds for (String method : methods) { @@ -4117,16 +4176,18 @@ public class IoTCompiler { String simpleType = getGenericType(paramType); if (isStructClass(simpleType)) { int methodNumId = intDecl.getMethodNumId(method); - print("int ___"); + print("int " + newSkelClass + "::___"); String helperMethod = methodNumId + "struct" + i; - println(helperMethod + "() {"); + println(helperMethod + "(" + newSkelClass + "* skel) {"); // Now, write the helper body of skeleton! + writeMethodBytesCopy(); println("string paramCls[] = { \"int\" };"); println("int numParam = 1;"); println("int param0 = 0;"); println("void* paramObj[] = { ¶m0 };"); - println("rmiObj->getMethodParams(paramCls, numParam, paramObj);"); + println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);"); println("return param0;"); + println("delete[] localMethodBytes;"); println("}\n"); } } @@ -4160,7 +4221,7 @@ public class IoTCompiler { println("int numParam = 1;"); println("int param0 = 0;"); println("void* paramObj[] = { ¶m0 };"); - println("rmiObj->getMethodParams(paramCls, numParam, paramObj);"); + println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);"); println("return param0;"); println("}\n"); } @@ -4179,15 +4240,14 @@ public class IoTCompiler { for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { String newIntface = intMeth.getKey(); int newObjectId = getNewIntfaceObjectId(newIntface); - println("if (_objectId == object" + newObjectId + "Id) {"); + println("if (_objectId == objectId) {"); println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {"); println("cerr << \"Object with object Id: \" << _objectId << \" is not allowed to access method: \" << methodId << endl;"); println("return;"); println("}"); println("}"); println("else {"); - println("cerr << \"Object Id: \" << _objectId << \" not recognized!\" << endl;"); - println("return;"); + println("continue;"); println("}"); } } @@ -4196,17 +4256,24 @@ public class IoTCompiler { /** * HELPER: writeCplusWaitRequestInvokeMethod() writes the main loop of the skeleton class */ - private void writeCplusWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, boolean callbackExist, String intface) { + private void writeCplusWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, + boolean callbackExist, String intface, String newSkelClass) { // Use this set to handle two same methodIds Set uniqueMethodIds = new HashSet(); - println("void ___waitRequestInvokeMethod() {"); + println("void " + newSkelClass + "::___waitRequestInvokeMethod(" + newSkelClass + "* skel) {"); // Write variables here if we have callbacks or enums or structs writeCountVarStructSkeleton(methods, intDecl); + println("skel->didAlreadyInitWaitInvoke = true;"); println("while (true) {"); - println("rmiObj->getMethodBytes();"); - println("int _objectId = rmiObj->getObjectId();"); - println("int methodId = rmiObj->getMethodId();"); + println("if (!methodReceived) {"); + println("continue;"); + println("}"); + println("skel->methodBytes = skel->rmiComm->getMethodBytes();"); + println("skel->methodLen = skel->rmiComm->getMethodLength();"); + println("methodReceived = false;"); + println("int _objectId = skel->rmiComm->getObjectId(skel->methodBytes);"); + println("int methodId = skel->rmiComm->getMethodId(skel->methodBytes);"); // Generate permission check writeCplusMethodPermission(intface); println("switch (methodId) {"); @@ -4214,26 +4281,25 @@ public class IoTCompiler { for (String method : methods) { String methodId = intDecl.getMethodId(method); int methodNumId = intDecl.getMethodNumId(method); - print("case " + methodNumId + ": ___"); + println("case " + methodNumId + ": {"); + print("thread th" + methodNumId + " (&" + newSkelClass + "::___"); String helperMethod = methodId; if (uniqueMethodIds.contains(methodId)) helperMethod = helperMethod + methodNumId; else uniqueMethodIds.add(methodId); - print(helperMethod + "("); - writeInputCountVarStructSkeleton(method, intDecl); - println("); break;"); - } - String method = "___initCallBack()"; - // Print case -9999 (callback handler) if callback exists - if (callbackExist) { - int methodId = intDecl.getHelperMethodNumId(method); - println("case " + methodId + ": ___regCB(); break;"); + print(helperMethod + ", skel, "); + boolean structExists = writeInputCountVarStructCplusSkeleton(method, intDecl); + if (structExists) + print(", "); + println("skel);"); + println("th" + methodNumId + ".detach(); break;"); + println("}"); } - writeMethodCallStructSkeleton(methods, intDecl); + writeMethodCallStructCplusSkeleton(methods, intDecl); println("default: "); println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;"); - println("throw exception();"); + println("return;"); println("}"); println("}"); println("}\n"); @@ -4241,279 +4307,167 @@ public class IoTCompiler { /** - * generateCplusSkeletonClass() generate skeletons based on the methods list in C++ + * generateCplusSkeletonClassHpp() generate skeletons based on the methods list in C++ (.hpp file) */ - public void generateCplusSkeletonClass() throws IOException { + public void generateCplusSkeletonClassHpp() throws IOException { // 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 "); - 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 methods = intDecl.getMethods(); - Set includeClasses = getIncludeClasses(methods, intDecl, intface, true); - List stdIncludeClasses = getStandardCplusIncludeClasses(); - List allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses); - printIncludeStatements(allIncludeClasses); println(""); - println("using namespace std;\n"); - // Find out if there are callback objects - Set 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 constructor - writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods); - // Write deconstructor - writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses); - // Write methods - writeMethodCplusSkeleton(methods, intDecl, callbackClasses, false, intface); - // Write method helper - writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses); - // Write waitRequestInvokeMethod() - main loop - writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface); - println("};"); - writePermissionInitializationCplus(intface, newSkelClass, intDecl); - writeObjectIdCountInitializationCplus(newSkelClass, callbackExist); - println("#endif"); - pw.close(); - System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp..."); - } - } - - - /** - * HELPER: writePropertiesCplusCallbackSkeleton() writes the properties of the callback skeleton class - */ - private void writePropertiesCplusCallbackSkeleton(String intface, boolean callbackExist, Set callbackClasses) { + + // Check if there is more than 1 class that uses the same interface + List drvList = mapInt2Drv.get(intface); + for(int i = 0; i < drvList.size(); i++) { - println(intface + " *mainObj;"); - // Keep track of object Ids of all stubs registered to this interface - println("int objectId;"); - println("vector ports;\n"); - println("string callbackAddress;"); - // Callback - if (callbackExist) { - Iterator it = callbackClasses.iterator(); - String callbackType = (String) it.next(); - String exchangeType = checkAndGetParamClass(callbackType); - println("// Callback properties"); - println("IoTRMICall* rmiCall;"); - println("vector<" + exchangeType + "*> vecCallbackObj;"); - println("static int objIdCnt;"); + // 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 "); + 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 methods = intDecl.getMethods(); + List stdIncludeClasses = getStandardCplusIncludeClasses(); + printIncludeStatements(stdIncludeClasses); println(""); + println("using namespace std;\n"); + // Find out if there are callback objects + Set 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..."); + } } - println("\n"); } - /** - * HELPER: writeConstructorCplusCallbackSkeleton() writes the constructor of the skeleton class + * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke */ - private void writeConstructorCplusCallbackSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection methods) { + private void writeReturnDidAlreadyInitWaitInvoke(String newSkelClass) { - println(newSkelClass + "(" + intface + " *_mainObj, string _callbackAddress, int _objectId) {"); - println("mainObj = _mainObj;"); - println("callbackAddress = _callbackAddress;"); - println("objectId = _objectId;"); + println("bool " + newSkelClass + "::didInitWaitInvoke() {"); + println("return didAlreadyInitWaitInvoke;"); println("}\n"); } /** - * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class - */ - private void writeDeconstructorCplusCallbackSkeleton(String newStubClass, boolean callbackExist, - Set callbackClasses) { - - println("~" + newStubClass + "() {"); - if (callbackExist) { - // We assume that each class only has one callback interface for now - println("if (rmiCall != NULL) {"); - println("delete rmiCall;"); - println("rmiCall = NULL;"); - println("}"); - 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(""); - } - - - /** - * HELPER: writeMethodHelperCplusCallbackSkeleton() writes the method helper of callback skeleton class - */ - private void writeMethodHelperCplusCallbackSkeleton(Collection methods, InterfaceDecl intDecl, - Set callbackClasses) { - - // Use this set to handle two same methodIds - Set uniqueMethodIds = new HashSet(); - for (String method : methods) { - - List methParams = intDecl.getMethodParams(method); - List methPrmTypes = intDecl.getMethodParamTypes(method); - if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently - String methodId = intDecl.getMethodId(method); - print("void ___"); - String helperMethod = methodId; - if (uniqueMethodIds.contains(methodId)) - helperMethod = helperMethod + intDecl.getMethodNumId(method); - else - uniqueMethodIds.add(methodId); - String retType = intDecl.getMethodType(method); - print(helperMethod + "("); - boolean begin = true; - for (int i = 0; i < methParams.size(); i++) { // Print size variables - String paramType = methPrmTypes.get(i); - String param = methParams.get(i); - String simpleType = getGenericType(paramType); - if (isStructClass(simpleType)) { - if (!begin) // Generate comma for not the beginning variable - print(", "); - else - begin = false; - int methodNumId = intDecl.getMethodNumId(method); - print("int struct" + methodNumId + "Size" + i); - } - } - println(", IoTRMIObject* rmiObj) {"); - writeMethodHelperStructCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses); - println("}\n"); - } else { - String methodId = intDecl.getMethodId(method); - print("void ___"); - String helperMethod = methodId; - if (uniqueMethodIds.contains(methodId)) - helperMethod = helperMethod + intDecl.getMethodNumId(method); - else - uniqueMethodIds.add(methodId); - // Check if this is "void" - String retType = intDecl.getMethodType(method); - println(helperMethod + "(IoTRMIObject* rmiObj) {"); - // Now, write the helper body of skeleton! - writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses); - println("}\n"); - } - } - // Write method helper for structs - writeMethodHelperStructSetupCplusCallbackSkeleton(methods, intDecl); - } - - - /** - * HELPER: writeCplusCallbackWaitRequestInvokeMethod() writes the request invoke method of the skeleton callback class + * writeSkelExternalCFunctions() generate external functions for .so file */ - private void writeCplusCallbackWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, - boolean callbackExist) { + public void writeSkelExternalCFunctions(String newSkelClass, String intface) throws IOException { - // Use this set to handle two same methodIds - Set uniqueMethodIds = new HashSet(); - println("void invokeMethod(IoTRMIObject* rmiObj) {"); - // Write variables here if we have callbacks or enums or structs - writeCountVarStructSkeleton(methods, intDecl); - // Write variables here if we have callbacks or enums or structs - println("int methodId = rmiObj->getMethodId();"); - // TODO: code the permission check here! - println("switch (methodId) {"); - // Print methods and method Ids - for (String method : methods) { - String methodId = intDecl.getMethodId(method); - int methodNumId = intDecl.getMethodNumId(method); - print("case " + methodNumId + ": ___"); - String helperMethod = methodId; - if (uniqueMethodIds.contains(methodId)) - helperMethod = helperMethod + methodNumId; - else - uniqueMethodIds.add(methodId); - print(helperMethod + "("); - if (writeInputCountVarStructSkeleton(method, intDecl)) - println(", rmiObj); break;"); - else - println("rmiObj); break;"); - } - String method = "___initCallBack()"; - // Print case -9999 (callback handler) if callback exists - if (callbackExist) { - int methodId = intDecl.getHelperMethodNumId(method); - println("case " + methodId + ": ___regCB(rmiObj); break;"); - } - writeMethodCallStructCallbackSkeleton(methods, intDecl); - println("default: "); - println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;"); - println("throw exception();"); - println("}"); + println("extern \"C\" void* create" + newSkelClass + "(void** params) {"); + println("// Args: *_mainObj, int _portSend, int _portRecv"); + 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("}\n"); } /** - * generateCplusCallbackSkeletonClass() generate callback skeletons based on the methods list in C++ + * generateCplusSkeletonClassCpp() generate skeletons based on the methods list in C++ (.cpp file) */ - public void generateCplusCallbackSkeletonClass() throws IOException { + public void generateCplusSkeletonClassCpp() throws IOException { // Create a new directory String path = createDirectories(dir, subdir); for (String intface : mapIntfacePTH.keySet()) { - // Open a new file to write into - String newSkelClass = intface + "_CallbackSkeleton"; - 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 "); - 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 methods = intDecl.getMethods(); - Set includeClasses = getIncludeClasses(methods, intDecl, intface, true); - List stdIncludeClasses = getStandardCplusIncludeClasses(); - List allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses); - printIncludeStatements(allIncludeClasses); println(""); - // Find out if there are callback objects - Set callbackClasses = getCallbackClasses(methods, intDecl); - boolean callbackExist = !callbackClasses.isEmpty(); - println("using namespace std;\n"); - // Write class header - println("class " + newSkelClass + " : public " + intface); println("{"); - println("private:\n"); - // Write properties - writePropertiesCplusCallbackSkeleton(intface, callbackExist, callbackClasses); - println("public:\n"); - // Write constructor - writeConstructorCplusCallbackSkeleton(newSkelClass, intface, callbackExist, intDecl, methods); - // Write deconstructor - writeDeconstructorCplusCallbackSkeleton(newSkelClass, callbackExist, callbackClasses); - // Write methods - writeMethodCplusSkeleton(methods, intDecl, callbackClasses, true, intface); - // Write method helper - writeMethodHelperCplusCallbackSkeleton(methods, intDecl, callbackClasses); - // Write waitRequestInvokeMethod() - main loop - writeCplusCallbackWaitRequestInvokeMethod(methods, intDecl, callbackExist); - println("};"); - writeObjectIdCountInitializationCplus(newSkelClass, callbackExist); - println("#endif"); - pw.close(); - System.out.println("IoTCompiler: Generated callback skeleton class " + newSkelClass + ".hpp..."); + + // Check if there is more than 1 class that uses the same interface + List 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 + ".cpp"); + pw = new PrintWriter(new BufferedWriter(fw)); + // Write file headers + println("#include "); + 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 methods = intDecl.getMethods(); + // Find out if there are callback objects + Set 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..."); + } } } @@ -4563,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:"); @@ -4573,8 +4527,14 @@ public class IoTCompiler { System.out.println("\tjava IoTCompiler [ ] [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\tGenerate Java stub files"); - System.out.println("\t-cplus\t\tGenerate C++ stub files"); + System.out.println("\t-cont\t\tSpecify controller class name"); + System.out.println("\t-drv\t\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\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\t\tGenerate C++ stub files"); + System.out.println("\t-java\t\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(); } @@ -4711,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; } @@ -4789,8 +4743,13 @@ public class IoTCompiler { importClasses.add("java.util.List"); importClasses.add("java.util.ArrayList"); importClasses.add("java.util.Arrays"); - importClasses.add("iotrmi.Java.IoTRMICall"); - importClasses.add("iotrmi.Java.IoTRMIObject"); + importClasses.add("java.util.Map"); + importClasses.add("java.util.HashMap"); + importClasses.add("java.util.concurrent.atomic.AtomicBoolean"); + importClasses.add("iotrmi.Java.IoTRMIComm"); + importClasses.add("iotrmi.Java.IoTRMICommClient"); + importClasses.add("iotrmi.Java.IoTRMICommServer"); + importClasses.add("iotrmi.Java.IoTRMIUtil"); return importClasses; } @@ -4803,8 +4762,9 @@ public class IoTCompiler { // Add the standard list first importClasses.add(""); importClasses.add(""); - importClasses.add("\"IoTRMICall.hpp\""); - importClasses.add("\"IoTRMIObject.hpp\""); + importClasses.add("\"IoTRMIComm.hpp\""); + importClasses.add("\"IoTRMICommClient.hpp\""); + importClasses.add("\"IoTRMICommServer.hpp\""); return importClasses; } @@ -4993,24 +4953,30 @@ public class IoTCompiler { List methParams = intDecl.getMethodParams(method); for (int i = 0; i < methPrmTypes.size(); i++) { + String genericType = getGenericType(methPrmTypes.get(i)); String simpleType = getSimpleType(methPrmTypes.get(i)); String param = methParams.get(i); if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) { includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">"); - } else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) { + //} else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) { + } + if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.USERDEFINED) { // For original interface, we need it exchanged... not for stub interfaces if (needExchange) { - includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\""); - includeClasses.add("\"" + exchangeParamType(simpleType) + "_CallbackStub.hpp\""); + //includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\""); + includeClasses.add("\"" + exchangeParamType(getSimpleArrayType(genericType)) + ".hpp\""); } else { - includeClasses.add("\"" + simpleType + ".hpp\""); - includeClasses.add("\"" + simpleType + "_CallbackSkeleton.hpp\""); + //includeClasses.add("\"" + simpleType + ".hpp\""); + includeClasses.add("\"" + getSimpleArrayType(genericType) + ".hpp\""); } - } else if (getParamCategory(getSimpleArrayType(simpleType)) == ParamCategory.ENUM) { - includeClasses.add("\"" + simpleType + ".hpp\""); - } else if (getParamCategory(getSimpleArrayType(simpleType)) == ParamCategory.STRUCT) { - includeClasses.add("\"" + simpleType + ".hpp\""); - } else if (param.contains("[]")) { + } + if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.ENUM) { + includeClasses.add("\"" + genericType + ".hpp\""); + } + if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.STRUCT) { + includeClasses.add("\"" + genericType + ".hpp\""); + } + if (param.contains("[]")) { // Check if this is array for C++; translate into vector includeClasses.add(""); } @@ -5044,6 +5010,45 @@ public class IoTCompiler { } return callbackClasses; } + + + // Check if this is a callback class + private boolean isCallbackClass(String className) { + + Set intfaceSet = mapIntDeclHand.keySet(); + for(String intface : intfaceSet) { + + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + Set methods = intMeth.getValue(); + for (String method : methods) { + + List methPrmTypes = intDecl.getMethodParamTypes(method); + List 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 @@ -5348,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) { @@ -5382,17 +5408,15 @@ public class IoTCompiler { comp.generateJavaLocalInterfaces(); comp.generateJavaInterfaces(); comp.generateJavaStubClasses(); - comp.generateJavaCallbackStubClasses(); comp.generateJavaSkeletonClass(); - comp.generateJavaCallbackSkeletonClass(); comp.generateEnumCplus(); comp.generateStructCplus(); comp.generateCplusLocalInterfaces(); comp.generateCPlusInterfaces(); - comp.generateCPlusStubClasses(); - comp.generateCPlusCallbackStubClasses(); - comp.generateCplusSkeletonClass(); - comp.generateCplusCallbackSkeletonClass(); + comp.generateCPlusStubClassesHpp(); + comp.generateCPlusStubClassesCpp(); + comp.generateCplusSkeletonClassHpp(); + comp.generateCplusSkeletonClassCpp(); } else { // Check other options while(i < args.length) { @@ -5412,18 +5436,16 @@ public class IoTCompiler { comp.generateJavaLocalInterfaces(); comp.generateJavaInterfaces(); comp.generateJavaStubClasses(); - comp.generateJavaCallbackStubClasses(); comp.generateJavaSkeletonClass(); - comp.generateJavaCallbackSkeletonClass(); } else { comp.generateEnumCplus(); comp.generateStructCplus(); comp.generateCplusLocalInterfaces(); comp.generateCPlusInterfaces(); - comp.generateCPlusStubClasses(); - comp.generateCPlusCallbackStubClasses(); - comp.generateCplusSkeletonClass(); - comp.generateCplusCallbackSkeletonClass(); + comp.generateCPlusStubClassesHpp(); + comp.generateCPlusStubClassesCpp(); + comp.generateCplusSkeletonClassHpp(); + comp.generateCplusSkeletonClassCpp(); } } i = i + 2; @@ -5438,3 +5460,4 @@ public class IoTCompiler { } +