+ * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
+ * <p>
+ * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
+ * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
+ * The local interface has to be the input parameter for the stub and the stub
+ * interface has to be the input parameter for the local class.
+ */
+ public void generateCplusLocalInterfaces() throws IOException {
+
+ // Create a new directory
+ createDirectory(dir);
+ for (String intface : mapIntfacePTH.keySet()) {
+ // Open a new file to write into
+ FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
+ pw = new PrintWriter(new BufferedWriter(fw));
+ // Write file headers
+ println("#ifndef _" + intface.toUpperCase() + "_HPP__");
+ println("#define _" + intface.toUpperCase() + "_HPP__");
+ println("#include <iostream>");
+ // Pass in set of methods and get include classes
+ DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+ InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+ List<String> methods = intDecl.getMethods();
+ Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, true);
+ printIncludeStatements(includeClasses); println("");
+ println("using namespace std;\n");
+ Set<String> 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
+ writeMethodCplusLocalInterface(methods, intDecl);
+ println("};");
+ println("#endif");
+ pw.close();
+ System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
+ }
+ }
+
+
+ /**
+ * HELPER: writeMethodCplusInterfaceForwardDecl() writes the forward declaration of the interface
+ */
+ private void writeMethodCplusInterfaceForwardDecl(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, boolean needNewIntface) {
+
+ Set<String> isDefined = new HashSet<String>();
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> 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++
+ * <p>
+ * For C++ we use virtual classe as interface
+ */
+ public void generateCPlusInterfaces() throws IOException {
+
+ // Create a new directory
+ String path = createDirectories(dir, subdir);
+ for (String intface : mapIntfacePTH.keySet()) {
+
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+
+ // Open a new file to write into
+ String newIntface = intMeth.getKey();
+ FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
+ pw = new PrintWriter(new BufferedWriter(fw));
+ DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+ InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+ // Write file headers
+ println("#ifndef _" + newIntface.toUpperCase() + "_HPP__");
+ println("#define _" + newIntface.toUpperCase() + "_HPP__");
+ println("#include <iostream>");
+ updateIntfaceObjIdMap(intface, newIntface);
+ // Pass in set of methods and get import classes
+ Set<String> methods = intMeth.getValue();
+ Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, false);
+ printIncludeStatements(includeClasses); println("");
+ println("using namespace std;\n");
+ Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
+ writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, false);
+ println("class " + newIntface);
+ println("{");
+ println("public:");
+ // Write methods
+ writeMethodCplusInterface(methods, intDecl);
+ println("};");
+ println("#endif");
+ pw.close();
+ System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeMethodDeclCplusStub() writes the method declarations of the stub
+ */
+ private void writeMethodDeclCplusStub(Collection<String> methods, InterfaceDecl intDecl) {
+
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> 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<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
+
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(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;
+ Set<String> callbackType = new HashSet<String>();
+ for (int i = 0; i < methParams.size(); i++) {
+
+ String paramType = returnGenericCallbackType(methPrmTypes.get(i));
+ // Check if this has callback object
+ if (callbackClasses.contains(paramType)) {
+ isCallbackMethod = true;
+ //callbackType = paramType;
+ callbackType.add(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)
+ if (i != methParams.size() - 1) {
+ print(", ");
+ }
+ }
+ println(") { ");
+ println("lock_guard<mutex> guard(" + mutexVar + ");");
+ if (isCallbackMethod)
+ writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType);
+ writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType, isCallbackMethod);
+ println("}\n");
+
+ }
+ }
+
+
+ /**
+ * 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, std::ref(skel" + counter +
+ "), std::ref(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<String> methParams,
+ List<String> methPrmTypes, String method, Set<String> callbackType) {
+
+ // Check if this is single object, array, or list of objects
+ boolean isArrayOrList = false;
+ String callbackParam = null;
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
+ println("vector<int> objIdSent" + i + ";");
+ String param = methParams.get(i);
+ if (isArrayOrList(paramType, param)) { // Generate loop
+ println("for (" + getGenericType(paramType) + "* cb : " + getSimpleIdentifier(param) + ") {");
+ writeCallbackInstantiationMethodBodyCplusStub("cb", returnGenericCallbackType(paramType), i);
+ isArrayOrList = true;
+ callbackParam = getSimpleIdentifier(param);
+ } else {
+ writeCallbackInstantiationMethodBodyCplusStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i);
+ }
+ if (isArrayOrList)
+ println("}");
+ println("vector<int> ___paramCB" + i + " = objIdSent" + i + ";");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: checkAndWriteEnumTypeCplusStub() writes the enum type (convert from enum to int)
+ */
+ private void checkAndWriteEnumTypeCplusStub(List<String> methParams, List<String> methPrmTypes) {
+
+ // Iterate and find enum declarations
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ if (isEnumClass(getGenericType(paramType))) {
+ // Check if this is enum type
+ if (isArrayOrList(paramType, param)) { // An array or vector
+ println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
+ println("vector<int> paramEnum" + i + "(len" + i + ");");
+ println("for (int i = 0; i < len" + i + "; i++) {");
+ println("paramEnum" + i + "[i] = (int) " + getSimpleIdentifier(param) + "[i];");
+ println("}");
+ } else { // Just one element
+ println("vector<int> paramEnum" + i + "(1);");
+ println("paramEnum" + i + "[0] = (int) " + param + ";");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: checkAndWriteEnumRetTypeCplusStub() writes the enum return type (convert from enum to int)
+ */
+ private void checkAndWriteEnumRetTypeCplusStub(String retType, String method, InterfaceDecl intDecl) {
+
+ // Strips off array "[]" for return type
+ String pureType = getSimpleArrayType(getGenericType(retType));
+ // Take the inner type of generic
+ if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
+ pureType = getGenericType(retType);
+ if (isEnumClass(pureType)) {
+ // Check if this is enum type
+ println("vector<int> retEnumInt;");
+ println("void* retObj = &retEnumInt;");
+ 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);");
+ println("for (int i = 0; i < retLen; i++) {");
+ println("retVal[i] = (" + pureType + ") retEnumInt[i];");
+ println("}");
+ } else { // Just one element
+ println(pureType + " retVal = (" + pureType + ") retEnumInt[0];");
+ }
+ println("return retVal;");
+ }
+ }
+
+
+ /**
+ * HELPER: checkAndWriteStructSetupCplusStub() writes the struct type setup
+ */
+ private void checkAndWriteStructSetupCplusStub(List<String> methParams, List<String> methPrmTypes,
+ InterfaceDecl intDecl, String method) {
+
+ // Iterate and find struct declarations
+ 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)) {
+ // Check if this is enum type
+ println("int numParam" + i + " = 1;");
+ int methodNumId = intDecl.getMethodNumId(method);
+ String helperMethod = methodNumId + "struct" + i;
+ println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
+ //println("string retTypeStruct" + i + " = \"void\";");
+ println("string paramClsStruct" + i + "[] = { \"int\" };");
+ print("int structLen" + i + " = ");
+ if (isArrayOrList(paramType, param)) { // An array
+ println(getSimpleArrayType(param) + ".size();");
+ } else { // Just one element
+ println("1;");
+ }
+ println("void* paramObjStruct" + i + "[] = { &structLen" + i + " };");
+ //println("void* retStructLen" + i + " = NULL;");
+ println("rmiComm->remoteCall(objectId, methodIdStruct" + i +
+ ", paramClsStruct" + i + ", paramObjStruct" + i +
+ ", numParam" + i + ");\n");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeLengthStructParamClassCplusStub() writes lengths of params
+ */
+ private void writeLengthStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes) {
+
+ // Iterate and find struct declarations - count number of params
+ 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 members = getNumOfMembers(simpleType);
+ if (isArrayOrList(paramType, param)) { // An array or list
+ String structLen = getSimpleIdentifier(param) + ".size()";
+ print(members + "*" + structLen);
+ } else
+ print(Integer.toString(members));
+ } else
+ print("1");
+ if (i != methParams.size() - 1) {
+ print("+");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeStructMembersCplusStub() writes member parameters of struct
+ */
+ private void writeStructMembersCplusStub(String simpleType, String paramType, String param) {
+
+ // Get the struct declaration for this struct and generate initialization code
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ if (isArrayOrList(paramType, param)) { // An array or list
+ println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
+ }
+ if (isArrayOrList(paramType, param)) { // An array or list
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
+ println("paramCls[pos] = \"" + prmTypeC + "\";");
+ print("paramObj[pos++] = &" + getSimpleIdentifier(param) + "[i].");
+ print(getSimpleIdentifier(members.get(i)));
+ println(";");
+ }
+ println("}");
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
+ println("paramCls[pos] = \"" + prmTypeC + "\";");
+ print("paramObj[pos++] = &" + param + ".");
+ print(getSimpleIdentifier(members.get(i)));
+ println(";");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeStructParamClassCplusStub() writes member parameters of struct
+ */
+ private void writeStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
+
+ print("int numParam = ");
+ writeLengthStructParamClassCplusStub(methParams, methPrmTypes);
+ println(";");
+ println("void* paramObj[numParam];");
+ println("string paramCls[numParam];");
+ println("int pos = 0;");
+ // Iterate again over the parameters
+ 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)) {
+ writeStructMembersCplusStub(simpleType, paramType, param);
+ } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
+ println("paramCls[pos] = \"int\";");
+ println("paramObj[pos++] = &___paramCB" + i + ";");
+ } else {
+ String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
+ println("paramCls[pos] = \"" + prmTypeC + "\";");
+ print("paramObj[pos++] = &");
+ print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
+ println(";");
+ }
+ }
+
+ }
+
+
+ /**
+ * HELPER: writeStructRetMembersCplusStub() writes member parameters of struct for return statement
+ */
+ private void writeStructRetMembersCplusStub(String simpleType, String retType) {
+
+ // Get the struct declaration for this struct and generate initialization code
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ if (isArrayOrList(retType, retType)) { // An array or list
+ println("for(int i = 0; i < retLen; i++) {");
+ }
+ if (isArrayOrList(retType, retType)) { // An array or list
+ 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(" = retParam" + i + "[i];");
+ }
+ println("}");
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
+ print("structRet." + getSimpleIdentifier(members.get(i)));
+ println(" = retParam" + i + ";");
+ }
+ }
+ println("return structRet;");
+ }
+
+
+ /**
+ * HELPER: writeStructReturnCplusStub() writes member parameters of struct for return statement
+ */
+ 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("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];");
+ println("void* retObj[numRet];");
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ // Set up variables
+ if (isArrayOrList(retType, retType)) { // An array or list
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusType(memTypes.get(i));
+ String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
+ println(getSimpleType(getEnumType(prmType)) + " retParam" + i + "[retLen];");
+ }
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusType(memTypes.get(i));
+ String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
+ println(getSimpleType(getEnumType(prmType)) + " retParam" + i + ";");
+ }
+ }
+ println("int retPos = 0;");
+ // Get the struct declaration for this struct and generate initialization code
+ if (isArrayOrList(retType, retType)) { // An array or list
+ println("for(int i = 0; i < retLen; i++) {");
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
+ println("retCls[retPos] = \"" + prmTypeC + "\";");
+ println("retObj[retPos++] = &retParam" + i + "[i];");
+ }
+ println("}");
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
+ println("retCls[retPos] = \"" + prmTypeC + "\";");
+ println("retObj[retPos++] = &retParam" + i + ";");
+ }
+ }
+ //println("rmiComm->getStructObjects(retCls, numRet, retObj);");
+ writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getStructObjects(retCls, numRet, retObj);");
+ if (isArrayOrList(retType, retType)) { // An array or list
+ println("vector<" + simpleType + "> structRet(retLen);");
+ } else
+ println(simpleType + " structRet;");
+ writeStructRetMembersCplusStub(simpleType, retType);
+ }
+
+
+ /**
+ * 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<String> methParams,
+ List<String> methPrmTypes, String method, Set<String> callbackType, boolean isCallbackMethod) {
+
+ checkAndWriteStructSetupCplusStub(methParams, methPrmTypes, intDecl, method);
+ println("int methodId = " + intDecl.getMethodNumId(method) + ";");
+ String retType = intDecl.getMethodType(method);
+ println("string retType = \"" + checkAndGetCplusRetClsType(getStructType(getEnumType(retType))) + "\";");
+ checkAndWriteEnumTypeCplusStub(methParams, methPrmTypes);
+ // Generate array of parameter types
+ if (isStructPresent(methParams, methPrmTypes)) {
+ writeStructParamClassCplusStub(methParams, methPrmTypes, callbackType);
+ } else {
+ println("int numParam = " + methParams.size() + ";");
+ print("string paramCls[] = { ");
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = returnGenericCallbackType(methPrmTypes.get(i));
+ if (checkCallbackType(paramType, callbackType)) {
+ print("\"int*\"");
+ } else {
+ String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
+ print("\"" + paramTypeC + "\"");
+ }
+ // Check if this is the last element (don't print a comma)
+ if (i != methParams.size() - 1) {
+ print(", ");
+ }
+ }
+ println(" };");
+ // Generate array of parameter objects
+ print("void* paramObj[] = { ");
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = returnGenericCallbackType(methPrmTypes.get(i));
+ if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
+ print("&___paramCB" + i);
+ else
+ print("&" + getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
+ // Check if this is the last element (don't print a comma)
+ if (i != methParams.size() - 1) {
+ print(", ");
+ }
+ }
+ println(" };");
+ }
+ // Check if this is "void"
+ if (retType.equals("void")) {
+ 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, method, intDecl);
+ } else {
+ // Check if the return value NONPRIMITIVES
+ if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) {
+ checkAndWriteEnumRetTypeCplusStub(retType, method, intDecl);
+ } else {
+ //if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
+ if (isArrayOrList(retType,retType))
+ println(checkAndGetCplusType(retType) + " retVal;");
+ else {
+ println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";");
+ }
+ println("void* retObj = &retVal;");
+ println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
+ writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
+ println("return retVal;");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writePropertiesCplusPermission() writes the properties of the stub class
+ */
+ private void writePropertiesCplusPermission(String intface) {
+
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+ String newIntface = intMeth.getKey();
+ int newObjectId = getNewIntfaceObjectId(newIntface);
+ println("static set<int> set" + newObjectId + "Allowed;");
+ }
+ }
+
+ /**
+ * HELPER: writePropertiesCplusStub() writes the properties of the stub class
+ */
+ private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist,
+ Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
+
+ println("IoTRMIComm *rmiComm;");
+ // Get the object Id
+ Integer objId = mapIntfaceObjId.get(intface);
+ 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");
+ }
+
+
+ /**
+ * HELPER: writeConstructorCplusStub() writes the constructor of the stub class
+ */
+ private void writeConstructorCplusStub(String newStubClass, boolean callbackExist,
+ Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
+
+ 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 + ");");
+ }
+ }
+ println("IoTRMIUtil::mapStub->insert(make_pair(objectId, this));");
+ println("}\n");
+ }
+
+
+ /**
+ * HELPER: writeCallbackConstructorCplusStub() writes the callback constructor of the stub class
+ */
+ private void writeCallbackConstructorCplusStub(String newStubClass, boolean callbackExist,
+ Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
+
+ 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: writeDeconstructorCplusStub() writes the deconstructor of the stub class
+ */
+ private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
+
+ println(newStubClass + "::~" + newStubClass + "() {");
+ println("if (rmiComm != NULL) {");
+ println("delete rmiComm;");
+ println("rmiComm = NULL;");
+ println("}");
+ println("}");
+ println("");
+ }
+
+
+ /**
+ * generateCPlusStubClassesHpp() generate stubs based on the methods list in C++ (.hpp file)
+ */
+ public void generateCPlusStubClassesHpp() throws IOException {
+
+ // Create a new directory
+ String path = createDirectories(dir, subdir);
+ for (String intface : mapIntfacePTH.keySet()) {
+
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+ // Open a new file to write into
+ String newIntface = intMeth.getKey();
+ String newStubClass = newIntface + "_Stub";
+ FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
+ pw = new PrintWriter(new BufferedWriter(fw));
+ // Write file headers
+ println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
+ println("#define _" + newStubClass.toUpperCase() + "_HPP__");
+ println("#include <iostream>");
+ // Find out if there are callback objects
+ Set<String> methods = intMeth.getValue();
+ DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+ InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+ Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
+ boolean callbackExist = !callbackClasses.isEmpty();
+ println("#include <thread>");
+ println("#include <mutex>");
+ List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
+ printIncludeStatements(stdIncludeClasses); println("");
+ println("#include \"" + newIntface + ".hpp\""); println("");
+ println("using namespace std;"); println("");
+ println("class " + newStubClass + " : public " + newIntface); println("{");
+ println("private:\n");
+ writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses, methods, intDecl);
+ println("public:\n");
+ // Add default constructor and destructor
+ println(newStubClass + "();");
+ // Declarations
+ println(newStubClass + "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult);");
+ println(newStubClass + "(IoTRMIComm* _rmiComm, int _objectId);");
+ println("~" + newStubClass + "();");
+ // Write methods
+ writeMethodDeclCplusStub(methods, intDecl);
+ print("}"); println(";");
+ println("#endif");
+ pw.close();
+ System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
+ }
+ }
+ }
+
+
+ /**
+ * writeStubExternalCFunctions() generate external functions for .so file
+ */
+ public void writeStubExternalCFunctions(String newStubClass) throws IOException {
+
+ 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(newStubClass + "* obj = (" + newStubClass + "*) t;");
+ //println("obj->init();");
+ //println("while(true);");
+ println("}\n");
+ }
+
+
+ /**
+ * generateCPlusStubClassesCpp() generate stubs based on the methods list in C++ (.cpp file)
+ */
+ public void generateCPlusStubClassesCpp() throws IOException {
+
+ // Create a new directory
+ String path = createDirectories(dir, subdir);
+ for (String intface : mapIntfacePTH.keySet()) {
+
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+ // Open a new file to write into
+ String newIntface = intMeth.getKey();
+ String newStubClass = newIntface + "_Stub";
+ FileWriter fw = new FileWriter(path + "/" + newStubClass + ".cpp");
+ pw = new PrintWriter(new BufferedWriter(fw));
+ // Write file headers
+ println("#include <iostream>");
+ // Find out if there are callback objects
+ Set<String> methods = intMeth.getValue();
+ DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+ InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+ Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
+ boolean callbackExist = !callbackClasses.isEmpty();
+ println("#include \"" + newStubClass + ".hpp\""); println("");
+ for(String str: callbackClasses) {
+ if (intface.equals(mainClass))
+ println("#include \"" + str + "_Skeleton.cpp\"\n");
+ else
+ println("#include \"" + str + "_Skeleton.hpp\"\n");
+ }
+ println("using namespace std;"); println("");
+ // Add default constructor and destructor
+ //println(newStubClass + "() { }"); println("");
+ writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
+ writeCallbackConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
+ writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
+ // Write methods
+ writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass);
+ // Write external functions for .so file
+ writeStubExternalCFunctions(newStubClass);
+ // TODO: Remove this later
+ if (intface.equals(mainClass)) {
+ println("int main() {");
+ println("return 0;");
+ println("}");
+ }
+ pw.close();
+ System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".cpp...");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writePropertiesCplusSkeleton() writes the properties of the skeleton class
+ */
+ private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
+
+ println(intface + " *mainObj;");
+ 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");
+ }
+
+
+ /**
+ * HELPER: writeObjectIdCountInitializationCplus() writes the initialization of objIdCnt variable
+ */
+ private void writeObjectIdCountInitializationCplus(String newSkelClass, boolean callbackExist) {
+
+ if (callbackExist)
+ println("int " + newSkelClass + "::objIdCnt = 0;");
+ }
+
+
+ /**
+ * HELPER: writePermissionInitializationCplus() writes the initialization of permission set
+ */
+ private void writePermissionInitializationCplus(String intface, String newSkelClass, InterfaceDecl intDecl) {
+
+ // Keep track of object Ids of all stubs registered to this interface
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+ String newIntface = intMeth.getKey();
+ int newObjectId = getNewIntfaceObjectId(newIntface);
+ print("set<int> " + newSkelClass + "::set" + newObjectId + "Allowed { ");
+ Set<String> methodIds = intMeth.getValue();
+ int i = 0;
+ for (String methodId : methodIds) {
+ int methodNumId = intDecl.getMethodNumId(methodId);
+ print(Integer.toString(methodNumId));
+ // Check if this is the last element (don't print a comma)
+ if (i != methodIds.size() - 1) {
+ print(", ");
+ }
+ i++;
+ }
+ println(" };");
+ }
+ }
+
+
+ /**
+ * HELPER: writeStructPermissionCplusSkeleton() writes permission for struct helper
+ */
+ private void writeStructPermissionCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
+
+ // Use this set to handle two same methodIds
+ for (String method : methods) {
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> 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);
+ String helperMethod = methodNumId + "struct" + i;
+ int helperMethodNumId = intDecl.getHelperMethodNumId(helperMethod);
+ // Iterate over interfaces to give permissions to
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+ String newIntface = intMeth.getKey();
+ int newObjectId = getNewIntfaceObjectId(newIntface);
+ println("set" + newObjectId + "Allowed.insert(" + helperMethodNumId + ");");
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeConstructorCplusSkeleton() writes the constructor of the skeleton class
+ */
+ private void writeConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
+
+ println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, int _portSend, int _portRecv) {");
+ println("bool _bResult = false;");
+ println("mainObj = _mainObj;");
+ 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