From 3722cc0869c775457bf044aff6ced55cd15dcb5d Mon Sep 17 00:00:00 2001 From: rtrimana Date: Fri, 3 Feb 2017 11:31:59 -0800 Subject: [PATCH] Minor tests for multiple callbacks, enum, and struct for both Java and C++; Fixing small bugs in compiler and RMI client --- iotjava/Makefile | 27 +- iotjava/iotpolicy/IoTCompiler.java | 985 +++++++++++++----- iotjava/iotrmi/Java/IoTRMICommServer.java | 1 + .../Java/basics/TestClassCallbacks_Stub.java | 37 +- .../development/testclasspolicy_callbacks.pol | 10 +- 5 files changed, 803 insertions(+), 257 deletions(-) diff --git a/iotjava/Makefile b/iotjava/Makefile index 2afe366..4aa6ad3 100644 --- a/iotjava/Makefile +++ b/iotjava/Makefile @@ -24,7 +24,8 @@ run-compiler-dev: cp ../localconfig/iotpolicy/development/*.pol $(BIN_DIR)/iotpolicy/ #cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler testclasspolicy.pol testclassrequires.pol callbackpolicy.pol callbackrequires.pol -cplus Cplus -java Java #cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler callbackpolicy.pol callbackrequires.pol testclasspolicy_advanced.pol testclassrequires_advanced.pol -cplus Cplus -java Java - cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler callbackpolicy.pol callbackrequires.pol testclasspolicy_callbacks.pol testclassrequires_callbacks.pol -cplus Cplus -java Java + #cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler callbackpolicy.pol callbackrequires.pol testclasspolicy_callbacks.pol testclassrequires_callbacks.pol -cplus Cplus -java Java + cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler testclasspolicy_callbacks.pol testclassrequires_callbacks.pol callbackpolicy.pol callbackrequires.pol -cplus Cplus -java Java PHONY += run-compiler-lbtest run-compiler-lbtest: @@ -109,23 +110,23 @@ run-compiler-smart: PHONY += compile compile: cp ./iotrmi/Java/basics/* $(BIN_DIR)/iotpolicy/output_files/Java - cp ./iotrmi/C++/basics/* $(BIN_DIR)/iotpolicy/output_files/Cplus + #cp ./iotrmi/C++/basics/* $(BIN_DIR)/iotpolicy/output_files/Cplus 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) TestClass_Skeleton.java # cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) TestClassAdvanced_Stub.java cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) TestClassCallbacks_Stub.java - cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) TestClassInterface_Skeleton.java - cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) TestClassComplete_Stub.java - cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) CallBackInterfaceWithCallBack_Stub.java - cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) CallBackInterface_Skeleton.java + cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) TestClassInterface_Skeleton.java -Xlint:unchecked + cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) TestClassComplete_Stub.java -Xlint:unchecked + cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) CallBackInterfaceWithCallBack_Stub.java -Xlint:unchecked + cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) CallBackInterface_Skeleton.java -Xlint:unchecked # cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) CallBackInterface_CallbackSkeleton.java # cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) CallBackInterfaceWithCallBack_CallbackStub.java -# cd $(BIN_DIR)/iotpolicy/output_files/Cplus; $(G++) ./TestClassInterface_Skeleton.cpp -o ./TestClassInterface_Skeleton.out --std=c++11 -pthread -pg -I../../../../iotjava/iotrmi/C++/ -# cd $(BIN_DIR)/iotpolicy/output_files/Cplus; $(G++) ./TestClassComplete_Stub.cpp -o ./TestClassComplete_Stub.out --std=c++11 -pthread -pg -I../../../../iotjava/iotrmi/C++/ -# cp ./iotrmi/C++/ConcurrentLinkedListQueue.cpp $(BIN_DIR)/iotpolicy/output_files/Cplus -# cd $(BIN_DIR)/iotpolicy/output_files/Cplus; $(G++) ./ConcurrentLinkedListQueue.cpp -o ./ConcurrentLinkedListQueue.out --std=c++11 -pthread -pg -I../../../../iotjava/iotrmi/C++/ + cd $(BIN_DIR)/iotpolicy/output_files/Cplus; $(G++) ./TestClassInterface_Skeleton.cpp -o ./TestClassInterface_Skeleton.out --std=c++11 -pthread -pg -I../../../../iotjava/iotrmi/C++/ + cd $(BIN_DIR)/iotpolicy/output_files/Cplus; $(G++) ./TestClassComplete_Stub.cpp -o ./TestClassComplete_Stub.out --std=c++11 -pthread -pg -I../../../../iotjava/iotrmi/C++/ + #cp ./iotrmi/C++/ConcurrentLinkedListQueue.cpp $(BIN_DIR)/iotpolicy/output_files/Cplus + #cd $(BIN_DIR)/iotpolicy/output_files/Cplus; $(G++) ./ConcurrentLinkedListQueue.cpp -o ./ConcurrentLinkedListQueue.out --std=c++11 -pthread -pg -I../../../../iotjava/iotrmi/C++/ #cd $(BIN_DIR)/iotpolicy/output_files/Cplus; $(G++) ./TestClassAdvanced_Stub.cpp -o ./TestClassAdvanced_Stub.out --std=c++11 -pthread -pg -I../../../../iotjava/iotrmi/C++/ #cd $(BIN_DIR)/iotpolicy/output_files/Cplus; $(G++) ./TestClass.hpp -o ./TestClass.out --std=c++11 -pthread -pg -I../../../../iotjava/iotrmi/C++/ @@ -147,13 +148,15 @@ run-java-stub: PHONY += run-cplus-skeleton run-cplus-skeleton: - ../bin/iotpolicy/output_files/Cplus/TestClass_Skeleton.out +# ../bin/iotpolicy/output_files/Cplus/TestClass_Skeleton.out + ../bin/iotpolicy/output_files/Cplus/TestClassInterface_Skeleton.out PHONY += run-cplus-stub run-cplus-stub: # ../bin/iotpolicy/output_files/Cplus/TestClass_Stub.out # ../bin/iotpolicy/output_files/Cplus/TestClassAdvanced_Stub.out - ../bin/iotpolicy/output_files/Cplus/TestClassCallbacks_Stub.out +# ../bin/iotpolicy/output_files/Cplus/TestClassCallbacks_Stub.out + ../bin/iotpolicy/output_files/Cplus/TestClassComplete_Stub.out PHONY += folderclean folderclean: diff --git a/iotjava/iotpolicy/IoTCompiler.java b/iotjava/iotpolicy/IoTCompiler.java index 030d856..0a8e5dd 100644 --- a/iotjava/iotpolicy/IoTCompiler.java +++ b/iotjava/iotpolicy/IoTCompiler.java @@ -61,6 +61,7 @@ public class IoTCompiler { private String subdir; private Map mapPortCount; // Counter for ports private static int portCount = 0; + private String mainClass; /** @@ -99,6 +100,7 @@ public class IoTCompiler { pw = null; dir = OUTPUT_DIRECTORY; subdir = null; + mainClass = null; } @@ -185,6 +187,8 @@ 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); @@ -597,7 +601,7 @@ public class IoTCompiler { private void checkAndWriteEnumRetTypeJavaStub(String retType, String method, InterfaceDecl intDecl) { // Write the wait-for-return-value part - writeWaitForReturnValue(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);"); + 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 @@ -644,7 +648,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 };"); @@ -832,7 +835,7 @@ public class IoTCompiler { private void writeStructReturnJavaStub(String simpleType, String retType, String method, InterfaceDecl intDecl) { // Handle the returned struct size - writeWaitForReturnValue(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);"); + writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);"); // Minimum retLen is 1 if this is a single struct object println("int retLen = (int) retObj;"); int numMem = getNumOfMembers(simpleType); @@ -860,7 +863,7 @@ public class IoTCompiler { } //println("Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);"); // Handle the actual returned struct - writeWaitForReturnValue(method, intDecl, "Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);"); + 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++) {"); @@ -876,9 +879,9 @@ public class IoTCompiler { /** - * HELPER: writeWaitForReturnValue() writes the synchronization part for return values + * HELPER: writeWaitForReturnValueJava() writes the synchronization part for return values */ - private void writeWaitForReturnValue(String method, InterfaceDecl intDecl, String getReturnValue) { + private void writeWaitForReturnValueJava(String method, InterfaceDecl intDecl, String getReturnValue) { println("// Waiting for return value"); int methodNumId = intDecl.getMethodNumId(method); @@ -950,10 +953,10 @@ public class IoTCompiler { // Check if the return value NONPRIMITIVES String retGenValType = getGenericType(retType); println("Class retGenValType = " + retGenValType + ".class;"); - writeWaitForReturnValue(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, retGenValType);"); + writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, retGenValType);"); println("return (" + retType + ")retObj;"); } else { - writeWaitForReturnValue(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);"); + writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);"); println("return (" + retType + ")retObj;"); } } @@ -1013,7 +1016,7 @@ public class IoTCompiler { println("}"); println("};"); println("thread.start();"); - println("while(!skel0.didAlreadyInitWaitInvoke());"); + println("while(!skel" + counter + ".didAlreadyInitWaitInvoke());"); println("}"); println("else"); println("{"); @@ -1075,7 +1078,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); @@ -1106,11 +1108,6 @@ public class IoTCompiler { //else writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType); println("}\n"); - // Write the init callback helper method - if (isCallbackMethod && !isDefined) { - //writeInitCallbackJavaStub(callbackType, intDecl, newStubClass); - isDefined = true; - } } } @@ -1300,7 +1297,6 @@ public class IoTCompiler { private void writeMethodJavaSkeleton(Collection methods, InterfaceDecl intDecl, Set callbackClasses, boolean callbackSkeleton, String intface) { - boolean isDefined = false; for (String method : methods) { List methParams = intDecl.getMethodParams(method); @@ -1327,10 +1323,6 @@ 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; - } } } @@ -1338,7 +1330,7 @@ public class IoTCompiler { /** * HELPER: writeCallbackInstantiationJavaStubGeneration() writes the instantiation of callback stubs */ - private void writeCallbackInstantiationJavaStubGeneration(int counter, String exchParamType) { + private void writeCallbackInstantiationJavaStubGeneration(String exchParamType) { //println("int objIdRecv = (int[]) paramObj[0];"); println(exchParamType + " newStub = null;"); @@ -1380,7 +1372,7 @@ public class IoTCompiler { println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();"); } else { println("int objIdRecv = stubIdArray" + i + "[0];"); - writeCallbackInstantiationJavaStubGeneration(i, exchParamType); + writeCallbackInstantiationJavaStubGeneration(exchParamType); } } // Generate a loop if needed @@ -1388,14 +1380,14 @@ public class IoTCompiler { String exchParamType = checkAndGetParamClass(getGenericType(paramType)); if (isArray(param)) { println("for (int i = 0; i < numStubs" + i + "; i++) {"); - println("int objIdRecv = stubIdArray" + i + "[numStubs" + i + "];"); - writeCallbackInstantiationJavaStubGeneration(i, exchParamType); + println("int objIdRecv = stubIdArray" + i + "[i];"); + writeCallbackInstantiationJavaStubGeneration(exchParamType); println("stub" + i + "[i] = newStub;"); println("}"); } else if (isList(paramType)) { println("for (int i = 0; i < numStubs" + i + "; i++) {"); - println("int objIdRecv = stubIdArray" + i + "[numStubs" + i + "];"); - writeCallbackInstantiationJavaStubGeneration(i, exchParamType); + println("int objIdRecv = stubIdArray" + i + "[i];"); + writeCallbackInstantiationJavaStubGeneration(exchParamType); println("stub" + i + ".add(newStub);"); println("}"); } else @@ -1992,11 +1984,11 @@ 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); @@ -2020,11 +2012,39 @@ public class IoTCompiler { 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); + 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); + } + } + return structExist; + } + /** - * 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) { @@ -2050,6 +2070,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 */ @@ -2089,7 +2138,7 @@ 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("}"); @@ -2165,7 +2214,7 @@ public class IoTCompiler { else uniqueMethodIds.add(methodId); print(helperMethod + "("); - writeInputCountVarStructSkeleton(method, intDecl); + writeInputCountVarStructJavaSkeleton(method, intDecl); println(");"); println("}"); println("catch (Exception ex) {"); @@ -2176,7 +2225,7 @@ public class IoTCompiler { println("break;"); } String method = "___initCallBack()"; - writeMethodCallStructSkeleton(methods, intDecl); + writeMethodCallStructJavaSkeleton(methods, intDecl); println("default: "); println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");"); println("}"); @@ -2243,9 +2292,11 @@ public class IoTCompiler { } -/*================ - * C++ generation - *================/ +/*================================================================================ + * + * C++ generation + * + *================================================================================/ /** * HELPER: writeMethodCplusLocalInterface() writes the method of the local interface @@ -2414,7 +2465,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 @@ -2427,6 +2480,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++ *

@@ -2455,10 +2535,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:"); @@ -2473,17 +2553,55 @@ public class IoTCompiler { } + /** + * HELPER: writeMethodDeclCplusStub() writes the method declarations of the stub + */ + private void writeMethodDeclCplusStub(Collection methods, InterfaceDecl intDecl, Set callbackClasses, String newStubClass) { + + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + 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 = returnGenericCallbackType(methPrmTypes.get(i)); + // Check if this has callback object + if (callbackClasses.contains(paramType)) { + isCallbackMethod = true; + callbackType = paramType; + // Even if there're 2 callback arguments, we expect them to be of the same interface + } + String methPrmType = checkAndGetCplusType(methPrmTypes.get(i)); + String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i)); + print(methParamComplete); + // 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; @@ -2505,20 +2623,42 @@ 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 = IoTRMIUtil::mapSkel->find(" + paramIdent + ");"); + println("if (it == IoTRMIUtil::mapSkel->end()) {"); + println("int newObjIdSent = rmiComm->getObjectIdCounter();"); + println("objIdSent.push_back(newObjIdSent);"); + println("rmiComm->decrementObjectIdCounter();"); + println(callbackType + "_Skeleton* skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);"); + println("vecCallbackObj.push_back(skel0);"); + println("IoTRMIUtil::mapSkel->insert(make_pair(" + paramIdent + ", skel0));"); + println("IoTRMIUtil::mapSkelId->insert(make_pair(" + paramIdent + ", newObjIdSent));"); + println("thread th0 (&" + callbackType + "_Skeleton::___waitRequestInvokeMethod, std::ref(skel0), std::ref(skel0));"); + println("th0.detach();"); + println("while(!skel" + counter + "->didInitWaitInvoke());"); + println("}"); + println("else"); + println("{"); + println("auto itId = IoTRMIUtil::mapSkelId->find(" + paramIdent + ");"); + println("objIdSent.push_back(itId->second);"); + println("}"); + } + + /** * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class */ @@ -2528,27 +2668,23 @@ public class IoTCompiler { // Check if this is single object, array, or list of objects boolean isArrayOrList = false; String callbackParam = null; + println("vector objIdSent;"); 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 + 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", callbackType, 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), callbackType, i); + } if (isArrayOrList) println("}"); - print("int ___paramCB" + i + " = "); - if (isArrayOrList) - println(callbackParam + ".size();"); - else - println("1;"); + println("vector ___paramCB" + i + " = objIdSent;"); } } } @@ -2583,7 +2719,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)); @@ -2594,7 +2730,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);"); @@ -2626,7 +2763,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 @@ -2635,10 +2772,10 @@ 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("void* retStructLen" + i + " = NULL;"); + println("rmiComm->remoteCall(objectId, methodIdStruct" + i + + ", paramClsStruct" + i + ", paramObjStruct" + i + + ", numParam" + i + ");\n"); } } } @@ -2769,13 +2906,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];"); @@ -2814,7 +2952,8 @@ public class IoTCompiler { println("retObj[retPos++] = &retParam" + i + ";"); } } - println("rmiCall->getStructObjects(retCls, numRet, retObj);"); + //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 @@ -2823,6 +2962,20 @@ 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 */ @@ -2843,7 +2996,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 + "\""); @@ -2871,16 +3024,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)) @@ -2889,7 +3041,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;"); } } @@ -2898,7 +3051,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) { @@ -2906,7 +3059,7 @@ 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("int objectId = " + newObjectId + ";"); println("static set set" + newObjectId + "Allowed;"); } } @@ -2914,24 +3067,28 @@ 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 + ";"); + println("int objectId = " + objId + ";"); if (callbackExist) { // We assume that each class only has one callback interface for now Iterator it = callbackClasses.iterator(); String callbackType = (String) it.next(); println("// Callback properties"); - println("IoTRMIObject *rmiObj;"); println("vector<" + callbackType + "*> vecCallbackObj;"); - println("static int objIdCnt;"); - // Generate permission stuff for callback stubs - writePropertiesCplusPermission(callbackType); + } + 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"); } @@ -2940,22 +3097,43 @@ public class IoTCompiler { /** * HELPER: writeConstructorCplusStub() writes the constructor of the stub class */ - private void writeConstructorCplusStub(String newStubClass, boolean callbackExist, Set callbackClasses) { + private void writeConstructorCplusStub(String newStubClass, boolean callbackExist, + Set callbackClasses, Set methods, InterfaceDecl intDecl) { - 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(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 callbackClasses, Set 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"); } @@ -2966,17 +3144,13 @@ public class IoTCompiler { */ private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set callbackClasses) { - println("~" + newStubClass + "() {"); - println("if (rmiCall != NULL) {"); - println("delete rmiCall;"); - println("rmiCall = NULL;"); + println(newStubClass + "::~" + newStubClass + "() {"); + 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 (rmiObj != NULL) {"); - println("delete rmiObj;"); - println("rmiObj = NULL;"); - println("}"); Iterator it = callbackClasses.iterator(); String callbackType = (String) it.next(); println("for(" + callbackType + "* cb : vecCallbackObj) {"); @@ -3009,9 +3183,9 @@ public class IoTCompiler { /** - * 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); @@ -3034,30 +3208,25 @@ public class IoTCompiler { 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 "); + 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); + writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses, methods, intDecl); println("public:\n"); // Add default constructor and destructor - println(newStubClass + "() { }"); println(""); - writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses); - writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses); + 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 - writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass); + writeMethodDeclCplusStub(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); - } - writeObjectIdCountInitializationCplus(newStubClass, callbackExist); println("#endif"); pw.close(); System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp..."); @@ -3066,27 +3235,104 @@ public class IoTCompiler { } + /** + * 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> 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 + ".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 + //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 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;"); // 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"); } @@ -3164,14 +3410,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"); } @@ -3181,17 +3445,13 @@ 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); @@ -3226,20 +3486,55 @@ public class IoTCompiler { } + /** + * HELPER: writeMethodDeclCplusSkeleton() writes the method declaration of the skeleton class + */ + private void writeMethodDeclCplusSkeleton(Collection methods, InterfaceDecl intDecl, + Set callbackClasses) { + + 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 + " " + methodId + "("); + boolean isCallbackMethod = false; + String callbackType = null; + for (int i = 0; i < methParams.size(); i++) { + + String origParamType = methPrmTypes.get(i); + if (callbackClasses.contains(origParamType)) { // Check if this has callback object + isCallbackMethod = true; + callbackType = origParamType; + } + String paramType = checkAndGetParamClass(methPrmTypes.get(i)); + String methPrmType = checkAndGetCplusType(paramType); + String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i)); + print(methParamComplete); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } + } + println(");"); + } + } + + /** * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class */ private void writeMethodCplusSkeleton(Collection methods, InterfaceDecl intDecl, - Set callbackClasses, boolean callbackSkeleton, String intface) { + Set callbackClasses, boolean callbackSkeleton, String intface, String newSkelClass) { - boolean isDefined = false; 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 + " " + methodId + "("); + print(methodType + " " + newSkelClass + "::" + methodId + "("); boolean isCallbackMethod = false; String callbackType = null; for (int i = 0; i < methParams.size(); i++) { @@ -3262,10 +3557,6 @@ public class IoTCompiler { // Now, write the body of skeleton! writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method)); println("}\n"); - if (isCallbackMethod && !isDefined) { - //writeInitCallbackCplusSkeleton(callbackSkeleton, intface); - isDefined = true; - } } } @@ -3280,11 +3571,33 @@ public class IoTCompiler { 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("int numStubs" + i + " = 0;"); + println("vector numStubIdArray" + i + ";"); } } + /** + * HELPER: writeCallbackInstantiationCplusStubGeneration() writes the instantiation of callback stubs + */ + private void writeCallbackInstantiationCplusStubGeneration(String exchParamType) { + + //println("int objIdRecv = (int[]) paramObj[0];"); + println(exchParamType + "* newStub = NULL;"); + println("auto it = IoTRMIUtil::mapStub->find(objIdRecv);"); + println("if (it == IoTRMIUtil::mapStub->end()) {"); + println("newStub = new " + exchParamType + "_Stub(rmiComm, objIdRecv);"); + println("IoTRMIUtil::mapStub->insert(make_pair(objIdRecv, newStub));"); + println("rmiComm->setObjectIdCounter(objIdRecv);"); + println("rmiComm->decrementObjectIdCounter();"); + println("skel->vecCallbackObj.push_back(newStub);"); + println("}"); + println("else {"); + println("newStub = (" + exchParamType + "_Stub*) it->second;"); + println("}"); + } + + /** * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part */ @@ -3299,16 +3612,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 = numStubIdArray" + i + "[i];"); + writeCallbackInstantiationCplusStubGeneration(exchParamType); + println("stub" + i + ".push_back(newStub);"); println("}"); } else { - println(exchParamType + "* stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);"); - println("vecCallbackObj.push_back(stub" + i + ");"); - println("objIdCnt++;"); + println("int objIdRecv = numStubIdArray" + i + "[0];"); + writeCallbackInstantiationCplusStubGeneration(exchParamType); + println(exchParamType + "* stub" + i + " = newStub;"); } } } @@ -3401,7 +3713,7 @@ public class IoTCompiler { List methPrmTypes, String method, boolean isCallbackMethod, String 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); @@ -3429,9 +3741,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);"); } } @@ -3451,7 +3763,7 @@ public class IoTCompiler { if (callbackClasses.contains(paramType)) { isCallbackMethod = true; callbackType = paramType; - print("\"int\""); + print("\"int*\""); } else { // Generate normal classes if it's not a callback object String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i)); print("\"" + paramTypeC + "\""); @@ -3484,7 +3796,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 @@ -3597,7 +3909,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];"); @@ -3657,9 +3969,10 @@ public class IoTCompiler { if (callbackClasses.contains(prmType)) { isCallbackMethod = true; callbackType = prmType; - println("int numStubs" + i + " = 0;"); - println("paramCls[pos] = \"int\";"); - println("paramObj[pos++] = &numStubs" + i + ";"); + //println("int numStubs" + i + " = 0;"); + 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 @@ -3684,9 +3997,10 @@ public class IoTCompiler { /** - * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class + * HELPER: writeMethodHelperDeclCplusSkeleton() writes the method helper declarations of the skeleton class */ - private void writeMethodHelperCplusSkeleton(Collection methods, InterfaceDecl intDecl, Set callbackClasses) { + private void writeMethodHelperDeclCplusSkeleton(Collection methods, InterfaceDecl intDecl, + Set callbackClasses, String newSkelClass) { // Use this set to handle two same methodIds Set uniqueMethodIds = new HashSet(); @@ -3718,12 +4032,107 @@ public class IoTCompiler { print("int struct" + methodNumId + "Size" + i); } } - println(") {"); + 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, 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 " + newSkelClass + "::___"); + 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) {"); + 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); @@ -3731,14 +4140,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); } @@ -3746,7 +4157,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) { @@ -3760,16 +4171,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"); } } @@ -3803,7 +4216,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"); } @@ -3822,15 +4235,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("}"); } } @@ -3839,17 +4251,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) {"); @@ -3857,26 +4276,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 + ", std::ref(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"); @@ -3884,9 +4302,9 @@ 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); @@ -3904,10 +4322,8 @@ public class IoTCompiler { 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(""); + printIncludeStatements(stdIncludeClasses); println(""); println("using namespace std;\n"); // Find out if there are callback objects Set callbackClasses = getCallbackClasses(methods, intDecl); @@ -3918,22 +4334,112 @@ public class IoTCompiler { // Write properties writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses); println("public:\n"); + // Write constructors + println(newSkelClass + "();"); + println(newSkelClass + "(" + intface + "*_mainObj, int _portSend, int _portRecv);"); + println(newSkelClass + "(" + intface + "*_mainObj, IoTRMIComm *rmiComm, int _objectId);"); + // Write deconstructor + println("~" + newSkelClass + "();"); + // Write method declarations + println("bool didInitWaitInvoke();"); + writeMethodDeclCplusSkeleton(methods, intDecl, callbackClasses); + // Write method helper declarations + writeMethodHelperDeclCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass); + // Write waitRequestInvokeMethod() declaration - main loop + println("void ___waitRequestInvokeMethod(" + newSkelClass + "* skel);"); + println("};"); + writePermissionInitializationCplus(intface, newSkelClass, intDecl); + println("#endif"); + pw.close(); + System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp..."); + } + } + + /** + * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke + */ + private void writeReturnDidAlreadyInitWaitInvoke(String newSkelClass) { + + println("bool " + newSkelClass + "::didInitWaitInvoke() {"); + println("return didAlreadyInitWaitInvoke;"); + println("}\n"); + } + + + /** + * writeSkelExternalCFunctions() generate external functions for .so file + */ + public void writeSkelExternalCFunctions(String newSkelClass, String intface) throws IOException { + + println("extern \"C\" void* create" + newSkelClass + "(void** params) {"); + println("// Args: *_mainObj, int _portSend, int _portRecv"); + println("return new " + newSkelClass + "((" + intface + "*) params[0], *((int*) params[0]), *((int*) params[1]));"); + println("}\n"); + println("extern \"C\" void destroy" + newSkelClass + "(void* t) {"); + println(newSkelClass + "* obj = (" + newSkelClass + "*) t;"); + println("delete obj;"); + println("}\n"); + //println("extern \"C\" void init" + newSkelClass + "(void* t) {"); + //println(newSkelClass + "* obj = (" + newSkelClass + "*) t;"); + //println("obj->init();"); + //println("while(true);"); + //println("}\n"); + } + + + /** + * generateCplusSkeletonClassCpp() generate skeletons based on the methods list in C++ (.cpp file) + */ + 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 + "_Skeleton"; + 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, callbackClasses, false, intface); + writeMethodCplusSkeleton(methods, intDecl, callbackClasses, false, intface, newSkelClass); // Write method helper - writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses); + writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass); // Write waitRequestInvokeMethod() - main loop - writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface); - println("};"); - writePermissionInitializationCplus(intface, newSkelClass, intDecl); - writeObjectIdCountInitializationCplus(newSkelClass, callbackExist); - println("#endif"); + 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 + ".hpp..."); + System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".cpp..."); } } @@ -4228,8 +4734,11 @@ public class IoTCompiler { // Add the standard list first importClasses.add(""); importClasses.add(""); - importClasses.add("\"IoTRMICall.hpp\""); - importClasses.add("\"IoTRMIObject.hpp\""); + //importClasses.add("\"IoTRMICall.hpp\""); + //importClasses.add("\"IoTRMIObject.hpp\""); + importClasses.add("\"IoTRMIComm.hpp\""); + importClasses.add("\"IoTRMICommClient.hpp\""); + importClasses.add("\"IoTRMICommServer.hpp\""); return importClasses; } @@ -4418,24 +4927,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(""); } @@ -4807,16 +5322,16 @@ 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.generateCPlusStubClassesHpp(); + comp.generateCPlusStubClassesCpp(); //comp.generateCPlusCallbackStubClasses(); - comp.generateCplusSkeletonClass(); + comp.generateCplusSkeletonClassHpp(); + comp.generateCplusSkeletonClassCpp(); //comp.generateCplusCallbackSkeletonClass(); } else { // Check other options @@ -4837,17 +5352,17 @@ 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.generateCPlusStubClassesHpp(); + comp.generateCPlusStubClassesCpp(); //comp.generateCPlusCallbackStubClasses(); - comp.generateCplusSkeletonClass(); + comp.generateCplusSkeletonClassHpp(); + comp.generateCplusSkeletonClassCpp(); //comp.generateCplusCallbackSkeletonClass(); } } diff --git a/iotjava/iotrmi/Java/IoTRMICommServer.java b/iotjava/iotrmi/Java/IoTRMICommServer.java index 96032d1..6668745 100644 --- a/iotjava/iotrmi/Java/IoTRMICommServer.java +++ b/iotjava/iotrmi/Java/IoTRMICommServer.java @@ -174,6 +174,7 @@ public class IoTRMICommServer extends IoTRMIComm { byte[] packetTypeBytes = IoTRMIUtil.intToByteArray(packetType); System.arraycopy(packetTypeBytes, 0, retAllBytes, objMethIdLen, IoTRMIUtil.PACKET_TYPE_LEN); // Copy array of bytes (return object) + System.arraycopy(retObjBytes, 0, retAllBytes, headerLen, retObjBytes.length); try { rmiServerSend.sendBytes(retAllBytes); } catch (IOException ex) { diff --git a/iotjava/iotrmi/Java/basics/TestClassCallbacks_Stub.java b/iotjava/iotrmi/Java/basics/TestClassCallbacks_Stub.java index 1220e3f..082e95f 100644 --- a/iotjava/iotrmi/Java/basics/TestClassCallbacks_Stub.java +++ b/iotjava/iotrmi/Java/basics/TestClassCallbacks_Stub.java @@ -30,14 +30,43 @@ public class TestClassCallbacks_Stub { CallBackInterface cbSingle = new CallBack(2354); tcstub.registerCallback(cbSingle); System.out.println("Registered callback!"); - CallBackInterface cbSingle1 = new CallBack(2356); - tcstub.registerCallback(cbSingle1); - System.out.println("Registered callback!"); +// CallBackInterface cbSingle1 = new CallBack(2356); +// tcstub.registerCallback(cbSingle1); +// System.out.println("Registered callback!"); // CallBackInterface cbSingle2 = new CallBack(2360); // tcstub.registerCallback(cbSingle2); // System.out.println("Registered callback!"); + /*CallBackInterface cb1 = new CallBack(23); + CallBackInterface cb2 = new CallBack(33); + CallBackInterface cb3 = new CallBack(43); + CallBackInterface[] cb = { cb1, cb2, cb3 }; + tcstub.registerCallbackArray(cb); + List cblist = new ArrayList(); + CallBackInterface cb4 = new CallBack(53); cblist.add(cb4); + CallBackInterface cb5 = new CallBack(63); cblist.add(cb5); + CallBackInterface cb6 = new CallBack(73); cblist.add(cb6); + tcstub.registerCallbackList(cblist);*/ + /*Enum[] enArr = { Enum.APPLE, Enum.ORANGE, Enum.APPLE, Enum.GRAPE }; + List enArr2 = new ArrayList(Arrays.asList(enArr)); + List resArr2 = tcstub.handleEnumList(enArr2); + System.out.println("Enum members: " + resArr2.toString());*/ + Struct str = new Struct(); + str.name = "Rahmadi"; + str.value = 0.123f; + str.year = 2016; + Struct str2 = new Struct(); + str2.name = "Trimananda"; + str2.value = 0.124f; + str2.year = 2017; + Struct[] arrStr = { str, str2 }; + Struct[] arrRet = tcstub.handleStructArray(arrStr); + for(Struct st : arrRet) { + System.out.println("Name: " + st.name); + System.out.println("Value: " + st.value); + System.out.println("Year: " + st.year); + } - System.out.println("Return value from callback 1: " + tcstub.callBack() + "\n\n"); +// System.out.println("Return value from callback 1: " + tcstub.callBack() + "\n\n"); // System.out.println("\n\nCalling short one more time value: " + tcstub.getShort((short)4576) + "\n\n"); // System.out.println("Return value from callback 2: " + tcstub.callBack() + "\n\n"); // System.out.println("\n\nCalling short one more time value: " + tcstub.getShort((short)1233) + "\n\n"); diff --git a/localconfig/iotpolicy/development/testclasspolicy_callbacks.pol b/localconfig/iotpolicy/development/testclasspolicy_callbacks.pol index 2883100..a045faf 100644 --- a/localconfig/iotpolicy/development/testclasspolicy_callbacks.pol +++ b/localconfig/iotpolicy/development/testclasspolicy_callbacks.pol @@ -3,9 +3,8 @@ public interface TestClassInterface { public short getShort(short in); public void registerCallback(CallBackInterface _cb); public int callBack(); - public List getCharList(List in); - public Enum[] handleEnumStruct(Enum en[], List str, char c); - public List handleStructList(List str); + public List handleEnumList(List en); + public Struct[] handleStructArray(Struct str[]); public void registerCallbackArray(CallBackInterface _cb[]); public void registerCallbackList(List _cb); @@ -14,9 +13,8 @@ public interface TestClassInterface { method = "getShort(short in)"; method = "registerCallback(CallBackInterface _cb)"; method = "callBack()"; - method = "getCharList(List in)"; - method = "handleEnumStruct(Enum en[], List str, char c)"; - method = "handleStructList(List str)"; + method = "handleEnumList(List en)"; + method = "handleStructArray(Struct str[])"; method = "registerCallbackArray(CallBackInterface _cb[])"; method = "registerCallbackList(List _cb)"; } -- 2.34.1