From: rtrimana Date: Thu, 17 Nov 2016 00:38:20 +0000 (-0800) Subject: Adding callback support for C++; still missing dynamic policy checks for both X-Git-Url: http://plrg.eecs.uci.edu/git/?p=iot2.git;a=commitdiff_plain;h=ebdd9c5108950cc797d6c157aaf6ffbd214376ac;hp=117609a31aadb0eca91a6080447ba3819177b7a0;ds=sidebyside Adding callback support for C++; still missing dynamic policy checks for both --- diff --git a/iotjava/Makefile b/iotjava/Makefile index e748017..a63d357 100644 --- a/iotjava/Makefile +++ b/iotjava/Makefile @@ -32,8 +32,9 @@ PHONY += compile compile: cd $(BIN_DIR)/iotpolicy/output_files; cp *.java ./Java cd $(BIN_DIR)/iotpolicy/output_files; cp *.hpp ./Cplus - cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) *.java +# cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) *.java # cd $(BIN_DIR)/iotpolicy/output_files/Cplus; $(G++) ./*.hpp --std=c++11 -pthread -pg -I../../../../iotjava/iotrmi/C++/ + cd $(BIN_DIR)/iotpolicy/output_files/Cplus; $(G++) ./Camera_CallbackSkeleton.hpp --std=c++11 -pthread -pg -I../../../../iotjava/iotrmi/C++/ PHONY += clean clean: @@ -45,8 +46,8 @@ clean: PHONY += rmi rmi: mkdir -p $(BIN_DIR) - $(JAVAC) -cp .:../$(BIN_DIR) -d $(BIN_DIR) iotrmi/Java/*.java - $(JAVAC) -cp .:../$(BIN_DIR) -d $(BIN_DIR) iotrmi/Java/sample/*.java +# $(JAVAC) -cp .:../$(BIN_DIR) -d $(BIN_DIR) iotrmi/Java/*.java +# $(JAVAC) -cp .:../$(BIN_DIR) -d $(BIN_DIR) iotrmi/Java/sample/*.java # mkdir -p $(BIN_DIR)/iotrmi/C++ #$(G++) iotrmi/C++/IoTSocketServer.cpp -o $(BIN_DIR)/iotrmi/C++/IoTSocketServer.out #$(G++) iotrmi/C++/IoTSocketClient.cpp -o $(BIN_DIR)/iotrmi/C++/IoTSocketClient.out diff --git a/iotjava/iotpolicy/IoTCompiler.java b/iotjava/iotpolicy/IoTCompiler.java index 7681ff5..619146e 100644 --- a/iotjava/iotpolicy/IoTCompiler.java +++ b/iotjava/iotpolicy/IoTCompiler.java @@ -194,7 +194,7 @@ public class IoTCompiler { for (int i = 0; i < methParams.size(); i++) { // Check for params with driver class types and exchange it // with its remote interface - String paramType = checkAndGetParamClass(methPrmTypes.get(i), false); + String paramType = checkAndGetParamClass(methPrmTypes.get(i)); print(paramType + " " + methParams.get(i)); // Check if this is the last element (don't print a comma) if (i != methParams.size() - 1) { @@ -487,14 +487,25 @@ public class IoTCompiler { } + /** + * HELPER: returnGenericCallbackType() returns the callback type + */ + private String returnGenericCallbackType(String paramType) { + + if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) + return getTypeOfGeneric(paramType)[0]; + else + return paramType; + } + + /** * HELPER: checkCallbackType() checks the callback type */ private boolean checkCallbackType(String paramType, String callbackType) { - if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) - paramType = getTypeOfGeneric(paramType)[0]; - return callbackType.equals(paramType); + String prmType = returnGenericCallbackType(paramType); + return callbackType.equals(prmType); } @@ -593,16 +604,12 @@ public class IoTCompiler { String callbackType = null; for (int i = 0; i < methParams.size(); i++) { - String paramType = methPrmTypes.get(i); - if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) - paramType = getTypeOfGeneric(paramType)[0]; + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); // Check if this has callback object - if (callbackClasses != null) { - if (callbackClasses.contains(paramType)) { - isCallbackMethod = true; - callbackType = paramType; - // Even if there're 2 callback arguments, we expect them to be of the same interface - } + if (callbackClasses.contains(paramType)) { + isCallbackMethod = true; + callbackType = paramType; + // Even if there're 2 callback arguments, we expect them to be of the same interface } print(methPrmTypes.get(i) + " " + methParams.get(i)); // Check if this is the last element (don't print a comma) @@ -647,7 +654,7 @@ public class IoTCompiler { Set methods = intMeth.getValue(); Set importClasses = getImportClasses(methods, intDecl); List stdImportClasses = getStandardJavaImportClasses(); - List allImportClasses = getAllImportClasses(stdImportClasses, importClasses); + List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); printImportStatements(allImportClasses); println(""); // Find out if there are callback objects Set callbackClasses = getCallbackClasses(methods, intDecl); @@ -738,7 +745,7 @@ public class IoTCompiler { Set methods = intMeth.getValue(); Set importClasses = getImportClasses(methods, intDecl); List stdImportClasses = getStandardJavaImportClasses(); - List allImportClasses = getAllImportClasses(stdImportClasses, importClasses); + List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); printImportStatements(allImportClasses); println(""); // Find out if there are callback objects Set callbackClasses = getCallbackClasses(methods, intDecl); @@ -854,12 +861,10 @@ public class IoTCompiler { for (int i = 0; i < methParams.size(); i++) { String origParamType = methPrmTypes.get(i); - String paramType = checkAndGetParamClass(origParamType, false); - if (callbackClasses != null) { // Check if this has callback object - if (callbackClasses.contains(origParamType)) { - isCallbackMethod = true; - callbackType = origParamType; - } + 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) @@ -878,9 +883,9 @@ public class IoTCompiler { /** - * HELPER: writeCallbackStubGeneration() writes the callback stub generation part + * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part */ - private Map writeCallbackStubGeneration(List methParams, List methPrmTypes, String callbackType) { + private Map writeCallbackJavaStubGeneration(List methParams, List methPrmTypes, String callbackType) { Map mapStubParam = new HashMap(); // Iterate over callback objects @@ -890,7 +895,7 @@ public class IoTCompiler { //if (callbackType.equals(paramType)) { if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object println("try {"); - String exchParamType = checkAndGetParamClass(paramType, false); + String exchParamType = checkAndGetParamClass(paramType); // Print array if this is array or list if this is a list of callback objects if (isArray(paramType, param)) { println("int numStubs" + i + " = (int) paramObj[" + i + "];"); @@ -905,7 +910,7 @@ public class IoTCompiler { } // Generate a loop if needed if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object - String exchParamType = checkAndGetParamClass(paramType, false); + String exchParamType = checkAndGetParamClass(paramType); if (isArray(paramType, param)) { println("for (int objId = 0; objId < numStubs" + i + "; objId++) {"); println("stub" + i + "[objId] = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);"); @@ -917,8 +922,8 @@ public class IoTCompiler { println("objIdCnt++;"); println("}"); } + mapStubParam.put(i, "stub" + i); // List of all stub parameters } - mapStubParam.put(i, "stub" + i); // List of all stub parameters } return mapStubParam; } @@ -934,19 +939,13 @@ public class IoTCompiler { String callbackType = null; print("Object[] paramObj = rmiObj.getMethodParams(new Class[] { "); for (int i = 0; i < methParams.size(); i++) { - String paramType = methPrmTypes.get(i); - if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) - paramType = getTypeOfGeneric(paramType)[0]; - if (callbackClasses != null) { - if (callbackClasses.contains(paramType)) { - isCallbackMethod = true; - callbackType = paramType; - print("int.class"); - } else { - String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); - print(getSimpleType(prmType) + ".class"); - } - } else { // Generate normal classes if it's not a callback object + + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); + if (callbackClasses.contains(paramType)) { + isCallbackMethod = true; + callbackType = 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(prmType) + ".class"); } @@ -968,7 +967,7 @@ public class IoTCompiler { println(" });"); Map mapStubParam = null; if (isCallbackMethod) - mapStubParam = writeCallbackStubGeneration(methParams, methPrmTypes, callbackType); + mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType); // Check if this is "void" String retType = intDecl.getMethodType(method); if (retType.equals("void")) { @@ -1089,7 +1088,7 @@ public class IoTCompiler { List methods = intDecl.getMethods(); Set importClasses = getImportClasses(methods, intDecl); List stdImportClasses = getStandardJavaImportClasses(); - List allImportClasses = getAllImportClasses(stdImportClasses, importClasses); + List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); printImportStatements(allImportClasses); // Find out if there are callback objects Set callbackClasses = getCallbackClasses(methods, intDecl); @@ -1229,7 +1228,7 @@ public class IoTCompiler { List methods = intDecl.getMethods(); Set importClasses = getImportClasses(methods, intDecl); List stdImportClasses = getStandardJavaImportClasses(); - List allImportClasses = getAllImportClasses(stdImportClasses, importClasses); + List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); printImportStatements(allImportClasses); // Find out if there are callback objects Set callbackClasses = getCallbackClasses(methods, intDecl); @@ -1254,6 +1253,35 @@ public class IoTCompiler { } + /** + * HELPER: writeMethodCplusLocalInterface() writes the method of the interface + */ + private void writeMethodCplusLocalInterface(Collection methods, InterfaceDecl intDecl) { + + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " + + intDecl.getMethodId(method) + "("); + for (int i = 0; i < methParams.size(); i++) { + // Check for params with driver class types and exchange it + // with its remote interface + String paramType = checkAndGetParamClass(methPrmTypes.get(i)); + paramType = checkAndGetCplusType(paramType); + // Check for arrays - translate into vector in C++ + String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i)); + print(paramComplete); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } + } + println(") = 0;"); + } + } + + /** * HELPER: writeMethodCplusInterface() writes the method of the interface */ @@ -1268,7 +1296,6 @@ public class IoTCompiler { for (int i = 0; i < methParams.size(); i++) { // Check for params with driver class types and exchange it // with its remote interface - //String paramType = checkAndGetParamClass(methPrmTypes.get(i), true); String paramType = methPrmTypes.get(i); paramType = checkAndGetCplusType(paramType); // Check for arrays - translate into vector in C++ @@ -1359,7 +1386,7 @@ public class IoTCompiler { DeclarationHandler decHandler = mapIntDeclHand.get(intface); InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); List methods = intDecl.getMethods(); - Set includeClasses = getIncludeClasses(methods, intDecl); + Set includeClasses = getIncludeClasses(methods, intDecl, true); printIncludeStatements(includeClasses); println(""); println("using namespace std;\n"); // Write enum if any... @@ -1371,7 +1398,7 @@ public class IoTCompiler { println("class " + intface); println("{"); println("public:"); // Write methods - writeMethodCplusInterface(methods, intDecl); + writeMethodCplusLocalInterface(methods, intDecl); println("};"); println("#endif"); pw.close(); @@ -1405,9 +1432,9 @@ public class IoTCompiler { println("#define _" + newIntface.toUpperCase() + "_HPP__"); println("#include "); // Pass in set of methods and get import classes - Set includeClasses = getIncludeClasses(intMeth.getValue(), intDecl); + Set includeClasses = getIncludeClasses(intMeth.getValue(), intDecl, false); List stdIncludeClasses = getStandardCplusIncludeClasses(); - List allIncludeClasses = getAllImportClasses(stdIncludeClasses, includeClasses); + List allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses); printIncludeStatements(allIncludeClasses); println(""); println("using namespace std;\n"); println("class " + newIntface); @@ -1427,7 +1454,7 @@ public class IoTCompiler { /** * HELPER: writeMethodCplusStub() writes the method of the stub */ - private void writeMethodCplusStub(Collection methods, InterfaceDecl intDecl) { + private void writeMethodCplusStub(Collection methods, InterfaceDecl intDecl, Set callbackClasses) { for (String method : methods) { @@ -1435,11 +1462,18 @@ public class IoTCompiler { List methPrmTypes = intDecl.getMethodParamTypes(method); print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " + intDecl.getMethodId(method) + "("); + boolean isCallbackMethod = false; + String callbackType = null; for (int i = 0; i < methParams.size(); i++) { - //String paramType = checkAndGetParamClass(methPrmTypes.get(i), true); String paramType = methPrmTypes.get(i); - String methPrmType = checkAndGetCplusType(paramType); + // Check if this has callback object + if (callbackClasses.contains(paramType)) { + isCallbackMethod = true; + callbackType = paramType; + // Even if there're 2 callback arguments, we expect them to be of the same interface + } + String methPrmType = checkAndGetCplusType(methPrmTypes.get(i)); String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i)); print(methParamComplete); // Check if this is the last element (don't print a comma) @@ -1448,8 +1482,96 @@ public class IoTCompiler { } } println(") { "); - writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method); + if (isCallbackMethod) + writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType); + else + writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method); println("}\n"); + // Write the init callback helper method + if (isCallbackMethod) { + writeInitCallbackCplusStub(callbackType, intDecl); + writeInitCallbackSendInfoCplusStub(intDecl); + } + } + } + + + /** + * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class + */ + private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method, String 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 + String param = methParams.get(i); + if (isArrayOrList(paramType, param)) { // Generate loop + println("for (" + paramType + "* cb : " + getSimpleIdentifier(param) + ") {"); + println(callbackType + "_CallbackSkeleton* skel = new " + callbackType + "_CallbackSkeleton(cb, objIdCnt++);"); + isArrayOrList = true; + callbackParam = getSimpleIdentifier(param); + } else + println(callbackType + "_CallbackSkeleton* skel = new " + callbackType + "_CallbackSkeleton(" + + getSimpleIdentifier(param) + ", objIdCnt++);"); + println("vecCallbackObj.push_back(skel);"); + if (isArrayOrList(paramType, param)) + println("}"); + } + } + println("int numParam = " + methParams.size() + ";"); + println("int methodId = " + intDecl.getMethodNumId(method) + ";"); + String retType = intDecl.getMethodType(method); + String retTypeC = checkAndGetCplusType(retType); + println("string retType = \"" + checkAndGetCplusArrayType(retTypeC) + "\";"); + // Generate array of parameter types + print("string paramCls[] = { "); + 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\""); + } else { // Generate normal classes if it's not a callback object + String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i)); + String prmType = checkAndGetCplusArrayType(paramTypeC, methParams.get(i)); + print("\"" + prmType + "\""); + } + if (i != methParams.size() - 1) // Check if this is the last element + print(", "); + } + println(" };"); + print("int ___paramCB = "); + if (isArrayOrList) + println(callbackParam + ".size();"); + else + println("1;"); + // Generate array of parameter objects + print("void* paramObj[] = { "); + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object + print("&___paramCB"); + } else + print(getSimpleIdentifier(methParams.get(i))); + if (i != methParams.size() - 1) + print(", "); + } + println(" };"); + // Check if this is "void" + if (retType.equals("void")) { + println("void* retObj = NULL;"); + println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);"); + } else { // We do have a return value + if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) + println(checkAndGetCplusType(retType) + " retVal;"); + else + println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";"); + println("void* retObj = &retVal;"); + println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);"); + println("return retVal;"); } } @@ -1480,7 +1602,7 @@ public class IoTCompiler { // Generate array of parameter objects print("void* paramObj[] = { "); for (int i = 0; i < methParams.size(); i++) { - print("&" + checkAndGetCplusType(getSimpleIdentifier(methParams.get(i)))); + print("&" + getSimpleIdentifier(methParams.get(i))); // Check if this is the last element (don't print a comma) if (i != methParams.size() - 1) { print(", "); @@ -1506,7 +1628,7 @@ public class IoTCompiler { /** * HELPER: writePropertiesCplusStub() writes the properties of the stub class */ - private void writePropertiesCplusStub(String intface, String newIntface) { + private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist, Set callbackClasses) { println("IoTRMICall *rmiCall;"); //println("IoTRMIObject\t\t\t*rmiObj;"); @@ -1517,6 +1639,15 @@ public class IoTCompiler { println("const 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("IoTRMIObject *rmiObj;"); + println("vector<" + callbackType + "*> vecCallbackObj;"); + println("static int objIdCnt;"); + } println("\n"); } @@ -1524,13 +1655,21 @@ public class IoTCompiler { /** * HELPER: writeConstructorCplusStub() writes the constructor of the stub class */ - private void writeConstructorCplusStub(String newStubClass) { + private void writeConstructorCplusStub(String newStubClass, boolean callbackExist, Set callbackClasses) { println(newStubClass + "(int _port, const char* _address, int _rev, bool* _bResult, vector _ports) {"); println("address = _address;"); println("ports = _ports;"); println("rmiCall = new IoTRMICall(_port, _address, _rev, _bResult);"); + if (callbackExist) { + println("objIdCnt = 0;"); + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + println("thread th1 (&" + newStubClass + "::___initCallBack, this);"); + println("th1.detach();"); + println("___regCB();"); + } println("}\n"); } @@ -1538,16 +1677,74 @@ public class IoTCompiler { /** * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class */ - private void writeDeconstructorCplusStub(String newStubClass) { + 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(""); - // Check if this is callback!!! and print "delete rmiObj and vecCBObj" + } + + + /** + * HELPER: writeInitCallbackCplusStub() writes the constructor of the stub class + */ + private void writeInitCallbackCplusStub(String intface, InterfaceDecl intDecl) { + + println("void ___initCallBack() {"); + println("bool bResult = false;"); + println("rmiObj = new IoTRMIObject(ports[0], &bResult);"); + println("while (true) {"); + println("char* method = rmiObj->getMethodBytes();"); + println("int methodId = IoTRMIObject::getMethodId(method);"); + 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));"); + println("skel->invokeMethod(rmiObj);"); + 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("exit(-1);"); + println("}"); + println("}"); + println("}\n"); + } + + + /** + * HELPER: writeInitCallbackSendInfoCplusStub() writes the constructor of the stub class + */ + private void writeInitCallbackSendInfoCplusStub(InterfaceDecl intDecl) { + + // Generate info sending part + println("void ___regCB() {"); + println("int numParam = 3;"); + String method = "___initCallBack()"; + println("int methodId = " + intDecl.getHelperMethodNumId(method) + ";"); + println("string retType = \"void\";"); + println("string paramCls[] = { \"int\", \"string\", \"int\" };"); + println("int rev = 0;"); + println("void* paramObj[] = { &ports[0], &address, &rev };"); + println("void* retObj = NULL;"); + println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);"); + println("}\n"); } @@ -1571,24 +1768,30 @@ public class IoTCompiler { 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 + println("#include "); println("#include \"" + newIntface + ".hpp\""); println(""); println("using namespace std;"); println(""); println("class " + newStubClass + " : public " + newIntface); println("{"); println("private:\n"); - writePropertiesCplusStub(intface, newIntface); + writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses); println("public:\n"); // Add default constructor and destructor println(newStubClass + "() { }"); println(""); - writeConstructorCplusStub(newStubClass); - writeDeconstructorCplusStub(newStubClass); - DeclarationHandler decHandler = mapIntDeclHand.get(intface); - InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses); + writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses); // Write methods - writeMethodCplusStub(intMeth.getValue(), intDecl); + writeMethodCplusStub(methods, intDecl, callbackClasses); print("}"); println(";"); println("#endif"); pw.close(); - System.out.println("IoTCompiler: Generated stub class " + newIntface + ".hpp..."); + System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp..."); } } } @@ -1597,11 +1800,23 @@ public class IoTCompiler { /** * HELPER: writePropertiesCplusCallbackStub() writes the properties of the stub class */ - private void writePropertiesCplusCallbackStub(String intface, String newIntface) { + private void writePropertiesCplusCallbackStub(String intface, String newIntface, boolean callbackExist, Set callbackClasses) { println("IoTRMICall *rmiCall;"); // Get the object Id println("static int objectId;"); + 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 + println("string address;"); + println("vector ports;\n"); + } println("\n"); } @@ -1609,11 +1824,18 @@ public class IoTCompiler { /** * HELPER: writeConstructorCplusCallbackStub() writes the constructor of the stub class */ - private void writeConstructorCplusCallbackStub(String newStubClass) { + private void writeConstructorCplusCallbackStub(String newStubClass, boolean callbackExist, Set callbackClasses) { println(newStubClass + "(IoTRMICall* _rmiCall, int _objectId) {"); println("objectId = _objectId;"); println("rmiCall = _rmiCall;"); + if (callbackExist) { + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + println("thread th1 (&" + newStubClass + "::___initCallBack, this);"); + println("th1.detach();"); + println("___regCB();"); + } println("}\n"); } @@ -1634,24 +1856,30 @@ public class IoTCompiler { 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); + writePropertiesCplusCallbackStub(intface, newIntface, callbackExist, callbackClasses); println("public:\n"); // Add default constructor and destructor println(newStubClass + "() { }"); println(""); - writeConstructorCplusCallbackStub(newStubClass); - writeDeconstructorCplusStub(newStubClass); - DeclarationHandler decHandler = mapIntDeclHand.get(intface); - InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + writeConstructorCplusCallbackStub(newStubClass, callbackExist, callbackClasses); + writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses); // Write methods - writeMethodCplusStub(intMeth.getValue(), intDecl); + writeMethodCplusStub(methods, intDecl, callbackClasses); print("}"); println(";"); println("#endif"); pw.close(); @@ -1664,11 +1892,20 @@ public class IoTCompiler { /** * HELPER: writePropertiesCplusSkeleton() writes the properties of the skeleton class */ - private void writePropertiesCplusSkeleton(String intface) { + private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set callbackClasses) { println(intface + " *mainObj;"); //println("private int ports;"); - //println("private IoTRMICall rmiCall;"); + // 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"); // Keep track of object Ids of all stubs registered to this interface Map> mapNewIntMethods = mapInt2NewInts.get(intface); @@ -1678,8 +1915,6 @@ public class IoTCompiler { // println("const static int object" + newObjectId + "Id = " + // newObjectId + ";\t//" + newIntface); } - // TODO: CALLBACKS! - // TODO: code the set of allowed functions here println("\n"); } @@ -1687,14 +1922,18 @@ public class IoTCompiler { /** * HELPER: writeConstructorCplusSkeleton() writes the constructor of the skeleton class */ - private void writeConstructorCplusSkeleton(String newSkelClass, String intface) { + private void writeConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist) { println(newSkelClass + "(" + intface + " *_mainObj, int _port) {"); println("bool _bResult = false;"); println("mainObj = _mainObj;"); println("rmiObj = new IoTRMIObject(_port, &_bResult);"); + // Callback + if (callbackExist) { + println("objIdCnt = 0;"); + } //println("set0Allowed = Arrays.asList(object0Permission);"); - //println("___waitRequestInvokeMethod();"); + println("___waitRequestInvokeMethod();"); println("}\n"); } @@ -1702,16 +1941,29 @@ public class IoTCompiler { /** * HELPER: writeDeconstructorCplusSkeleton() writes the deconstructor of the skeleton class */ - private void writeDeconstructorCplusSkeleton(String newSkelClass) { + private void writeDeconstructorCplusSkeleton(String newSkelClass, boolean callbackExist, Set callbackClasses) { println("~" + newSkelClass + "() {"); println("if (rmiObj != NULL) {"); println("delete rmiObj;"); println("rmiObj = 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(""); - // Check if this is callback!!! and print "delete rmiObj and vecCBObj" } @@ -1736,10 +1988,32 @@ public class IoTCompiler { } + /** + * HELPER: writeInitCallbackCplusSkeleton() writes the init callback method for skeleton class + */ + private void writeInitCallbackCplusSkeleton(boolean callbackSkeleton) { + + // This is a callback skeleton generation + if (callbackSkeleton) + println("void ___regCB(IoTRMIObject* rmiObj) {"); + else + println("void ___regCB() {"); + println("int numParam = 3;"); + println("int param1 = 0;"); + println("string param2 = \"\";"); + println("int param3 = 0;"); + println("void* paramObj[] = { ¶m1, ¶m2, ¶m3 };"); + println("bool bResult = false;"); + println("rmiCall = new IoTRMICall(param1, param2.c_str(), param3, &bResult);"); + println("}\n"); + } + + /** * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class */ - private void writeMethodCplusSkeleton(Collection methods, InterfaceDecl intDecl) { + private void writeMethodCplusSkeleton(Collection methods, InterfaceDecl intDecl, + Set callbackClasses, boolean callbackSkeleton) { for (String method : methods) { @@ -1748,9 +2022,16 @@ public class IoTCompiler { String methodId = intDecl.getMethodId(method); String methodType = checkAndGetCplusType(intDecl.getMethodType(method)); print(methodType + " " + methodId + "("); + boolean isCallbackMethod = false; + String callbackType = null; for (int i = 0; i < methParams.size(); i++) { - String paramType = checkAndGetParamClass(methPrmTypes.get(i), true); + String origParamType = methPrmTypes.get(i); + if (callbackClasses.contains(origParamType)) { // Check if this has callback object + isCallbackMethod = true; + callbackType = origParamType; + } + String paramType = checkAndGetParamClass(methPrmTypes.get(i)); String methPrmType = checkAndGetCplusType(paramType); String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i)); print(methParamComplete); @@ -1763,6 +2044,56 @@ public class IoTCompiler { // Now, write the body of skeleton! writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method)); println("}\n"); + if (isCallbackMethod) + writeInitCallbackCplusSkeleton(callbackSkeleton); + } + } + + + /** + * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable + */ + private void writeCallbackCplusNumStubs(List methParams, List methPrmTypes, String callbackType) { + + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + //if (callbackType.equals(paramType)) { + if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object + String exchParamType = checkAndGetParamClass(paramType); + // Print array if this is array or list if this is a list of callback objects + println("int numStubs" + i + " = 0;"); + } + } + } + + + /** + * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part + */ + private void writeCallbackCplusStubGeneration(List methParams, List methPrmTypes, String callbackType) { + + // Iterate over callback objects + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + // Generate a loop if needed + if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object + String exchParamType = checkAndGetParamClass(paramType); + if (isArrayOrList(paramType, param)) { + println("vector<" + exchParamType + "> stub;"); + println("for (int objId = 0; objId < numStubs" + i + "; objId++) {"); + println(exchParamType + "* cb" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);"); + println("stub" + i + ".push_back(cb);"); + println("vecCallbackObj.push_back(cb);"); + println("objIdCnt++;"); + println("}"); + } else { + println(exchParamType + "* stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);"); + println("vecCallbackObj.push_back(stub" + i + ");"); + println("objIdCnt++;"); + } + } } } @@ -1771,42 +2102,66 @@ public class IoTCompiler { * HELPER: writeStdMethodHelperBodyCplusSkeleton() writes the standard method body helper in the skeleton class */ private void writeStdMethodHelperBodyCplusSkeleton(InterfaceDecl intDecl, List methParams, - List methPrmTypes, String method, String methodId) { + List methPrmTypes, String method, String methodId, Set callbackClasses) { // Generate array of parameter types + boolean isCallbackMethod = false; + String callbackType = null; print("string paramCls[] = { "); for (int i = 0; i < methParams.size(); i++) { - String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i)); - String paramType = checkAndGetCplusArrayType(paramTypeC, methParams.get(i)); - print("\"" + paramType + "\""); + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); + if (callbackClasses.contains(paramType)) { + isCallbackMethod = true; + callbackType = paramType; + print("\"int\""); + } else { // Generate normal classes if it's not a callback object + String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i)); + String prmType = checkAndGetCplusArrayType(paramTypeC, methParams.get(i)); + print("\"" + prmType + "\""); + } if (i != methParams.size() - 1) { print(", "); } } println(" };"); println("int numParam = " + methParams.size() + ";"); + if (isCallbackMethod) + writeCallbackCplusNumStubs(methParams, methPrmTypes, callbackType); // Generate parameters for (int i = 0; i < methParams.size(); i++) { - String methPrmType = checkAndGetCplusType(methPrmTypes.get(i)); - String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i)); - println(methParamComplete + ";"); + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); + if (!callbackClasses.contains(paramType)) { + String methPrmType = checkAndGetCplusType(methPrmTypes.get(i)); + String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i)); + println(methParamComplete + ";"); + } } // Generate array of parameter objects print("void* paramObj[] = { "); for (int i = 0; i < methParams.size(); i++) { - print("&" + getSimpleIdentifier(methParams.get(i))); + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); + if (callbackClasses.contains(paramType)) + print("&numStubs" + i); + else + print("&" + getSimpleIdentifier(methParams.get(i))); if (i != methParams.size() - 1) { print(", "); } } println(" };"); println("rmiObj->getMethodParams(paramCls, numParam, paramObj);"); + if (isCallbackMethod) + writeCallbackCplusStubGeneration(methParams, methPrmTypes, callbackType); String retType = intDecl.getMethodType(method); // Check if this is "void" if (retType.equals("void")) { print(methodId + "("); for (int i = 0; i < methParams.size(); i++) { - print(getSimpleIdentifier(methParams.get(i))); + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); + if (callbackClasses.contains(paramType)) + print("stub" + i); + else + print(getSimpleIdentifier(methParams.get(i))); if (i != methParams.size() - 1) { print(", "); } @@ -1815,7 +2170,11 @@ public class IoTCompiler { } else { // We do have a return value print(checkAndGetCplusType(retType) + " retVal = " + methodId + "("); for (int i = 0; i < methParams.size(); i++) { - print(getSimpleIdentifier(methParams.get(i))); + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); + if (callbackClasses.contains(paramType)) + print("stub" + i); + else + print(getSimpleIdentifier(methParams.get(i))); if (i != methParams.size() - 1) { print(", "); } @@ -1831,7 +2190,7 @@ public class IoTCompiler { /** * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class */ - private void writeMethodHelperCplusSkeleton(Collection methods, InterfaceDecl intDecl) { + private void writeMethodHelperCplusSkeleton(Collection methods, InterfaceDecl intDecl, Set callbackClasses) { // Use this set to handle two same methodIds Set uniqueMethodIds = new HashSet(); @@ -1850,7 +2209,7 @@ public class IoTCompiler { String retType = intDecl.getMethodType(method); println(helperMethod + "() {"); // Now, write the helper body of skeleton! - writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId); + writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses); println("}\n"); } } @@ -1859,7 +2218,7 @@ public class IoTCompiler { /** * HELPER: writeCplusWaitRequestInvokeMethod() writes the main loop of the skeleton class */ - private void writeCplusWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl) { + private void writeCplusWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, boolean callbackExist) { // Use this set to handle two same methodIds Set uniqueMethodIds = new HashSet(); @@ -1883,6 +2242,12 @@ public class IoTCompiler { uniqueMethodIds.add(methodId); println(helperMethod + "(); break;"); } + String method = "___initCallBack()"; + // Print case -9999 (callback handler) if callback exists + if (callbackExist) { + int methodId = intDecl.getHelperMethodNumId(method); + println("case " + methodId + ": ___regCB(); break;"); + } println("default: "); println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;"); println("throw exception();"); @@ -1913,27 +2278,30 @@ public class IoTCompiler { DeclarationHandler decHandler = mapIntDeclHand.get(intface); InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); List methods = intDecl.getMethods(); - Set includeClasses = getIncludeClasses(methods, intDecl); + Set includeClasses = getIncludeClasses(methods, intDecl, true); List stdIncludeClasses = getStandardCplusIncludeClasses(); - List allIncludeClasses = getAllImportClasses(stdIncludeClasses, includeClasses); - printIncludeStatements(allIncludeClasses); println(""); + 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); + writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses); println("public:\n"); // Write constructor - writeConstructorCplusSkeleton(newSkelClass, intface); + writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist); // Write deconstructor - writeDeconstructorCplusSkeleton(newSkelClass); + writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses); // Write methods - writeMethodCplusSkeleton(methods, intDecl); + writeMethodCplusSkeleton(methods, intDecl, callbackClasses, false); // Write method helper - writeMethodHelperCplusSkeleton(methods, intDecl); + writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses); // Write waitRequestInvokeMethod() - main loop - writeCplusWaitRequestInvokeMethod(methods, intDecl); + writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist); println("};"); println("#endif"); pw.close(); @@ -1945,12 +2313,21 @@ public class IoTCompiler { /** * HELPER: writePropertiesCplusCallbackSkeleton() writes the properties of the callback skeleton class */ - private void writePropertiesCplusCallbackSkeleton(String intface) { + private void writePropertiesCplusCallbackSkeleton(String intface, boolean callbackExist, Set callbackClasses) { println(intface + " *mainObj;"); - //println("IoTRMIObject *rmiObj;\n"); // Keep track of object Ids of all stubs registered to this interface println("static int objectId;"); + // 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;"); + } println("\n"); } @@ -1958,19 +2335,50 @@ public class IoTCompiler { /** * HELPER: writeConstructorCplusCallbackSkeleton() writes the constructor of the skeleton class */ - private void writeConstructorCplusCallbackSkeleton(String newSkelClass, String intface) { + private void writeConstructorCplusCallbackSkeleton(String newSkelClass, String intface, boolean callbackExist) { println(newSkelClass + "(" + intface + " *_mainObj, int _objectId) {"); println("mainObj = _mainObj;"); println("objectId = _objectId;"); + // Callback + if (callbackExist) { + println("objIdCnt = 0;"); + } 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 the callback skeleton class */ - private void writeMethodHelperCplusCallbackSkeleton(Collection methods, InterfaceDecl intDecl) { + private void writeMethodHelperCplusCallbackSkeleton(Collection methods, InterfaceDecl intDecl, + Set callbackClasses) { // Use this set to handle two same methodIds Set uniqueMethodIds = new HashSet(); @@ -1989,7 +2397,7 @@ public class IoTCompiler { String retType = intDecl.getMethodType(method); println(helperMethod + "(IoTRMIObject* rmiObj) {"); // Now, write the helper body of skeleton! - writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId); + writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses); println("}\n"); } } @@ -1998,7 +2406,8 @@ public class IoTCompiler { /** * HELPER: writeCplusCallbackWaitRequestInvokeMethod() writes the main loop of the skeleton class */ - private void writeCplusCallbackWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl) { + private void writeCplusCallbackWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, + boolean callbackExist) { // Use this set to handle two same methodIds Set uniqueMethodIds = new HashSet(); @@ -2019,6 +2428,12 @@ public class IoTCompiler { uniqueMethodIds.add(methodId); println(helperMethod + "(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;"); + } println("default: "); println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;"); println("throw exception();"); @@ -2049,27 +2464,30 @@ public class IoTCompiler { DeclarationHandler decHandler = mapIntDeclHand.get(intface); InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); List methods = intDecl.getMethods(); - Set includeClasses = getIncludeClasses(methods, intDecl); + Set includeClasses = getIncludeClasses(methods, intDecl, true); List stdIncludeClasses = getStandardCplusIncludeClasses(); - List allIncludeClasses = getAllImportClasses(stdIncludeClasses, includeClasses); + 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); + writePropertiesCplusCallbackSkeleton(intface, callbackExist, callbackClasses); println("public:\n"); // Write constructor - writeConstructorCplusCallbackSkeleton(newSkelClass, intface); + writeConstructorCplusCallbackSkeleton(newSkelClass, intface, callbackExist); // Write deconstructor - //writeDeconstructorCplusSkeleton(newSkelClass); + writeDeconstructorCplusCallbackSkeleton(newSkelClass, callbackExist, callbackClasses); // Write methods - writeMethodCplusSkeleton(methods, intDecl); + writeMethodCplusSkeleton(methods, intDecl, callbackClasses, true); // Write method helper - writeMethodHelperCplusCallbackSkeleton(methods, intDecl); + writeMethodHelperCplusCallbackSkeleton(methods, intDecl, callbackClasses); // Write waitRequestInvokeMethod() - main loop - writeCplusCallbackWaitRequestInvokeMethod(methods, intDecl); + writeCplusCallbackWaitRequestInvokeMethod(methods, intDecl, callbackExist); println("};"); println("#endif"); pw.close(); @@ -2222,7 +2640,7 @@ public class IoTCompiler { private void println(String str) { if (newline) { int tab = tablevel; - if (str.equals("}")) + if (str.contains("}") && !str.contains("{")) tab--; for(int i=0; i getAllImportClasses(Collection stdImportClasses, Collection importClasses) { + private List getAllLibClasses(Collection stdLibClasses, Collection libClasses) { - List allImportClasses = new ArrayList(stdImportClasses); + List allLibClasses = new ArrayList(stdLibClasses); // Iterate over the list of import classes - for (String str : importClasses) { - if (!stdImportClasses.contains(str)) { - stdImportClasses.add(str); + for (String str : libClasses) { + if (!allLibClasses.contains(str)) { + allLibClasses.add(str); } } - return allImportClasses; + return allLibClasses; } @@ -2393,7 +2812,7 @@ public class IoTCompiler { // Generate a set of classes for include statements - private Set getIncludeClasses(Collection methods, InterfaceDecl intDecl) { + private Set getIncludeClasses(Collection methods, InterfaceDecl intDecl, boolean needExchange) { Set includeClasses = new HashSet(); for (String method : methods) { @@ -2407,7 +2826,14 @@ public class IoTCompiler { if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) { includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">"); } else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) { - includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\""); + // For original interface, we need it exchanged... not for stub interfaces + if (needExchange) { + includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\""); + includeClasses.add("\"" + exchangeParamType(simpleType) + "_CallbackStub.hpp\""); + } else { + includeClasses.add("\"" + simpleType + ".hpp\""); + includeClasses.add("\"" + simpleType + "_CallbackSkeleton.hpp\""); + } } else if (param.contains("[]")) { // Check if this is array for C++; translate into vector includeClasses.add(""); @@ -2504,9 +2930,12 @@ public class IoTCompiler { return cplusTemplate; } else return getNonPrimitiveCplusClass(paramType); + } else if(getParamCategory(paramType) == ParamCategory.USERDEFINED) { + return paramType + "*"; } else // Just return it as is if it's not non-primitives return paramType; + //return checkAndGetParamClass(paramType, true); } @@ -2619,15 +3048,11 @@ public class IoTCompiler { // Get the right type for a callback object - private String checkAndGetParamClass(String paramType, boolean needPtr) { + private String checkAndGetParamClass(String paramType) { // Check if this is generics if(getParamCategory(paramType) == ParamCategory.USERDEFINED) { - // If true then return with pointer (C++) - if (needPtr) - return exchangeParamType(paramType) + "*"; - else // Java, so no pointer needed - return exchangeParamType(paramType); + return exchangeParamType(paramType); } else return paramType; }