X-Git-Url: http://plrg.eecs.uci.edu/git/?p=iot2.git;a=blobdiff_plain;f=iotjava%2Fiotpolicy%2FIoTCompiler.java;h=a46a20be8ffc9a63d42ee85d52289a400b1535b5;hp=8849c4d5dc55ea7471a2df4025c536be204e76b3;hb=9056ba9d1b09be0fe455e7a68e9bf6a9ce5cf88d;hpb=c3bf5191e624be8b17e823804c84914afa916a1f diff --git a/iotjava/iotpolicy/IoTCompiler.java b/iotjava/iotpolicy/IoTCompiler.java index 8849c4d..a46a20b 100644 --- a/iotjava/iotpolicy/IoTCompiler.java +++ b/iotjava/iotpolicy/IoTCompiler.java @@ -3,6 +3,8 @@ package iotpolicy; import java_cup.runtime.ComplexSymbolFactory; import java_cup.runtime.ScannerBuffer; import java.io.*; +import java.util.Arrays; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -22,6 +24,8 @@ import iotpolicy.tree.DeclarationHandler; import iotpolicy.tree.CapabilityDecl; import iotpolicy.tree.InterfaceDecl; import iotpolicy.tree.RequiresDecl; +import iotpolicy.tree.EnumDecl; +import iotpolicy.tree.StructDecl; import iotrmi.Java.IoTRMITypes; @@ -44,13 +48,20 @@ public class IoTCompiler { private Map mapIntfacePTH; private Map mapIntDeclHand; private Map>> mapInt2NewInts; + private Map mapInt2NewIntName; // Data structure to store our types (primitives and non-primitives) for compilation private Map mapPrimitives; private Map mapNonPrimitivesJava; private Map mapNonPrimitivesCplus; + // Other data structures + private Map mapIntfaceObjId; // Maps interface name to object Id + private Map mapNewIntfaceObjId; // Maps new interface name to its object Id (keep track of stubs) private PrintWriter pw; private String dir; private String subdir; + private Map mapPortCount; // Counter for ports + private static int portCount = 0; + /** * Class constants @@ -61,9 +72,12 @@ public class IoTCompiler { PRIMITIVES, // All the primitive types, e.g. byte, short, int, long, etc. NONPRIMITIVES, // Non-primitive types, e.g. Set, Map, List, etc. - USERDEFINED // Non-supported type by default; assumed as driver classes + ENUM, // Enum type + STRUCT, // Struct type + USERDEFINED // Assumed as driver classes } + /** * Class constructors */ @@ -72,12 +86,16 @@ public class IoTCompiler { mapIntfacePTH = new HashMap(); mapIntDeclHand = new HashMap(); mapInt2NewInts = new HashMap>>(); + mapInt2NewIntName = new HashMap(); + mapIntfaceObjId = new HashMap(); + mapNewIntfaceObjId = new HashMap(); mapPrimitives = new HashMap(); arraysToMap(mapPrimitives, IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus); mapNonPrimitivesJava = new HashMap(); arraysToMap(mapNonPrimitivesJava, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitiveJavaLibs); mapNonPrimitivesCplus = new HashMap(); arraysToMap(mapNonPrimitivesCplus, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus); + mapPortCount = new HashMap(); pw = null; dir = OUTPUT_DIRECTORY; subdir = null; @@ -85,7 +103,7 @@ public class IoTCompiler { /** - * setParseTree() sets parse tree based on policy files. + * setDataStructures() sets parse tree and other data structures based on policy files. *

* It also generates parse tree (ParseTreeHandler) and * copies useful information from parse tree into @@ -93,26 +111,37 @@ public class IoTCompiler { * data structures. * Additionally, the data structure handles are * returned from tree-parsing for further process. - * */ - public void setParseTree(String origInt, ParseNode pnPol, ParseNode pnReq) { + public void setDataStructures(String origInt, ParseNode pnPol, ParseNode pnReq) { ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq); DeclarationHandler decHandler = new DeclarationHandler(); - // Process ParseNode and generate Declaration objects + // Interface ptHandler.processInterfaceDecl(); InterfaceDecl intDecl = ptHandler.getInterfaceDecl(); decHandler.addInterfaceDecl(origInt, intDecl); + // Capabilities ptHandler.processCapabilityDecl(); CapabilityDecl capDecl = ptHandler.getCapabilityDecl(); decHandler.addCapabilityDecl(origInt, capDecl); + // Requires ptHandler.processRequiresDecl(); RequiresDecl reqDecl = ptHandler.getRequiresDecl(); decHandler.addRequiresDecl(origInt, reqDecl); + // Enumeration + ptHandler.processEnumDecl(); + EnumDecl enumDecl = ptHandler.getEnumDecl(); + decHandler.addEnumDecl(origInt, enumDecl); + // Struct + ptHandler.processStructDecl(); + StructDecl structDecl = ptHandler.getStructDecl(); + decHandler.addStructDecl(origInt, structDecl); mapIntfacePTH.put(origInt, ptHandler); mapIntDeclHand.put(origInt, decHandler); + // Set object Id counter to 0 for each interface + mapIntfaceObjId.put(origInt, new Integer(0)); } @@ -153,12 +182,41 @@ public class IoTCompiler { } // Add interface and methods information into map mapNewIntMethods.put(strInt, setMethods); + // 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); } // Map the map of interface-methods to the original interface mapInt2NewInts.put(origInt, mapNewIntMethods); } + /** + * HELPER: writeMethodJavaLocalInterface() writes the method of the local interface + */ + private void writeMethodJavaLocalInterface(Collection methods, InterfaceDecl intDecl) { + + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + print("public " + intDecl.getMethodType(method) + " " + + intDecl.getMethodId(method) + "("); + for (int i = 0; i < methParams.size(); i++) { + // Check for params with driver class types and exchange it + // with its remote interface + String paramType = checkAndGetParamClass(methPrmTypes.get(i)); + print(paramType + " " + methParams.get(i)); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } + } + println(");"); + } + } + + /** * HELPER: writeMethodJavaInterface() writes the method of the interface */ @@ -173,7 +231,7 @@ public class IoTCompiler { for (int i = 0; i < methParams.size(); i++) { // Check for params with driver class types and exchange it // with its remote interface - String paramType = checkAndGetParamClass(methPrmTypes.get(i), false); + String paramType = methPrmTypes.get(i); print(paramType + " " + methParams.get(i)); // Check if this is the last element (don't print a comma) if (i != methParams.size() - 1) { @@ -185,6 +243,77 @@ public class IoTCompiler { } + /** + * HELPER: generateEnumJava() writes the enumeration declaration + */ + private void generateEnumJava() throws IOException { + + // Create a new directory + createDirectory(dir); + for (String intface : mapIntfacePTH.keySet()) { + // Get the right EnumDecl + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface); + Set enumTypes = enumDecl.getEnumDeclarations(); + // Iterate over enum declarations + for (String enType : enumTypes) { + // Open a new file to write into + FileWriter fw = new FileWriter(dir + "/" + enType + ".java"); + pw = new PrintWriter(new BufferedWriter(fw)); + println("public enum " + enType + " {"); + List enumMembers = enumDecl.getMembers(enType); + for (int i = 0; i < enumMembers.size(); i++) { + + String member = enumMembers.get(i); + print(member); + // Check if this is the last element (don't print a comma) + if (i != enumMembers.size() - 1) + println(","); + else + println(""); + } + println("}\n"); + pw.close(); + System.out.println("IoTCompiler: Generated enum class " + enType + ".java..."); + } + } + } + + + /** + * HELPER: generateStructJava() writes the struct declaration + */ + private void generateStructJava() throws IOException { + + // Create a new directory + createDirectory(dir); + for (String intface : mapIntfacePTH.keySet()) { + // Get the right StructDecl + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface); + List structTypes = structDecl.getStructTypes(); + // Iterate over enum declarations + for (String stType : structTypes) { + // Open a new file to write into + FileWriter fw = new FileWriter(dir + "/" + stType + ".java"); + pw = new PrintWriter(new BufferedWriter(fw)); + println("public class " + stType + " {"); + List structMemberTypes = structDecl.getMemberTypes(stType); + List structMembers = structDecl.getMembers(stType); + for (int i = 0; i < structMembers.size(); i++) { + + String memberType = structMemberTypes.get(i); + String member = structMembers.get(i); + println("public static " + memberType + " " + member + ";"); + } + println("}\n"); + pw.close(); + System.out.println("IoTCompiler: Generated struct class " + stType + ".java..."); + } + } + } + + /** * generateJavaLocalInterface() writes the local interface and provides type-checking. *

@@ -206,12 +335,14 @@ public class IoTCompiler { InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); List methods = intDecl.getMethods(); Set importClasses = getImportClasses(methods, intDecl); - printImportStatements(importClasses); + List stdImportClasses = getStandardJavaIntfaceImportClasses(); + List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); + printImportStatements(allImportClasses); // Write interface header println(""); println("public interface " + intface + " {"); // Write methods - writeMethodJavaInterface(methods, intDecl); + writeMethodJavaLocalInterface(methods, intDecl); println("}"); pw.close(); System.out.println("IoTCompiler: Generated local interface " + intface + ".java..."); @@ -219,6 +350,17 @@ public class IoTCompiler { } + /** + * HELPER: updateIntfaceObjIdMap() updates the mapping between new interface and object Id + */ + private void updateIntfaceObjIdMap(String intface, String newIntface) { + + Integer objId = mapIntfaceObjId.get(intface); + mapNewIntfaceObjId.put(newIntface, objId); + mapIntfaceObjId.put(intface, objId++); + } + + /** * generateJavaInterfaces() generate stub interfaces based on the methods list in Java */ @@ -238,13 +380,17 @@ public class IoTCompiler { DeclarationHandler decHandler = mapIntDeclHand.get(intface); InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); // Pass in set of methods and get import classes - Set importClasses = getImportClasses(intMeth.getValue(), intDecl); - printImportStatements(importClasses); + Set methods = intMeth.getValue(); + Set importClasses = getImportClasses(methods, intDecl); + List stdImportClasses = getStandardJavaIntfaceImportClasses(); + List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); + printImportStatements(allImportClasses); // Write interface header println(""); - println("public interface " + newIntface + " {"); + println("public interface " + newIntface + " {\n"); + updateIntfaceObjIdMap(intface, newIntface); // Write methods - writeMethodJavaInterface(intMeth.getValue(), intDecl); + writeMethodJavaInterface(methods, intDecl); println("}"); pw.close(); System.out.println("IoTCompiler: Generated interface " + newIntface + ".java..."); @@ -254,278 +400,4150 @@ public class IoTCompiler { /** - * HELPER: writeMethodJavaStub() writes the method of the stub class + * HELPER: writePropertiesJavaPermission() writes the permission in properties */ - private void writeMethodJavaStub(Collection methods, InterfaceDecl intDecl) { - - for (String method : methods) { - - List methParams = intDecl.getMethodParams(method); - List methPrmTypes = intDecl.getMethodParamTypes(method); - print("public " + intDecl.getMethodType(method) + " " + - intDecl.getMethodId(method) + "("); - for (int i = 0; i < methParams.size(); i++) { - - print(methPrmTypes.get(i) + " " + methParams.get(i)); + private void writePropertiesJavaPermission(String intface, InterfaceDecl intDecl) { + + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + String newIntface = intMeth.getKey(); + int newObjectId = getNewIntfaceObjectId(newIntface); + println("private final static int object" + newObjectId + "Id = " + + newObjectId + ";\t//" + newIntface); + Set methodIds = intMeth.getValue(); + print("private static Integer[] object" + newObjectId + "Permission = { "); + int i = 0; + 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 != methParams.size() - 1) { + if (i != methodIds.size() - 1) { print(", "); } + i++; } - println(") {"); - // Check if this is not "void" - if (!intDecl.getMethodType(method).equals("void")) { - String retStmt = generateReturnStmt(intDecl.getMethodType(method)); - println("return " + retStmt + ";"); - } - println("}"); println(""); + println(" };"); + println("private static List set" + newObjectId + "Allowed;"); } } /** - * generateJavaStubClasses() generate stubs based on the methods list in Java + * HELPER: writePropertiesJavaStub() writes the properties of the stub class */ - public void generateJavaStubClasses() throws IOException { + private void writePropertiesJavaStub(String intface, String newIntface, boolean callbackExist, Set callbackClasses) { + + println("private IoTRMICall rmiCall;"); + println("private String callbackAddress;"); + println("private int[] ports;\n"); + // Get the object Id + Integer objId = mapIntfaceObjId.get(intface); + println("private final static int objectId = " + objId + ";"); + //mapNewIntfaceObjId.put(newIntface, objId); + //mapIntfaceObjId.put(intface, objId++); + if (callbackExist) { + // We assume that each class only has one callback interface for now + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + println("// Callback properties"); + println("private IoTRMIObject rmiObj;"); + println("List<" + callbackType + "> listCallbackObj;"); + println("private int objIdCnt = 0;"); + // Generate permission stuff for callback stubs + DeclarationHandler decHandler = mapIntDeclHand.get(callbackType); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType); + writePropertiesJavaPermission(callbackType, intDecl); + } + println("\n"); + } - // Create a new directory - String path = createDirectories(dir, subdir); - for (String intface : mapIntfacePTH.keySet()) { + /** + * HELPER: writeConstructorJavaPermission() writes the permission in constructor + */ + private void writeConstructorJavaPermission(String intface) { + + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + String newIntface = intMeth.getKey(); + int newObjectId = getNewIntfaceObjectId(newIntface); + println("set" + newObjectId + "Allowed = new ArrayList(Arrays.asList(object" + newObjectId +"Permission));"); + } + } + + + /** + * HELPER: writeConstructorJavaStub() writes the constructor of the stub class + */ + private void writeConstructorJavaStub(String intface, String newStubClass, boolean callbackExist, Set callbackClasses) { + + println("public " + newStubClass + "(int _port, String _skeletonAddress, String _callbackAddress, int _rev, int[] _ports) throws Exception {"); + println("callbackAddress = _callbackAddress;"); + println("ports = _ports;"); + println("rmiCall = new IoTRMICall(_port, _skeletonAddress, _rev);"); + if (callbackExist) { + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + writeConstructorJavaPermission(callbackType); + println("listCallbackObj = new ArrayList<" + callbackType + ">();"); + DeclarationHandler decHandler = mapIntDeclHand.get(callbackType); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType); + writeJavaInitCallbackPermission(callbackType, intDecl, callbackExist); + println("___initCallBack();"); + } + println("}\n"); + } + + + /** + * HELPER: writeJavaMethodCallbackPermission() writes permission checks in stub for callbacks + */ + private void writeJavaMethodCallbackPermission(String intface) { + + println("int methodId = IoTRMIObject.getMethodId(method);"); + // Get all the different stubs + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + String newIntface = intMeth.getKey(); + int newObjectId = getNewIntfaceObjectId(newIntface); + println("if (!set" + newObjectId + "Allowed.contains(methodId)) {"); + println("throw new Error(\"Callback object for " + intface + " is not allowed to access method: \" + methodId);"); + println("}"); + } + } + + + /** + * HELPER: writeJavaInitCallbackPermission() writes the permission for callback + */ + private void writeJavaInitCallbackPermission(String intface, InterfaceDecl intDecl, boolean callbackExist) { + + if (callbackExist) { + String method = "___initCallBack()"; + int methodNumId = intDecl.getHelperMethodNumId(method); Map> mapNewIntMethods = mapInt2NewInts.get(intface); for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { - - // Open a new file to write into String newIntface = intMeth.getKey(); - String newStubClass = newIntface + "_Stub"; - FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java"); - pw = new PrintWriter(new BufferedWriter(fw)); - DeclarationHandler decHandler = mapIntDeclHand.get(intface); - InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); - // Pass in set of methods and get import classes - Set importClasses = getImportClasses(intMeth.getValue(), intDecl); - printImportStatements(importClasses); - // Write interface header - println(""); - println("public class " + newStubClass + " implements " + newIntface + " {"); - println(""); - // Write methods - writeMethodJavaStub(intMeth.getValue(), intDecl); - println("}"); - pw.close(); - System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java..."); + int newObjectId = getNewIntfaceObjectId(newIntface); + println("set" + newObjectId + "Allowed.add(" + methodNumId + ");"); } } } /** - * HELPER: writeMethodCplusInterface() writes the method of the interface + * HELPER: getPortCount() gets port count for different stubs and skeletons */ - private void writeMethodCplusInterface(Collection methods, InterfaceDecl intDecl) { + private int getPortCount(String intface) { - for (String method : methods) { + if (!mapPortCount.containsKey(intface)) + mapPortCount.put(intface, portCount++); + return mapPortCount.get(intface); + } - List methParams = intDecl.getMethodParams(method); - List methPrmTypes = intDecl.getMethodParamTypes(method); - print("virtual " + convertType(intDecl.getMethodType(method)) + " " + - intDecl.getMethodId(method) + "("); - for (int i = 0; i < methParams.size(); i++) { - // Check for params with driver class types and exchange it - // with its remote interface - String paramType = checkAndGetParamClass(methPrmTypes.get(i), true); - paramType = checkAndGetCplusType(paramType); - // Check for arrays - translate into vector in C++ - String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i)); - print(paramComplete); - // Check if this is the last element (don't print a comma) - if (i != methParams.size() - 1) { - print(", "); + + /** + * HELPER: writeInitCallbackJavaStub() writes callback initialization in stub + */ + private void writeInitCallbackJavaStub(String intface, InterfaceDecl intDecl, String newStubClass) { + + println("public void ___initCallBack() {"); + // Generate main thread for callbacks + println("Thread thread = new Thread() {"); + println("public void run() {"); + println("try {"); + int port = getPortCount(newStubClass); + println("rmiObj = new IoTRMIObject(ports[" + port + "]);"); + println("while (true) {"); + println("byte[] method = rmiObj.getMethodBytes();"); + println("int objId = IoTRMIObject.getObjectId(method);"); + println(intface + "_CallbackSkeleton skel = (" + intface + "_CallbackSkeleton) listCallbackObj.get(objId);"); + println("if (skel != null) {"); + writeJavaMethodCallbackPermission(intface); + println("skel.invokeMethod(rmiObj);"); + print("}"); + println(" else {"); + println("throw new Error(\"" + intface + ": Object with Id \" + objId + \" not found!\");"); + println("}"); + println("}"); + print("}"); + println(" catch (Exception ex) {"); + println("ex.printStackTrace();"); + println("throw new Error(\"Error instantiating class " + intface + "_CallbackSkeleton!\");"); + println("}"); + println("}"); + println("};"); + println("thread.start();\n"); + // Generate info sending part + String method = "___initCallBack()"; + int methodNumId = intDecl.getHelperMethodNumId(method); + println("int methodId = " + methodNumId + ";"); + println("Class retType = void.class;"); + println("Class[] paramCls = new Class[] { int[].class, String.class, int.class };"); + println("Object[] paramObj = new Object[] { ports, callbackAddress, 0 };"); + println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); + println("}\n"); + } + + + /** + * HELPER: checkAndWriteEnumTypeJavaStub() writes the enum type (convert from enum to int) + */ + private void checkAndWriteEnumTypeJavaStub(List methParams, List methPrmTypes) { + + // Iterate and find enum declarations + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isEnumClass(simpleType)) { + // Check if this is enum type + if (isArray(param)) { // An array + println("int len" + i + " = " + getSimpleIdentifier(param) + ".length;"); + println("int paramEnum" + i + "[] = new int[len" + i + "];"); + println("for (int i = 0; i < len" + i + "; i++) {"); + println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + "[i].ordinal();"); + println("}"); + } else if (isList(paramType)) { // A list + println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();"); + println("int paramEnum" + i + "[] = new int[len" + i + "];"); + println("for (int i = 0; i < len" + i + "; i++) {"); + println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + ".get(i).ordinal();"); + println("}"); + } else { // Just one element + println("int paramEnum" + i + "[] = new int[1];"); + println("paramEnum" + i + "[0] = " + param + ".ordinal();"); } } - println(") = 0;"); } } /** - * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking. - *

- * 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. + * HELPER: checkAndWriteEnumRetTypeJavaStub() writes the enum return type (convert from enum to int) */ - public void generateCplusLocalInterfaces() throws IOException { + private void checkAndWriteEnumRetTypeJavaStub(String retType) { + + // 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 + // Enum decoder + println("int[] retEnum = (int[]) retObj;"); + println(pureType + "[] enumVals = " + pureType + ".values();"); + if (isArray(retType)) { // An array + println("int retLen = retEnum.length;"); + println(pureType + "[] enumRetVal = new " + pureType + "[retLen];"); + println("for (int i = 0; i < retLen; i++) {"); + println("enumRetVal[i] = enumVals[retEnum[i]];"); + println("}"); + } else if (isList(retType)) { // A list + println("int retLen = retEnum.length;"); + println("List<" + pureType + "> enumRetVal = new ArrayList<" + pureType + ">();"); + println("for (int i = 0; i < retLen; i++) {"); + println("enumRetVal.add(enumVals[retEnum[i]]);"); + println("}"); + } else { // Just one element + println(pureType + " enumRetVal = enumVals[retEnum[0]];"); + } + println("return enumRetVal;"); + } + } - // 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("#include "); - // Pass in set of methods and get include classes - DeclarationHandler decHandler = mapIntDeclHand.get(intface); - InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); - List methods = intDecl.getMethods(); - Set includeClasses = getIncludeClasses(methods, intDecl); - printIncludeStatements(includeClasses); - println(""); - println("using namespace std;"); - println(""); - println("class " + intface); - println("{"); - println("public:"); - // Write methods - writeMethodCplusInterface(methods, intDecl); - print("}"); - println(";"); - pw.close(); - System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp..."); + + /** + * HELPER: checkAndWriteStructSetupJavaStub() writes the struct type setup + */ + private void checkAndWriteStructSetupJavaStub(List methParams, List 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 + 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 };"); + } else if (isList(paramType)) { // A list + println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".size() };"); + } else { // Just one element + println("Object[] paramObjStruct" + i + " = new Object[] { new Integer(1) };"); + } + println("rmiCall.remoteCall(objectId, methodIdStruct" + i + + ", retTypeStruct" + i + ", null, paramClsStruct" + i + + ", paramObjStruct" + i + ");\n"); + } } } /** - * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++ - *

- * For C++ we use virtual classe as interface + * HELPER: isStructPresent() checks presence of struct */ - public void generateCPlusInterfaces() throws IOException { + private boolean isStructPresent(List methParams, List methPrmTypes) { + + // Iterate and find enum 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)) + return true; + } + return false; + } - // 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()) { + /** + * HELPER: writeLengthStructParamClassJavaStub() writes lengths of parameters + */ + private void writeLengthStructParamClassJavaStub(List methParams, List 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 (isArray(param)) { // An array + String structLen = getSimpleArrayType(param) + ".length"; + print(members + "*" + structLen); + } else if (isList(paramType)) { // A list + String structLen = getSimpleArrayType(param) + ".size()"; + print(members + "*" + structLen); + } else + print(Integer.toString(members)); + } else + print("1"); + if (i != methParams.size() - 1) { + print("+"); + } + } + } - // 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("#include "); - // Pass in set of methods and get import classes - Set includeClasses = getIncludeClasses(intMeth.getValue(), intDecl); - printIncludeStatements(includeClasses); - println(""); - println("using namespace std;"); - println(""); - println("class " + newIntface); - println("{"); - println("public:"); - // Write methods - writeMethodCplusInterface(intMeth.getValue(), intDecl); - print("}"); + + /** + * HELPER: writeStructMembersJavaStub() writes parameters of struct + */ + private void writeStructMembersJavaStub(String simpleType, String paramType, String param) { + + // Get the struct declaration for this struct and generate initialization code + StructDecl structDecl = getStructDecl(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + List members = structDecl.getMembers(simpleType); + if (isArray(param)) { // An array + println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".length; i++) {"); + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + print("paramObj[pos++] = " + getSimpleIdentifier(param) + "[i]."); + print(getSimpleIdentifier(members.get(i))); println(";"); - pw.close(); - System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp..."); } + println("}"); + } else if (isList(paramType)) { // A list + println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {"); + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".get(i)."); + print(getSimpleIdentifier(members.get(i))); + println(";"); + } + println("}"); + } else { // Just one struct element + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + print("paramObj[pos++] = " + getSimpleIdentifier(param) + "."); + print(getSimpleIdentifier(members.get(i))); + println(";"); + } + } + } + + + /** + * HELPER: writeStructParamClassJavaStub() writes parameters if struct is present + */ + private void writeStructParamClassJavaStub(List methParams, List methPrmTypes, String callbackType) { + + print("int paramLen = "); + writeLengthStructParamClassJavaStub(methParams, methPrmTypes); + println(";"); + println("Object[] paramObj = new Object[paramLen];"); + println("Class[] paramCls = new Class[paramLen];"); + 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)) { + writeStructMembersJavaStub(simpleType, paramType, param); + } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object + println("paramCls[pos] = int.class;"); + print("paramObj[pos++] = "); + if (isArray(methParams.get(i))) + print(getSimpleIdentifier(methParams.get(i)) + ".length"); + else if (isList(methPrmTypes.get(i))) + print(getSimpleIdentifier(methParams.get(i)) + ".size()"); + else + print("new Integer(1)"); + println(";"); + } else { + String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); + println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + print("paramObj[pos++] = "); + print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i)); + println(";"); + } + } + + } + + + /** + * HELPER: writeStructRetMembersJavaStub() writes parameters of struct for return statement + */ + private void writeStructRetMembersJavaStub(String simpleType, String retType) { + + // Get the struct declaration for this struct and generate initialization code + StructDecl structDecl = getStructDecl(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + List members = structDecl.getMembers(simpleType); + if (isArrayOrList(retType, retType)) { // An array or list + println("for(int i = 0; i < retLen; i++) {"); + } + if (isArray(retType)) { // An array + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + print("structRet[i]." + getSimpleIdentifier(members.get(i))); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];"); + } + println("}"); + } else if (isList(retType)) { // A list + println(simpleType + " structRetMem = new " + simpleType + "();"); + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + print("structRetMem." + getSimpleIdentifier(members.get(i))); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];"); + } + println("structRet.add(structRetMem);"); + 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(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];"); + } + } + println("return structRet;"); + } + + + /** + * HELPER: writeStructReturnJavaStub() writes parameters if struct is present for return statement + */ + private void writeStructReturnJavaStub(String simpleType, String retType) { + + // Handle the returned struct!!! + println("Object retLenObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); + // Minimum retLen is 1 if this is a single struct object + println("int retLen = (int) retLenObj;"); + int numMem = getNumOfMembers(simpleType); + println("Class[] retCls = new Class[" + numMem + "*retLen];"); + println("Class[] retClsVal = new Class[" + numMem + "*retLen];"); + println("int retPos = 0;"); + // Get the struct declaration for this struct and generate initialization code + StructDecl structDecl = getStructDecl(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + List members = structDecl.getMembers(simpleType); + 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 prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + println("retClsVal[retPos++] = null;"); + } + println("}"); + } else { // Just one struct element + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + println("retClsVal[retPos++] = null;"); + } + } + println("Object[] retObj = rmiCall.getStructObjects(retCls, retClsVal);"); + if (isArray(retType)) { // An array + println(simpleType + "[] structRet = new " + simpleType + "[retLen];"); + println("for(int i = 0; i < retLen; i++) {"); + println("structRet[i] = new " + simpleType + "();"); + println("}"); + } else if (isList(retType)) { // A list + println("List<" + simpleType + "> structRet = new ArrayList<" + simpleType + ">();"); + } else + println(simpleType + " structRet = new " + simpleType + "();"); + println("int retObjPos = 0;"); + writeStructRetMembersJavaStub(simpleType, retType); + } + + + /** + * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class + */ + private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method, String callbackType) { + + checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method); + println("int methodId = " + intDecl.getMethodNumId(method) + ";"); + String retType = intDecl.getMethodType(method); + println("Class retType = " + getSimpleType(getStructType(getEnumType(retType))) + ".class;"); + checkAndWriteEnumTypeJavaStub(methParams, methPrmTypes); + // Generate array of parameter types + if (isStructPresent(methParams, methPrmTypes)) { + writeStructParamClassJavaStub(methParams, methPrmTypes, callbackType); + } else { + print("Class[] paramCls = new Class[] { "); + for (int i = 0; i < methParams.size(); i++) { + String prmType = methPrmTypes.get(i); + if (checkCallbackType(prmType, callbackType)) { // Check if this has callback object + print("int.class"); + } else { // Generate normal classes if it's not a callback object + String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); + print(getSimpleType(getEnumType(paramType)) + ".class"); + } + // 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("Object[] paramObj = new Object[] { "); + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object + //if (isArray(methPrmTypes.get(i), methParams.get(i))) + if (isArray(methParams.get(i))) + print(getSimpleIdentifier(methParams.get(i)) + ".length"); + else if (isList(methPrmTypes.get(i))) + print(getSimpleIdentifier(methParams.get(i)) + ".size()"); + else + print("new Integer(1)"); + } 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("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); + } else { // We do have a return value + // Generate array of parameter types + if (isStructClass(getGenericType(getSimpleArrayType(retType)))) { + writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType); + } else { + // This is an enum type + if (getParamCategory(getGenericType(getSimpleArrayType(retType))) == ParamCategory.ENUM) { + println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); + checkAndWriteEnumRetTypeJavaStub(retType); + } else if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) { + // Check if the return value NONPRIMITIVES + String retGenValType = getGenericType(retType); + println("Class retGenValType = " + retGenValType + ".class;"); + println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, retGenValType, paramCls, paramObj);"); + println("return (" + retType + ")retObj;"); + } else { + println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); + println("return (" + retType + ")retObj;"); + } + } + } + } + + + /** + * HELPER: returnGenericCallbackType() returns the callback type + */ + private String returnGenericCallbackType(String paramType) { + + if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) + return getGenericType(paramType); + else + return paramType; + } + + + /** + * HELPER: checkCallbackType() checks the callback type + */ + private boolean checkCallbackType(String paramType, String callbackType) { + + String prmType = returnGenericCallbackType(paramType); + if (callbackType == null) // If there is no callbackType it means not a callback method + return false; + else + return callbackType.equals(prmType); + } + + + /** + * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class + */ + private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method, String callbackType) { + + println("try {"); + // Check if this is single object, array, or list of objects + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object + String param = methParams.get(i); + if (isArrayOrList(paramType, param)) { // Generate loop + println("for (" + getGenericType(paramType) + " cb : " + getSimpleIdentifier(param) + ") {"); + println(callbackType + "_CallbackSkeleton skel" + i + " = new " + callbackType + "_CallbackSkeleton(cb, callbackAddress, objIdCnt++);"); + } else + println(callbackType + "_CallbackSkeleton skel" + i + " = new " + callbackType + "_CallbackSkeleton(" + + getSimpleIdentifier(param) + ", callbackAddress, objIdCnt++);"); + println("listCallbackObj.add(skel" + i + ");"); + if (isArrayOrList(paramType, param)) + println("}"); + } + } + print("}"); + println(" catch (Exception ex) {"); + println("ex.printStackTrace();"); + println("throw new Error(\"Exception when generating skeleton objects!\");"); + println("}\n"); + } + + + /** + * HELPER: writeMethodJavaStub() writes the methods of the stub class + */ + private void writeMethodJavaStub(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("public " + 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 + } + print(methPrmTypes.get(i) + " " + methParams.get(i)); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } + } + println(") {"); + // Now, write the body of stub! + if (isCallbackMethod) + writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType); + //else + writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType); + println("}\n"); + // Write the init callback helper method + if (isCallbackMethod && !isDefined) { + writeInitCallbackJavaStub(callbackType, intDecl, newStubClass); + isDefined = true; + } + } + } + + + /** + * HELPER: getStubInterface() gets stub interface name based on original interface + */ + public String getStubInterface(String intface) { + + return mapInt2NewIntName.get(intface); + } + + + /** + * generateJavaStubClasses() generate stubs based on the methods list in Java + */ + public void generateJavaStubClasses() 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 + ".java"); + pw = new PrintWriter(new BufferedWriter(fw)); + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + // Pass in set of methods and get import classes + Set methods = intMeth.getValue(); + Set importClasses = getImportClasses(methods, intDecl); + List stdImportClasses = getStandardJavaImportClasses(); + List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); + printImportStatements(allImportClasses); println(""); + // Find out if there are callback objects + Set callbackClasses = getCallbackClasses(methods, intDecl); + boolean callbackExist = !callbackClasses.isEmpty(); + // Write class header + println("public class " + newStubClass + " implements " + newIntface + " {\n"); + // Write properties + writePropertiesJavaStub(intface, newIntface, callbackExist, callbackClasses); + // Write constructor + writeConstructorJavaStub(intface, newStubClass, callbackExist, callbackClasses); + // Write methods + writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass); + println("}"); + pw.close(); + System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java..."); + } + } + } + + + /** + * HELPER: writePropertiesJavaCallbackStub() writes the properties of the callback stub class + */ + private void writePropertiesJavaCallbackStub(String intface, String newIntface, boolean callbackExist, Set callbackClasses) { + + println("private IoTRMICall rmiCall;"); + println("private String callbackAddress;"); + println("private int[] ports;\n"); + // Get the object Id + println("private int objectId = 0;"); + if (callbackExist) { + // We assume that each class only has one callback interface for now + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + println("// Callback properties"); + println("private IoTRMIObject rmiObj;"); + println("List<" + callbackType + "> listCallbackObj;"); + println("private int objIdCnt = 0;"); + // Generate permission stuff for callback stubs + DeclarationHandler decHandler = mapIntDeclHand.get(callbackType); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType); + writePropertiesJavaPermission(callbackType, intDecl); + } + println("\n"); + } + + + /** + * HELPER: writeConstructorJavaCallbackStub() writes the constructor of the callback stub class + */ + private void writeConstructorJavaCallbackStub(String intface, String newStubClass, boolean callbackExist, Set callbackClasses) { + + // TODO: If we want callback in callback, then we need to add address and port initializations + println("public " + newStubClass + "(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {"); + println("callbackAddress = _callbackAddress;"); + println("objectId = _objectId;"); + println("rmiCall = _rmiCall;"); + println("ports = _ports;"); + if (callbackExist) { + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + writeConstructorJavaPermission(callbackType); + println("listCallbackObj = new ArrayList<" + callbackType + ">();"); + DeclarationHandler decHandler = mapIntDeclHand.get(callbackType); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType); + writeJavaInitCallbackPermission(callbackType, intDecl, callbackExist); + println("___initCallBack();"); + } + println("}\n"); + } + + + /** + * generateJavaCallbackStubClasses() generate callback stubs based on the methods list in Java + *

+ * Callback stubs gets the IoTRMICall objects from outside of the class as contructor input + * because all these stubs are populated by the class that takes in this object as a callback + * object. In such a class, we only use one socket, hence one IoTRMICall, for all callback objects. + */ + public void generateJavaCallbackStubClasses() throws IOException { + + // Create a new directory + String path = createDirectories(dir, subdir); + for (String intface : mapIntfacePTH.keySet()) { + + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + + // Open a new file to write into + String newIntface = intMeth.getKey(); + String newStubClass = newIntface + "_CallbackStub"; + FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java"); + pw = new PrintWriter(new BufferedWriter(fw)); + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + // Pass in set of methods and get import classes + Set methods = intMeth.getValue(); + Set importClasses = getImportClasses(methods, intDecl); + List stdImportClasses = getStandardJavaImportClasses(); + List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); + printImportStatements(allImportClasses); println(""); + // Find out if there are callback objects + Set callbackClasses = getCallbackClasses(methods, intDecl); + boolean callbackExist = !callbackClasses.isEmpty(); + // Write class header + println("public class " + newStubClass + " implements " + newIntface + " {\n"); + // Write properties + writePropertiesJavaCallbackStub(intface, newIntface, callbackExist, callbackClasses); + // Write constructor + writeConstructorJavaCallbackStub(intface, newStubClass, callbackExist, callbackClasses); + // Write methods + // TODO: perhaps need to generate callback for callback + writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass); + println("}"); + pw.close(); + System.out.println("IoTCompiler: Generated callback stub class " + newStubClass + ".java..."); + } + } + } + + + /** + * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class + */ + private void writePropertiesJavaSkeleton(String intface, boolean callbackExist, InterfaceDecl intDecl) { + + println("private " + intface + " mainObj;"); + //println("private int ports;"); + println("private IoTRMIObject rmiObj;\n"); + println("private String callbackAddress;"); + // Callback + if (callbackExist) { + println("private int objIdCnt = 0;"); + println("private IoTRMICall rmiCall;"); + println("private int[] ports;\n"); + } + writePropertiesJavaPermission(intface, intDecl); + println("\n"); + } + + + /** + * HELPER: writeStructPermissionJavaSkeleton() writes permission for struct helper + */ + private void writeStructPermissionJavaSkeleton(Collection methods, InterfaceDecl intDecl, String intface) { + + // 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); + String helperMethod = methodNumId + "struct" + i; + int methodHelperNumId = intDecl.getHelperMethodNumId(helperMethod); + // Iterate over interfaces to give permissions to + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + String newIntface = intMeth.getKey(); + int newObjectId = getNewIntfaceObjectId(newIntface); + println("set" + newObjectId + "Allowed.add(" + methodHelperNumId + ");"); + } + } + } + } + } + + + /** + * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class + */ + private void writeConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, Collection methods, boolean callbackExist) { + + println("public " + newSkelClass + "(" + intface + " _mainObj, String _callbackAddress, int _port) throws Exception {"); + println("mainObj = _mainObj;"); + println("callbackAddress = _callbackAddress;"); + println("rmiObj = new IoTRMIObject(_port);"); + // Generate permission control initialization + writeConstructorJavaPermission(intface); + writeJavaInitCallbackPermission(intface, intDecl, callbackExist); + writeStructPermissionJavaSkeleton(methods, intDecl, intface); + println("___waitRequestInvokeMethod();"); + println("}\n"); + } + + + /** + * HELPER: writeStdMethodBodyJavaSkeleton() writes the standard method body in the skeleton class + */ + private void writeStdMethodBodyJavaSkeleton(List methParams, String methodId, String methodType) { + + if (methodType.equals("void")) + print("mainObj." + methodId + "("); + else + print("return mainObj." + methodId + "("); + for (int i = 0; i < methParams.size(); i++) { + + print(getSimpleIdentifier(methParams.get(i))); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } + } + println(");"); + } + + + /** + * HELPER: writeInitCallbackJavaSkeleton() writes the init callback method for skeleton class + */ + private void writeInitCallbackJavaSkeleton(boolean callbackSkeleton, String intface) { + + // This is a callback skeleton generation + if (callbackSkeleton) + println("public void ___regCB(IoTRMIObject rmiObj) throws IOException {"); + else + println("public void ___regCB() throws IOException {"); + print("Object[] paramObj = rmiObj.getMethodParams(new Class[] { int[].class, String.class, int.class },"); + println("new Class[] { null, null, null });"); + println("ports = (int[]) paramObj[0];"); + String stubInt = null; + if (callbackSkeleton) + stubInt = getStubInterface(intface) + "_CallbackStub"; + else + stubInt = getStubInterface(intface) + "_Stub"; + int port = getPortCount(stubInt); + println("rmiCall = new IoTRMICall(ports[" + port + "], (String) paramObj[1], (int) paramObj[2]);"); + println("}\n"); + } + + + /** + * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class + */ + private void writeMethodJavaSkeleton(Collection methods, InterfaceDecl intDecl, Set callbackClasses, + boolean callbackSkeleton, String intface) { + + boolean isDefined = false; + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + String methodId = intDecl.getMethodId(method); + print("public " + intDecl.getMethodType(method) + " " + methodId + "("); + boolean isCallbackMethod = false; + String callbackType = null; + for (int i = 0; i < methParams.size(); i++) { + + String origParamType = methPrmTypes.get(i); + String paramType = checkAndGetParamClass(origParamType); + if (callbackClasses.contains(origParamType)) { // Check if this has callback object + isCallbackMethod = true; + callbackType = origParamType; + } + print(paramType + " " + methParams.get(i)); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } + } + println(") {"); + // Now, write the body of skeleton! + writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method)); + println("}\n"); + if (isCallbackMethod && !isDefined) { // Make sure that this function is only defined once! + writeInitCallbackJavaSkeleton(callbackSkeleton, intface); + isDefined = true; + } + } + } + + + /** + * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part + */ + private Map writeCallbackJavaStubGeneration(List methParams, List methPrmTypes, + String callbackType, boolean isStructMethod) { + + Map mapStubParam = new HashMap(); + String offsetPfx = ""; + if (isStructMethod) + offsetPfx = "offset"; + // Iterate over callback objects + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object + String exchParamType = checkAndGetParamClass(getGenericType(paramType)); + // Print array if this is array or list if this is a list of callback objects + if (isArray(param)) { + println("int numStubs" + i + " = (int) paramObj[" + offsetPfx + i + "];"); + println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];"); + } else if (isList(paramType)) { + println("int numStubs" + i + " = (int) paramObj[" + offsetPfx + i + "];"); + println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();"); + } else { + println(exchParamType + " stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);"); + println("objIdCnt++;"); + } + } + // Generate a loop if needed + if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object + String exchParamType = checkAndGetParamClass(getGenericType(paramType)); + if (isArray(param)) { + println("for (int objId = 0; objId < numStubs" + i + "; objId++) {"); + println("stub" + i + "[objId] = new " + exchParamType + "_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);"); + println("objIdCnt++;"); + println("}"); + } else if (isList(paramType)) { + println("for (int objId = 0; objId < numStubs" + i + "; objId++) {"); + println("stub" + i + ".add(new " + exchParamType + "_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports));"); + println("objIdCnt++;"); + println("}"); + } + mapStubParam.put(i, "stub" + i); // List of all stub parameters + } + } + return mapStubParam; + } + + + /** + * HELPER: checkAndWriteEnumTypeJavaSkeleton() writes the enum type (convert from enum to int) + */ + private void checkAndWriteEnumTypeJavaSkeleton(List methParams, List methPrmTypes, boolean isStructMethod) { + + String offsetPfx = ""; + if (isStructMethod) + offsetPfx = "offset"; + // Iterate and find enum declarations + boolean printed = false; + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isEnumClass(simpleType)) { + // Check if this is enum type + println("int paramInt" + i + "[] = (int[]) paramObj[" + offsetPfx + i + "];"); + if (!printed) { + println(simpleType + "[] enumVals = " + simpleType + ".values();"); + printed = true; + } + if (isArray(param)) { // An array + println("int len" + i + " = paramInt" + i + ".length;"); + println(simpleType + "[] paramEnum" + i + " = new " + simpleType + "[len" + i + "];"); + println("for (int i = 0; i < len" + i + "; i++) {"); + println("paramEnum" + i + "[i] = enumVals[paramInt" + i + "[i]];"); + println("}"); + } else if (isList(paramType)) { // A list + println("int len" + i + " = paramInt" + i + ".length;"); + println("List<" + simpleType + "> paramEnum" + i + " = new ArrayList<" + simpleType + ">();"); + println("for (int i = 0; i < len" + i + "; i++) {"); + println("paramEnum" + i + ".add(enumVals[paramInt" + i + "[i]]);"); + println("}"); + } else { // Just one element + println(simpleType + " paramEnum" + i + " = enumVals[paramInt" + i + "[0]];"); + } + } + } + } + + + /** + * HELPER: checkAndWriteEnumRetTypeJavaSkeleton() writes the enum return type (convert from enum to int) + */ + private void checkAndWriteEnumRetTypeJavaSkeleton(String retType, String methodId) { + + // 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 + // Enum decoder + if (isArray(retType)) { // An array + print(pureType + "[] retEnum = " + methodId + "("); + } else if (isList(retType)) { // A list + print("List<" + pureType + "> retEnum = " + methodId + "("); + } else { // Just one element + print(pureType + " retEnum = " + methodId + "("); + } + } + } + + + /** + * HELPER: checkAndWriteEnumRetConvJavaSkeleton() writes the enum return type (convert from enum to int) + */ + private void checkAndWriteEnumRetConvJavaSkeleton(String retType) { + + // 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 + if (isArray(retType)) { // An array + println("int retLen = retEnum.length;"); + println("int[] retEnumVal = new int[retLen];"); + println("for (int i = 0; i < retLen; i++) {"); + println("retEnumVal[i] = retEnum[i].ordinal();"); + println("}"); + } else if (isList(retType)) { // A list + println("int retLen = retEnum.size();"); + println("int[] retEnumVal = new int[retLen];"); + println("for (int i = 0; i < retLen; i++) {"); + println("retEnumVal[i] = retEnum.get(i).ordinal();"); + println("}"); + } else { // Just one element + println("int[] retEnumVal = new int[1];"); + println("retEnumVal[0] = retEnum.ordinal();"); + } + println("Object retObj = retEnumVal;"); + } + } + + + /** + * HELPER: writeLengthStructParamClassSkeleton() writes lengths of params + */ + private void writeLengthStructParamClassSkeleton(List methParams, List methPrmTypes, + String method, InterfaceDecl intDecl) { + + // 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); + print(Integer.toString(members) + "*"); + int methodNumId = intDecl.getMethodNumId(method); + print("struct" + methodNumId + "Size" + i); + } else + print("1"); + if (i != methParams.size() - 1) { + print("+"); + } + } + } + + + /** + * HELPER: writeStructMembersJavaSkeleton() writes member parameters of struct + */ + private void writeStructMembersJavaSkeleton(String simpleType, String paramType, + String param, String method, InterfaceDecl intDecl, int iVar) { + + // Get the struct declaration for this struct and generate initialization code + StructDecl structDecl = getStructDecl(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + List members = structDecl.getMembers(simpleType); + if (isArrayOrList(paramType, param)) { // An array or list + int methodNumId = intDecl.getMethodNumId(method); + String counter = "struct" + methodNumId + "Size" + iVar; + println("for(int i = 0; i < " + counter + "; i++) {"); + } + if (isArrayOrList(paramType, param)) { // An array or list + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + println("paramClsGen[pos++] = null;"); + } + println("}"); + } else { // Just one struct element + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + println("paramClsGen[pos++] = null;"); + } + } + } + + + /** + * HELPER: writeStructMembersInitJavaSkeleton() writes member parameters initialization of struct + */ + private void writeStructMembersInitJavaSkeleton(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method) { + + println("int objPos = 0;"); + 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 counter = "struct" + methodNumId + "Size" + i; + // Declaration + if (isArray(param)) { // An array + println(simpleType + "[] paramStruct" + i + " = new " + simpleType + "[" + counter + "];"); + println("for(int i = 0; i < " + counter + "; i++) {"); + println("paramStruct" + i + "[i] = new " + simpleType + "();"); + println("}"); + } else if (isList(paramType)) { // A list + println("List<" + simpleType + "> paramStruct" + i + " = new ArrayList<" + simpleType + ">();"); + } else + println(simpleType + " paramStruct" + i + " = new " + simpleType + "();"); + // Initialize members + StructDecl structDecl = getStructDecl(simpleType); + List members = structDecl.getMembers(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + if (isArrayOrList(paramType, param)) { // An array or list + println("for(int i = 0; i < " + counter + "; i++) {"); + } + if (isArray(param)) { // An array + for (int j = 0; j < members.size(); j++) { + String prmType = checkAndGetArray(memTypes.get(j), members.get(j)); + print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j))); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];"); + } + println("}"); + } else if (isList(paramType)) { // A list + println(simpleType + " paramStructMem = new " + simpleType + "();"); + for (int j = 0; j < members.size(); j++) { + String prmType = checkAndGetArray(memTypes.get(j), members.get(j)); + print("paramStructMem." + getSimpleIdentifier(members.get(j))); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];"); + } + println("paramStruct" + i + ".add(paramStructMem);"); + println("}"); + } else { // Just one struct element + for (int j = 0; j < members.size(); j++) { + String prmType = checkAndGetArray(memTypes.get(j), members.get(j)); + print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j))); + println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];"); + } + } + } else { + // Take offsets of parameters + println("int offset" + i +" = objPos++;"); + } + } + } + + + /** + * HELPER: writeStructReturnJavaSkeleton() writes struct for return statement + */ + private void writeStructReturnJavaSkeleton(String simpleType, String retType) { + + // Minimum retLen is 1 if this is a single struct object + if (isArray(retType)) + println("int retLen = retStruct.length;"); + else if (isList(retType)) + println("int retLen = retStruct.size();"); + else // Just single struct object + println("int retLen = 1;"); + println("Object retLenObj = retLen;"); + println("rmiObj.sendReturnObj(retLenObj);"); + int numMem = getNumOfMembers(simpleType); + println("Class[] retCls = new Class[" + numMem + "*retLen];"); + println("Object[] retObj = new Object[" + numMem + "*retLen];"); + println("int retPos = 0;"); + // Get the struct declaration for this struct and generate initialization code + StructDecl structDecl = getStructDecl(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + List members = structDecl.getMembers(simpleType); + if (isArray(retType)) { // An array or list + println("for(int i = 0; i < retLen; i++) {"); + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + print("retObj[retPos++] = retStruct[i]."); + print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i)); + println(";"); + } + println("}"); + } else if (isList(retType)) { // An array or list + println("for(int i = 0; i < retLen; i++) {"); + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + print("retObj[retPos++] = retStruct.get(i)."); + print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i)); + println(";"); + } + println("}"); + } else { // Just one struct element + for (int i = 0; i < members.size(); i++) { + String prmType = checkAndGetArray(memTypes.get(i), members.get(i)); + println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;"); + print("retObj[retPos++] = retStruct."); + print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i)); + println(";"); + } + } + + } + + + /** + * HELPER: writeMethodHelperReturnJavaSkeleton() writes return statement part in skeleton + */ + private void writeMethodHelperReturnJavaSkeleton(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method, boolean isCallbackMethod, String callbackType, + boolean isStructMethod) { + + checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes, isStructMethod); + Map mapStubParam = null; + if (isCallbackMethod) { + println("try {"); + mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType, isStructMethod); + } + // Check if this is "void" + String retType = intDecl.getMethodType(method); + if (retType.equals("void")) { + print(intDecl.getMethodId(method) + "("); + } else if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type + checkAndWriteEnumRetTypeJavaSkeleton(retType, intDecl.getMethodId(method)); + } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type + print(retType + " retStruct = " + intDecl.getMethodId(method) + "("); + } else { // We do have a return value + print("Object retObj = " + intDecl.getMethodId(method) + "("); + } + for (int i = 0; i < methParams.size(); i++) { + + String paramType = methPrmTypes.get(i); + if (isCallbackMethod && checkCallbackType(paramType, callbackType)) { + print(mapStubParam.get(i)); // Get the callback parameter + } else if (isEnumClass(getGenericType(paramType))) { // Enum class + print(getEnumParam(paramType, methParams.get(i), i)); + } else if (isStructClass(getGenericType(paramType))) { + print("paramStruct" + i); + } else { + String prmType = checkAndGetArray(paramType, methParams.get(i)); + if (isStructMethod) + print("(" + prmType + ") paramObj[offset" + i + "]"); + else + print("(" + prmType + ") paramObj[" + i + "]"); + } + if (i != methParams.size() - 1) + print(", "); + } + println(");"); + if (!retType.equals("void")) { + if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type + checkAndWriteEnumRetConvJavaSkeleton(retType); + println("rmiObj.sendReturnObj(retObj);"); + } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type + writeStructReturnJavaSkeleton(getSimpleArrayType(getGenericType(retType)), retType); + println("rmiObj.sendReturnObj(retCls, retObj);"); + } else + println("rmiObj.sendReturnObj(retObj);"); + } + if (isCallbackMethod) { // Catch exception if this is callback + print("}"); + println(" catch(Exception ex) {"); + println("ex.printStackTrace();"); + println("throw new Error(\"Exception from callback object instantiation!\");"); + println("}"); + } + } + + + /** + * HELPER: writeMethodHelperStructJavaSkeleton() writes the struct in skeleton + */ + private void writeMethodHelperStructJavaSkeleton(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method, Set callbackClasses) { + + // Generate array of parameter objects + boolean isCallbackMethod = false; + String callbackType = null; + print("int paramLen = "); + writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl); + println(";"); + println("Class[] paramCls = new Class[paramLen];"); + println("Class[] paramClsGen = new Class[paramLen];"); + 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)) { + writeStructMembersJavaSkeleton(simpleType, paramType, param, method, intDecl, i); + } else { + String prmType = returnGenericCallbackType(methPrmTypes.get(i)); + if (callbackClasses.contains(prmType)) { + isCallbackMethod = true; + callbackType = prmType; + println("paramCls[pos] = int.class;"); + println("paramClsGen[pos++] = null;"); + } else { // Generate normal classes if it's not a callback object + String paramTypeOth = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); + println("paramCls[pos] = " + getSimpleType(getEnumType(paramTypeOth)) + ".class;"); + print("paramClsGen[pos++] = "); + String prmTypeOth = methPrmTypes.get(i); + if (getParamCategory(prmTypeOth) == ParamCategory.NONPRIMITIVES) + println(getTypeOfGeneric(prmType)[0] + ".class;"); + else + println("null;"); + } + } + } + println("Object[] paramObj = rmiObj.getMethodParams(paramCls, paramClsGen);"); + writeStructMembersInitJavaSkeleton(intDecl, methParams, methPrmTypes, method); + // Write the return value part + writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, true); + } + + + /** + * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class + */ + private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method, Set callbackClasses) { + + // Generate array of parameter objects + boolean isCallbackMethod = false; + String callbackType = null; + print("Object[] paramObj = rmiObj.getMethodParams(new Class[] { "); + for (int i = 0; i < methParams.size(); i++) { + + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); + if (callbackClasses.contains(paramType)) { + isCallbackMethod = true; + callbackType = paramType; + print("int.class"); + } else { // Generate normal classes if it's not a callback object + String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); + print(getSimpleType(getEnumType(prmType)) + ".class"); + } + if (i != methParams.size() - 1) + print(", "); + } + println(" }, "); + // Generate generic class if it's a generic type.. null otherwise + print("new Class[] { "); + for (int i = 0; i < methParams.size(); i++) { + String prmType = methPrmTypes.get(i); + if ((getParamCategory(prmType) == ParamCategory.NONPRIMITIVES) && + !isEnumClass(getGenericType(prmType)) && + !callbackClasses.contains(getGenericType(prmType))) + print(getGenericType(prmType) + ".class"); + else + print("null"); + if (i != methParams.size() - 1) + print(", "); + } + println(" });"); + // Write the return value part + writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, false); + } + + + /** + * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class + */ + private void writeMethodHelperJavaSkeleton(Collection methods, InterfaceDecl intDecl, Set callbackClasses) { + + // Use this set to handle two same methodIds + Set uniqueMethodIds = new HashSet(); + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently + String methodId = intDecl.getMethodId(method); + print("public void ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + intDecl.getMethodNumId(method); + else + uniqueMethodIds.add(methodId); + String retType = intDecl.getMethodType(method); + print(helperMethod + "("); + boolean begin = true; + for (int i = 0; i < methParams.size(); i++) { // Print size variables + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + if (!begin) // Generate comma for not the beginning variable + print(", "); + else + begin = false; + int methodNumId = intDecl.getMethodNumId(method); + print("int struct" + methodNumId + "Size" + i); + } + } + // Check if this is "void" + if (retType.equals("void")) + println(") {"); + else + println(") throws IOException {"); + writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses); + println("}\n"); + } else { + String methodId = intDecl.getMethodId(method); + print("public void ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + intDecl.getMethodNumId(method); + else + uniqueMethodIds.add(methodId); + // Check if this is "void" + String retType = intDecl.getMethodType(method); + if (retType.equals("void")) + println(helperMethod + "() {"); + else + println(helperMethod + "() throws IOException {"); + // Now, write the helper body of skeleton! + writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses); + println("}\n"); + } + } + // Write method helper for structs + writeMethodHelperStructSetupJavaSkeleton(methods, intDecl); + } + + + /** + * HELPER: writeMethodHelperStructSetupJavaSkeleton() writes the method helper of struct setup in skeleton class + */ + private void writeMethodHelperStructSetupJavaSkeleton(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("public int ___"); + String helperMethod = methodNumId + "struct" + i; + println(helperMethod + "() {"); + // Now, write the helper body of skeleton! + println("Object[] paramObj = rmiObj.getMethodParams(new Class[] { int.class }, new Class[] { null });"); + println("return (int) paramObj[0];"); + println("}\n"); + } + } + } + } + + + /** + * HELPER: writeMethodHelperStructSetupJavaCallbackSkeleton() writes the method helper of struct setup in callback skeleton class + */ + private void writeMethodHelperStructSetupJavaCallbackSkeleton(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("public int ___"); + String helperMethod = methodNumId + "struct" + i; + println(helperMethod + "(IoTRMIObject rmiObj) {"); + // Now, write the helper body of skeleton! + println("Object[] paramObj = rmiObj.getMethodParams(new Class[] { int.class }, new Class[] { null });"); + println("return (int) paramObj[0];"); + println("}\n"); + } + } + } + } + + + /** + * HELPER: writeCountVarStructSkeleton() writes counter variable of struct for skeleton + */ + private void writeCountVarStructSkeleton(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); + println("int struct" + methodNumId + "Size" + i + " = 0;"); + } + } + } + } + + + /** + * HELPER: writeInputCountVarStructSkeleton() writes input counter variable of struct for skeleton + */ + private boolean writeInputCountVarStructSkeleton(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 + */ + private void writeMethodCallStructSkeleton(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 + "(); break;"); + } + } + } + } + + + /** + * HELPER: writeMethodCallStructCallbackSkeleton() writes method call for wait invoke in skeleton + */ + private void writeMethodCallStructCallbackSkeleton(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 + "(rmiObj); break;"); + } + } + } + } + + + /** + * HELPER: writeJavaMethodPermission() writes permission checks in skeleton + */ + private void writeJavaMethodPermission(String intface) { + + // Get all the different stubs + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + String newIntface = intMeth.getKey(); + int newObjectId = getNewIntfaceObjectId(newIntface); + println("if (_objectId == object" + newObjectId + "Id) {"); + println("if (!set" + newObjectId + "Allowed.contains(methodId)) {"); + println("throw new Error(\"Object with object Id: \" + _objectId + \" is not allowed to access method: \" + methodId);"); + println("}"); + println("}"); + println("else {"); + println("throw new Error(\"Object Id: \" + _objectId + \" not recognized!\");"); + println("}"); + } + } + + + /** + * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class + */ + private void writeJavaWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, boolean callbackExist, String intface) { + + // Use this set to handle two same methodIds + Set uniqueMethodIds = new HashSet(); + println("private void ___waitRequestInvokeMethod() throws IOException {"); + // Write variables here if we have callbacks or enums or structs + writeCountVarStructSkeleton(methods, intDecl); + println("while (true) {"); + println("rmiObj.getMethodBytes();"); + println("int _objectId = rmiObj.getObjectId();"); + println("int methodId = rmiObj.getMethodId();"); + // Generate permission check + writeJavaMethodPermission(intface); + println("switch (methodId) {"); + // Print methods and method Ids + for (String method : methods) { + String methodId = intDecl.getMethodId(method); + int methodNumId = intDecl.getMethodNumId(method); + print("case " + methodNumId + ": ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + methodNumId; + else + uniqueMethodIds.add(methodId); + print(helperMethod + "("); + 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;"); + } + writeMethodCallStructSkeleton(methods, intDecl); + println("default: "); + println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");"); + println("}"); + println("}"); + println("}\n"); + } + + + /** + * generateJavaSkeletonClass() generate skeletons based on the methods list in Java + */ + public void generateJavaSkeletonClass() throws IOException { + + // Create a new directory + String path = createDirectories(dir, subdir); + for (String intface : mapIntfacePTH.keySet()) { + // Open a new file to write into + String newSkelClass = intface + "_Skeleton"; + FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java"); + pw = new PrintWriter(new BufferedWriter(fw)); + // Pass in set of methods and get import classes + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + List methods = intDecl.getMethods(); + Set importClasses = getImportClasses(methods, intDecl); + List stdImportClasses = getStandardJavaImportClasses(); + List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); + printImportStatements(allImportClasses); + // Find out if there are callback objects + Set callbackClasses = getCallbackClasses(methods, intDecl); + boolean callbackExist = !callbackClasses.isEmpty(); + // Write class header + println(""); + println("public class " + newSkelClass + " implements " + intface + " {\n"); + // Write properties + writePropertiesJavaSkeleton(intface, callbackExist, intDecl); + // Write constructor + writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist); + // Write methods + writeMethodJavaSkeleton(methods, intDecl, callbackClasses, false, intface); + // Write method helper + writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses); + // Write waitRequestInvokeMethod() - main loop + writeJavaWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface); + println("}"); + pw.close(); + System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java..."); + } + } + + + /** + * HELPER: writePropertiesJavaCallbackSkeleton() writes the properties of the callback skeleton class + */ + private void writePropertiesJavaCallbackSkeleton(String intface, boolean callbackExist) { + + println("private " + intface + " mainObj;"); + // For callback skeletons, this is its own object Id + println("private int objectId = 0;"); + println("private String callbackAddress;"); + // Callback + if (callbackExist) { + + println("private int objIdCnt = 0;"); + println("private IoTRMICall rmiCall;"); + println("private int[] ports;\n"); + } + println("\n"); + } + + + /** + * HELPER: writeConstructorJavaCallbackSkeleton() writes the constructor of the skeleton class + */ + private void writeConstructorJavaCallbackSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, Collection methods) { + + println("public " + newSkelClass + "(" + intface + " _mainObj, String _callbackAddress, int _objectId) throws Exception {"); + println("callbackAddress = _callbackAddress;"); + println("mainObj = _mainObj;"); + println("objectId = _objectId;"); + println("}\n"); + } + + + /** + * HELPER: writeMethodHelperJavaCallbackSkeleton() writes the method helper of the callback skeleton class + */ + private void writeMethodHelperJavaCallbackSkeleton(Collection methods, InterfaceDecl intDecl, Set callbackClasses) { + + // Use this set to handle two same methodIds + Set uniqueMethodIds = new HashSet(); + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently + String methodId = intDecl.getMethodId(method); + print("public void ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + intDecl.getMethodNumId(method); + else + uniqueMethodIds.add(methodId); + String retType = intDecl.getMethodType(method); + print(helperMethod + "("); + boolean begin = true; + for (int i = 0; i < methParams.size(); i++) { // Print size variables + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + if (!begin) // Generate comma for not the beginning variable + print(", "); + else + begin = false; + int methodNumId = intDecl.getMethodNumId(method); + print("int struct" + methodNumId + "Size" + i); + } + } + // Check if this is "void" + if (retType.equals("void")) + println(", IoTRMIObject rmiObj) {"); + else + println(", IoTRMIObject rmiObj) throws IOException {"); + writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses); + println("}\n"); + } else { + String methodId = intDecl.getMethodId(method); + print("public void ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + intDecl.getMethodNumId(method); + else + uniqueMethodIds.add(methodId); + // Check if this is "void" + String retType = intDecl.getMethodType(method); + if (retType.equals("void")) + println(helperMethod + "(IoTRMIObject rmiObj) {"); + else + println(helperMethod + "(IoTRMIObject rmiObj) throws IOException {"); + // Now, write the helper body of skeleton! + writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses); + println("}\n"); + } + } + // Write method helper for structs + writeMethodHelperStructSetupJavaCallbackSkeleton(methods, intDecl); + } + + + /** + * HELPER: writeJavaCallbackWaitRequestInvokeMethod() writes the request invoke method of the callback skeleton class + */ + private void writeJavaCallbackWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, boolean callbackExist) { + + // Use this set to handle two same methodIds + Set uniqueMethodIds = new HashSet(); + println("public void invokeMethod(IoTRMIObject rmiObj) throws IOException {"); + // Write variables here if we have callbacks or enums or structs + writeCountVarStructSkeleton(methods, intDecl); + // Write variables here if we have callbacks or enums or structs + println("int methodId = rmiObj.getMethodId();"); + // TODO: code the permission check here! + println("switch (methodId) {"); + // Print methods and method Ids + for (String method : methods) { + String methodId = intDecl.getMethodId(method); + int methodNumId = intDecl.getMethodNumId(method); + print("case " + methodNumId + ": ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + methodNumId; + else + uniqueMethodIds.add(methodId); + print(helperMethod + "("); + if (writeInputCountVarStructSkeleton(method, intDecl)) + println(", rmiObj); break;"); + else + println("rmiObj); break;"); + } + String method = "___initCallBack()"; + // Print case -9999 (callback handler) if callback exists + if (callbackExist) { + int methodId = intDecl.getHelperMethodNumId(method); + println("case " + methodId + ": ___regCB(rmiObj); break;"); + } + writeMethodCallStructCallbackSkeleton(methods, intDecl); + println("default: "); + println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");"); + println("}"); + println("}\n"); + } + + + /** + * generateJavaCallbackSkeletonClass() generate callback skeletons based on the methods list in Java + */ + public void generateJavaCallbackSkeletonClass() throws IOException { + + // Create a new directory + String path = createDirectories(dir, subdir); + for (String intface : mapIntfacePTH.keySet()) { + // Open a new file to write into + String newSkelClass = intface + "_CallbackSkeleton"; + FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java"); + pw = new PrintWriter(new BufferedWriter(fw)); + // Pass in set of methods and get import classes + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + List methods = intDecl.getMethods(); + Set importClasses = getImportClasses(methods, intDecl); + List stdImportClasses = getStandardJavaImportClasses(); + List allImportClasses = getAllLibClasses(stdImportClasses, importClasses); + printImportStatements(allImportClasses); + // Find out if there are callback objects + Set callbackClasses = getCallbackClasses(methods, intDecl); + boolean callbackExist = !callbackClasses.isEmpty(); + // Write class header + println(""); + println("public class " + newSkelClass + " implements " + intface + " {\n"); + // Write properties + writePropertiesJavaCallbackSkeleton(intface, callbackExist); + // Write constructor + writeConstructorJavaCallbackSkeleton(newSkelClass, intface, intDecl, methods); + // Write methods + writeMethodJavaSkeleton(methods, intDecl, callbackClasses, true, intface); + // Write method helper + writeMethodHelperJavaCallbackSkeleton(methods, intDecl, callbackClasses); + // Write waitRequestInvokeMethod() - main loop + writeJavaCallbackWaitRequestInvokeMethod(methods, intDecl, callbackExist); + println("}"); + pw.close(); + System.out.println("IoTCompiler: Generated callback skeleton class " + newSkelClass + ".java..."); + } + } + + + /** + * HELPER: writeMethodCplusLocalInterface() writes the method of the local interface + */ + private void writeMethodCplusLocalInterface(Collection methods, InterfaceDecl intDecl) { + + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " + + intDecl.getMethodId(method) + "("); + for (int i = 0; i < methParams.size(); i++) { + // Check for params with driver class types and exchange it + // with its remote interface + String paramType = checkAndGetParamClass(methPrmTypes.get(i)); + paramType = checkAndGetCplusType(paramType); + // Check for arrays - translate into vector in C++ + String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i)); + print(paramComplete); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } + } + println(") = 0;"); + } + } + + + /** + * HELPER: writeMethodCplusInterface() writes the method of the interface + */ + private void writeMethodCplusInterface(Collection methods, InterfaceDecl intDecl) { + + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " + + intDecl.getMethodId(method) + "("); + for (int i = 0; i < methParams.size(); i++) { + // Check for params with driver class types and exchange it + // with its remote interface + String paramType = methPrmTypes.get(i); + paramType = checkAndGetCplusType(paramType); + // Check for arrays - translate into vector in C++ + String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i)); + print(paramComplete); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } + } + println(") = 0;"); + } + } + + + /** + * HELPER: generateEnumCplus() writes the enumeration declaration + */ + public void generateEnumCplus() throws IOException { + + // Create a new directory + createDirectory(dir); + for (String intface : mapIntfacePTH.keySet()) { + // Get the right StructDecl + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface); + Set enumTypes = enumDecl.getEnumDeclarations(); + // Iterate over enum declarations + for (String enType : enumTypes) { + // Open a new file to write into + FileWriter fw = new FileWriter(dir + "/" + enType + ".hpp"); + pw = new PrintWriter(new BufferedWriter(fw)); + // Write file headers + println("#ifndef _" + enType.toUpperCase() + "_HPP__"); + println("#define _" + enType.toUpperCase() + "_HPP__"); + println("enum " + enType + " {"); + List enumMembers = enumDecl.getMembers(enType); + for (int i = 0; i < enumMembers.size(); i++) { + + String member = enumMembers.get(i); + print(member); + // Check if this is the last element (don't print a comma) + if (i != enumMembers.size() - 1) + println(","); + else + println(""); + } + println("};\n"); + println("#endif"); + pw.close(); + System.out.println("IoTCompiler: Generated enum " + enType + ".hpp..."); + } + } + } + + + /** + * HELPER: generateStructCplus() writes the struct declaration + */ + public void generateStructCplus() throws IOException { + + // Create a new directory + createDirectory(dir); + for (String intface : mapIntfacePTH.keySet()) { + // Get the right StructDecl + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface); + List structTypes = structDecl.getStructTypes(); + // Iterate over enum declarations + for (String stType : structTypes) { + // Open a new file to write into + FileWriter fw = new FileWriter(dir + "/" + stType + ".hpp"); + pw = new PrintWriter(new BufferedWriter(fw)); + // Write file headers + println("#ifndef _" + stType.toUpperCase() + "_HPP__"); + println("#define _" + stType.toUpperCase() + "_HPP__"); + println("using namespace std;"); + println("struct " + stType + " {"); + List structMemberTypes = structDecl.getMemberTypes(stType); + List structMembers = structDecl.getMembers(stType); + for (int i = 0; i < structMembers.size(); i++) { + + String memberType = structMemberTypes.get(i); + String member = structMembers.get(i); + String structTypeC = checkAndGetCplusType(memberType); + String structComplete = checkAndGetCplusArray(structTypeC, member); + println(structComplete + ";"); + } + println("};\n"); + println("#endif"); + pw.close(); + System.out.println("IoTCompiler: Generated struct " + stType + ".hpp..."); + } + } + } + + + /** + * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking. + *

+ * 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 "); + // Pass in set of methods and get include classes + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + List methods = intDecl.getMethods(); + Set includeClasses = getIncludeClasses(methods, intDecl, intface, true); + printIncludeStatements(includeClasses); println(""); + println("using namespace std;\n"); + //writeStructCplus(structDecl); + 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..."); + } + } + + + /** + * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++ + *

+ * 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> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> 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 "); + updateIntfaceObjIdMap(intface, newIntface); + // 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(""); + println("using namespace std;\n"); + 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: 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)) + " " + + 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(") { "); + 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: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class + */ + private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method, String callbackType) { + + // Check if this is single object, array, or list of objects + boolean isArrayOrList = false; + String callbackParam = null; + for (int i = 0; i < methParams.size(); i++) { + + String paramType = methPrmTypes.get(i); + if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object + String param = methParams.get(i); + if (isArrayOrList(paramType, param)) { // Generate loop + println("for (" + getGenericType(paramType) + "* cb : " + getSimpleIdentifier(param) + ") {"); + println(callbackType + "_CallbackSkeleton* skel" + i + " = new " + callbackType + "_CallbackSkeleton(cb, callbackAddress, objIdCnt++);"); + isArrayOrList = true; + callbackParam = getSimpleIdentifier(param); + } else + println(callbackType + "_CallbackSkeleton* skel" + i + " = new " + callbackType + "_CallbackSkeleton(" + + getSimpleIdentifier(param) + ", callbackAddress, objIdCnt++);"); + println("vecCallbackObj.push_back(skel" + i + ");"); + if (isArrayOrList) + println("}"); + print("int ___paramCB" + i + " = "); + if (isArrayOrList) + println(callbackParam + ".size();"); + else + println("1;"); + } + } + } + + + /** + * HELPER: checkAndWriteEnumTypeCplusStub() writes the enum type (convert from enum to int) + */ + private void checkAndWriteEnumTypeCplusStub(List methParams, List 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 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 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) { + + // 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 retEnumInt;"); + println("void* retObj = &retEnumInt;"); + println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, 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 methParams, List 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("rmiCall->remoteCall(objectId, methodIdStruct" + i + + ", retTypeStruct" + i + ", paramClsStruct" + i + ", paramObjStruct" + i + + ", numParam" + i + ", retStructLen" + i + ");\n"); + } + } + } + + + /** + * HELPER: writeLengthStructParamClassCplusStub() writes lengths of params + */ + private void writeLengthStructParamClassCplusStub(List methParams, List 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 memTypes = structDecl.getMemberTypes(simpleType); + List 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 methParams, List methPrmTypes, 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 memTypes = structDecl.getMemberTypes(simpleType); + List 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) { + + // 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);"); + int numMem = getNumOfMembers(simpleType); + println("int numRet = " + numMem + "*retLen;"); + println("string retCls[numRet];"); + println("void* retObj[numRet];"); + StructDecl structDecl = getStructDecl(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + List 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("rmiCall->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: writeStdMethodBodyCplusStub() writes the standard method body in the stub class + */ + private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method, String callbackType, boolean isCallbackMethod) { + + 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("void* retObj = NULL;"); + println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);"); + } else { // We do have a return value + // Generate array of parameter types + if (isStructClass(getGenericType(getSimpleArrayType(retType)))) { + writeStructReturnCplusStub(getGenericType(getSimpleArrayType(retType)), retType); + } else { + // Check if the return value NONPRIMITIVES + if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { + checkAndWriteEnumRetTypeCplusStub(retType); + } 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("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);"); + println("return retVal;"); + } + } + } + } + + + /** + * HELPER: writePropertiesCplusStub() writes the properties of the stub class + */ + private void writePropertiesCplusPermission(String intface) { + + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + String newIntface = intMeth.getKey(); + int newObjectId = getNewIntfaceObjectId(newIntface); + println("const static int object" + newObjectId + "Id = " + newObjectId + ";\t//" + newIntface); + println("static set set" + newObjectId + "Allowed;"); + } + } + + /** + * HELPER: writePropertiesCplusStub() writes the properties of the stub class + */ + private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist, Set callbackClasses) { + + println("IoTRMICall *rmiCall;"); + println("string callbackAddress;"); + println("vector ports;\n"); + // Get the object Id + Integer objId = mapIntfaceObjId.get(intface); + println("const static int objectId = " + objId + ";"); + if (callbackExist) { + // We assume that each class only has one callback interface for now + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + println("// Callback properties"); + println("IoTRMIObject *rmiObj;"); + println("vector<" + callbackType + "*> vecCallbackObj;"); + println("static int objIdCnt;"); + // Generate permission stuff for callback stubs + writePropertiesCplusPermission(callbackType); + } + println("\n"); + } + + + /** + * HELPER: writeConstructorCplusStub() writes the constructor of the stub class + */ + private void writeConstructorCplusStub(String newStubClass, boolean callbackExist, Set callbackClasses) { + + println(newStubClass + + "(int _port, const char* _skeletonAddress, string _callbackAddress, int _rev, bool* _bResult, vector _ports) {"); + println("callbackAddress = _callbackAddress;"); + println("ports = _ports;"); + println("rmiCall = new IoTRMICall(_port, _skeletonAddress, _rev, _bResult);"); + if (callbackExist) { + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + DeclarationHandler decHandler = mapIntDeclHand.get(callbackType); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType); + writeCplusInitCallbackPermission(callbackType, intDecl, callbackExist); + println("thread th1 (&" + newStubClass + "::___initCallBack, this);"); + println("th1.detach();"); + println("___regCB();"); + } + println("}\n"); + } + + + /** + * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class + */ + private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set callbackClasses) { + + println("~" + newStubClass + "() {"); + println("if (rmiCall != NULL) {"); + println("delete rmiCall;"); + println("rmiCall = NULL;"); + println("}"); + if (callbackExist) { + // We assume that each class only has one callback interface for now + println("if (rmiObj != NULL) {"); + println("delete rmiObj;"); + println("rmiObj = NULL;"); + println("}"); + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + println("for(" + callbackType + "* cb : vecCallbackObj) {"); + println("delete cb;"); + println("cb = NULL;"); + println("}"); + } + println("}"); + println(""); + } + + + /** + * HELPER: writeCplusMethodCallbackPermission() writes permission checks in stub for callbacks + */ + private void writeCplusMethodCallbackPermission(String intface) { + + println("int methodId = IoTRMIObject::getMethodId(method);"); + // Get all the different stubs + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + String newIntface = intMeth.getKey(); + int newObjectId = getNewIntfaceObjectId(newIntface); + println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {"); + println("cerr << \"Callback object for " + intface + " is not allowed to access method: \" << methodId;"); + println("return;"); + println("}"); + } + } + + + /** + * HELPER: writeInitCallbackCplusStub() writes the initialization of callback + */ + private void writeInitCallbackCplusStub(String intface, InterfaceDecl intDecl, String newStubClass) { + + println("void ___initCallBack() {"); + println("bool bResult = false;"); + int port = getPortCount(newStubClass); + println("rmiObj = new IoTRMIObject(ports[" + port + "], &bResult);"); + println("while (true) {"); + println("char* method = rmiObj->getMethodBytes();"); + //writeCplusMethodCallbackPermission(intface); + println("int objId = IoTRMIObject::getObjectId(method);"); + println("if (objId < vecCallbackObj.size()) { // Check if still within range"); + println(intface + "_CallbackSkeleton* skel = dynamic_cast<" + intface + + "_CallbackSkeleton*> (vecCallbackObj.at(objId));"); + writeCplusMethodCallbackPermission(intface); + println("skel->invokeMethod(rmiObj);"); + print("}"); + println(" else {"); + println("cerr << \"Illegal object Id: \" << to_string(objId);"); + // TODO: perhaps need to change this into "throw" to make it cleaner (allow stack unfolding) + println("return;"); + println("}"); + println("}"); + println("}\n"); + } + + + /** + * HELPER: writeCplusInitCallbackPermission() writes the permission for callback + */ + private void writeCplusInitCallbackPermission(String intface, InterfaceDecl intDecl, boolean callbackExist) { + + if (callbackExist) { + String method = "___initCallBack()"; + int methodNumId = intDecl.getHelperMethodNumId(method); + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + String newIntface = intMeth.getKey(); + int newObjectId = getNewIntfaceObjectId(newIntface); + println("set" + newObjectId + "Allowed.insert(" + methodNumId + ");"); + } + } + } + + + /** + * HELPER: writeInitCallbackSendInfoCplusStub() writes the initialization (send info part) of callback + */ + private void writeInitCallbackSendInfoCplusStub(InterfaceDecl intDecl) { + + // Generate info sending part + println("void ___regCB() {"); + println("int numParam = 3;"); + String method = "___initCallBack()"; + int methodNumId = intDecl.getHelperMethodNumId(method); + println("int methodId = " + methodNumId + ";"); + println("string retType = \"void\";"); + println("string paramCls[] = { \"int*\", \"String\", \"int\" };"); + println("int rev = 0;"); + println("void* paramObj[] = { &ports, &callbackAddress, &rev };"); + println("void* retObj = NULL;"); + println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);"); + println("}\n"); + } + + + /** + * generateCPlusStubClasses() generate stubs based on the methods list in C++ + */ + public void generateCPlusStubClasses() throws IOException { + + // Create a new directory + String path = createDirectories(dir, subdir); + for (String intface : mapIntfacePTH.keySet()) { + + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + // Open a new file to write into + String newIntface = intMeth.getKey(); + String newStubClass = newIntface + "_Stub"; + FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp"); + pw = new PrintWriter(new BufferedWriter(fw)); + // Write file headers + println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__"); + println("#define _" + newStubClass.toUpperCase() + "_HPP__"); + println("#include "); + // Find out if there are callback objects + Set methods = intMeth.getValue(); + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + Set callbackClasses = getCallbackClasses(methods, intDecl); + boolean callbackExist = !callbackClasses.isEmpty(); + if (callbackExist) // Need thread library if this has callback + println("#include "); + println("#include \"" + newIntface + ".hpp\""); println(""); + println("using namespace std;"); println(""); + println("class " + newStubClass + " : public " + newIntface); println("{"); + println("private:\n"); + writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses); + println("public:\n"); + // Add default constructor and destructor + println(newStubClass + "() { }"); println(""); + writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses); + writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses); + // Write methods + writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass); + print("}"); println(";"); + if (callbackExist) { + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + // Generate permission stuff for callback stubs + DeclarationHandler decHandlerCallback = mapIntDeclHand.get(callbackType); + InterfaceDecl intDeclCallback = (InterfaceDecl) decHandlerCallback.getInterfaceDecl(callbackType); + writePermissionInitializationCplus(callbackType, newStubClass, intDeclCallback); + } + writeObjectIdCountInitializationCplus(newStubClass, callbackExist); + println("#endif"); + pw.close(); + System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp..."); + } + } + } + + + /** + * HELPER: writePropertiesCplusCallbackStub() writes the properties of the stub class + */ + private void writePropertiesCplusCallbackStub(String intface, String newIntface, boolean callbackExist, Set callbackClasses) { + + println("IoTRMICall *rmiCall;"); + // Get the object Id + println("int objectId;"); + println("vector ports;\n"); + println("string callbackAddress;"); + if (callbackExist) { + // We assume that each class only has one callback interface for now + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + println("// Callback properties"); + println("IoTRMIObject *rmiObj;"); + println("vector<" + callbackType + "*> vecCallbackObj;"); + println("static int objIdCnt;"); + // TODO: Need to initialize address and ports if we want to have callback-in-callback + writePropertiesCplusPermission(callbackType); + } + println("\n"); + } + + + /** + * HELPER: writeConstructorCplusCallbackStub() writes the constructor of the stub class + */ + private void writeConstructorCplusCallbackStub(String newStubClass, boolean callbackExist, Set callbackClasses) { + + println(newStubClass + "(IoTRMICall* _rmiCall, string _callbackAddress, int _objectId, vector _ports) {"); + println("objectId = _objectId;"); + println("callbackAddress = _callbackAddress;"); + println("rmiCall = _rmiCall;"); + println("ports = _ports;"); + if (callbackExist) { + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + DeclarationHandler decHandler = mapIntDeclHand.get(callbackType); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType); + writeCplusInitCallbackPermission(callbackType, intDecl, callbackExist); + println("thread th1 (&" + newStubClass + "::___initCallBack, this);"); + println("th1.detach();"); + println("___regCB();"); + } + println("}\n"); + } + + + /** + * generateCPlusCallbackStubClasses() generate callback stubs based on the methods list in C++ + */ + public void generateCPlusCallbackStubClasses() throws IOException { + + // Create a new directory + String path = createDirectories(dir, subdir); + for (String intface : mapIntfacePTH.keySet()) { + + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + // Open a new file to write into + String newIntface = intMeth.getKey(); + String newStubClass = newIntface + "_CallbackStub"; + FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp"); + pw = new PrintWriter(new BufferedWriter(fw)); + // Find out if there are callback objects + Set methods = intMeth.getValue(); + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + Set callbackClasses = getCallbackClasses(methods, intDecl); + boolean callbackExist = !callbackClasses.isEmpty(); + // Write file headers + println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__"); + println("#define _" + newStubClass.toUpperCase() + "_HPP__"); + println("#include "); + if (callbackExist) + println("#include "); + println("#include \"" + newIntface + ".hpp\""); println(""); + println("using namespace std;"); println(""); + println("class " + newStubClass + " : public " + newIntface); println("{"); + println("private:\n"); + writePropertiesCplusCallbackStub(intface, newIntface, callbackExist, callbackClasses); + println("public:\n"); + // Add default constructor and destructor + println(newStubClass + "() { }"); println(""); + writeConstructorCplusCallbackStub(newStubClass, callbackExist, callbackClasses); + writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses); + // Write methods + writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass); + println("};"); + if (callbackExist) { + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + // Generate permission stuff for callback stubs + DeclarationHandler decHandlerCallback = mapIntDeclHand.get(callbackType); + InterfaceDecl intDeclCallback = (InterfaceDecl) decHandlerCallback.getInterfaceDecl(callbackType); + writePermissionInitializationCplus(callbackType, newStubClass, intDeclCallback); + } + writeObjectIdCountInitializationCplus(newStubClass, callbackExist); + println("#endif"); + pw.close(); + System.out.println("IoTCompiler: Generated callback stub class " + newIntface + ".hpp..."); + } + } + } + + + /** + * 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"); + // Keep track of object Ids of all stubs registered to this interface + writePropertiesCplusPermission(intface); + 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> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + String newIntface = intMeth.getKey(); + int newObjectId = getNewIntfaceObjectId(newIntface); + print("set " + newSkelClass + "::set" + newObjectId + "Allowed { "); + Set 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 methods, InterfaceDecl intDecl, String intface) { + + // 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); + String helperMethod = methodNumId + "struct" + i; + int helperMethodNumId = intDecl.getHelperMethodNumId(helperMethod); + // Iterate over interfaces to give permissions to + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> 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 methods) { + + println(newSkelClass + "(" + intface + " *_mainObj, string _callbackAddress, int _port) {"); + println("bool _bResult = false;"); + println("mainObj = _mainObj;"); + println("callbackAddress = _callbackAddress;"); + println("rmiObj = new IoTRMIObject(_port, &_bResult);"); + writeCplusInitCallbackPermission(intface, intDecl, callbackExist); + writeStructPermissionCplusSkeleton(methods, intDecl, intface); + println("___waitRequestInvokeMethod();"); + println("}\n"); + } + + + /** + * HELPER: writeDeconstructorCplusSkeleton() writes the deconstructor of the skeleton class + */ + private void writeDeconstructorCplusSkeleton(String newSkelClass, boolean callbackExist, Set callbackClasses) { + + println("~" + newSkelClass + "() {"); + println("if (rmiObj != NULL) {"); + println("delete rmiObj;"); + println("rmiObj = NULL;"); + println("}"); + if (callbackExist) { + // We assume that each class only has one callback interface for now + println("if (rmiCall != NULL) {"); + println("delete rmiCall;"); + println("rmiCall = NULL;"); + println("}"); + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + String exchangeType = checkAndGetParamClass(callbackType); + println("for(" + exchangeType + "* cb : vecCallbackObj) {"); + println("delete cb;"); + println("cb = NULL;"); + println("}"); + } + println("}"); + println(""); + } + + + /** + * HELPER: writeStdMethodBodyCplusSkeleton() writes the standard method body in the skeleton class + */ + private void writeStdMethodBodyCplusSkeleton(List methParams, String methodId, String methodType) { + + if (methodType.equals("void")) + print("mainObj->" + methodId + "("); + else + print("return mainObj->" + methodId + "("); + for (int i = 0; i < methParams.size(); i++) { + + print(getSimpleIdentifier(methParams.get(i))); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } + } + println(");"); + } + + + /** + * HELPER: writeInitCallbackCplusSkeleton() writes the init callback method for skeleton class + */ + private void writeInitCallbackCplusSkeleton(boolean callbackSkeleton, String intface) { + + // This is a callback skeleton generation + if (callbackSkeleton) + println("void ___regCB(IoTRMIObject* rmiObj) {"); + else + println("void ___regCB() {"); + println("int numParam = 3;"); + println("vector param1;"); + println("string param2 = \"\";"); + println("int param3 = 0;"); + println("string paramCls[] = { \"int*\", \"String\", \"int\" };"); + println("void* paramObj[] = { ¶m1, ¶m2, ¶m3 };"); + println("rmiObj->getMethodParams(paramCls, numParam, paramObj);"); + println("bool bResult = false;"); + String stubInt = null; + if (callbackSkeleton) + stubInt = getStubInterface(intface) + "_CallbackStub"; + else + stubInt = getStubInterface(intface) + "_Stub"; + int port = getPortCount(stubInt); + println("rmiCall = new IoTRMICall(param1[" + port + "], param2.c_str(), param3, &bResult);"); + println("}\n"); + } + + + /** + * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class + */ + private void writeMethodCplusSkeleton(Collection methods, InterfaceDecl intDecl, + Set callbackClasses, boolean callbackSkeleton, String intface) { + + 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 + "("); + 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(") {"); + // Now, write the body of skeleton! + writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method)); + println("}\n"); + if (isCallbackMethod && !isDefined) { + writeInitCallbackCplusSkeleton(callbackSkeleton, intface); + isDefined = true; + } + } + } + + + /** + * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable + */ + private void writeCallbackCplusNumStubs(List methParams, List methPrmTypes, String callbackType) { + + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + //if (callbackType.equals(paramType)) { + if (checkCallbackType(paramType, callbackType)) // Check if this has callback object + println("int numStubs" + i + " = 0;"); + } + } + + + /** + * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part + */ + private void writeCallbackCplusStubGeneration(List methParams, List methPrmTypes, String callbackType) { + + // Iterate over callback objects + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + // Generate a loop if needed + if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object + String exchParamType = checkAndGetParamClass(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("}"); + } else { + println(exchParamType + "* stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);"); + println("vecCallbackObj.push_back(stub" + i + ");"); + println("objIdCnt++;"); + } + } + } + } + + + /** + * HELPER: checkAndWriteEnumTypeCplusSkeleton() writes the enum type (convert from enum to int) + */ + private void checkAndWriteEnumTypeCplusSkeleton(List methParams, List methPrmTypes) { + + // Iterate and find enum declarations + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isEnumClass(simpleType)) { + // Check if this is enum type + if (isArrayOrList(paramType, param)) { // An array + println("int len" + i + " = paramEnumInt" + i + ".size();"); + println("vector<" + simpleType + "> paramEnum" + i + "(len" + i + ");"); + println("for (int i=0; i < len" + i + "; i++) {"); + println("paramEnum" + i + "[i] = (" + simpleType + ") paramEnumInt" + i + "[i];"); + println("}"); + } else { // Just one element + println(simpleType + " paramEnum" + i + ";"); + println("paramEnum" + i + " = (" + simpleType + ") paramEnumInt" + i + "[0];"); + } + } + } + } + + + /** + * HELPER: checkAndWriteEnumRetTypeCplusSkeleton() writes the enum return type (convert from enum to int) + */ + private void checkAndWriteEnumRetTypeCplusSkeleton(String retType) { + + // 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 + // Enum decoder + if (isArrayOrList(retType, retType)) { // An array + println("int retLen = retEnum.size();"); + println("vector retEnumInt(retLen);"); + println("for (int i=0; i < retLen; i++) {"); + println("retEnumInt[i] = (int) retEnum[i];"); + println("}"); + } else { // Just one element + println("vector retEnumInt(1);"); + println("retEnumInt[0] = (int) retEnum;"); + } + } + } + + + /** + * HELPER: writeMethodInputParameters() writes the parameter variables for C++ skeleton + */ + private void writeMethodInputParameters(List methParams, List methPrmTypes, + Set callbackClasses, String methodId) { + + print(methodId + "("); + for (int i = 0; i < methParams.size(); i++) { + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); + if (callbackClasses.contains(paramType)) + print("stub" + i); + else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type + print("paramEnum" + i); + else if (isStructClass(getGenericType(paramType))) // Struct type + print("paramStruct" + i); + else + print(getSimpleIdentifier(methParams.get(i))); + if (i != methParams.size() - 1) { + print(", "); + } + } + println(");"); + } + + + /** + * HELPER: writeMethodHelperReturnCplusSkeleton() writes the return statement part in skeleton + */ + private void writeMethodHelperReturnCplusSkeleton(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method, boolean isCallbackMethod, String callbackType, + String methodId, Set callbackClasses) { + + println("rmiObj->getMethodParams(paramCls, numParam, paramObj);"); + if (isCallbackMethod) + writeCallbackCplusStubGeneration(methParams, methPrmTypes, callbackType); + checkAndWriteEnumTypeCplusSkeleton(methParams, methPrmTypes); + writeStructMembersInitCplusSkeleton(intDecl, methParams, methPrmTypes, method); + // Check if this is "void" + String retType = intDecl.getMethodType(method); + // Check if this is "void" + if (retType.equals("void")) { + writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId); + } else { // We do have a return value + if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type + print(checkAndGetCplusType(retType) + " retEnum = "); + else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type + print(checkAndGetCplusType(retType) + " retStruct = "); + else + print(checkAndGetCplusType(retType) + " retVal = "); + writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId); + checkAndWriteEnumRetTypeCplusSkeleton(retType); + if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type + writeStructReturnCplusSkeleton(getSimpleArrayType(getGenericType(retType)), retType); + if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type + println("void* retObj = &retEnumInt;"); + else + if (!isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type + println("void* retObj = &retVal;"); + String retTypeC = checkAndGetCplusType(retType); + if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type + println("rmiObj->sendReturnObj(retObj, retCls, numRetObj);"); + else + println("rmiObj->sendReturnObj(retObj, \"" + checkAndGetCplusRetClsType(getEnumType(retType)) + "\");"); + } + } + + + /** + * HELPER: writeStdMethodHelperBodyCplusSkeleton() writes the standard method body helper in the skeleton class + */ + private void writeStdMethodHelperBodyCplusSkeleton(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method, String methodId, Set callbackClasses) { + + // Generate array of parameter types + boolean isCallbackMethod = false; + String callbackType = null; + print("string paramCls[] = { "); + for (int i = 0; i < methParams.size(); i++) { + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); + if (callbackClasses.contains(paramType)) { + isCallbackMethod = true; + callbackType = paramType; + print("\"int\""); + } else { // Generate normal classes if it's not a callback object + String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i)); + print("\"" + paramTypeC + "\""); + } + if (i != methParams.size() - 1) { + print(", "); + } + } + println(" };"); + println("int numParam = " + methParams.size() + ";"); + if (isCallbackMethod) + writeCallbackCplusNumStubs(methParams, methPrmTypes, callbackType); + // Generate parameters + for (int i = 0; i < methParams.size(); i++) { + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); + if (!callbackClasses.contains(paramType)) { + String methParamType = methPrmTypes.get(i); + if (isEnumClass(getSimpleArrayType(getGenericType(methParamType)))) { + // Check if this is enum type + println("vector paramEnumInt" + i + ";"); + } else { + String methPrmType = checkAndGetCplusType(methParamType); + String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i)); + println(methParamComplete + ";"); + } + } + } + // Generate array of parameter objects + print("void* paramObj[] = { "); + for (int i = 0; i < methParams.size(); i++) { + String paramType = returnGenericCallbackType(methPrmTypes.get(i)); + if (callbackClasses.contains(paramType)) + print("&numStubs" + i); + else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type + print("¶mEnumInt" + i); + else + print("&" + getSimpleIdentifier(methParams.get(i))); + if (i != methParams.size() - 1) { + print(", "); + } + } + println(" };"); + // Write the return value part + writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, + callbackType, methodId, callbackClasses); + } + + + /** + * HELPER: writeStructMembersCplusSkeleton() writes member parameters of struct + */ + private void writeStructMembersCplusSkeleton(String simpleType, String paramType, + String param, String method, InterfaceDecl intDecl, int iVar) { + + // Get the struct declaration for this struct and generate initialization code + StructDecl structDecl = getStructDecl(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + List members = structDecl.getMembers(simpleType); + int methodNumId = intDecl.getMethodNumId(method); + String counter = "struct" + methodNumId + "Size" + iVar; + // Set up variables + if (isArrayOrList(paramType, param)) { // 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)) + " param" + iVar + i + "[" + counter + "];"); + } + } 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)) + " param" + iVar + i + ";"); + } + } + if (isArrayOrList(paramType, param)) { // An array or list + println("for(int i = 0; i < " + counter + "; 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 + "\";"); + println("paramObj[pos++] = ¶m" + iVar + 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("paramCls[pos] = \"" + prmTypeC + "\";"); + println("paramObj[pos++] = ¶m" + iVar + i + ";"); + } + } + } + + + /** + * HELPER: writeStructMembersInitCplusSkeleton() writes member parameters initialization of struct + */ + private void writeStructMembersInitCplusSkeleton(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method) { + + 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 counter = "struct" + methodNumId + "Size" + i; + // Declaration + if (isArrayOrList(paramType, param)) { // An array or list + println("vector<" + simpleType + "> paramStruct" + i + "(" + counter + ");"); + } else + println(simpleType + " paramStruct" + i + ";"); + // Initialize members + StructDecl structDecl = getStructDecl(simpleType); + List members = structDecl.getMembers(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + if (isArrayOrList(paramType, param)) { // An array or list + println("for(int i = 0; i < " + counter + "; i++) {"); + for (int j = 0; j < members.size(); j++) { + print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j))); + println(" = param" + i + j + "[i];"); + } + println("}"); + } else { // Just one struct element + for (int j = 0; j < members.size(); j++) { + print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j))); + println(" = param" + i + j + ";"); + } + } + } + } + } + + + /** + * HELPER: writeStructReturnCplusSkeleton() writes parameters of struct for return statement + */ + private void writeStructReturnCplusSkeleton(String simpleType, String retType) { + + // Minimum retLen is 1 if this is a single struct object + if (isArrayOrList(retType, retType)) + println("int retLen = retStruct.size();"); + else // Just single struct object + println("int retLen = 1;"); + println("void* retLenObj = &retLen;"); + println("rmiObj->sendReturnObj(retLenObj, \"int\");"); + int numMem = getNumOfMembers(simpleType); + println("int numRetObj = " + numMem + "*retLen;"); + println("string retCls[numRetObj];"); + println("void* retObj[numRetObj];"); + println("int retPos = 0;"); + // Get the struct declaration for this struct and generate initialization code + StructDecl structDecl = getStructDecl(simpleType); + List memTypes = structDecl.getMemberTypes(simpleType); + List members = structDecl.getMembers(simpleType); + 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 + "\";"); + print("retObj[retPos++] = &retStruct[i]."); + print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), 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("retCls[retPos] = \"" + prmTypeC + "\";"); + print("retObj[retPos++] = &retStruct."); + print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i)); + println(";"); + } + } + + } + + + /** + * HELPER: writeMethodHelperStructCplusSkeleton() writes the struct in skeleton + */ + private void writeMethodHelperStructCplusSkeleton(InterfaceDecl intDecl, List methParams, + List methPrmTypes, String method, String methodId, Set callbackClasses) { + + // Generate array of parameter objects + boolean isCallbackMethod = false; + String callbackType = null; + print("int numParam = "); + writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl); + println(";"); + println("string paramCls[numParam];"); + println("void* paramObj[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)) { + writeStructMembersCplusSkeleton(simpleType, paramType, param, method, intDecl, i); + } else { + String prmType = returnGenericCallbackType(methPrmTypes.get(i)); + if (callbackClasses.contains(prmType)) { + isCallbackMethod = true; + callbackType = prmType; + println("int numStubs" + i + " = 0;"); + println("paramCls[pos] = \"int\";"); + println("paramObj[pos++] = &numStubs" + i + ";"); + } 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 + println("vector paramEnumInt" + i + ";"); + } else { + String methParamComplete = checkAndGetCplusArray(paramTypeC, methParams.get(i)); + println(methParamComplete + ";"); + } + String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i)); + println("paramCls[pos] = \"" + prmTypeC + "\";"); + if (isEnumClass(getGenericType(paramType))) // Check if this is enum type + println("paramObj[pos++] = ¶mEnumInt" + i + ";"); + else + println("paramObj[pos++] = &" + getSimpleIdentifier(methParams.get(i)) + ";"); + } + } + } + // Write the return value part + writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, + callbackType, methodId, callbackClasses); + } + + + /** + * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class + */ + private void writeMethodHelperCplusSkeleton(Collection methods, InterfaceDecl intDecl, Set callbackClasses) { + + // Use this set to handle two same methodIds + Set uniqueMethodIds = new HashSet(); + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently + String methodId = intDecl.getMethodId(method); + print("void ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + intDecl.getMethodNumId(method); + else + uniqueMethodIds.add(methodId); + String retType = intDecl.getMethodType(method); + print(helperMethod + "("); + boolean begin = true; + for (int i = 0; i < methParams.size(); i++) { // Print size variables + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + if (!begin) // Generate comma for not the beginning variable + print(", "); + else + begin = false; + int methodNumId = intDecl.getMethodNumId(method); + print("int struct" + methodNumId + "Size" + i); + } + } + println(") {"); + writeMethodHelperStructCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses); + println("}\n"); + } else { + String methodId = intDecl.getMethodId(method); + print("void ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + intDecl.getMethodNumId(method); + else + uniqueMethodIds.add(methodId); + // Check if this is "void" + String retType = intDecl.getMethodType(method); + println(helperMethod + "() {"); + // Now, write the helper body of skeleton! + writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses); + println("}\n"); + } + } + // Write method helper for structs + writeMethodHelperStructSetupCplusSkeleton(methods, intDecl); + } + + + /** + * HELPER: writeMethodHelperStructSetupCplusSkeleton() writes the method helper of struct in skeleton class + */ + private void writeMethodHelperStructSetupCplusSkeleton(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("int ___"); + String helperMethod = methodNumId + "struct" + i; + println(helperMethod + "() {"); + // Now, write the helper body of skeleton! + println("string paramCls[] = { \"int\" };"); + println("int numParam = 1;"); + println("int param0 = 0;"); + println("void* paramObj[] = { ¶m0 };"); + println("rmiObj->getMethodParams(paramCls, numParam, paramObj);"); + println("return param0;"); + println("}\n"); + } + } + } + } + + + /** + * HELPER: writeMethodHelperStructSetupCplusCallbackSkeleton() writes the method helper of struct in skeleton class + */ + private void writeMethodHelperStructSetupCplusCallbackSkeleton(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("int ___"); + String helperMethod = methodNumId + "struct" + i; + println(helperMethod + "(IoTRMIObject* rmiObj) {"); + // Now, write the helper body of skeleton! + println("string paramCls[] = { \"int\" };"); + println("int numParam = 1;"); + println("int param0 = 0;"); + println("void* paramObj[] = { ¶m0 };"); + println("rmiObj->getMethodParams(paramCls, numParam, paramObj);"); + println("return param0;"); + println("}\n"); + } + } + } + } + + + /** + * HELPER: writeCplusMethodPermission() writes permission checks in skeleton + */ + private void writeCplusMethodPermission(String intface) { + + // Get all the different stubs + Map> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { + String newIntface = intMeth.getKey(); + int newObjectId = getNewIntfaceObjectId(newIntface); + println("if (_objectId == object" + newObjectId + "Id) {"); + 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("}"); + } + } + + + /** + * HELPER: writeCplusWaitRequestInvokeMethod() writes the main loop of the skeleton class + */ + private void writeCplusWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, boolean callbackExist, String intface) { + + // Use this set to handle two same methodIds + Set uniqueMethodIds = new HashSet(); + println("void ___waitRequestInvokeMethod() {"); + // Write variables here if we have callbacks or enums or structs + writeCountVarStructSkeleton(methods, intDecl); + println("while (true) {"); + println("rmiObj->getMethodBytes();"); + println("int _objectId = rmiObj->getObjectId();"); + println("int methodId = rmiObj->getMethodId();"); + // Generate permission check + writeCplusMethodPermission(intface); + println("switch (methodId) {"); + // Print methods and method Ids + for (String method : methods) { + String methodId = intDecl.getMethodId(method); + int methodNumId = intDecl.getMethodNumId(method); + print("case " + methodNumId + ": ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + methodNumId; + else + uniqueMethodIds.add(methodId); + print(helperMethod + "("); + 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;"); + } + writeMethodCallStructSkeleton(methods, intDecl); + println("default: "); + println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;"); + println("throw exception();"); + println("}"); + println("}"); + println("}\n"); + } + + + /** + * generateCplusSkeletonClass() generate skeletons based on the methods list in C++ + */ + public void generateCplusSkeletonClass() throws IOException { + + // Create a new directory + String path = createDirectories(dir, subdir); + for (String intface : mapIntfacePTH.keySet()) { + // Open a new file to write into + String newSkelClass = intface + "_Skeleton"; + FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp"); + pw = new PrintWriter(new BufferedWriter(fw)); + // Write file headers + println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__"); + println("#define _" + newSkelClass.toUpperCase() + "_HPP__"); + println("#include "); + println("#include \"" + intface + ".hpp\"\n"); + // Pass in set of methods and get import classes + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + List methods = intDecl.getMethods(); + Set includeClasses = getIncludeClasses(methods, intDecl, intface, true); + List stdIncludeClasses = getStandardCplusIncludeClasses(); + List allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses); + printIncludeStatements(allIncludeClasses); println(""); + println("using namespace std;\n"); + // Find out if there are callback objects + Set callbackClasses = getCallbackClasses(methods, intDecl); + boolean callbackExist = !callbackClasses.isEmpty(); + // Write class header + println("class " + newSkelClass + " : public " + intface); println("{"); + println("private:\n"); + // Write properties + writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses); + println("public:\n"); + // Write constructor + writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods); + // Write deconstructor + writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses); + // Write methods + writeMethodCplusSkeleton(methods, intDecl, callbackClasses, false, intface); + // Write method helper + writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses); + // Write waitRequestInvokeMethod() - main loop + writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface); + println("};"); + writePermissionInitializationCplus(intface, newSkelClass, intDecl); + writeObjectIdCountInitializationCplus(newSkelClass, callbackExist); + println("#endif"); + pw.close(); + System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp..."); + } + } + + + /** + * HELPER: writePropertiesCplusCallbackSkeleton() writes the properties of the callback skeleton class + */ + private void writePropertiesCplusCallbackSkeleton(String intface, boolean callbackExist, Set callbackClasses) { + + println(intface + " *mainObj;"); + // Keep track of object Ids of all stubs registered to this interface + println("int objectId;"); + println("vector ports;\n"); + println("string callbackAddress;"); + // Callback + if (callbackExist) { + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + String exchangeType = checkAndGetParamClass(callbackType); + println("// Callback properties"); + println("IoTRMICall* rmiCall;"); + println("vector<" + exchangeType + "*> vecCallbackObj;"); + println("static int objIdCnt;"); + } + println("\n"); + } + + + /** + * HELPER: writeConstructorCplusCallbackSkeleton() writes the constructor of the skeleton class + */ + private void writeConstructorCplusCallbackSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection methods) { + + println(newSkelClass + "(" + intface + " *_mainObj, string _callbackAddress, int _objectId) {"); + println("mainObj = _mainObj;"); + println("callbackAddress = _callbackAddress;"); + println("objectId = _objectId;"); + println("}\n"); + } + + + /** + * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class + */ + private void writeDeconstructorCplusCallbackSkeleton(String newStubClass, boolean callbackExist, + Set callbackClasses) { + + println("~" + newStubClass + "() {"); + if (callbackExist) { + // We assume that each class only has one callback interface for now + println("if (rmiCall != NULL) {"); + println("delete rmiCall;"); + println("rmiCall = NULL;"); + println("}"); + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + String exchangeType = checkAndGetParamClass(callbackType); + println("for(" + exchangeType + "* cb : vecCallbackObj) {"); + println("delete cb;"); + println("cb = NULL;"); + println("}"); } + println("}"); + println(""); } /** - * HELPER: writeMethodCplusStub() writes the method of the stub + * HELPER: writeMethodHelperCplusCallbackSkeleton() writes the method helper of callback skeleton class */ - private void writeMethodCplusStub(Collection methods, InterfaceDecl intDecl) { + private void writeMethodHelperCplusCallbackSkeleton(Collection methods, InterfaceDecl intDecl, + Set callbackClasses) { + // Use this set to handle two same methodIds + Set uniqueMethodIds = new HashSet(); for (String method : methods) { List methParams = intDecl.getMethodParams(method); List methPrmTypes = intDecl.getMethodParamTypes(method); - print(convertType(intDecl.getMethodType(method)) + " " + - intDecl.getMethodId(method) + "("); - for (int i = 0; i < methParams.size(); 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(") { "); - // Check if this is not "void" - if (!intDecl.getMethodType(method).equals("void")) { - String retStmt = generateReturnStmt(intDecl.getMethodType(method)); - if (retStmt.equals("null")) { // null = NULL in C++ - retStmt = "NULL"; + if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently + String methodId = intDecl.getMethodId(method); + print("void ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + intDecl.getMethodNumId(method); + else + uniqueMethodIds.add(methodId); + String retType = intDecl.getMethodType(method); + print(helperMethod + "("); + boolean begin = true; + for (int i = 0; i < methParams.size(); i++) { // Print size variables + String paramType = methPrmTypes.get(i); + String param = methParams.get(i); + String simpleType = getGenericType(paramType); + if (isStructClass(simpleType)) { + if (!begin) // Generate comma for not the beginning variable + print(", "); + else + begin = false; + int methodNumId = intDecl.getMethodNumId(method); + print("int struct" + methodNumId + "Size" + i); + } } - println("return " + retStmt + ";"); + println(", IoTRMIObject* rmiObj) {"); + writeMethodHelperStructCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses); + println("}\n"); + } else { + String methodId = intDecl.getMethodId(method); + print("void ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + intDecl.getMethodNumId(method); + else + uniqueMethodIds.add(methodId); + // Check if this is "void" + String retType = intDecl.getMethodType(method); + println(helperMethod + "(IoTRMIObject* rmiObj) {"); + // Now, write the helper body of skeleton! + writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses); + println("}\n"); } - println("}"); println(""); } + // Write method helper for structs + writeMethodHelperStructSetupCplusCallbackSkeleton(methods, intDecl); } /** - * generateCPlusStubClasses() generate stubs based on the methods list in C++ + * HELPER: writeCplusCallbackWaitRequestInvokeMethod() writes the request invoke method of the skeleton callback class */ - public void generateCPlusStubClasses() throws IOException { + private void writeCplusCallbackWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, + boolean callbackExist) { + + // Use this set to handle two same methodIds + Set uniqueMethodIds = new HashSet(); + println("void invokeMethod(IoTRMIObject* rmiObj) {"); + // Write variables here if we have callbacks or enums or structs + writeCountVarStructSkeleton(methods, intDecl); + // Write variables here if we have callbacks or enums or structs + println("int methodId = rmiObj->getMethodId();"); + // TODO: code the permission check here! + println("switch (methodId) {"); + // Print methods and method Ids + for (String method : methods) { + String methodId = intDecl.getMethodId(method); + int methodNumId = intDecl.getMethodNumId(method); + print("case " + methodNumId + ": ___"); + String helperMethod = methodId; + if (uniqueMethodIds.contains(methodId)) + helperMethod = helperMethod + methodNumId; + else + uniqueMethodIds.add(methodId); + print(helperMethod + "("); + if (writeInputCountVarStructSkeleton(method, intDecl)) + println(", rmiObj); break;"); + else + println("rmiObj); break;"); + } + String method = "___initCallBack()"; + // Print case -9999 (callback handler) if callback exists + if (callbackExist) { + int methodId = intDecl.getHelperMethodNumId(method); + println("case " + methodId + ": ___regCB(rmiObj); break;"); + } + writeMethodCallStructCallbackSkeleton(methods, intDecl); + println("default: "); + println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;"); + println("throw exception();"); + println("}"); + println("}\n"); + } + + + /** + * generateCplusCallbackSkeletonClass() generate callback skeletons based on the methods list in C++ + */ + public void generateCplusCallbackSkeletonClass() throws IOException { // Create a new directory String path = createDirectories(dir, subdir); for (String intface : mapIntfacePTH.keySet()) { - - Map> mapNewIntMethods = mapInt2NewInts.get(intface); - for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { - // Open a new file to write into - String newIntface = intMeth.getKey(); - String newStubClass = newIntface + "_Stub"; - FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp"); - pw = new PrintWriter(new BufferedWriter(fw)); - // Write file headers - println("#include "); - println("#include \"" + newIntface + ".hpp\""); println(""); - println("using namespace std;"); println(""); - println("class " + newStubClass + " : public " + newIntface); println("{"); - println("public:"); println(""); - // Add default constructor and destructor - println(newStubClass + "() { }"); println(""); - println("~" + newStubClass + "() { }"); println(""); - DeclarationHandler decHandler = mapIntDeclHand.get(intface); - InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); - // Write methods - writeMethodCplusStub(intMeth.getValue(), intDecl); - print("}"); println(";"); - pw.close(); - System.out.println("IoTCompiler: Generated stub class " + newIntface + ".hpp..."); - } + // Open a new file to write into + String newSkelClass = intface + "_CallbackSkeleton"; + FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp"); + pw = new PrintWriter(new BufferedWriter(fw)); + // Write file headers + println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__"); + println("#define _" + newSkelClass.toUpperCase() + "_HPP__"); + println("#include "); + println("#include \"" + intface + ".hpp\"\n"); + // Pass in set of methods and get import classes + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + List methods = intDecl.getMethods(); + Set includeClasses = getIncludeClasses(methods, intDecl, intface, true); + List stdIncludeClasses = getStandardCplusIncludeClasses(); + List allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses); + printIncludeStatements(allIncludeClasses); println(""); + // Find out if there are callback objects + Set callbackClasses = getCallbackClasses(methods, intDecl); + boolean callbackExist = !callbackClasses.isEmpty(); + println("using namespace std;\n"); + // Write class header + println("class " + newSkelClass + " : public " + intface); println("{"); + println("private:\n"); + // Write properties + writePropertiesCplusCallbackSkeleton(intface, callbackExist, callbackClasses); + println("public:\n"); + // Write constructor + writeConstructorCplusCallbackSkeleton(newSkelClass, intface, callbackExist, intDecl, methods); + // Write deconstructor + writeDeconstructorCplusCallbackSkeleton(newSkelClass, callbackExist, callbackClasses); + // Write methods + writeMethodCplusSkeleton(methods, intDecl, callbackClasses, true, intface); + // Write method helper + writeMethodHelperCplusCallbackSkeleton(methods, intDecl, callbackClasses); + // Write waitRequestInvokeMethod() - main loop + writeCplusCallbackWaitRequestInvokeMethod(methods, intDecl, callbackExist); + println("};"); + writeObjectIdCountInitializationCplus(newSkelClass, callbackExist); + println("#endif"); + pw.close(); + System.out.println("IoTCompiler: Generated callback skeleton class " + newSkelClass + ".hpp..."); } } /** - * generateReturnStmt() generate return statement based on methType + * generateInitializer() generate initializer based on type */ - public String generateReturnStmt(String methType) { + public String generateCplusInitializer(String type) { // Generate dummy returns for now - if (methType.equals("short")|| - methType.equals("int") || - methType.equals("long") || - methType.equals("float")|| - methType.equals("double")) { - - return "1"; - } else if ( methType.equals("String")) { + if (type.equals("short")|| + type.equals("int") || + type.equals("long") || + type.equals("float")|| + type.equals("double")) { + + return "0"; + } else if ( type.equals("String") || + type.equals("string")) { - return "\"a\""; - } else if ( methType.equals("char") || - methType.equals("byte")) { + return "\"\""; + } else if ( type.equals("char") || + type.equals("byte")) { - return "\'a\'"; - } else if ( methType.equals("boolean")) { + return "\' \'"; + } else if ( type.equals("boolean")) { - return "true"; + return "false"; } else { - return "null"; + return "NULL"; } } @@ -575,7 +4593,7 @@ public class IoTCompiler { pn = (ParseNode) parse.parse().value; } catch (Exception e) { e.printStackTrace(); - throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file); + throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file + "\n"); } return pn; @@ -583,7 +4601,7 @@ public class IoTCompiler { /**================ - * Helper functions + * Basic helper functions **================ */ boolean newline=true; @@ -602,19 +4620,26 @@ public class IoTCompiler { newline=false; } + /** * This function converts Java to C++ type for compilation */ - private String convertType(String jType) { + private String convertType(String type) { - return mapPrimitives.get(jType); + if (mapPrimitives.containsKey(type)) + return mapPrimitives.get(type); + else + return type; } + /** + * A collection of methods with print-to-file functionality + */ private void println(String str) { if (newline) { int tab = tablevel; - if (str.equals("}")) + if (str.contains("}") && !str.contains("{")) tab--; for(int i=0; i for Set, #include for Map + // e.g. #include for Set private String getNonPrimitiveCplusClass(String paramNonPrimitives) { return mapNonPrimitivesCplus.get(paramNonPrimitives); @@ -722,6 +4768,63 @@ public class IoTCompiler { } + // Generate a set of standard classes for import statements + private List getStandardJavaIntfaceImportClasses() { + + List importClasses = new ArrayList(); + // Add the standard list first + importClasses.add("java.util.List"); + importClasses.add("java.util.ArrayList"); + + return importClasses; + } + + + // Generate a set of standard classes for import statements + private List getStandardJavaImportClasses() { + + List importClasses = new ArrayList(); + // Add the standard list first + importClasses.add("java.io.IOException"); + importClasses.add("java.util.List"); + importClasses.add("java.util.ArrayList"); + importClasses.add("java.util.Arrays"); + importClasses.add("iotrmi.Java.IoTRMICall"); + importClasses.add("iotrmi.Java.IoTRMIObject"); + + return importClasses; + } + + + // Generate a set of standard classes for import statements + private List getStandardCplusIncludeClasses() { + + List importClasses = new ArrayList(); + // Add the standard list first + importClasses.add(""); + importClasses.add(""); + importClasses.add("\"IoTRMICall.hpp\""); + importClasses.add("\"IoTRMIObject.hpp\""); + + return importClasses; + } + + + // Combine all classes for import statements + private List getAllLibClasses(Collection stdLibClasses, Collection libClasses) { + + List allLibClasses = new ArrayList(stdLibClasses); + // Iterate over the list of import classes + for (String str : libClasses) { + if (!allLibClasses.contains(str)) { + allLibClasses.add(str); + } + } + return allLibClasses; + } + + + // Generate a set of classes for import statements private Set getImportClasses(Collection methods, InterfaceDecl intDecl) { @@ -740,8 +4843,148 @@ public class IoTCompiler { } + // Handle and return the correct enum declaration + // In Java, if we declare enum in Camera interface, then it becomes "Camera." + private String getEnumParamDecl(String type, InterfaceDecl intDecl) { + + // Strips off array "[]" for return type + String pureType = getSimpleArrayType(type); + // Take the inner type of generic + if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) + pureType = getTypeOfGeneric(type)[0]; + if (isEnumClass(pureType)) { + String enumType = intDecl.getInterface() + "." + type; + return enumType; + } else + return type; + } + + + // Handle and return the correct type + private String getEnumParam(String type, String param, int i) { + + // Strips off array "[]" for return type + String pureType = getSimpleArrayType(type); + // Take the inner type of generic + if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) + pureType = getTypeOfGeneric(type)[0]; + if (isEnumClass(pureType)) { + String enumParam = "paramEnum" + i; + return enumParam; + } else + return param; + } + + + // Handle and return the correct enum declaration translate into int[] + private String getEnumType(String type) { + + // Strips off array "[]" for return type + String pureType = getSimpleArrayType(type); + // Take the inner type of generic + if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) + pureType = getGenericType(type); + if (isEnumClass(pureType)) { + String enumType = "int[]"; + return enumType; + } else + return type; + } + + // Handle and return the correct enum declaration translate into int* for C + private String getEnumCplusClsType(String type) { + + // Strips off array "[]" for return type + String pureType = getSimpleArrayType(type); + // Take the inner type of generic + if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) + pureType = getGenericType(type); + if (isEnumClass(pureType)) { + String enumType = "int*"; + return enumType; + } else + return type; + } + + + // Handle and return the correct struct declaration + private String getStructType(String type) { + + // Strips off array "[]" for return type + String pureType = getSimpleArrayType(type); + // Take the inner type of generic + if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) + pureType = getGenericType(type); + if (isStructClass(pureType)) { + String structType = "int"; + return structType; + } else + return type; + } + + + // Check if this an enum declaration + private boolean isEnumClass(String type) { + + // Just iterate over the set of interfaces + for (String intface : mapIntfacePTH.keySet()) { + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface); + Set setEnumDecl = enumDecl.getEnumDeclarations(); + if (setEnumDecl.contains(type)) + return true; + } + return false; + } + + + // Check if this an struct declaration + private boolean isStructClass(String type) { + + // Just iterate over the set of interfaces + for (String intface : mapIntfacePTH.keySet()) { + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface); + List listStructDecl = structDecl.getStructTypes(); + if (listStructDecl.contains(type)) + return true; + } + return false; + } + + + // Return a struct declaration + private StructDecl getStructDecl(String type) { + + // Just iterate over the set of interfaces + for (String intface : mapIntfacePTH.keySet()) { + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface); + List listStructDecl = structDecl.getStructTypes(); + if (listStructDecl.contains(type)) + return structDecl; + } + return null; + } + + + // Return number of members (-1 if not found) + private int getNumOfMembers(String type) { + + // Just iterate over the set of interfaces + for (String intface : mapIntfacePTH.keySet()) { + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface); + List listStructDecl = structDecl.getStructTypes(); + if (listStructDecl.contains(type)) + return structDecl.getNumOfMembers(type); + } + return -1; + } + + // Generate a set of classes for include statements - private Set getIncludeClasses(Collection methods, InterfaceDecl intDecl) { + private Set getIncludeClasses(Collection methods, InterfaceDecl intDecl, String intface, boolean needExchange) { Set includeClasses = new HashSet(); for (String method : methods) { @@ -755,7 +4998,18 @@ public class IoTCompiler { if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) { includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">"); } else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) { - includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\""); + // For original interface, we need it exchanged... not for stub interfaces + if (needExchange) { + includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\""); + includeClasses.add("\"" + exchangeParamType(simpleType) + "_CallbackStub.hpp\""); + } else { + includeClasses.add("\"" + simpleType + ".hpp\""); + includeClasses.add("\"" + simpleType + "_CallbackSkeleton.hpp\""); + } + } else if (getParamCategory(getSimpleArrayType(simpleType)) == ParamCategory.ENUM) { + includeClasses.add("\"" + simpleType + ".hpp\""); + } else if (getParamCategory(getSimpleArrayType(simpleType)) == ParamCategory.STRUCT) { + includeClasses.add("\"" + simpleType + ".hpp\""); } else if (param.contains("[]")) { // Check if this is array for C++; translate into vector includeClasses.add(""); @@ -766,7 +5020,34 @@ public class IoTCompiler { } - private void printImportStatements(Set importClasses) { + // Generate a set of callback classes + private Set getCallbackClasses(Collection methods, InterfaceDecl intDecl) { + + Set callbackClasses = new HashSet(); + for (String method : methods) { + + List methPrmTypes = intDecl.getMethodParamTypes(method); + List methParams = intDecl.getMethodParams(method); + for (int i = 0; i < methPrmTypes.size(); i++) { + + String type = methPrmTypes.get(i); + if (getParamCategory(type) == ParamCategory.USERDEFINED) { + callbackClasses.add(type); + } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) { + // Can be a List<...> of callback objects ... + String genericType = getTypeOfGeneric(type)[0]; + if (getParamCategory(type) == ParamCategory.USERDEFINED) { + callbackClasses.add(type); + } + } + } + } + return callbackClasses; + } + + + // Print import statements into file + private void printImportStatements(Collection importClasses) { for(String cls : importClasses) { println("import " + cls + ";"); @@ -774,7 +5055,8 @@ public class IoTCompiler { } - private void printIncludeStatements(Set includeClasses) { + // Print include statements into file + private void printIncludeStatements(Collection includeClasses) { for(String cls : includeClasses) { println("#include " + cls); @@ -793,6 +5075,43 @@ public class IoTCompiler { } + // Gets generic type inside "<" and ">" + private String getGenericType(String type) { + + // Handle <, >, and , for 2-type generic/template + if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) { + String[] substr = type.split("<")[1].split(">")[0].split(","); + return substr[0]; + } else + return type; + } + + + // This helper function strips off array declaration, e.g. int[] becomes int + private String getSimpleArrayType(String type) { + + // Handle [ for array declaration + String substr = type; + if (type.contains("[]")) { + substr = type.split("\\[\\]")[0]; + } + return substr; + } + + + // This helper function strips off array declaration, e.g. D[] becomes D + private String getSimpleIdentifier(String ident) { + + // Handle [ for array declaration + String substr = ident; + if (ident.contains("[]")) { + substr = ident.split("\\[\\]")[0]; + } + return substr; + } + + + // Checks and gets type in C++ private String checkAndGetCplusType(String paramType) { if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) { @@ -803,17 +5122,22 @@ public class IoTCompiler { if (paramType.contains("<") && paramType.contains(">")) { String genericClass = getSimpleType(paramType); - String[] genericType = getTypeOfGeneric(paramType); + String genericType = getGenericType(paramType); String cplusTemplate = null; - if (genericType.length == 1) // Generic/template with one type - cplusTemplate = getNonPrimitiveCplusClass(genericClass) + - "<" + convertType(genericType[0]) + ">"; - else // Generic/template with two types - cplusTemplate = getNonPrimitiveCplusClass(genericClass) + - "<" + convertType(genericType[0]) + "," + convertType(genericType[1]) + ">"; + cplusTemplate = getNonPrimitiveCplusClass(genericClass); + if(getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED) { + cplusTemplate = cplusTemplate + "<" + genericType + "*>"; + } else { + cplusTemplate = cplusTemplate + "<" + convertType(genericType) + ">"; + } return cplusTemplate; } else return getNonPrimitiveCplusClass(paramType); + } else if(paramType.contains("[]")) { // Array type (used for return type only) + String cArray = "vector<" + convertType(getSimpleArrayType(paramType)) + ">"; + return cArray; + } else if(getParamCategory(paramType) == ParamCategory.USERDEFINED) { + return paramType + "*"; } else // Just return it as is if it's not non-primitives return paramType; @@ -834,19 +5158,156 @@ public class IoTCompiler { return paramComplete; } + + + // Detect array declaration, e.g. int A[], + // then generate "int A[]" in C++ as "vector A" + // This method just returns the type + private String checkAndGetCplusArrayType(String paramType) { + + String paramTypeRet = null; + // Check for array declaration + if (paramType.contains("[]")) { + String type = paramType.split("\\[\\]")[0]; + paramTypeRet = checkAndGetCplusType(type) + "[]"; + } else if (paramType.contains("vector")) { + // Just return it as is if it's not an array + String type = paramType.split("<")[1].split(">")[0]; + paramTypeRet = checkAndGetCplusType(type) + "[]"; + } else + paramTypeRet = paramType; + + return paramTypeRet; + } + + + // Detect array declaration, e.g. int A[], + // then generate "int A[]" in C++ as "vector A" + // This method just returns the type + private String checkAndGetCplusArrayType(String paramType, String param) { + String paramTypeRet = null; + // Check for array declaration + if (param.contains("[]")) { + paramTypeRet = checkAndGetCplusType(paramType) + "[]"; + } else if (paramType.contains("vector")) { + // Just return it as is if it's not an array + String type = paramType.split("<")[1].split(">")[0]; + paramTypeRet = checkAndGetCplusType(type) + "[]"; + } else + paramTypeRet = paramType; + + return paramTypeRet; + } + + + // Return the class type for class resolution (for return value) + // - Check and return C++ array class, e.g. int A[] into int* + // - Check and return C++ vector class, e.g. List A into vector + private String checkAndGetCplusRetClsType(String paramType) { + + String paramTypeRet = null; + // Check for array declaration + if (paramType.contains("[]")) { + String type = paramType.split("\\[\\]")[0]; + paramTypeRet = getSimpleArrayType(type) + "*"; + } else if (paramType.contains("<") && paramType.contains(">")) { + // Just return it as is if it's not an array + String type = paramType.split("<")[1].split(">")[0]; + paramTypeRet = "vector<" + getGenericType(type) + ">"; + } else + paramTypeRet = paramType; + + return paramTypeRet; + } + + + // Return the class type for class resolution (for method arguments) + // - Check and return C++ array class, e.g. int A[] into int* + // - Check and return C++ vector class, e.g. List A into vector + private String checkAndGetCplusArgClsType(String paramType, String param) { + + String paramTypeRet = getEnumCplusClsType(paramType); + if (!paramTypeRet.equals(paramType)) + // Just return if it is an enum type + // Type will still be the same if it's not an enum type + return paramTypeRet; + + // Check for array declaration + if (param.contains("[]")) { + paramTypeRet = getSimpleArrayType(paramType) + "*"; + } else if (paramType.contains("<") && paramType.contains(">")) { + // Just return it as is if it's not an array + String type = paramType.split("<")[1].split(">")[0]; + paramTypeRet = "vector<" + getGenericType(type) + ">"; + } else + paramTypeRet = paramType; + + return paramTypeRet; + } + + + // Detect array declaration, e.g. int A[], + // then generate type "int[]" + private String checkAndGetArray(String paramType, String param) { + + String paramTypeRet = null; + // Check for array declaration + if (param.contains("[]")) { + paramTypeRet = paramType + "[]"; + } else + // Just return it as is if it's not an array + paramTypeRet = paramType; + + return paramTypeRet; + } + + + // Is array or list? + private boolean isArrayOrList(String paramType, String param) { + + // Check for array declaration + if (isArray(param)) + return true; + else if (isList(paramType)) + return true; + else + return false; + } + + + // Is array? + // For return type we use retType as input parameter + private boolean isArray(String param) { + + // Check for array declaration + if (param.contains("[]")) + return true; + else + return false; + } - // Get simple types, e.g. HashSet for HashSet<...> - // Basically strip off the "<...>" - private String checkAndGetParamClass(String paramType, boolean needPtr) { + + // Is list? + private boolean isList(String paramType) { + + // Check for array declaration + if (paramType.contains("List")) + return true; + else + return false; + } + + + // Get the right type for a callback object + private String checkAndGetParamClass(String paramType) { // Check if this is generics if(getParamCategory(paramType) == ParamCategory.USERDEFINED) { - // If true then return with pointer (C++) - if (needPtr) - return exchangeParamType(paramType) + "*"; - else // Java, so no pointer needed - return exchangeParamType(paramType); + return exchangeParamType(paramType); + } else if (isList(paramType) && + (getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED)) { + return "List<" + exchangeParamType(getGenericType(paramType)) + ">"; } else return paramType; } @@ -870,7 +5331,7 @@ public class IoTCompiler { } else { throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() + ". Only one new interface can be declared if the object " + intface + - " needs to be passed in as an input parameter!"); + " needs to be passed in as an input parameter!\n"); } } else { // NULL value - this means policy files missing @@ -879,7 +5340,7 @@ public class IoTCompiler { " If this is an array please type the brackets after the variable name," + " e.g. \"String str[]\", not \"String[] str\"." + " If this is a Collections (Java) / STL (C++) type, this compiler only" + - " supports List/ArrayList (Java) or list (C++)."); + " supports List/ArrayList (Java) or list (C++).\n"); } } @@ -905,7 +5366,7 @@ public class IoTCompiler { ParseNode pnReq = IoTCompiler.parseFile(args[i+1]); // Get interface name String intface = ParseTreeHandler.getOrigIntface(pnPol); - comp.setParseTree(intface, pnPol, pnReq); + comp.setDataStructures(intface, pnPol, pnReq); comp.getMethodsForIntface(intface); i = i + 2; // 1) Check if this is the last option before "-java" or "-cplus" @@ -916,33 +5377,53 @@ public class IoTCompiler { // Generate everything if we don't see "-java" or "-cplus" if (i == args.length) { + comp.generateEnumJava(); + comp.generateStructJava(); comp.generateJavaLocalInterfaces(); comp.generateJavaInterfaces(); comp.generateJavaStubClasses(); + comp.generateJavaCallbackStubClasses(); + comp.generateJavaSkeletonClass(); + comp.generateJavaCallbackSkeletonClass(); + comp.generateEnumCplus(); + comp.generateStructCplus(); comp.generateCplusLocalInterfaces(); comp.generateCPlusInterfaces(); comp.generateCPlusStubClasses(); + comp.generateCPlusCallbackStubClasses(); + comp.generateCplusSkeletonClass(); + comp.generateCplusCallbackSkeletonClass(); } else { // Check other options while(i < args.length) { // Error checking if (!args[i].equals("-java") && !args[i].equals("-cplus")) { - throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i]); + throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i] + "\n"); } else { if (i + 1 < args.length) { comp.setDirectory(args[i+1]); } else - throw new Error("IoTCompiler: ERROR - please provide after option: " + args[i]); + throw new Error("IoTCompiler: ERROR - please provide after option: " + args[i] + "\n"); if (args[i].equals("-java")) { + comp.generateEnumJava(); + comp.generateStructJava(); comp.generateJavaLocalInterfaces(); comp.generateJavaInterfaces(); comp.generateJavaStubClasses(); + comp.generateJavaCallbackStubClasses(); + comp.generateJavaSkeletonClass(); + comp.generateJavaCallbackSkeletonClass(); } else { + comp.generateEnumCplus(); + comp.generateStructCplus(); comp.generateCplusLocalInterfaces(); comp.generateCPlusInterfaces(); comp.generateCPlusStubClasses(); + comp.generateCPlusCallbackStubClasses(); + comp.generateCplusSkeletonClass(); + comp.generateCplusCallbackSkeletonClass(); } } i = i + 2; @@ -951,11 +5432,9 @@ public class IoTCompiler { } else { // Need to at least have exactly 2 parameters, i.e. main policy file and requires file IoTCompiler.printUsage(); - throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!"); + throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!\n"); } } } - -