3 import java_cup.runtime.ComplexSymbolFactory;
4 import java_cup.runtime.ScannerBuffer;
6 import java.util.Arrays;
7 import java.util.ArrayList;
8 import java.util.Collection;
9 import java.util.Collections;
10 import java.util.HashMap;
11 import java.util.HashSet;
12 import java.util.Iterator;
13 import java.util.List;
17 import iotpolicy.parser.Lexer;
18 import iotpolicy.parser.Parser;
19 import iotpolicy.tree.ParseNode;
20 import iotpolicy.tree.ParseNodeVector;
21 import iotpolicy.tree.ParseTreeHandler;
22 import iotpolicy.tree.Declaration;
23 import iotpolicy.tree.DeclarationHandler;
24 import iotpolicy.tree.CapabilityDecl;
25 import iotpolicy.tree.InterfaceDecl;
26 import iotpolicy.tree.RequiresDecl;
27 import iotpolicy.tree.EnumDecl;
28 import iotpolicy.tree.StructDecl;
30 import iotrmi.Java.IoTRMITypes;
33 /** Class IoTCompiler is the main interface/stub compiler for
34 * files generation. This class calls helper classes
35 * such as Parser, Lexer, InterfaceDecl, CapabilityDecl,
36 * RequiresDecl, ParseTreeHandler, etc.
38 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
42 public class IoTCompiler {
47 // Maps multiple interfaces to multiple objects of ParseTreeHandler
48 private Map<String,ParseTreeHandler> mapIntfacePTH;
49 private Map<String,DeclarationHandler> mapIntDeclHand;
50 private Map<String,Map<String,Set<String>>> mapInt2NewInts;
51 private Map<String,String> mapInt2NewIntName;
52 // Data structure to store our types (primitives and non-primitives) for compilation
53 private Map<String,String> mapPrimitives;
54 private Map<String,String> mapNonPrimitivesJava;
55 private Map<String,String> mapNonPrimitivesCplus;
56 // Other data structures
57 private Map<String,Integer> mapIntfaceObjId; // Maps interface name to object Id
58 private Map<String,Integer> mapNewIntfaceObjId; // Maps new interface name to its object Id (keep track of stubs)
59 private PrintWriter pw;
61 private String subdir;
62 private Map<String,Integer> mapPortCount; // Counter for ports
63 private static int portCount = 0;
64 private String mainClass;
70 private final static String OUTPUT_DIRECTORY = "output_files";
72 private enum ParamCategory {
74 PRIMITIVES, // All the primitive types, e.g. byte, short, int, long, etc.
75 NONPRIMITIVES, // Non-primitive types, e.g. Set, Map, List, etc.
77 STRUCT, // Struct type
78 USERDEFINED // Assumed as driver classes
85 public IoTCompiler() {
87 mapIntfacePTH = new HashMap<String,ParseTreeHandler>();
88 mapIntDeclHand = new HashMap<String,DeclarationHandler>();
89 mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
90 mapInt2NewIntName = new HashMap<String,String>();
91 mapIntfaceObjId = new HashMap<String,Integer>();
92 mapNewIntfaceObjId = new HashMap<String,Integer>();
93 mapPrimitives = new HashMap<String,String>();
94 arraysToMap(mapPrimitives, IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus);
95 mapNonPrimitivesJava = new HashMap<String,String>();
96 arraysToMap(mapNonPrimitivesJava, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitiveJavaLibs);
97 mapNonPrimitivesCplus = new HashMap<String,String>();
98 arraysToMap(mapNonPrimitivesCplus, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus);
99 mapPortCount = new HashMap<String,Integer>();
101 dir = OUTPUT_DIRECTORY;
108 * setDataStructures() sets parse tree and other data structures based on policy files.
110 * It also generates parse tree (ParseTreeHandler) and
111 * copies useful information from parse tree into
112 * InterfaceDecl, CapabilityDecl, and RequiresDecl
114 * Additionally, the data structure handles are
115 * returned from tree-parsing for further process.
117 public void setDataStructures(String origInt, ParseNode pnPol, ParseNode pnReq) {
119 ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq);
120 DeclarationHandler decHandler = new DeclarationHandler();
121 // Process ParseNode and generate Declaration objects
123 ptHandler.processInterfaceDecl();
124 InterfaceDecl intDecl = ptHandler.getInterfaceDecl();
125 decHandler.addInterfaceDecl(origInt, intDecl);
127 ptHandler.processCapabilityDecl();
128 CapabilityDecl capDecl = ptHandler.getCapabilityDecl();
129 decHandler.addCapabilityDecl(origInt, capDecl);
131 ptHandler.processRequiresDecl();
132 RequiresDecl reqDecl = ptHandler.getRequiresDecl();
133 decHandler.addRequiresDecl(origInt, reqDecl);
135 ptHandler.processEnumDecl();
136 EnumDecl enumDecl = ptHandler.getEnumDecl();
137 decHandler.addEnumDecl(origInt, enumDecl);
139 ptHandler.processStructDecl();
140 StructDecl structDecl = ptHandler.getStructDecl();
141 decHandler.addStructDecl(origInt, structDecl);
143 mapIntfacePTH.put(origInt, ptHandler);
144 mapIntDeclHand.put(origInt, decHandler);
145 // Set object Id counter to 0 for each interface
146 mapIntfaceObjId.put(origInt, new Integer(0));
151 * getMethodsForIntface() reads for methods in the data structure
153 * It is going to give list of methods for a certain interface
154 * based on the declaration of capabilities.
156 public void getMethodsForIntface(String origInt) {
158 ParseTreeHandler ptHandler = mapIntfacePTH.get(origInt);
159 Map<String,Set<String>> mapNewIntMethods = new HashMap<String,Set<String>>();
160 // Get set of new interfaces, e.g. CameraWithCaptureAndData
161 // Generate this new interface with all the methods it needs
162 // from different capabilities it declares
163 DeclarationHandler decHandler = mapIntDeclHand.get(origInt);
164 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(origInt);
165 Set<String> setIntfaces = reqDecl.getInterfaces();
166 for (String strInt : setIntfaces) {
168 // Initialize a set of methods
169 Set<String> setMethods = new HashSet<String>();
170 // Get list of capabilities, e.g. ImageCapture, VideoRecording, etc.
171 List<String> listCapab = reqDecl.getCapabList(strInt);
172 for (String strCap : listCapab) {
174 // Get list of methods for each capability
175 CapabilityDecl capDecl = (CapabilityDecl) decHandler.getCapabilityDecl(origInt);
176 List<String> listCapabMeth = capDecl.getMethods(strCap);
177 for (String strMeth : listCapabMeth) {
179 // Add methods into setMethods
180 // This is to also handle redundancies (say two capabilities
181 // share the same methods)
182 setMethods.add(strMeth);
185 // Add interface and methods information into map
186 mapNewIntMethods.put(strInt, setMethods);
187 // Map new interface method name to the original interface
188 // TODO: perhaps need to check in the future if we have more than 1 stub interface for one original interface
189 mapInt2NewIntName.put(origInt, strInt);
190 if (mainClass == null) // Take the first class as the main class (whichever is placed first in the order of compilation files)
193 // Map the map of interface-methods to the original interface
194 mapInt2NewInts.put(origInt, mapNewIntMethods);
203 * HELPER: writeMethodJavaLocalInterface() writes the method of the local interface
205 private void writeMethodJavaLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
207 for (String method : methods) {
209 List<String> methParams = intDecl.getMethodParams(method);
210 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
211 print("public " + intDecl.getMethodType(method) + " " +
212 intDecl.getMethodId(method) + "(");
213 for (int i = 0; i < methParams.size(); i++) {
214 // Check for params with driver class types and exchange it
215 // with its remote interface
216 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
217 print(paramType + " " + methParams.get(i));
218 // Check if this is the last element (don't print a comma)
219 if (i != methParams.size() - 1) {
229 * HELPER: writeMethodJavaInterface() writes the method of the interface
231 private void writeMethodJavaInterface(Collection<String> methods, InterfaceDecl intDecl) {
233 for (String method : methods) {
235 List<String> methParams = intDecl.getMethodParams(method);
236 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
237 print("public " + intDecl.getMethodType(method) + " " +
238 intDecl.getMethodId(method) + "(");
239 for (int i = 0; i < methParams.size(); i++) {
240 // Check for params with driver class types and exchange it
241 // with its remote interface
242 String paramType = methPrmTypes.get(i);
243 print(paramType + " " + methParams.get(i));
244 // Check if this is the last element (don't print a comma)
245 if (i != methParams.size() - 1) {
255 * HELPER: generateEnumJava() writes the enumeration declaration
257 private void generateEnumJava() throws IOException {
259 // Create a new directory
260 createDirectory(dir);
261 for (String intface : mapIntfacePTH.keySet()) {
262 // Get the right EnumDecl
263 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
264 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
265 Set<String> enumTypes = enumDecl.getEnumDeclarations();
266 // Iterate over enum declarations
267 for (String enType : enumTypes) {
268 // Open a new file to write into
269 FileWriter fw = new FileWriter(dir + "/" + enType + ".java");
270 pw = new PrintWriter(new BufferedWriter(fw));
271 println("public enum " + enType + " {");
272 List<String> enumMembers = enumDecl.getMembers(enType);
273 for (int i = 0; i < enumMembers.size(); i++) {
275 String member = enumMembers.get(i);
277 // Check if this is the last element (don't print a comma)
278 if (i != enumMembers.size() - 1)
285 System.out.println("IoTCompiler: Generated enum class " + enType + ".java...");
292 * HELPER: generateStructJava() writes the struct declaration
294 private void generateStructJava() throws IOException {
296 // Create a new directory
297 createDirectory(dir);
298 for (String intface : mapIntfacePTH.keySet()) {
299 // Get the right StructDecl
300 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
301 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
302 List<String> structTypes = structDecl.getStructTypes();
303 // Iterate over enum declarations
304 for (String stType : structTypes) {
305 // Open a new file to write into
306 FileWriter fw = new FileWriter(dir + "/" + stType + ".java");
307 pw = new PrintWriter(new BufferedWriter(fw));
308 println("public class " + stType + " {");
309 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
310 List<String> structMembers = structDecl.getMembers(stType);
311 for (int i = 0; i < structMembers.size(); i++) {
313 String memberType = structMemberTypes.get(i);
314 String member = structMembers.get(i);
315 println("public static " + memberType + " " + member + ";");
319 System.out.println("IoTCompiler: Generated struct class " + stType + ".java...");
326 * generateJavaLocalInterface() writes the local interface and provides type-checking.
328 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
329 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
330 * The local interface has to be the input parameter for the stub and the stub
331 * interface has to be the input parameter for the local class.
333 public void generateJavaLocalInterfaces() throws IOException {
335 // Create a new directory
336 createDirectory(dir);
337 for (String intface : mapIntfacePTH.keySet()) {
338 // Open a new file to write into
339 FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
340 pw = new PrintWriter(new BufferedWriter(fw));
341 // Pass in set of methods and get import classes
342 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
343 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
344 List<String> methods = intDecl.getMethods();
345 Set<String> importClasses = getImportClasses(methods, intDecl);
346 List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
347 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
348 printImportStatements(allImportClasses);
349 // Write interface header
351 println("public interface " + intface + " {");
353 writeMethodJavaLocalInterface(methods, intDecl);
356 System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
362 * HELPER: updateIntfaceObjIdMap() updates the mapping between new interface and object Id
364 private void updateIntfaceObjIdMap(String intface, String newIntface) {
366 Integer objId = mapIntfaceObjId.get(intface);
367 mapNewIntfaceObjId.put(newIntface, objId);
368 mapIntfaceObjId.put(intface, objId++);
373 * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
375 public void generateJavaInterfaces() throws IOException {
377 // Create a new directory
378 String path = createDirectories(dir, subdir);
379 for (String intface : mapIntfacePTH.keySet()) {
381 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
382 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
384 // Open a new file to write into
385 String newIntface = intMeth.getKey();
386 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
387 pw = new PrintWriter(new BufferedWriter(fw));
388 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
389 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
390 // Pass in set of methods and get import classes
391 Set<String> methods = intMeth.getValue();
392 Set<String> importClasses = getImportClasses(methods, intDecl);
393 List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
394 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
395 printImportStatements(allImportClasses);
396 // Write interface header
398 println("public interface " + newIntface + " {\n");
399 updateIntfaceObjIdMap(intface, newIntface);
401 writeMethodJavaInterface(methods, intDecl);
404 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
411 * HELPER: writePropertiesJavaPermission() writes the permission in properties
413 private void writePropertiesJavaPermission(String intface, InterfaceDecl intDecl) {
415 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
416 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
417 String newIntface = intMeth.getKey();
418 int newObjectId = getNewIntfaceObjectId(newIntface);
419 println("private final static int object" + newObjectId + "Id = " +
420 newObjectId + ";\t//" + newIntface);
421 Set<String> methodIds = intMeth.getValue();
422 print("private static Integer[] object" + newObjectId + "Permission = { ");
424 for (String methodId : methodIds) {
425 int methodNumId = intDecl.getMethodNumId(methodId);
426 print(Integer.toString(methodNumId));
427 // Check if this is the last element (don't print a comma)
428 if (i != methodIds.size() - 1) {
434 println("private static List<Integer> set" + newObjectId + "Allowed;");
440 * HELPER: writePropertiesJavaStub() writes the properties of the stub class
442 private void writePropertiesJavaStub(String intface, Set<String> methods, InterfaceDecl intDecl) {
445 Integer objId = mapIntfaceObjId.get(intface);
446 println("private int objectId = " + objId + ";");
447 println("private IoTRMIComm rmiComm;");
448 // Write the list of AtomicBoolean variables
449 println("// Synchronization variables");
450 for (String method : methods) {
451 // Generate AtomicBooleans for methods that have return values
452 String returnType = intDecl.getMethodType(method);
453 int methodNumId = intDecl.getMethodNumId(method);
454 if (!returnType.equals("void")) {
455 println("private AtomicBoolean retValueReceived" + methodNumId + " = new AtomicBoolean(false);");
463 * HELPER: writeConstructorJavaPermission() writes the permission in constructor
465 private void writeConstructorJavaPermission(String intface) {
467 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
468 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
469 String newIntface = intMeth.getKey();
470 int newObjectId = getNewIntfaceObjectId(newIntface);
471 println("set" + newObjectId + "Allowed = new ArrayList<Integer>(Arrays.asList(object" + newObjectId +"Permission));");
477 * HELPER: writeConstructorJavaStub() writes the constructor of the stub class
479 private void writeConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
481 println("public " + newStubClass + "(int _localPortSend, int _localPortRecv, int _portSend, int _portRecv, String _skeletonAddress, int _rev) throws Exception {");
482 println("if (_localPortSend != 0 && _localPortRecv != 0) {");
483 println("rmiComm = new IoTRMICommClient(_localPortSend, _localPortRecv, _portSend, _portRecv, _skeletonAddress, _rev);");
486 println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev);");
488 // Register the AtomicBoolean variables
489 for (String method : methods) {
490 // Generate AtomicBooleans for methods that have return values
491 String returnType = intDecl.getMethodType(method);
492 int methodNumId = intDecl.getMethodNumId(method);
493 if (!returnType.equals("void")) {
494 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
497 println("IoTRMIUtil.mapStub.put(objectId, this);");
503 * HELPER: writeCallbackConstructorJavaStub() writes the callback constructor of the stub class
505 private void writeCallbackConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
507 println("public " + newStubClass + "(IoTRMIComm _rmiComm, int _objectId) throws Exception {");
508 println("rmiComm = _rmiComm;");
509 println("objectId = _objectId;");
510 // Register the AtomicBoolean variables
511 for (String method : methods) {
512 // Generate AtomicBooleans for methods that have return values
513 String returnType = intDecl.getMethodType(method);
514 int methodNumId = intDecl.getMethodNumId(method);
515 if (!returnType.equals("void")) {
516 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
524 * HELPER: writeJavaMethodCallbackPermission() writes permission checks in stub for callbacks
526 private void writeJavaMethodCallbackPermission(String intface) {
528 println("int methodId = IoTRMIObject.getMethodId(method);");
529 // Get all the different stubs
530 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
531 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
532 String newIntface = intMeth.getKey();
533 int newObjectId = getNewIntfaceObjectId(newIntface);
534 println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
535 println("throw new Error(\"Callback object for " + intface + " is not allowed to access method: \" + methodId);");
542 * HELPER: writeJavaInitCallbackPermission() writes the permission for callback
544 private void writeJavaInitCallbackPermission(String intface, InterfaceDecl intDecl, boolean callbackExist) {
547 String method = "___initCallBack()";
548 int methodNumId = intDecl.getHelperMethodNumId(method);
549 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
550 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
551 String newIntface = intMeth.getKey();
552 int newObjectId = getNewIntfaceObjectId(newIntface);
553 println("set" + newObjectId + "Allowed.add(" + methodNumId + ");");
560 * HELPER: getPortCount() gets port count for different stubs and skeletons
562 private int getPortCount(String intface) {
564 if (!mapPortCount.containsKey(intface))
565 mapPortCount.put(intface, portCount++);
566 return mapPortCount.get(intface);
571 * HELPER: checkAndWriteEnumTypeJavaStub() writes the enum type (convert from enum to int)
573 private void checkAndWriteEnumTypeJavaStub(List<String> methParams, List<String> methPrmTypes) {
575 // Iterate and find enum declarations
576 for (int i = 0; i < methParams.size(); i++) {
577 String paramType = methPrmTypes.get(i);
578 String param = methParams.get(i);
579 String simpleType = getGenericType(paramType);
580 if (isEnumClass(simpleType)) {
581 // Check if this is enum type
582 if (isArray(param)) { // An array
583 println("int len" + i + " = " + getSimpleIdentifier(param) + ".length;");
584 println("int paramEnum" + i + "[] = new int[len" + i + "];");
585 println("for (int i = 0; i < len" + i + "; i++) {");
586 println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + "[i].ordinal();");
588 } else if (isList(paramType)) { // A list
589 println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
590 println("int paramEnum" + i + "[] = new int[len" + i + "];");
591 println("for (int i = 0; i < len" + i + "; i++) {");
592 println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + ".get(i).ordinal();");
594 } else { // Just one element
595 println("int paramEnum" + i + "[] = new int[1];");
596 println("paramEnum" + i + "[0] = " + param + ".ordinal();");
604 * HELPER: checkAndWriteEnumRetTypeJavaStub() writes the enum return type (convert from enum to int)
606 private void checkAndWriteEnumRetTypeJavaStub(String retType, String method, InterfaceDecl intDecl) {
608 // Write the wait-for-return-value part
609 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
610 // Strips off array "[]" for return type
611 String pureType = getSimpleArrayType(getGenericType(retType));
612 // Take the inner type of generic
613 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
614 pureType = getGenericType(retType);
615 if (isEnumClass(pureType)) {
616 // Check if this is enum type
618 println("int[] retEnum = (int[]) retObj;");
619 println(pureType + "[] enumVals = " + pureType + ".values();");
620 if (isArray(retType)) { // An array
621 println("int retLen = retEnum.length;");
622 println(pureType + "[] enumRetVal = new " + pureType + "[retLen];");
623 println("for (int i = 0; i < retLen; i++) {");
624 println("enumRetVal[i] = enumVals[retEnum[i]];");
626 } else if (isList(retType)) { // A list
627 println("int retLen = retEnum.length;");
628 println("List<" + pureType + "> enumRetVal = new ArrayList<" + pureType + ">();");
629 println("for (int i = 0; i < retLen; i++) {");
630 println("enumRetVal.add(enumVals[retEnum[i]]);");
632 } else { // Just one element
633 println(pureType + " enumRetVal = enumVals[retEnum[0]];");
635 println("return enumRetVal;");
641 * HELPER: checkAndWriteStructSetupJavaStub() writes the struct type setup
643 private void checkAndWriteStructSetupJavaStub(List<String> methParams, List<String> methPrmTypes,
644 InterfaceDecl intDecl, String method) {
646 // Iterate and find struct declarations
647 for (int i = 0; i < methParams.size(); i++) {
648 String paramType = methPrmTypes.get(i);
649 String param = methParams.get(i);
650 String simpleType = getGenericType(paramType);
651 if (isStructClass(simpleType)) {
652 // Check if this is enum type
653 int methodNumId = intDecl.getMethodNumId(method);
654 String helperMethod = methodNumId + "struct" + i;
655 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
656 println("Class<?>[] paramClsStruct" + i + " = new Class<?>[] { int.class };");
657 if (isArray(param)) { // An array
658 println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".length };");
659 } else if (isList(paramType)) { // A list
660 println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".size() };");
661 } else { // Just one element
662 println("Object[] paramObjStruct" + i + " = new Object[] { new Integer(1) };");
664 println("rmiComm.remoteCall(objectId, methodIdStruct" + i +
665 ", paramClsStruct" + i + ", paramObjStruct" + i + ");\n");
672 * HELPER: isStructPresent() checks presence of struct
674 private boolean isStructPresent(List<String> methParams, List<String> methPrmTypes) {
676 // Iterate and find enum declarations
677 for (int i = 0; i < methParams.size(); i++) {
678 String paramType = methPrmTypes.get(i);
679 String param = methParams.get(i);
680 String simpleType = getGenericType(paramType);
681 if (isStructClass(simpleType))
689 * HELPER: writeLengthStructParamClassJavaStub() writes lengths of parameters
691 private void writeLengthStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes) {
693 // Iterate and find struct declarations - count number of params
694 for (int i = 0; i < methParams.size(); i++) {
695 String paramType = methPrmTypes.get(i);
696 String param = methParams.get(i);
697 String simpleType = getGenericType(paramType);
698 if (isStructClass(simpleType)) {
699 int members = getNumOfMembers(simpleType);
700 if (isArray(param)) { // An array
701 String structLen = getSimpleArrayType(param) + ".length";
702 print(members + "*" + structLen);
703 } else if (isList(paramType)) { // A list
704 String structLen = getSimpleArrayType(param) + ".size()";
705 print(members + "*" + structLen);
707 print(Integer.toString(members));
710 if (i != methParams.size() - 1) {
718 * HELPER: writeStructMembersJavaStub() writes parameters of struct
720 private void writeStructMembersJavaStub(String simpleType, String paramType, String param) {
722 // Get the struct declaration for this struct and generate initialization code
723 StructDecl structDecl = getStructDecl(simpleType);
724 List<String> memTypes = structDecl.getMemberTypes(simpleType);
725 List<String> members = structDecl.getMembers(simpleType);
726 if (isArray(param)) { // An array
727 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".length; i++) {");
728 for (int i = 0; i < members.size(); i++) {
729 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
730 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
731 print("paramObj[pos++] = " + getSimpleIdentifier(param) + "[i].");
732 print(getSimpleIdentifier(members.get(i)));
736 } else if (isList(paramType)) { // A list
737 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
738 for (int i = 0; i < members.size(); i++) {
739 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
740 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
741 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".get(i).");
742 print(getSimpleIdentifier(members.get(i)));
746 } else { // Just one struct element
747 for (int i = 0; i < members.size(); i++) {
748 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
749 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
750 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".");
751 print(getSimpleIdentifier(members.get(i)));
759 * HELPER: writeStructParamClassJavaStub() writes parameters if struct is present
761 private void writeStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
763 print("int paramLen = ");
764 writeLengthStructParamClassJavaStub(methParams, methPrmTypes);
766 println("Object[] paramObj = new Object[paramLen];");
767 println("Class<?>[] paramCls = new Class<?>[paramLen];");
768 println("int pos = 0;");
769 // Iterate again over the parameters
770 for (int i = 0; i < methParams.size(); i++) {
771 String paramType = methPrmTypes.get(i);
772 String param = methParams.get(i);
773 String simpleType = getGenericType(paramType);
774 if (isStructClass(simpleType)) {
775 writeStructMembersJavaStub(simpleType, paramType, param);
776 } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
777 println("paramCls[pos] = int[].class;");
778 println("paramObj[pos++] = objIdSent" + i + ";");
780 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
781 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
782 print("paramObj[pos++] = ");
783 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
792 * HELPER: writeStructRetMembersJavaStub() writes parameters of struct for return statement
794 private void writeStructRetMembersJavaStub(String simpleType, String retType) {
796 // Get the struct declaration for this struct and generate initialization code
797 StructDecl structDecl = getStructDecl(simpleType);
798 List<String> memTypes = structDecl.getMemberTypes(simpleType);
799 List<String> members = structDecl.getMembers(simpleType);
800 if (isArrayOrList(retType, retType)) { // An array or list
801 println("for(int i = 0; i < retLen; i++) {");
803 if (isArray(retType)) { // An array
804 for (int i = 0; i < members.size(); i++) {
805 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
806 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
807 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
810 } else if (isList(retType)) { // A list
811 println(simpleType + " structRetMem = new " + simpleType + "();");
812 for (int i = 0; i < members.size(); i++) {
813 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
814 print("structRetMem." + getSimpleIdentifier(members.get(i)));
815 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
817 println("structRet.add(structRetMem);");
819 } else { // Just one struct element
820 for (int i = 0; i < members.size(); i++) {
821 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
822 print("structRet." + getSimpleIdentifier(members.get(i)));
823 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
826 println("return structRet;");
831 * HELPER: writeStructReturnJavaStub() writes parameters if struct is present for return statement
833 private void writeStructReturnJavaStub(String simpleType, String retType, String method, InterfaceDecl intDecl) {
835 // Handle the returned struct size
836 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
837 // Minimum retLen is 1 if this is a single struct object
838 println("int retLen = (int) retObj;");
839 int numMem = getNumOfMembers(simpleType);
840 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
841 println("Class<?>[] retClsVal = new Class<?>[" + numMem + "*retLen];");
842 println("int retPos = 0;");
843 // Get the struct declaration for this struct and generate initialization code
844 StructDecl structDecl = getStructDecl(simpleType);
845 List<String> memTypes = structDecl.getMemberTypes(simpleType);
846 List<String> members = structDecl.getMembers(simpleType);
847 if (isArrayOrList(retType, retType)) { // An array or list
848 println("for(int i = 0; i < retLen; i++) {");
849 for (int i = 0; i < members.size(); i++) {
850 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
851 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
852 println("retClsVal[retPos++] = null;");
855 } else { // Just one struct element
856 for (int i = 0; i < members.size(); i++) {
857 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
858 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
859 println("retClsVal[retPos++] = null;");
862 //println("Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);");
863 // Handle the actual returned struct
864 writeWaitForReturnValueJava(method, intDecl, "Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);");
865 if (isArray(retType)) { // An array
866 println(simpleType + "[] structRet = new " + simpleType + "[retLen];");
867 println("for(int i = 0; i < retLen; i++) {");
868 println("structRet[i] = new " + simpleType + "();");
870 } else if (isList(retType)) { // A list
871 println("List<" + simpleType + "> structRet = new ArrayList<" + simpleType + ">();");
873 println(simpleType + " structRet = new " + simpleType + "();");
874 println("int retObjPos = 0;");
875 writeStructRetMembersJavaStub(simpleType, retType);
880 * HELPER: writeWaitForReturnValueJava() writes the synchronization part for return values
882 private void writeWaitForReturnValueJava(String method, InterfaceDecl intDecl, String getReturnValue) {
884 println("// Waiting for return value");
885 int methodNumId = intDecl.getMethodNumId(method);
886 println("while (!retValueReceived" + methodNumId + ".get());");
887 println(getReturnValue);
888 println("retValueReceived" + methodNumId + ".set(false);");
889 println("rmiComm.setGetReturnBytes();\n");
894 * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
896 private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
897 List<String> methPrmTypes, String method, Set<String> callbackType) {
899 checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method);
900 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
901 String retType = intDecl.getMethodType(method);
902 println("Class<?> retType = " + getSimpleType(getStructType(getEnumType(retType))) + ".class;");
903 checkAndWriteEnumTypeJavaStub(methParams, methPrmTypes);
904 // Generate array of parameter types
905 if (isStructPresent(methParams, methPrmTypes)) {
906 writeStructParamClassJavaStub(methParams, methPrmTypes, callbackType);
908 print("Class<?>[] paramCls = new Class<?>[] { ");
909 for (int i = 0; i < methParams.size(); i++) {
910 String prmType = methPrmTypes.get(i);
911 if (checkCallbackType(prmType, callbackType)) { // Check if this has callback object
912 print("int[].class");
913 } else { // Generate normal classes if it's not a callback object
914 String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
915 print(getSimpleType(getEnumType(paramType)) + ".class");
917 // Check if this is the last element (don't print a comma)
918 if (i != methParams.size() - 1) {
923 // Generate array of parameter objects
924 print("Object[] paramObj = new Object[] { ");
925 for (int i = 0; i < methParams.size(); i++) {
926 String paramType = methPrmTypes.get(i);
927 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
928 print("objIdSent" + i);
930 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
931 // Check if this is the last element (don't print a comma)
932 if (i != methParams.size() - 1) {
938 // Send method call first and wait for return value separately
939 println("rmiComm.remoteCall(objectId, methodId, paramCls, paramObj);");
940 // Check if this is "void"
941 if (!retType.equals("void")) { // We do have a return value
942 // Generate array of parameter types
943 if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
944 writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl);
946 // This is an enum type
947 if (getParamCategory(getGenericType(getSimpleArrayType(retType))) == ParamCategory.ENUM) {
948 //println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
949 checkAndWriteEnumRetTypeJavaStub(retType, method, intDecl);
950 } else if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
951 // Check if the return value NONPRIMITIVES
952 String retGenValType = getGenericType(retType);
953 println("Class<?> retGenValType = " + retGenValType + ".class;");
954 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, retGenValType);");
955 println("return (" + retType + ")retObj;");
957 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
958 println("return (" + retType + ")retObj;");
966 * HELPER: returnGenericCallbackType() returns the callback type
968 private String returnGenericCallbackType(String paramType) {
970 if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES)
971 return getGenericType(paramType);
978 * HELPER: checkCallbackType() checks the callback type
980 private boolean checkCallbackType(String paramType, Set<String> callbackType) {
982 String prmType = returnGenericCallbackType(paramType);
983 if (callbackType == null) // If there is no callbackType it means not a callback method
986 for (String type : callbackType) {
987 if (type.equals(prmType))
988 return true; // Check callbackType one by one
996 * HELPER: checkCallbackType() checks the callback type
998 private boolean checkCallbackType(String paramType, String callbackType) {
1000 String prmType = returnGenericCallbackType(paramType);
1001 if (callbackType == null) // If there is no callbackType it means not a callback method
1004 return callbackType.equals(prmType);
1009 * HELPER: writeCallbackInstantiationMethodBodyJavaStub() writes the callback object instantiation in the method of the stub class
1011 private void writeCallbackInstantiationMethodBodyJavaStub(String paramIdent, String callbackType, int counter, boolean isMultipleCallbacks) {
1013 println("if (!IoTRMIUtil.mapSkel.containsKey(" + paramIdent + ")) {");
1014 println("int newObjIdSent = rmiComm.getObjectIdCounter();");
1015 if (isMultipleCallbacks)
1016 println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
1018 println("objIdSent" + counter + "[0] = newObjIdSent;");
1019 println("rmiComm.decrementObjectIdCounter();");
1020 println(callbackType + "_Skeleton skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
1021 println("IoTRMIUtil.mapSkel.put(" + paramIdent + ", skel" + counter + ");");
1022 println("IoTRMIUtil.mapSkelId.put(" + paramIdent + ", newObjIdSent);");
1023 println("Thread thread = new Thread() {");
1024 println("public void run() {");
1026 println("skel" + counter + ".___waitRequestInvokeMethod();");
1027 println("} catch (Exception ex) {");
1028 println("ex.printStackTrace();");
1029 println("throw new Error(\"Exception when trying to run ___waitRequestInvokeMethod() for " +
1030 callbackType + "_Skeleton!\");");
1034 println("thread.start();");
1035 println("while(!skel" + counter + ".didAlreadyInitWaitInvoke());");
1039 println("int newObjIdSent = IoTRMIUtil.mapSkelId.get(" + paramIdent + ");");
1040 if (isMultipleCallbacks)
1041 println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
1043 println("objIdSent" + counter + "[0] = newObjIdSent;");
1049 * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class
1051 private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
1052 List<String> methPrmTypes, String method, Set<String> callbackType) {
1054 // Determine callback object counter type (List vs. single variable)
1055 for (int i = 0; i < methParams.size(); i++) {
1056 String paramType = methPrmTypes.get(i);
1057 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1058 print("int[] objIdSent" + i + " = ");
1059 String param = methParams.get(i);
1060 if (isArray(methParams.get(i)))
1061 println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".length];");
1062 else if (isList(methPrmTypes.get(i)))
1063 println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".size()];");
1065 println("new int[1];");
1069 // Check if this is single object, array, or list of objects
1070 for (int i = 0; i < methParams.size(); i++) {
1071 String paramType = methPrmTypes.get(i);
1072 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1073 String param = methParams.get(i);
1074 if (isArrayOrList(paramType, param)) { // Generate loop
1075 println("int cnt" + i + " = 0;");
1076 println("for (" + getGenericType(paramType) + " cb : " + getSimpleIdentifier(param) + ") {");
1077 writeCallbackInstantiationMethodBodyJavaStub("cb", returnGenericCallbackType(paramType), i, true);
1079 writeCallbackInstantiationMethodBodyJavaStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i, false);
1080 if (isArrayOrList(paramType, param))
1085 println(" catch (Exception ex) {");
1086 println("ex.printStackTrace();");
1087 println("throw new Error(\"Exception when generating skeleton objects!\");");
1093 * HELPER: writeMethodJavaStub() writes the methods of the stub class
1095 private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
1097 for (String method : methods) {
1099 List<String> methParams = intDecl.getMethodParams(method);
1100 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1101 print("public " + intDecl.getMethodType(method) + " " +
1102 intDecl.getMethodId(method) + "(");
1103 boolean isCallbackMethod = false;
1104 //String callbackType = null;
1105 Set<String> callbackType = new HashSet<String>();
1106 for (int i = 0; i < methParams.size(); i++) {
1108 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1109 // Check if this has callback object
1110 if (callbackClasses.contains(paramType)) {
1111 isCallbackMethod = true;
1112 //callbackType = paramType;
1113 callbackType.add(paramType);
1114 // Even if there're 2 callback arguments, we expect them to be of the same interface
1116 print(methPrmTypes.get(i) + " " + methParams.get(i));
1117 // Check if this is the last element (don't print a comma)
1118 if (i != methParams.size() - 1) {
1123 // Now, write the body of stub!
1124 if (isCallbackMethod)
1125 writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1127 writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1134 * HELPER: getStubInterface() gets stub interface name based on original interface
1136 public String getStubInterface(String intface) {
1138 return mapInt2NewIntName.get(intface);
1143 * generateJavaStubClasses() generate stubs based on the methods list in Java
1145 public void generateJavaStubClasses() throws IOException {
1147 // Create a new directory
1148 String path = createDirectories(dir, subdir);
1149 for (String intface : mapIntfacePTH.keySet()) {
1151 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1152 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1154 // Open a new file to write into
1155 String newIntface = intMeth.getKey();
1156 String newStubClass = newIntface + "_Stub";
1157 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
1158 pw = new PrintWriter(new BufferedWriter(fw));
1159 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1160 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1161 // Pass in set of methods and get import classes
1162 Set<String> methods = intMeth.getValue();
1163 Set<String> importClasses = getImportClasses(methods, intDecl);
1164 List<String> stdImportClasses = getStandardJavaImportClasses();
1165 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
1166 printImportStatements(allImportClasses); println("");
1167 // Find out if there are callback objects
1168 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
1169 boolean callbackExist = !callbackClasses.isEmpty();
1170 // Write class header
1171 println("public class " + newStubClass + " implements " + newIntface + " {\n");
1173 writePropertiesJavaStub(intface, intMeth.getValue(), intDecl);
1174 // Write constructor
1175 writeConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1176 // Write callback constructor (used if this stub is treated as a callback stub)
1177 writeCallbackConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1179 writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass);
1182 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
1189 * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class
1191 private void writePropertiesJavaSkeleton(String intface, InterfaceDecl intDecl) {
1193 println("private " + intface + " mainObj;");
1194 println("private int objectId = 0;");
1195 println("// Communications and synchronizations");
1196 println("private IoTRMIComm rmiComm;");
1197 println("private AtomicBoolean didAlreadyInitWaitInvoke;");
1198 println("private AtomicBoolean methodReceived;");
1199 println("private byte[] methodBytes = null;");
1200 println("// Permissions");
1201 writePropertiesJavaPermission(intface, intDecl);
1207 * HELPER: writeStructPermissionJavaSkeleton() writes permission for struct helper
1209 private void writeStructPermissionJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
1211 // Use this set to handle two same methodIds
1212 for (String method : methods) {
1213 List<String> methParams = intDecl.getMethodParams(method);
1214 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1215 // Check for params with structs
1216 for (int i = 0; i < methParams.size(); i++) {
1217 String paramType = methPrmTypes.get(i);
1218 String param = methParams.get(i);
1219 String simpleType = getGenericType(paramType);
1220 if (isStructClass(simpleType)) {
1221 int methodNumId = intDecl.getMethodNumId(method);
1222 String helperMethod = methodNumId + "struct" + i;
1223 int methodHelperNumId = intDecl.getHelperMethodNumId(helperMethod);
1224 // Iterate over interfaces to give permissions to
1225 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1226 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1227 String newIntface = intMeth.getKey();
1228 int newObjectId = getNewIntfaceObjectId(newIntface);
1229 println("set" + newObjectId + "Allowed.add(" + methodHelperNumId + ");");
1238 * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class
1240 private void writeConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl,
1241 Collection<String> methods, boolean callbackExist) {
1243 println("public " + newSkelClass + "(" + intface + " _mainObj, int _portSend, int _portRecv) throws Exception {");
1244 println("mainObj = _mainObj;");
1245 println("rmiComm = new IoTRMICommServer(_portSend, _portRecv);");
1246 // Generate permission control initialization
1247 writeConstructorJavaPermission(intface);
1248 //writeJavaInitCallbackPermission(intface, intDecl, callbackExist);
1249 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1250 println("IoTRMIUtil.mapSkel.put(_mainObj, this);");
1251 println("IoTRMIUtil.mapSkelId.put(_mainObj, objectId);");
1252 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1253 println("methodReceived = new AtomicBoolean(false);");
1254 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1255 println("Thread thread1 = new Thread() {");
1256 println("public void run() {");
1258 println("___waitRequestInvokeMethod();");
1260 println("catch (Exception ex)");
1262 println("ex.printStackTrace();");
1266 println("thread1.start();");
1272 * HELPER: writeCallbackConstructorJavaSkeleton() writes the constructor of the skeleton class
1274 private void writeCallbackConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl,
1275 Collection<String> methods, boolean callbackExist) {
1277 println("public " + newSkelClass + "(" + intface + " _mainObj, IoTRMIComm _rmiComm, int _objectId) throws Exception {");
1278 println("mainObj = _mainObj;");
1279 println("rmiComm = _rmiComm;");
1280 println("objectId = _objectId;");
1281 // Generate permission control initialization
1282 writeConstructorJavaPermission(intface);
1283 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1284 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1285 println("methodReceived = new AtomicBoolean(false);");
1286 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1292 * HELPER: writeStdMethodBodyJavaSkeleton() writes the standard method body in the skeleton class
1294 private void writeStdMethodBodyJavaSkeleton(List<String> methParams, String methodId, String methodType) {
1296 if (methodType.equals("void"))
1297 print("mainObj." + methodId + "(");
1299 print("return mainObj." + methodId + "(");
1300 for (int i = 0; i < methParams.size(); i++) {
1302 print(getSimpleIdentifier(methParams.get(i)));
1303 // Check if this is the last element (don't print a comma)
1304 if (i != methParams.size() - 1) {
1313 * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class
1315 private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1317 for (String method : methods) {
1319 List<String> methParams = intDecl.getMethodParams(method);
1320 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1321 String methodId = intDecl.getMethodId(method);
1322 print("public " + intDecl.getMethodType(method) + " " + methodId + "(");
1323 for (int i = 0; i < methParams.size(); i++) {
1325 String origParamType = methPrmTypes.get(i);
1326 String paramType = checkAndGetParamClass(origParamType);
1327 print(paramType + " " + methParams.get(i));
1328 // Check if this is the last element (don't print a comma)
1329 if (i != methParams.size() - 1) {
1334 // Now, write the body of skeleton!
1335 writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method));
1342 * HELPER: writeCallbackInstantiationJavaStubGeneration() writes the instantiation of callback stubs
1344 private void writeCallbackInstantiationJavaStubGeneration(String exchParamType, int counter) {
1346 println(exchParamType + " newStub" + counter + " = null;");
1347 println("if(!IoTRMIUtil.mapStub.containsKey(objIdRecv" + counter + ")) {");
1348 println("newStub" + counter + " = new " + exchParamType + "_Stub(rmiComm, objIdRecv" + counter + ");");
1349 println("IoTRMIUtil.mapStub.put(objIdRecv" + counter + ", newStub" + counter + ");");
1350 println("rmiComm.setObjectIdCounter(objIdRecv" + counter + ");");
1351 println("rmiComm.decrementObjectIdCounter();");
1354 println("newStub" + counter + " = (" + exchParamType + "_Stub) IoTRMIUtil.mapStub.get(objIdRecv" + counter + ");");
1360 * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part
1362 private Map<Integer,String> writeCallbackJavaStubGeneration(List<String> methParams, List<String> methPrmTypes,
1363 Set<String> callbackType, boolean isStructMethod) {
1365 Map<Integer,String> mapStubParam = new HashMap<Integer,String>();
1366 String offsetPfx = "";
1368 offsetPfx = "offset";
1369 // Iterate over callback objects
1370 for (int i = 0; i < methParams.size(); i++) {
1371 String paramType = methPrmTypes.get(i);
1372 String param = methParams.get(i);
1373 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1374 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1375 // Print array if this is array or list if this is a list of callback objects
1376 println("int[] stubIdArray" + i + " = (int[]) paramObj[" + offsetPfx + i + "];");
1377 if (isArray(param)) {
1378 println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1379 println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];");
1380 } else if (isList(paramType)) {
1381 println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1382 println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();");
1384 println("int objIdRecv" + i + " = stubIdArray" + i + "[0];");
1385 writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1388 // Generate a loop if needed
1389 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1390 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1391 if (isArray(param)) {
1392 println("for (int i = 0; i < numStubs" + i + "; i++) {");
1393 println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
1394 writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1395 println("stub" + i + "[i] = newStub" + i + ";");
1397 } else if (isList(paramType)) {
1398 println("for (int i = 0; i < numStubs" + i + "; i++) {");
1399 println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
1400 writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1401 println("stub" + i + ".add(newStub" + i + ");");
1404 println(exchParamType + " stub" + i + " = newStub" + i + ";");
1405 mapStubParam.put(i, "stub" + i); // List of all stub parameters
1408 return mapStubParam;
1413 * HELPER: checkAndWriteEnumTypeJavaSkeleton() writes the enum type (convert from enum to int)
1415 private void checkAndWriteEnumTypeJavaSkeleton(List<String> methParams, List<String> methPrmTypes, boolean isStructMethod) {
1417 String offsetPfx = "";
1419 offsetPfx = "offset";
1420 // Iterate and find enum declarations
1421 boolean printed = false;
1422 for (int i = 0; i < methParams.size(); i++) {
1423 String paramType = methPrmTypes.get(i);
1424 String param = methParams.get(i);
1425 String simpleType = getGenericType(paramType);
1426 if (isEnumClass(simpleType)) {
1427 // Check if this is enum type
1428 println("int paramInt" + i + "[] = (int[]) paramObj[" + offsetPfx + i + "];");
1430 println(simpleType + "[] enumVals = " + simpleType + ".values();");
1433 if (isArray(param)) { // An array
1434 println("int len" + i + " = paramInt" + i + ".length;");
1435 println(simpleType + "[] paramEnum" + i + " = new " + simpleType + "[len" + i + "];");
1436 println("for (int i = 0; i < len" + i + "; i++) {");
1437 println("paramEnum" + i + "[i] = enumVals[paramInt" + i + "[i]];");
1439 } else if (isList(paramType)) { // A list
1440 println("int len" + i + " = paramInt" + i + ".length;");
1441 println("List<" + simpleType + "> paramEnum" + i + " = new ArrayList<" + simpleType + ">();");
1442 println("for (int i = 0; i < len" + i + "; i++) {");
1443 println("paramEnum" + i + ".add(enumVals[paramInt" + i + "[i]]);");
1445 } else { // Just one element
1446 println(simpleType + " paramEnum" + i + " = enumVals[paramInt" + i + "[0]];");
1454 * HELPER: checkAndWriteEnumRetTypeJavaSkeleton() writes the enum return type (convert from enum to int)
1456 private void checkAndWriteEnumRetTypeJavaSkeleton(String retType, String methodId) {
1458 // Strips off array "[]" for return type
1459 String pureType = getSimpleArrayType(getGenericType(retType));
1460 // Take the inner type of generic
1461 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1462 pureType = getGenericType(retType);
1463 if (isEnumClass(pureType)) {
1464 // Check if this is enum type
1466 if (isArray(retType)) { // An array
1467 print(pureType + "[] retEnum = " + methodId + "(");
1468 } else if (isList(retType)) { // A list
1469 print("List<" + pureType + "> retEnum = " + methodId + "(");
1470 } else { // Just one element
1471 print(pureType + " retEnum = " + methodId + "(");
1478 * HELPER: checkAndWriteEnumRetConvJavaSkeleton() writes the enum return type (convert from enum to int)
1480 private void checkAndWriteEnumRetConvJavaSkeleton(String retType) {
1482 // Strips off array "[]" for return type
1483 String pureType = getSimpleArrayType(getGenericType(retType));
1484 // Take the inner type of generic
1485 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1486 pureType = getGenericType(retType);
1487 if (isEnumClass(pureType)) {
1488 // Check if this is enum type
1489 if (isArray(retType)) { // An array
1490 println("int retLen = retEnum.length;");
1491 println("int[] retEnumVal = new int[retLen];");
1492 println("for (int i = 0; i < retLen; i++) {");
1493 println("retEnumVal[i] = retEnum[i].ordinal();");
1495 } else if (isList(retType)) { // A list
1496 println("int retLen = retEnum.size();");
1497 println("int[] retEnumVal = new int[retLen];");
1498 println("for (int i = 0; i < retLen; i++) {");
1499 println("retEnumVal[i] = retEnum.get(i).ordinal();");
1501 } else { // Just one element
1502 println("int[] retEnumVal = new int[1];");
1503 println("retEnumVal[0] = retEnum.ordinal();");
1505 println("Object retObj = retEnumVal;");
1511 * HELPER: writeLengthStructParamClassSkeleton() writes lengths of params
1513 private void writeLengthStructParamClassSkeleton(List<String> methParams, List<String> methPrmTypes,
1514 String method, InterfaceDecl intDecl) {
1516 // Iterate and find struct declarations - count number of params
1517 for (int i = 0; i < methParams.size(); i++) {
1518 String paramType = methPrmTypes.get(i);
1519 String param = methParams.get(i);
1520 String simpleType = getGenericType(paramType);
1521 if (isStructClass(simpleType)) {
1522 int members = getNumOfMembers(simpleType);
1523 print(Integer.toString(members) + "*");
1524 int methodNumId = intDecl.getMethodNumId(method);
1525 print("struct" + methodNumId + "Size" + i);
1528 if (i != methParams.size() - 1) {
1536 * HELPER: writeStructMembersJavaSkeleton() writes member parameters of struct
1538 private void writeStructMembersJavaSkeleton(String simpleType, String paramType,
1539 String param, String method, InterfaceDecl intDecl, int iVar) {
1541 // Get the struct declaration for this struct and generate initialization code
1542 StructDecl structDecl = getStructDecl(simpleType);
1543 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1544 List<String> members = structDecl.getMembers(simpleType);
1545 if (isArrayOrList(paramType, param)) { // An array or list
1546 int methodNumId = intDecl.getMethodNumId(method);
1547 String counter = "struct" + methodNumId + "Size" + iVar;
1548 println("for(int i = 0; i < " + counter + "; i++) {");
1550 if (isArrayOrList(paramType, param)) { // An array or list
1551 for (int i = 0; i < members.size(); i++) {
1552 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1553 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1554 println("paramClsGen[pos++] = null;");
1557 } else { // Just one struct element
1558 for (int i = 0; i < members.size(); i++) {
1559 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1560 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1561 println("paramClsGen[pos++] = null;");
1568 * HELPER: writeStructMembersInitJavaSkeleton() writes member parameters initialization of struct
1570 private void writeStructMembersInitJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1571 List<String> methPrmTypes, String method) {
1573 println("int objPos = 0;");
1574 for (int i = 0; i < methParams.size(); i++) {
1575 String paramType = methPrmTypes.get(i);
1576 String param = methParams.get(i);
1577 String simpleType = getGenericType(paramType);
1578 if (isStructClass(simpleType)) {
1579 int methodNumId = intDecl.getMethodNumId(method);
1580 String counter = "struct" + methodNumId + "Size" + i;
1582 if (isArray(param)) { // An array
1583 println(simpleType + "[] paramStruct" + i + " = new " + simpleType + "[" + counter + "];");
1584 println("for(int i = 0; i < " + counter + "; i++) {");
1585 println("paramStruct" + i + "[i] = new " + simpleType + "();");
1587 } else if (isList(paramType)) { // A list
1588 println("List<" + simpleType + "> paramStruct" + i + " = new ArrayList<" + simpleType + ">();");
1590 println(simpleType + " paramStruct" + i + " = new " + simpleType + "();");
1591 // Initialize members
1592 StructDecl structDecl = getStructDecl(simpleType);
1593 List<String> members = structDecl.getMembers(simpleType);
1594 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1595 if (isArrayOrList(paramType, param)) { // An array or list
1596 println("for(int i = 0; i < " + counter + "; i++) {");
1598 if (isArray(param)) { // An array
1599 for (int j = 0; j < members.size(); j++) {
1600 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1601 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
1602 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1605 } else if (isList(paramType)) { // A list
1606 println(simpleType + " paramStructMem = new " + simpleType + "();");
1607 for (int j = 0; j < members.size(); j++) {
1608 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1609 print("paramStructMem." + getSimpleIdentifier(members.get(j)));
1610 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1612 println("paramStruct" + i + ".add(paramStructMem);");
1614 } else { // Just one struct element
1615 for (int j = 0; j < members.size(); j++) {
1616 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1617 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
1618 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1622 // Take offsets of parameters
1623 println("int offset" + i +" = objPos++;");
1630 * HELPER: writeStructReturnJavaSkeleton() writes struct for return statement
1632 private void writeStructReturnJavaSkeleton(String simpleType, String retType) {
1634 // Minimum retLen is 1 if this is a single struct object
1635 if (isArray(retType))
1636 println("int retLen = retStruct.length;");
1637 else if (isList(retType))
1638 println("int retLen = retStruct.size();");
1639 else // Just single struct object
1640 println("int retLen = 1;");
1641 println("Object retLenObj = retLen;");
1642 println("rmiComm.sendReturnObj(retLenObj, localMethodBytes);");
1643 int numMem = getNumOfMembers(simpleType);
1644 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
1645 println("Object[] retObj = new Object[" + numMem + "*retLen];");
1646 println("int retPos = 0;");
1647 // Get the struct declaration for this struct and generate initialization code
1648 StructDecl structDecl = getStructDecl(simpleType);
1649 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1650 List<String> members = structDecl.getMembers(simpleType);
1651 if (isArray(retType)) { // An array or list
1652 println("for(int i = 0; i < retLen; i++) {");
1653 for (int i = 0; i < members.size(); i++) {
1654 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1655 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1656 print("retObj[retPos++] = retStruct[i].");
1657 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1661 } else if (isList(retType)) { // An array or list
1662 println("for(int i = 0; i < retLen; i++) {");
1663 for (int i = 0; i < members.size(); i++) {
1664 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1665 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1666 print("retObj[retPos++] = retStruct.get(i).");
1667 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1671 } else { // Just one struct element
1672 for (int i = 0; i < members.size(); i++) {
1673 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1674 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1675 print("retObj[retPos++] = retStruct.");
1676 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1685 * HELPER: writeMethodHelperReturnJavaSkeleton() writes return statement part in skeleton
1687 private void writeMethodHelperReturnJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1688 List<String> methPrmTypes, String method, boolean isCallbackMethod, Set<String> callbackType,
1689 boolean isStructMethod) {
1691 checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes, isStructMethod);
1692 Map<Integer,String> mapStubParam = null;
1693 if (isCallbackMethod) {
1695 mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType, isStructMethod);
1697 // Check if this is "void"
1698 String retType = intDecl.getMethodType(method);
1699 if (retType.equals("void")) {
1700 print(intDecl.getMethodId(method) + "(");
1701 } else if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
1702 checkAndWriteEnumRetTypeJavaSkeleton(retType, intDecl.getMethodId(method));
1703 } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
1704 print(retType + " retStruct = " + intDecl.getMethodId(method) + "(");
1705 } else { // We do have a return value
1706 print("Object retObj = " + intDecl.getMethodId(method) + "(");
1708 for (int i = 0; i < methParams.size(); i++) {
1710 String paramType = methPrmTypes.get(i);
1711 if (isCallbackMethod && checkCallbackType(paramType, callbackType)) {
1712 print(mapStubParam.get(i)); // Get the callback parameter
1713 } else if (isEnumClass(getGenericType(paramType))) { // Enum class
1714 print(getEnumParam(paramType, methParams.get(i), i));
1715 } else if (isStructClass(getGenericType(paramType))) {
1716 print("paramStruct" + i);
1718 String prmType = checkAndGetArray(paramType, methParams.get(i));
1720 print("(" + prmType + ") paramObj[offset" + i + "]");
1722 print("(" + prmType + ") paramObj[" + i + "]");
1724 if (i != methParams.size() - 1)
1728 if (!retType.equals("void")) {
1729 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
1730 checkAndWriteEnumRetConvJavaSkeleton(retType);
1731 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1732 } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
1733 writeStructReturnJavaSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
1734 println("rmiComm.sendReturnObj(retCls, retObj, localMethodBytes);");
1736 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1738 if (isCallbackMethod) { // Catch exception if this is callback
1740 println(" catch(Exception ex) {");
1741 println("ex.printStackTrace();");
1742 println("throw new Error(\"Exception from callback object instantiation!\");");
1749 * HELPER: writeMethodHelperStructJavaSkeleton() writes the struct in skeleton
1751 private void writeMethodHelperStructJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1752 List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1754 // Generate array of parameter objects
1755 boolean isCallbackMethod = false;
1756 //String callbackType = null;
1757 Set<String> callbackType = new HashSet<String>();
1758 println("byte[] localMethodBytes = methodBytes;");
1759 println("rmiComm.setGetMethodBytes();");
1760 print("int paramLen = ");
1761 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
1763 println("Class<?>[] paramCls = new Class<?>[paramLen];");
1764 println("Class<?>[] paramClsGen = new Class<?>[paramLen];");
1765 println("int pos = 0;");
1766 // Iterate again over the parameters
1767 for (int i = 0; i < methParams.size(); i++) {
1768 String paramType = methPrmTypes.get(i);
1769 String param = methParams.get(i);
1770 String simpleType = getGenericType(paramType);
1771 if (isStructClass(simpleType)) {
1772 writeStructMembersJavaSkeleton(simpleType, paramType, param, method, intDecl, i);
1774 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
1775 if (callbackClasses.contains(prmType)) {
1776 isCallbackMethod = true;
1777 //callbackType = prmType;
1778 callbackType.add(prmType);
1779 println("paramCls[pos] = int[].class;");
1780 println("paramClsGen[pos++] = null;");
1781 } else { // Generate normal classes if it's not a callback object
1782 String paramTypeOth = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1783 println("paramCls[pos] = " + getSimpleType(getEnumType(paramTypeOth)) + ".class;");
1784 print("paramClsGen[pos++] = ");
1785 String prmTypeOth = methPrmTypes.get(i);
1786 if (getParamCategory(prmTypeOth) == ParamCategory.NONPRIMITIVES)
1787 println(getTypeOfGeneric(prmType)[0] + ".class;");
1793 println("Object[] paramObj = rmiComm.getMethodParams(paramCls, paramClsGen, localMethodBytes);");
1794 writeStructMembersInitJavaSkeleton(intDecl, methParams, methPrmTypes, method);
1795 // Write the return value part
1796 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, true);
1801 * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class
1803 private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1804 List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1806 // Generate array of parameter objects
1807 boolean isCallbackMethod = false;
1808 //String callbackType = null;
1809 Set<String> callbackType = new HashSet<String>();
1810 println("byte[] localMethodBytes = methodBytes;");
1811 println("rmiComm.setGetMethodBytes();");
1812 print("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { ");
1813 for (int i = 0; i < methParams.size(); i++) {
1815 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1816 if (callbackClasses.contains(paramType)) {
1817 isCallbackMethod = true;
1818 //callbackType = paramType;
1819 callbackType.add(paramType);
1820 print("int[].class");
1821 } else { // Generate normal classes if it's not a callback object
1822 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1823 print(getSimpleType(getEnumType(prmType)) + ".class");
1825 if (i != methParams.size() - 1)
1829 // Generate generic class if it's a generic type.. null otherwise
1830 print(" }, new Class<?>[] { ");
1831 for (int i = 0; i < methParams.size(); i++) {
1832 String prmType = methPrmTypes.get(i);
1833 if ((getParamCategory(prmType) == ParamCategory.NONPRIMITIVES) &&
1834 !isEnumClass(getGenericType(prmType)) &&
1835 !callbackClasses.contains(getGenericType(prmType)))
1836 print(getGenericType(prmType) + ".class");
1839 if (i != methParams.size() - 1)
1842 println(" }, localMethodBytes);");
1843 // Write the return value part
1844 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, false);
1849 * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class
1851 private void writeMethodHelperJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1853 // Use this set to handle two same methodIds
1854 Set<String> uniqueMethodIds = new HashSet<String>();
1855 for (String method : methods) {
1857 List<String> methParams = intDecl.getMethodParams(method);
1858 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1859 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
1860 String methodId = intDecl.getMethodId(method);
1861 print("public void ___");
1862 String helperMethod = methodId;
1863 if (uniqueMethodIds.contains(methodId))
1864 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1866 uniqueMethodIds.add(methodId);
1867 String retType = intDecl.getMethodType(method);
1868 print(helperMethod + "(");
1869 boolean begin = true;
1870 for (int i = 0; i < methParams.size(); i++) { // Print size variables
1871 String paramType = methPrmTypes.get(i);
1872 String param = methParams.get(i);
1873 String simpleType = getGenericType(paramType);
1874 if (isStructClass(simpleType)) {
1875 if (!begin) // Generate comma for not the beginning variable
1879 int methodNumId = intDecl.getMethodNumId(method);
1880 print("int struct" + methodNumId + "Size" + i);
1883 // Check if this is "void"
1884 if (retType.equals("void"))
1887 println(") throws IOException {");
1888 writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1891 String methodId = intDecl.getMethodId(method);
1892 print("public void ___");
1893 String helperMethod = methodId;
1894 if (uniqueMethodIds.contains(methodId))
1895 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1897 uniqueMethodIds.add(methodId);
1898 // Check if this is "void"
1899 String retType = intDecl.getMethodType(method);
1900 if (retType.equals("void"))
1901 println(helperMethod + "() {");
1903 println(helperMethod + "() throws IOException {");
1904 // Now, write the helper body of skeleton!
1905 writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1909 // Write method helper for structs
1910 writeMethodHelperStructSetupJavaSkeleton(methods, intDecl);
1915 * HELPER: writeMethodHelperStructSetupJavaSkeleton() writes the method helper of struct setup in skeleton class
1917 private void writeMethodHelperStructSetupJavaSkeleton(Collection<String> methods,
1918 InterfaceDecl intDecl) {
1920 // Use this set to handle two same methodIds
1921 for (String method : methods) {
1923 List<String> methParams = intDecl.getMethodParams(method);
1924 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1925 // Check for params with structs
1926 for (int i = 0; i < methParams.size(); i++) {
1927 String paramType = methPrmTypes.get(i);
1928 String param = methParams.get(i);
1929 String simpleType = getGenericType(paramType);
1930 if (isStructClass(simpleType)) {
1931 int methodNumId = intDecl.getMethodNumId(method);
1932 print("public int ___");
1933 String helperMethod = methodNumId + "struct" + i;
1934 println(helperMethod + "() {");
1935 // Now, write the helper body of skeleton!
1936 println("byte[] localMethodBytes = methodBytes;");
1937 println("rmiComm.setGetMethodBytes();");
1938 println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null }, localMethodBytes);");
1939 println("return (int) paramObj[0];");
1948 * HELPER: writeMethodHelperStructSetupJavaCallbackSkeleton() writes the method helper of struct setup in callback skeleton class
1950 private void writeMethodHelperStructSetupJavaCallbackSkeleton(Collection<String> methods,
1951 InterfaceDecl intDecl) {
1953 // Use this set to handle two same methodIds
1954 for (String method : methods) {
1956 List<String> methParams = intDecl.getMethodParams(method);
1957 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1958 // Check for params with structs
1959 for (int i = 0; i < methParams.size(); i++) {
1960 String paramType = methPrmTypes.get(i);
1961 String param = methParams.get(i);
1962 String simpleType = getGenericType(paramType);
1963 if (isStructClass(simpleType)) {
1964 int methodNumId = intDecl.getMethodNumId(method);
1965 print("public int ___");
1966 String helperMethod = methodNumId + "struct" + i;
1967 println(helperMethod + "(IoTRMIObject rmiObj) {");
1968 // Now, write the helper body of skeleton!
1969 println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null });");
1970 println("return (int) paramObj[0];");
1979 * HELPER: writeCountVarStructSkeleton() writes counter variable of struct for skeleton
1981 private void writeCountVarStructSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1983 // Use this set to handle two same methodIds
1984 for (String method : methods) {
1986 List<String> methParams = intDecl.getMethodParams(method);
1987 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1988 // Check for params with structs
1989 for (int i = 0; i < methParams.size(); i++) {
1990 String paramType = methPrmTypes.get(i);
1991 String param = methParams.get(i);
1992 String simpleType = getGenericType(paramType);
1993 if (isStructClass(simpleType)) {
1994 int methodNumId = intDecl.getMethodNumId(method);
1995 println("int struct" + methodNumId + "Size" + i + " = 0;");
2003 * HELPER: writeInputCountVarStructJavaSkeleton() writes input counter variable of struct for skeleton
2005 private boolean writeInputCountVarStructJavaSkeleton(String method, InterfaceDecl intDecl) {
2007 List<String> methParams = intDecl.getMethodParams(method);
2008 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2009 boolean structExist = false;
2010 boolean begin = true;
2011 // Check for params with structs
2012 for (int i = 0; i < methParams.size(); i++) {
2013 String paramType = methPrmTypes.get(i);
2014 String param = methParams.get(i);
2015 String simpleType = getGenericType(paramType);
2016 if (isStructClass(simpleType)) {
2022 int methodNumId = intDecl.getMethodNumId(method);
2023 print("struct" + methodNumId + "Size" + i + "Final");
2031 * HELPER: writeInputCountVarStructCplusSkeleton() writes input counter variable of struct for skeleton
2033 private boolean writeInputCountVarStructCplusSkeleton(String method, InterfaceDecl intDecl) {
2035 List<String> methParams = intDecl.getMethodParams(method);
2036 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2037 boolean structExist = false;
2038 boolean begin = true;
2039 // Check for params with structs
2040 for (int i = 0; i < methParams.size(); i++) {
2041 String paramType = methPrmTypes.get(i);
2042 String param = methParams.get(i);
2043 String simpleType = getGenericType(paramType);
2044 if (isStructClass(simpleType)) {
2050 int methodNumId = intDecl.getMethodNumId(method);
2051 print("struct" + methodNumId + "Size" + i);
2059 * HELPER: writeMethodCallStructJavaSkeleton() writes method call for wait invoke in skeleton
2061 private void writeMethodCallStructJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2063 // Use this set to handle two same methodIds
2064 for (String method : methods) {
2066 List<String> methParams = intDecl.getMethodParams(method);
2067 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2068 // Check for params with structs
2069 for (int i = 0; i < methParams.size(); i++) {
2070 String paramType = methPrmTypes.get(i);
2071 String param = methParams.get(i);
2072 String simpleType = getGenericType(paramType);
2073 if (isStructClass(simpleType)) {
2074 int methodNumId = intDecl.getMethodNumId(method);
2076 String helperMethod = methodNumId + "struct" + i;
2077 String tempVar = "struct" + methodNumId + "Size" + i;
2078 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2079 print(tempVar + " = ___");
2080 println(helperMethod + "(); break;");
2088 * HELPER: writeMethodCallStructCplusSkeleton() writes method call for wait invoke in skeleton
2090 private void writeMethodCallStructCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2092 // Use this set to handle two same methodIds
2093 for (String method : methods) {
2095 List<String> methParams = intDecl.getMethodParams(method);
2096 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2097 // Check for params with structs
2098 for (int i = 0; i < methParams.size(); i++) {
2099 String paramType = methPrmTypes.get(i);
2100 String param = methParams.get(i);
2101 String simpleType = getGenericType(paramType);
2102 if (isStructClass(simpleType)) {
2103 int methodNumId = intDecl.getMethodNumId(method);
2105 String helperMethod = methodNumId + "struct" + i;
2106 String tempVar = "struct" + methodNumId + "Size" + i;
2107 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2108 print(tempVar + " = ___");
2109 println(helperMethod + "(skel); break;");
2117 * HELPER: writeMethodCallStructCallbackSkeleton() writes method call for wait invoke in skeleton
2119 private void writeMethodCallStructCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2121 // Use this set to handle two same methodIds
2122 for (String method : methods) {
2124 List<String> methParams = intDecl.getMethodParams(method);
2125 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2126 // Check for params with structs
2127 for (int i = 0; i < methParams.size(); i++) {
2128 String paramType = methPrmTypes.get(i);
2129 String param = methParams.get(i);
2130 String simpleType = getGenericType(paramType);
2131 if (isStructClass(simpleType)) {
2132 int methodNumId = intDecl.getMethodNumId(method);
2134 String helperMethod = methodNumId + "struct" + i;
2135 String tempVar = "struct" + methodNumId + "Size" + i;
2136 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2137 print(tempVar + " = ___");
2138 println(helperMethod + "(rmiObj); break;");
2146 * HELPER: writeJavaMethodPermission() writes permission checks in skeleton
2148 private void writeJavaMethodPermission(String intface) {
2150 // Get all the different stubs
2151 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2152 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2153 String newIntface = intMeth.getKey();
2154 int newObjectId = getNewIntfaceObjectId(newIntface);
2155 println("if (_objectId == objectId) {");
2156 println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
2157 println("throw new Error(\"Object with object Id: \" + _objectId + \" is not allowed to access method: \" + methodId);");
2161 println("continue;");
2168 * HELPER: writeFinalInputCountVarStructSkeleton() writes the final version of input counter variable of struct for skeleton
2170 private boolean writeFinalInputCountVarStructSkeleton(String method, InterfaceDecl intDecl) {
2172 List<String> methParams = intDecl.getMethodParams(method);
2173 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2174 boolean structExist = false;
2175 boolean begin = true;
2176 // Check for params with structs
2177 for (int i = 0; i < methParams.size(); i++) {
2178 String paramType = methPrmTypes.get(i);
2179 String param = methParams.get(i);
2180 String simpleType = getGenericType(paramType);
2181 if (isStructClass(simpleType)) {
2183 int methodNumId = intDecl.getMethodNumId(method);
2184 println("final int struct" + methodNumId + "Size" + i +
2185 "Final = struct" + methodNumId + "Size" + i + ";");
2193 * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class
2195 private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, String intface) {
2197 // Use this set to handle two same methodIds
2198 Set<String> uniqueMethodIds = new HashSet<String>();
2199 println("public void ___waitRequestInvokeMethod() throws IOException {");
2200 // Write variables here if we have callbacks or enums or structs
2201 writeCountVarStructSkeleton(methods, intDecl);
2202 println("didAlreadyInitWaitInvoke.compareAndSet(false, true);");
2203 println("while (true) {");
2204 println("if (!methodReceived.get()) {");
2205 println("continue;");
2207 println("methodBytes = rmiComm.getMethodBytes();");
2208 println("methodReceived.set(false);");
2209 println("int _objectId = IoTRMIComm.getObjectId(methodBytes);");
2210 println("int methodId = IoTRMIComm.getMethodId(methodBytes);");
2211 // Generate permission check
2212 writeJavaMethodPermission(intface);
2213 println("switch (methodId) {");
2214 // Print methods and method Ids
2215 for (String method : methods) {
2216 String methodId = intDecl.getMethodId(method);
2217 int methodNumId = intDecl.getMethodNumId(method);
2218 println("case " + methodNumId + ":");
2219 // Check for stuct counters
2220 writeFinalInputCountVarStructSkeleton(method, intDecl);
2221 println("new Thread() {");
2222 println("public void run() {");
2225 String helperMethod = methodId;
2226 if (uniqueMethodIds.contains(methodId))
2227 helperMethod = helperMethod + methodNumId;
2229 uniqueMethodIds.add(methodId);
2230 print(helperMethod + "(");
2231 writeInputCountVarStructJavaSkeleton(method, intDecl);
2234 println("catch (Exception ex) {");
2235 println("ex.printStackTrace();");
2238 println("}.start();");
2241 String method = "___initCallBack()";
2242 writeMethodCallStructJavaSkeleton(methods, intDecl);
2243 println("default: ");
2244 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
2252 * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke
2254 private void writeReturnDidAlreadyInitWaitInvoke() {
2256 println("public boolean didAlreadyInitWaitInvoke() {");
2257 println("return didAlreadyInitWaitInvoke.get();");
2263 * generateJavaSkeletonClass() generate skeletons based on the methods list in Java
2265 public void generateJavaSkeletonClass() throws IOException {
2267 // Create a new directory
2268 String path = createDirectories(dir, subdir);
2269 for (String intface : mapIntfacePTH.keySet()) {
2270 // Open a new file to write into
2271 String newSkelClass = intface + "_Skeleton";
2272 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
2273 pw = new PrintWriter(new BufferedWriter(fw));
2274 // Pass in set of methods and get import classes
2275 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2276 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2277 List<String> methods = intDecl.getMethods();
2278 Set<String> importClasses = getImportClasses(methods, intDecl);
2279 List<String> stdImportClasses = getStandardJavaImportClasses();
2280 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
2281 printImportStatements(allImportClasses);
2282 // Find out if there are callback objects
2283 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2284 boolean callbackExist = !callbackClasses.isEmpty();
2285 // Write class header
2287 println("public class " + newSkelClass + " implements " + intface + " {\n");
2289 writePropertiesJavaSkeleton(intface, intDecl);
2290 // Write constructor
2291 writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2292 // Write constructor that is called when this object is a callback object
2293 writeCallbackConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2294 // Write function to return didAlreadyInitWaitInvoke
2295 writeReturnDidAlreadyInitWaitInvoke();
2297 writeMethodJavaSkeleton(methods, intDecl);
2298 // Write method helper
2299 writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
2300 // Write waitRequestInvokeMethod() - main loop
2301 writeJavaWaitRequestInvokeMethod(methods, intDecl, intface);
2304 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
2309 /*================================================================================
2313 *================================================================================/
2316 * HELPER: writeMethodCplusLocalInterface() writes the method of the local interface
2318 private void writeMethodCplusLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
2320 for (String method : methods) {
2322 List<String> methParams = intDecl.getMethodParams(method);
2323 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2324 print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2325 intDecl.getMethodId(method) + "(");
2326 for (int i = 0; i < methParams.size(); i++) {
2327 // Check for params with driver class types and exchange it
2328 // with its remote interface
2329 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
2330 paramType = checkAndGetCplusType(paramType);
2331 // Check for arrays - translate into vector in C++
2332 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2333 print(paramComplete);
2334 // Check if this is the last element (don't print a comma)
2335 if (i != methParams.size() - 1) {
2345 * HELPER: writeMethodCplusInterface() writes the method of the interface
2347 private void writeMethodCplusInterface(Collection<String> methods, InterfaceDecl intDecl) {
2349 for (String method : methods) {
2351 List<String> methParams = intDecl.getMethodParams(method);
2352 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2353 print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2354 intDecl.getMethodId(method) + "(");
2355 for (int i = 0; i < methParams.size(); i++) {
2356 // Check for params with driver class types and exchange it
2357 // with its remote interface
2358 String paramType = methPrmTypes.get(i);
2359 paramType = checkAndGetCplusType(paramType);
2360 // Check for arrays - translate into vector in C++
2361 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2362 print(paramComplete);
2363 // Check if this is the last element (don't print a comma)
2364 if (i != methParams.size() - 1) {
2374 * HELPER: generateEnumCplus() writes the enumeration declaration
2376 public void generateEnumCplus() throws IOException {
2378 // Create a new directory
2379 createDirectory(dir);
2380 for (String intface : mapIntfacePTH.keySet()) {
2381 // Get the right StructDecl
2382 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2383 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
2384 Set<String> enumTypes = enumDecl.getEnumDeclarations();
2385 // Iterate over enum declarations
2386 for (String enType : enumTypes) {
2387 // Open a new file to write into
2388 FileWriter fw = new FileWriter(dir + "/" + enType + ".hpp");
2389 pw = new PrintWriter(new BufferedWriter(fw));
2390 // Write file headers
2391 println("#ifndef _" + enType.toUpperCase() + "_HPP__");
2392 println("#define _" + enType.toUpperCase() + "_HPP__");
2393 println("enum " + enType + " {");
2394 List<String> enumMembers = enumDecl.getMembers(enType);
2395 for (int i = 0; i < enumMembers.size(); i++) {
2397 String member = enumMembers.get(i);
2399 // Check if this is the last element (don't print a comma)
2400 if (i != enumMembers.size() - 1)
2408 System.out.println("IoTCompiler: Generated enum " + enType + ".hpp...");
2415 * HELPER: generateStructCplus() writes the struct declaration
2417 public void generateStructCplus() throws IOException {
2419 // Create a new directory
2420 createDirectory(dir);
2421 for (String intface : mapIntfacePTH.keySet()) {
2422 // Get the right StructDecl
2423 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2424 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
2425 List<String> structTypes = structDecl.getStructTypes();
2426 // Iterate over enum declarations
2427 for (String stType : structTypes) {
2428 // Open a new file to write into
2429 FileWriter fw = new FileWriter(dir + "/" + stType + ".hpp");
2430 pw = new PrintWriter(new BufferedWriter(fw));
2431 // Write file headers
2432 println("#ifndef _" + stType.toUpperCase() + "_HPP__");
2433 println("#define _" + stType.toUpperCase() + "_HPP__");
2434 println("using namespace std;");
2435 println("struct " + stType + " {");
2436 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
2437 List<String> structMembers = structDecl.getMembers(stType);
2438 for (int i = 0; i < structMembers.size(); i++) {
2440 String memberType = structMemberTypes.get(i);
2441 String member = structMembers.get(i);
2442 String structTypeC = checkAndGetCplusType(memberType);
2443 String structComplete = checkAndGetCplusArray(structTypeC, member);
2444 println(structComplete + ";");
2449 System.out.println("IoTCompiler: Generated struct " + stType + ".hpp...");
2456 * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
2458 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
2459 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
2460 * The local interface has to be the input parameter for the stub and the stub
2461 * interface has to be the input parameter for the local class.
2463 public void generateCplusLocalInterfaces() throws IOException {
2465 // Create a new directory
2466 createDirectory(dir);
2467 for (String intface : mapIntfacePTH.keySet()) {
2468 // Open a new file to write into
2469 FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
2470 pw = new PrintWriter(new BufferedWriter(fw));
2471 // Write file headers
2472 println("#ifndef _" + intface.toUpperCase() + "_HPP__");
2473 println("#define _" + intface.toUpperCase() + "_HPP__");
2474 println("#include <iostream>");
2475 // Pass in set of methods and get include classes
2476 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2477 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2478 List<String> methods = intDecl.getMethods();
2479 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, true);
2480 printIncludeStatements(includeClasses); println("");
2481 println("using namespace std;\n");
2482 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2483 if (!intface.equals(mainClass)) // Forward declare if not main class
2484 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, true);
2485 println("class " + intface); println("{");
2488 writeMethodCplusLocalInterface(methods, intDecl);
2492 System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
2498 * HELPER: writeMethodCplusInterfaceForwardDecl() writes the forward declaration of the interface
2500 private void writeMethodCplusInterfaceForwardDecl(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, boolean needNewIntface) {
2502 Set<String> isDefined = new HashSet<String>();
2503 for (String method : methods) {
2505 List<String> methParams = intDecl.getMethodParams(method);
2506 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2507 for (int i = 0; i < methParams.size(); i++) {
2508 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2509 // Check if this has callback object
2510 if (callbackClasses.contains(paramType)) {
2511 if (!isDefined.contains(paramType)) {
2513 println("class " + getStubInterface(paramType) + ";\n");
2515 println("class " + paramType + ";\n");
2516 isDefined.add(paramType);
2525 * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
2527 * For C++ we use virtual classe as interface
2529 public void generateCPlusInterfaces() throws IOException {
2531 // Create a new directory
2532 String path = createDirectories(dir, subdir);
2533 for (String intface : mapIntfacePTH.keySet()) {
2535 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2536 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2538 // Open a new file to write into
2539 String newIntface = intMeth.getKey();
2540 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
2541 pw = new PrintWriter(new BufferedWriter(fw));
2542 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2543 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2544 // Write file headers
2545 println("#ifndef _" + newIntface.toUpperCase() + "_HPP__");
2546 println("#define _" + newIntface.toUpperCase() + "_HPP__");
2547 println("#include <iostream>");
2548 updateIntfaceObjIdMap(intface, newIntface);
2549 // Pass in set of methods and get import classes
2550 Set<String> methods = intMeth.getValue();
2551 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, false);
2552 printIncludeStatements(includeClasses); println("");
2553 println("using namespace std;\n");
2554 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2555 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, false);
2556 println("class " + newIntface);
2560 writeMethodCplusInterface(methods, intDecl);
2564 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
2571 * HELPER: writeMethodDeclCplusStub() writes the method declarations of the stub
2573 private void writeMethodDeclCplusStub(Collection<String> methods, InterfaceDecl intDecl) {
2575 for (String method : methods) {
2577 List<String> methParams = intDecl.getMethodParams(method);
2578 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2579 print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2580 intDecl.getMethodId(method) + "(");
2581 for (int i = 0; i < methParams.size(); i++) {
2583 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2584 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2585 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2586 print(methParamComplete);
2587 // Check if this is the last element (don't print a comma)
2588 if (i != methParams.size() - 1) {
2598 * HELPER: writeMethodCplusStub() writes the methods of the stub
2600 private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
2602 for (String method : methods) {
2604 List<String> methParams = intDecl.getMethodParams(method);
2605 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2606 // Print the mutex lock first
2607 int methodNumId = intDecl.getMethodNumId(method);
2608 String mutexVar = "mtx" + newStubClass + "MethodExec" + methodNumId;
2609 println("mutex " + mutexVar + ";");
2610 print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " + newStubClass + "::" +
2611 intDecl.getMethodId(method) + "(");
2612 boolean isCallbackMethod = false;
2613 Set<String> callbackType = new HashSet<String>();
2614 for (int i = 0; i < methParams.size(); i++) {
2616 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2617 // Check if this has callback object
2618 if (callbackClasses.contains(paramType)) {
2619 isCallbackMethod = true;
2620 //callbackType = paramType;
2621 callbackType.add(paramType);
2622 // Even if there're 2 callback arguments, we expect them to be of the same interface
2624 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2625 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2626 print(methParamComplete);
2627 // Check if this is the last element (don't print a comma)
2628 if (i != methParams.size() - 1) {
2633 println("lock_guard<mutex> guard(" + mutexVar + ");");
2634 if (isCallbackMethod)
2635 writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType);
2636 writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType, isCallbackMethod);
2644 * HELPER: writeCallbackInstantiationMethodBodyCplusStub() writes the callback object instantiation in the method of the stub class
2646 private void writeCallbackInstantiationMethodBodyCplusStub(String paramIdent, String callbackType, int counter) {
2648 println("auto it" + counter + " = IoTRMIUtil::mapSkel->find(" + paramIdent + ");");
2649 println("if (it" + counter + " == IoTRMIUtil::mapSkel->end()) {");
2650 println("int newObjIdSent = rmiComm->getObjectIdCounter();");
2651 println("objIdSent" + counter + ".push_back(newObjIdSent);");
2652 println("rmiComm->decrementObjectIdCounter();");
2653 println(callbackType + "_Skeleton* skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
2654 println("IoTRMIUtil::mapSkel->insert(make_pair(" + paramIdent + ", skel" + counter + "));");
2655 println("IoTRMIUtil::mapSkelId->insert(make_pair(" + paramIdent + ", newObjIdSent));");
2656 println("thread th" + counter + " (&" + callbackType + "_Skeleton::___waitRequestInvokeMethod, std::ref(skel" + counter +
2657 "), std::ref(skel" + counter +"));");
2658 println("th" + counter + ".detach();");
2659 println("while(!skel" + counter + "->didInitWaitInvoke());");
2663 println("auto itId = IoTRMIUtil::mapSkelId->find(" + paramIdent + ");");
2664 println("objIdSent" + counter + ".push_back(itId->second);");
2670 * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class
2672 private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
2673 List<String> methPrmTypes, String method, Set<String> callbackType) {
2675 // Check if this is single object, array, or list of objects
2676 boolean isArrayOrList = false;
2677 String callbackParam = null;
2678 for (int i = 0; i < methParams.size(); i++) {
2679 String paramType = methPrmTypes.get(i);
2680 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2681 println("vector<int> objIdSent" + i + ";");
2682 String param = methParams.get(i);
2683 if (isArrayOrList(paramType, param)) { // Generate loop
2684 println("for (" + getGenericType(paramType) + "* cb : " + getSimpleIdentifier(param) + ") {");
2685 writeCallbackInstantiationMethodBodyCplusStub("cb", returnGenericCallbackType(paramType), i);
2686 isArrayOrList = true;
2687 callbackParam = getSimpleIdentifier(param);
2689 writeCallbackInstantiationMethodBodyCplusStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i);
2693 println("vector<int> ___paramCB" + i + " = objIdSent" + i + ";");
2700 * HELPER: checkAndWriteEnumTypeCplusStub() writes the enum type (convert from enum to int)
2702 private void checkAndWriteEnumTypeCplusStub(List<String> methParams, List<String> methPrmTypes) {
2704 // Iterate and find enum declarations
2705 for (int i = 0; i < methParams.size(); i++) {
2706 String paramType = methPrmTypes.get(i);
2707 String param = methParams.get(i);
2708 if (isEnumClass(getGenericType(paramType))) {
2709 // Check if this is enum type
2710 if (isArrayOrList(paramType, param)) { // An array or vector
2711 println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
2712 println("vector<int> paramEnum" + i + "(len" + i + ");");
2713 println("for (int i = 0; i < len" + i + "; i++) {");
2714 println("paramEnum" + i + "[i] = (int) " + getSimpleIdentifier(param) + "[i];");
2716 } else { // Just one element
2717 println("vector<int> paramEnum" + i + "(1);");
2718 println("paramEnum" + i + "[0] = (int) " + param + ";");
2726 * HELPER: checkAndWriteEnumRetTypeCplusStub() writes the enum return type (convert from enum to int)
2728 private void checkAndWriteEnumRetTypeCplusStub(String retType, String method, InterfaceDecl intDecl) {
2730 // Strips off array "[]" for return type
2731 String pureType = getSimpleArrayType(getGenericType(retType));
2732 // Take the inner type of generic
2733 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
2734 pureType = getGenericType(retType);
2735 if (isEnumClass(pureType)) {
2736 // Check if this is enum type
2737 println("vector<int> retEnumInt;");
2738 println("void* retObj = &retEnumInt;");
2739 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
2740 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
2741 if (isArrayOrList(retType, retType)) { // An array or vector
2742 println("int retLen = retEnumInt.size();");
2743 println("vector<" + pureType + "> retVal(retLen);");
2744 println("for (int i = 0; i < retLen; i++) {");
2745 println("retVal[i] = (" + pureType + ") retEnumInt[i];");
2747 } else { // Just one element
2748 println(pureType + " retVal = (" + pureType + ") retEnumInt[0];");
2750 println("return retVal;");
2756 * HELPER: checkAndWriteStructSetupCplusStub() writes the struct type setup
2758 private void checkAndWriteStructSetupCplusStub(List<String> methParams, List<String> methPrmTypes,
2759 InterfaceDecl intDecl, String method) {
2761 // Iterate and find struct declarations
2762 for (int i = 0; i < methParams.size(); i++) {
2763 String paramType = methPrmTypes.get(i);
2764 String param = methParams.get(i);
2765 String simpleType = getGenericType(paramType);
2766 if (isStructClass(simpleType)) {
2767 // Check if this is enum type
2768 println("int numParam" + i + " = 1;");
2769 int methodNumId = intDecl.getMethodNumId(method);
2770 String helperMethod = methodNumId + "struct" + i;
2771 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
2772 //println("string retTypeStruct" + i + " = \"void\";");
2773 println("string paramClsStruct" + i + "[] = { \"int\" };");
2774 print("int structLen" + i + " = ");
2775 if (isArrayOrList(paramType, param)) { // An array
2776 println(getSimpleArrayType(param) + ".size();");
2777 } else { // Just one element
2780 println("void* paramObjStruct" + i + "[] = { &structLen" + i + " };");
2781 //println("void* retStructLen" + i + " = NULL;");
2782 println("rmiComm->remoteCall(objectId, methodIdStruct" + i +
2783 ", paramClsStruct" + i + ", paramObjStruct" + i +
2784 ", numParam" + i + ");\n");
2791 * HELPER: writeLengthStructParamClassCplusStub() writes lengths of params
2793 private void writeLengthStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes) {
2795 // Iterate and find struct declarations - count number of params
2796 for (int i = 0; i < methParams.size(); i++) {
2797 String paramType = methPrmTypes.get(i);
2798 String param = methParams.get(i);
2799 String simpleType = getGenericType(paramType);
2800 if (isStructClass(simpleType)) {
2801 int members = getNumOfMembers(simpleType);
2802 if (isArrayOrList(paramType, param)) { // An array or list
2803 String structLen = getSimpleIdentifier(param) + ".size()";
2804 print(members + "*" + structLen);
2806 print(Integer.toString(members));
2809 if (i != methParams.size() - 1) {
2817 * HELPER: writeStructMembersCplusStub() writes member parameters of struct
2819 private void writeStructMembersCplusStub(String simpleType, String paramType, String param) {
2821 // Get the struct declaration for this struct and generate initialization code
2822 StructDecl structDecl = getStructDecl(simpleType);
2823 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2824 List<String> members = structDecl.getMembers(simpleType);
2825 if (isArrayOrList(paramType, param)) { // An array or list
2826 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
2828 if (isArrayOrList(paramType, param)) { // An array or list
2829 for (int i = 0; i < members.size(); i++) {
2830 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2831 println("paramCls[pos] = \"" + prmTypeC + "\";");
2832 print("paramObj[pos++] = &" + getSimpleIdentifier(param) + "[i].");
2833 print(getSimpleIdentifier(members.get(i)));
2837 } else { // Just one struct element
2838 for (int i = 0; i < members.size(); i++) {
2839 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2840 println("paramCls[pos] = \"" + prmTypeC + "\";");
2841 print("paramObj[pos++] = &" + param + ".");
2842 print(getSimpleIdentifier(members.get(i)));
2850 * HELPER: writeStructParamClassCplusStub() writes member parameters of struct
2852 private void writeStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
2854 print("int numParam = ");
2855 writeLengthStructParamClassCplusStub(methParams, methPrmTypes);
2857 println("void* paramObj[numParam];");
2858 println("string paramCls[numParam];");
2859 println("int pos = 0;");
2860 // Iterate again over the parameters
2861 for (int i = 0; i < methParams.size(); i++) {
2862 String paramType = methPrmTypes.get(i);
2863 String param = methParams.get(i);
2864 String simpleType = getGenericType(paramType);
2865 if (isStructClass(simpleType)) {
2866 writeStructMembersCplusStub(simpleType, paramType, param);
2867 } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2868 println("paramCls[pos] = \"int\";");
2869 println("paramObj[pos++] = &___paramCB" + i + ";");
2871 String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
2872 println("paramCls[pos] = \"" + prmTypeC + "\";");
2873 print("paramObj[pos++] = &");
2874 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
2883 * HELPER: writeStructRetMembersCplusStub() writes member parameters of struct for return statement
2885 private void writeStructRetMembersCplusStub(String simpleType, String retType) {
2887 // Get the struct declaration for this struct and generate initialization code
2888 StructDecl structDecl = getStructDecl(simpleType);
2889 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2890 List<String> members = structDecl.getMembers(simpleType);
2891 if (isArrayOrList(retType, retType)) { // An array or list
2892 println("for(int i = 0; i < retLen; i++) {");
2894 if (isArrayOrList(retType, retType)) { // An array or list
2895 for (int i = 0; i < members.size(); i++) {
2896 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2897 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
2898 println(" = retParam" + i + "[i];");
2901 } else { // Just one struct element
2902 for (int i = 0; i < members.size(); i++) {
2903 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2904 print("structRet." + getSimpleIdentifier(members.get(i)));
2905 println(" = retParam" + i + ";");
2908 println("return structRet;");
2913 * HELPER: writeStructReturnCplusStub() writes member parameters of struct for return statement
2915 private void writeStructReturnCplusStub(String simpleType, String retType, String method, InterfaceDecl intDecl) {
2917 // Minimum retLen is 1 if this is a single struct object
2918 println("int retLen = 0;");
2919 println("void* retLenObj = { &retLen };");
2920 // Handle the returned struct!!!
2921 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
2922 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retLenObj);");
2923 int numMem = getNumOfMembers(simpleType);
2924 println("int numRet = " + numMem + "*retLen;");
2925 println("string retCls[numRet];");
2926 println("void* retObj[numRet];");
2927 StructDecl structDecl = getStructDecl(simpleType);
2928 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2929 List<String> members = structDecl.getMembers(simpleType);
2931 if (isArrayOrList(retType, retType)) { // An array or list
2932 for (int i = 0; i < members.size(); i++) {
2933 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2934 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2935 println(getSimpleType(getEnumType(prmType)) + " retParam" + i + "[retLen];");
2937 } else { // Just one struct element
2938 for (int i = 0; i < members.size(); i++) {
2939 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2940 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2941 println(getSimpleType(getEnumType(prmType)) + " retParam" + i + ";");
2944 println("int retPos = 0;");
2945 // Get the struct declaration for this struct and generate initialization code
2946 if (isArrayOrList(retType, retType)) { // An array or list
2947 println("for(int i = 0; i < retLen; i++) {");
2948 for (int i = 0; i < members.size(); i++) {
2949 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2950 println("retCls[retPos] = \"" + prmTypeC + "\";");
2951 println("retObj[retPos++] = &retParam" + i + "[i];");
2954 } else { // Just one struct element
2955 for (int i = 0; i < members.size(); i++) {
2956 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2957 println("retCls[retPos] = \"" + prmTypeC + "\";");
2958 println("retObj[retPos++] = &retParam" + i + ";");
2961 //println("rmiComm->getStructObjects(retCls, numRet, retObj);");
2962 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getStructObjects(retCls, numRet, retObj);");
2963 if (isArrayOrList(retType, retType)) { // An array or list
2964 println("vector<" + simpleType + "> structRet(retLen);");
2966 println(simpleType + " structRet;");
2967 writeStructRetMembersCplusStub(simpleType, retType);
2972 * HELPER: writeWaitForReturnValueCplus() writes the synchronization part for return values
2974 private void writeWaitForReturnValueCplus(String method, InterfaceDecl intDecl, String getReturnValue) {
2976 println("// Waiting for return value");
2977 int methodNumId = intDecl.getMethodNumId(method);
2978 println("while (!retValueReceived" + methodNumId + ");");
2979 println(getReturnValue);
2980 println("retValueReceived" + methodNumId + " = false;");
2981 println("didGetReturnBytes.exchange(true);\n");
2986 * HELPER: writeStdMethodBodyCplusStub() writes the standard method body in the stub class
2988 private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
2989 List<String> methPrmTypes, String method, Set<String> callbackType, boolean isCallbackMethod) {
2991 checkAndWriteStructSetupCplusStub(methParams, methPrmTypes, intDecl, method);
2992 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
2993 String retType = intDecl.getMethodType(method);
2994 println("string retType = \"" + checkAndGetCplusRetClsType(getStructType(getEnumType(retType))) + "\";");
2995 checkAndWriteEnumTypeCplusStub(methParams, methPrmTypes);
2996 // Generate array of parameter types
2997 if (isStructPresent(methParams, methPrmTypes)) {
2998 writeStructParamClassCplusStub(methParams, methPrmTypes, callbackType);
3000 println("int numParam = " + methParams.size() + ";");
3001 print("string paramCls[] = { ");
3002 for (int i = 0; i < methParams.size(); i++) {
3003 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3004 if (checkCallbackType(paramType, callbackType)) {
3007 String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3008 print("\"" + paramTypeC + "\"");
3010 // Check if this is the last element (don't print a comma)
3011 if (i != methParams.size() - 1) {
3016 // Generate array of parameter objects
3017 print("void* paramObj[] = { ");
3018 for (int i = 0; i < methParams.size(); i++) {
3019 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3020 if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
3021 print("&___paramCB" + i);
3023 print("&" + getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
3024 // Check if this is the last element (don't print a comma)
3025 if (i != methParams.size() - 1) {
3031 // Check if this is "void"
3032 if (retType.equals("void")) {
3033 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
3034 } else { // We do have a return value
3035 // Generate array of parameter types
3036 if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
3037 writeStructReturnCplusStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl);
3039 // Check if the return value NONPRIMITIVES
3040 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) {
3041 checkAndWriteEnumRetTypeCplusStub(retType, method, intDecl);
3043 //if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
3044 if (isArrayOrList(retType,retType))
3045 println(checkAndGetCplusType(retType) + " retVal;");
3047 println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";");
3049 println("void* retObj = &retVal;");
3050 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
3051 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
3052 println("return retVal;");
3060 * HELPER: writePropertiesCplusPermission() writes the properties of the stub class
3062 private void writePropertiesCplusPermission(String intface) {
3064 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3065 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3066 String newIntface = intMeth.getKey();
3067 int newObjectId = getNewIntfaceObjectId(newIntface);
3068 println("int objectId = " + newObjectId + ";");
3069 println("static set<int> set" + newObjectId + "Allowed;");
3074 * HELPER: writePropertiesCplusStub() writes the properties of the stub class
3076 private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist,
3077 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3079 println("IoTRMIComm *rmiComm;");
3080 // Get the object Id
3081 Integer objId = mapIntfaceObjId.get(intface);
3082 println("int objectId = " + objId + ";");
3083 println("// Synchronization variables");
3084 for (String method : methods) {
3085 // Generate AtomicBooleans for methods that have return values
3086 String returnType = intDecl.getMethodType(method);
3087 int methodNumId = intDecl.getMethodNumId(method);
3088 if (!returnType.equals("void")) {
3089 println("bool retValueReceived" + methodNumId + " = false;");
3097 * HELPER: writeConstructorCplusStub() writes the constructor of the stub class
3099 private void writeConstructorCplusStub(String newStubClass, boolean callbackExist,
3100 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3102 println(newStubClass + "::" + newStubClass +
3103 "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult) {");
3104 println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev, _bResult);");
3105 // Register the AtomicBoolean variables
3106 for (String method : methods) {
3107 // Generate AtomicBooleans for methods that have return values
3108 String returnType = intDecl.getMethodType(method);
3109 int methodNumId = intDecl.getMethodNumId(method);
3110 if (!returnType.equals("void")) {
3111 println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");");
3114 println("IoTRMIUtil::mapStub->insert(make_pair(objectId, this));");
3120 * HELPER: writeCallbackConstructorCplusStub() writes the callback constructor of the stub class
3122 private void writeCallbackConstructorCplusStub(String newStubClass, boolean callbackExist,
3123 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3125 println(newStubClass + "::" + newStubClass + "(IoTRMIComm* _rmiComm, int _objectId) {");
3126 println("rmiComm = _rmiComm;");
3127 println("objectId = _objectId;");
3128 // Register the AtomicBoolean variables
3129 for (String method : methods) {
3130 // Generate AtomicBooleans for methods that have return values
3131 String returnType = intDecl.getMethodType(method);
3132 int methodNumId = intDecl.getMethodNumId(method);
3133 if (!returnType.equals("void")) {
3134 println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");");
3142 * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
3144 private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
3146 println(newStubClass + "::~" + newStubClass + "() {");
3147 println("if (rmiComm != NULL) {");
3148 println("delete rmiComm;");
3149 println("rmiComm = NULL;");
3157 * HELPER: writeCplusMethodCallbackPermission() writes permission checks in stub for callbacks
3159 private void writeCplusMethodCallbackPermission(String intface) {
3161 println("int methodId = IoTRMIObject::getMethodId(method);");
3162 // Get all the different stubs
3163 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3164 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3165 String newIntface = intMeth.getKey();
3166 int newObjectId = getNewIntfaceObjectId(newIntface);
3167 println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
3168 println("cerr << \"Callback object for " + intface + " is not allowed to access method: \" << methodId;");
3176 * generateCPlusStubClassesHpp() generate stubs based on the methods list in C++ (.hpp file)
3178 public void generateCPlusStubClassesHpp() throws IOException {
3180 // Create a new directory
3181 String path = createDirectories(dir, subdir);
3182 for (String intface : mapIntfacePTH.keySet()) {
3184 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3185 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3186 // Open a new file to write into
3187 String newIntface = intMeth.getKey();
3188 String newStubClass = newIntface + "_Stub";
3189 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
3190 pw = new PrintWriter(new BufferedWriter(fw));
3191 // Write file headers
3192 println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
3193 println("#define _" + newStubClass.toUpperCase() + "_HPP__");
3194 println("#include <iostream>");
3195 // Find out if there are callback objects
3196 Set<String> methods = intMeth.getValue();
3197 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3198 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3199 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3200 boolean callbackExist = !callbackClasses.isEmpty();
3201 println("#include <thread>");
3202 println("#include <mutex>");
3203 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
3204 printIncludeStatements(stdIncludeClasses); println("");
3205 println("#include \"" + newIntface + ".hpp\""); println("");
3206 println("using namespace std;"); println("");
3207 println("class " + newStubClass + " : public " + newIntface); println("{");
3208 println("private:\n");
3209 writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses, methods, intDecl);
3210 println("public:\n");
3211 // Add default constructor and destructor
3212 println(newStubClass + "();");
3214 println(newStubClass + "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult);");
3215 println(newStubClass + "(IoTRMIComm* _rmiComm, int _objectId);");
3216 println("~" + newStubClass + "();");
3218 writeMethodDeclCplusStub(methods, intDecl);
3219 print("}"); println(";");
3222 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
3229 * writeStubExternalCFunctions() generate external functions for .so file
3231 public void writeStubExternalCFunctions(String newStubClass) throws IOException {
3233 println("extern \"C\" void* create" + newStubClass + "(void** params) {");
3234 println("// Args: int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult");
3235 println("return new " + newStubClass + "(*((int*) params[0]), *((int*) params[1]), ((string*) params[2])->c_str(), " +
3236 "*((int*) params[3]), (bool*) params[4]);");
3238 println("extern \"C\" void destroy" + newStubClass + "(void* t) {");
3239 println(newStubClass + "* obj = (" + newStubClass + "*) t;");
3240 println("delete obj;");
3242 println("extern \"C\" void init" + newStubClass + "(void* t) {");
3243 //println(newStubClass + "* obj = (" + newStubClass + "*) t;");
3244 //println("obj->init();");
3245 //println("while(true);");
3251 * generateCPlusStubClassesCpp() generate stubs based on the methods list in C++ (.cpp file)
3253 public void generateCPlusStubClassesCpp() throws IOException {
3255 // Create a new directory
3256 String path = createDirectories(dir, subdir);
3257 for (String intface : mapIntfacePTH.keySet()) {
3259 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3260 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3261 // Open a new file to write into
3262 String newIntface = intMeth.getKey();
3263 String newStubClass = newIntface + "_Stub";
3264 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".cpp");
3265 pw = new PrintWriter(new BufferedWriter(fw));
3266 // Write file headers
3267 println("#include <iostream>");
3268 // Find out if there are callback objects
3269 Set<String> methods = intMeth.getValue();
3270 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3271 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3272 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3273 boolean callbackExist = !callbackClasses.isEmpty();
3274 println("#include \"" + newStubClass + ".hpp\""); println("");
3275 for(String str: callbackClasses) {
3276 if (intface.equals(mainClass))
3277 println("#include \"" + str + "_Skeleton.cpp\"\n");
3279 println("#include \"" + str + "_Skeleton.hpp\"\n");
3281 println("using namespace std;"); println("");
3282 // Add default constructor and destructor
3283 //println(newStubClass + "() { }"); println("");
3284 writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
3285 writeCallbackConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
3286 writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
3288 writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass);
3289 // Write external functions for .so file
3290 writeStubExternalCFunctions(newStubClass);
3291 // TODO: Remove this later
3292 if (intface.equals(mainClass)) {
3293 println("int main() {");
3294 println("return 0;");
3298 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".cpp...");
3305 * HELPER: writePropertiesCplusSkeleton() writes the properties of the skeleton class
3307 private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
3309 println(intface + " *mainObj;");
3310 println("IoTRMIComm *rmiComm;");
3311 println("char* methodBytes;");
3312 println("int methodLen;");
3313 // Keep track of object Ids of all stubs registered to this interface
3314 writePropertiesCplusPermission(intface);
3315 println("// Synchronization variables");
3316 println("bool methodReceived = false;");
3317 println("bool didAlreadyInitWaitInvoke = false;");
3323 * HELPER: writeObjectIdCountInitializationCplus() writes the initialization of objIdCnt variable
3325 private void writeObjectIdCountInitializationCplus(String newSkelClass, boolean callbackExist) {
3328 println("int " + newSkelClass + "::objIdCnt = 0;");
3333 * HELPER: writePermissionInitializationCplus() writes the initialization of permission set
3335 private void writePermissionInitializationCplus(String intface, String newSkelClass, InterfaceDecl intDecl) {
3337 // Keep track of object Ids of all stubs registered to this interface
3338 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3339 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3340 String newIntface = intMeth.getKey();
3341 int newObjectId = getNewIntfaceObjectId(newIntface);
3342 print("set<int> " + newSkelClass + "::set" + newObjectId + "Allowed { ");
3343 Set<String> methodIds = intMeth.getValue();
3345 for (String methodId : methodIds) {
3346 int methodNumId = intDecl.getMethodNumId(methodId);
3347 print(Integer.toString(methodNumId));
3348 // Check if this is the last element (don't print a comma)
3349 if (i != methodIds.size() - 1) {
3360 * HELPER: writeStructPermissionCplusSkeleton() writes permission for struct helper
3362 private void writeStructPermissionCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
3364 // Use this set to handle two same methodIds
3365 for (String method : methods) {
3366 List<String> methParams = intDecl.getMethodParams(method);
3367 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3368 // Check for params with structs
3369 for (int i = 0; i < methParams.size(); i++) {
3370 String paramType = methPrmTypes.get(i);
3371 String param = methParams.get(i);
3372 String simpleType = getGenericType(paramType);
3373 if (isStructClass(simpleType)) {
3374 int methodNumId = intDecl.getMethodNumId(method);
3375 String helperMethod = methodNumId + "struct" + i;
3376 int helperMethodNumId = intDecl.getHelperMethodNumId(helperMethod);
3377 // Iterate over interfaces to give permissions to
3378 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3379 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3380 String newIntface = intMeth.getKey();
3381 int newObjectId = getNewIntfaceObjectId(newIntface);
3382 println("set" + newObjectId + "Allowed.insert(" + helperMethodNumId + ");");
3391 * HELPER: writeConstructorCplusSkeleton() writes the constructor of the skeleton class
3393 private void writeConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
3395 println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, int _portSend, int _portRecv) {");
3396 println("bool _bResult = false;");
3397 println("mainObj = _mainObj;");
3398 println("rmiComm = new IoTRMICommServer(_portSend, _portRecv, &_bResult);");
3399 println("IoTRMIUtil::mapSkel->insert(make_pair(_mainObj, this));");
3400 println("IoTRMIUtil::mapSkelId->insert(make_pair(_mainObj, objectId));");
3401 println("rmiComm->registerSkeleton(objectId, &methodReceived);");
3402 writeStructPermissionCplusSkeleton(methods, intDecl, intface);
3403 println("thread th1 (&" + newSkelClass + "::___waitRequestInvokeMethod, this, this);");
3404 println("th1.join();");
3410 * HELPER: writeCallbackConstructorCplusSkeleton() writes the callback constructor of the skeleton class
3412 private void writeCallbackConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
3414 println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, IoTRMIComm *_rmiComm, int _objectId) {");
3415 println("bool _bResult = false;");
3416 println("mainObj = _mainObj;");
3417 println("rmiComm = _rmiComm;");
3418 println("objectId = _objectId;");
3419 println("rmiComm->registerSkeleton(objectId, &methodReceived);");
3420 writeStructPermissionCplusSkeleton(methods, intDecl, intface);
3426 * HELPER: writeDeconstructorCplusSkeleton() writes the deconstructor of the skeleton class
3428 private void writeDeconstructorCplusSkeleton(String newSkelClass, boolean callbackExist, Set<String> callbackClasses) {
3430 println(newSkelClass + "::~" + newSkelClass + "() {");
3431 println("if (rmiComm != NULL) {");
3432 println("delete rmiComm;");
3433 println("rmiComm = NULL;");
3441 * HELPER: writeStdMethodBodyCplusSkeleton() writes the standard method body in the skeleton class
3443 private void writeStdMethodBodyCplusSkeleton(List<String> methParams, String methodId, String methodType) {
3445 if (methodType.equals("void"))
3446 print("mainObj->" + methodId + "(");
3448 print("return mainObj->" + methodId + "(");
3449 for (int i = 0; i < methParams.size(); i++) {
3451 print(getSimpleIdentifier(methParams.get(i)));
3452 // Check if this is the last element (don't print a comma)
3453 if (i != methParams.size() - 1) {
3462 * HELPER: writeMethodDeclCplusSkeleton() writes the method declaration of the skeleton class
3464 private void writeMethodDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
3465 Set<String> callbackClasses) {
3467 for (String method : methods) {
3469 List<String> methParams = intDecl.getMethodParams(method);
3470 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3471 String methodId = intDecl.getMethodId(method);
3472 String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
3473 print(methodType + " " + methodId + "(");
3474 boolean isCallbackMethod = false;
3475 String callbackType = null;
3476 for (int i = 0; i < methParams.size(); i++) {
3478 String origParamType = methPrmTypes.get(i);
3479 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
3480 isCallbackMethod = true;
3481 callbackType = origParamType;
3483 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
3484 String methPrmType = checkAndGetCplusType(paramType);
3485 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3486 print(methParamComplete);
3487 // Check if this is the last element (don't print a comma)
3488 if (i != methParams.size() - 1) {
3498 * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class
3500 private void writeMethodCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String newSkelClass) {
3502 for (String method : methods) {
3504 List<String> methParams = intDecl.getMethodParams(method);
3505 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3506 String methodId = intDecl.getMethodId(method);
3507 String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
3508 print(methodType + " " + newSkelClass + "::" + methodId + "(");
3509 for (int i = 0; i < methParams.size(); i++) {
3511 String origParamType = methPrmTypes.get(i);
3512 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
3513 String methPrmType = checkAndGetCplusType(paramType);
3514 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3515 print(methParamComplete);
3516 // Check if this is the last element (don't print a comma)
3517 if (i != methParams.size() - 1) {
3522 // Now, write the body of skeleton!
3523 writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method));
3530 * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable
3532 private void writeCallbackCplusNumStubs(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
3534 for (int i = 0; i < methParams.size(); i++) {
3535 String paramType = methPrmTypes.get(i);
3536 String param = methParams.get(i);
3537 //if (callbackType.equals(paramType)) {
3538 if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
3539 //println("int numStubs" + i + " = 0;");
3540 println("vector<int> numStubIdArray" + i + ";");
3546 * HELPER: writeCallbackInstantiationCplusStubGeneration() writes the instantiation of callback stubs
3548 private void writeCallbackInstantiationCplusStubGeneration(String exchParamType, int counter) {
3550 println(exchParamType + "* newStub" + counter + " = NULL;");
3551 println("auto it" + counter + " = IoTRMIUtil::mapStub->find(objIdRecv" + counter + ");");
3552 println("if (it" + counter + " == IoTRMIUtil::mapStub->end()) {");
3553 println("newStub" + counter + " = new " + exchParamType + "_Stub(rmiComm, objIdRecv" + counter + ");");
3554 println("IoTRMIUtil::mapStub->insert(make_pair(objIdRecv" + counter + ", newStub" + counter + "));");
3555 println("rmiComm->setObjectIdCounter(objIdRecv" + counter + ");");
3556 println("rmiComm->decrementObjectIdCounter();");
3559 println("newStub" + counter + " = (" + exchParamType + "_Stub*) it" + counter + "->second;");
3565 * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part
3567 private void writeCallbackCplusStubGeneration(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
3569 // Iterate over callback objects
3570 for (int i = 0; i < methParams.size(); i++) {
3571 String paramType = methPrmTypes.get(i);
3572 String param = methParams.get(i);
3573 // Generate a loop if needed
3574 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
3575 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
3576 if (isArrayOrList(paramType, param)) {
3577 println("vector<" + exchParamType + "*> stub" + i + ";");
3578 println("for (int i = 0; i < numStubIdArray" + i + ".size(); i++) {");
3579 println("int objIdRecv" + i + " = numStubIdArray" + i + "[i];");
3580 writeCallbackInstantiationCplusStubGeneration(exchParamType, i);
3581 println("stub" + i + ".push_back(newStub" + i + ");");
3584 println("int objIdRecv" + i + " = numStubIdArray" + i + "[0];");
3585 writeCallbackInstantiationCplusStubGeneration(exchParamType, i);
3586 println(exchParamType + "* stub" + i + " = newStub" + i + ";");
3594 * HELPER: checkAndWriteEnumTypeCplusSkeleton() writes the enum type (convert from enum to int)
3596 private void checkAndWriteEnumTypeCplusSkeleton(List<String> methParams, List<String> methPrmTypes) {
3598 // Iterate and find enum declarations
3599 for (int i = 0; i < methParams.size(); i++) {
3600 String paramType = methPrmTypes.get(i);
3601 String param = methParams.get(i);
3602 String simpleType = getGenericType(paramType);
3603 if (isEnumClass(simpleType)) {
3604 // Check if this is enum type
3605 if (isArrayOrList(paramType, param)) { // An array
3606 println("int len" + i + " = paramEnumInt" + i + ".size();");
3607 println("vector<" + simpleType + "> paramEnum" + i + "(len" + i + ");");
3608 println("for (int i=0; i < len" + i + "; i++) {");
3609 println("paramEnum" + i + "[i] = (" + simpleType + ") paramEnumInt" + i + "[i];");
3611 } else { // Just one element
3612 println(simpleType + " paramEnum" + i + ";");
3613 println("paramEnum" + i + " = (" + simpleType + ") paramEnumInt" + i + "[0];");
3621 * HELPER: checkAndWriteEnumRetTypeCplusSkeleton() writes the enum return type (convert from enum to int)
3623 private void checkAndWriteEnumRetTypeCplusSkeleton(String retType) {
3625 // Strips off array "[]" for return type
3626 String pureType = getSimpleArrayType(getGenericType(retType));
3627 // Take the inner type of generic
3628 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
3629 pureType = getGenericType(retType);
3630 if (isEnumClass(pureType)) {
3631 // Check if this is enum type
3633 if (isArrayOrList(retType, retType)) { // An array
3634 println("int retLen = retEnum.size();");
3635 println("vector<int> retEnumInt(retLen);");
3636 println("for (int i=0; i < retLen; i++) {");
3637 println("retEnumInt[i] = (int) retEnum[i];");
3639 } else { // Just one element
3640 println("vector<int> retEnumInt(1);");
3641 println("retEnumInt[0] = (int) retEnum;");
3648 * HELPER: writeMethodInputParameters() writes the parameter variables for C++ skeleton
3650 private void writeMethodInputParameters(List<String> methParams, List<String> methPrmTypes,
3651 Set<String> callbackClasses, String methodId) {
3653 print(methodId + "(");
3654 for (int i = 0; i < methParams.size(); i++) {
3655 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3656 if (callbackClasses.contains(paramType))
3658 else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3659 print("paramEnum" + i);
3660 else if (isStructClass(getGenericType(paramType))) // Struct type
3661 print("paramStruct" + i);
3663 print(getSimpleIdentifier(methParams.get(i)));
3664 if (i != methParams.size() - 1) {
3673 * HELPER: writeMethodHelperReturnCplusSkeleton() writes the return statement part in skeleton
3675 private void writeMethodHelperReturnCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3676 List<String> methPrmTypes, String method, boolean isCallbackMethod, Set<String> callbackType,
3677 String methodId, Set<String> callbackClasses) {
3679 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
3680 if (isCallbackMethod)
3681 writeCallbackCplusStubGeneration(methParams, methPrmTypes, callbackType);
3682 checkAndWriteEnumTypeCplusSkeleton(methParams, methPrmTypes);
3683 writeStructMembersInitCplusSkeleton(intDecl, methParams, methPrmTypes, method);
3684 // Check if this is "void"
3685 String retType = intDecl.getMethodType(method);
3686 // Check if this is "void"
3687 if (retType.equals("void")) {
3688 writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3689 } else { // We do have a return value
3690 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
3691 print(checkAndGetCplusType(retType) + " retEnum = ");
3692 else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3693 print(checkAndGetCplusType(retType) + " retStruct = ");
3695 print(checkAndGetCplusType(retType) + " retVal = ");
3696 writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3697 checkAndWriteEnumRetTypeCplusSkeleton(retType);
3698 if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3699 writeStructReturnCplusSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
3700 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
3701 println("void* retObj = &retEnumInt;");
3703 if (!isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3704 println("void* retObj = &retVal;");
3705 String retTypeC = checkAndGetCplusType(retType);
3706 if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3707 println("rmiComm->sendReturnObj(retObj, retCls, numRetObj, localMethodBytes);");
3709 println("rmiComm->sendReturnObj(retObj, \"" + checkAndGetCplusRetClsType(getEnumType(retType)) + "\", localMethodBytes);");
3715 * HELPER: writeStdMethodHelperBodyCplusSkeleton() writes the standard method body helper in the skeleton class
3717 private void writeStdMethodHelperBodyCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3718 List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3720 // Generate array of parameter types
3721 boolean isCallbackMethod = false;
3722 //String callbackType = null;
3723 Set<String> callbackType = new HashSet<String>();
3724 print("string paramCls[] = { ");
3725 for (int i = 0; i < methParams.size(); i++) {
3726 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3727 if (callbackClasses.contains(paramType)) {
3728 isCallbackMethod = true;
3729 //callbackType = paramType;
3730 callbackType.add(paramType);
3732 } else { // Generate normal classes if it's not a callback object
3733 String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3734 print("\"" + paramTypeC + "\"");
3736 if (i != methParams.size() - 1) {
3741 println("int numParam = " + methParams.size() + ";");
3742 if (isCallbackMethod)
3743 writeCallbackCplusNumStubs(methParams, methPrmTypes, callbackType);
3744 // Generate parameters
3745 for (int i = 0; i < methParams.size(); i++) {
3746 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3747 if (!callbackClasses.contains(paramType)) {
3748 String methParamType = methPrmTypes.get(i);
3749 if (isEnumClass(getSimpleArrayType(getGenericType(methParamType)))) {
3750 // Check if this is enum type
3751 println("vector<int> paramEnumInt" + i + ";");
3753 String methPrmType = checkAndGetCplusType(methParamType);
3754 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3755 println(methParamComplete + ";");
3759 // Generate array of parameter objects
3760 print("void* paramObj[] = { ");
3761 for (int i = 0; i < methParams.size(); i++) {
3762 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3763 if (callbackClasses.contains(paramType))
3764 print("&numStubIdArray" + i);
3765 else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3766 print("¶mEnumInt" + i);
3768 print("&" + getSimpleIdentifier(methParams.get(i)));
3769 if (i != methParams.size() - 1) {
3774 // Write the return value part
3775 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
3776 callbackType, methodId, callbackClasses);
3781 * HELPER: writeStructMembersCplusSkeleton() writes member parameters of struct
3783 private void writeStructMembersCplusSkeleton(String simpleType, String paramType,
3784 String param, String method, InterfaceDecl intDecl, int iVar) {
3786 // Get the struct declaration for this struct and generate initialization code
3787 StructDecl structDecl = getStructDecl(simpleType);
3788 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3789 List<String> members = structDecl.getMembers(simpleType);
3790 int methodNumId = intDecl.getMethodNumId(method);
3791 String counter = "struct" + methodNumId + "Size" + iVar;
3793 if (isArrayOrList(paramType, param)) { // An array or list
3794 for (int i = 0; i < members.size(); i++) {
3795 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3796 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3797 println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + "[" + counter + "];");
3799 } else { // Just one struct element
3800 for (int i = 0; i < members.size(); i++) {
3801 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3802 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3803 println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + ";");
3806 if (isArrayOrList(paramType, param)) { // An array or list
3807 println("for(int i = 0; i < " + counter + "; i++) {");
3809 if (isArrayOrList(paramType, param)) { // An array or list
3810 for (int i = 0; i < members.size(); i++) {
3811 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3812 println("paramCls[pos] = \"" + prmTypeC + "\";");
3813 println("paramObj[pos++] = ¶m" + iVar + i + "[i];");
3816 } else { // Just one struct element
3817 for (int i = 0; i < members.size(); i++) {
3818 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3819 println("paramCls[pos] = \"" + prmTypeC + "\";");
3820 println("paramObj[pos++] = ¶m" + iVar + i + ";");
3827 * HELPER: writeStructMembersInitCplusSkeleton() writes member parameters initialization of struct
3829 private void writeStructMembersInitCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3830 List<String> methPrmTypes, String method) {
3832 for (int i = 0; i < methParams.size(); i++) {
3833 String paramType = methPrmTypes.get(i);
3834 String param = methParams.get(i);
3835 String simpleType = getGenericType(paramType);
3836 if (isStructClass(simpleType)) {
3837 int methodNumId = intDecl.getMethodNumId(method);
3838 String counter = "struct" + methodNumId + "Size" + i;
3840 if (isArrayOrList(paramType, param)) { // An array or list
3841 println("vector<" + simpleType + "> paramStruct" + i + "(" + counter + ");");
3843 println(simpleType + " paramStruct" + i + ";");
3844 // Initialize members
3845 StructDecl structDecl = getStructDecl(simpleType);
3846 List<String> members = structDecl.getMembers(simpleType);
3847 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3848 if (isArrayOrList(paramType, param)) { // An array or list
3849 println("for(int i = 0; i < " + counter + "; i++) {");
3850 for (int j = 0; j < members.size(); j++) {
3851 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
3852 println(" = param" + i + j + "[i];");
3855 } else { // Just one struct element
3856 for (int j = 0; j < members.size(); j++) {
3857 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
3858 println(" = param" + i + j + ";");
3867 * HELPER: writeStructReturnCplusSkeleton() writes parameters of struct for return statement
3869 private void writeStructReturnCplusSkeleton(String simpleType, String retType) {
3871 // Minimum retLen is 1 if this is a single struct object
3872 if (isArrayOrList(retType, retType))
3873 println("int retLen = retStruct.size();");
3874 else // Just single struct object
3875 println("int retLen = 1;");
3876 println("void* retLenObj = &retLen;");
3877 println("rmiComm->sendReturnObj(retLenObj, \"int\", localMethodBytes);");
3878 int numMem = getNumOfMembers(simpleType);
3879 println("int numRetObj = " + numMem + "*retLen;");
3880 println("string retCls[numRetObj];");
3881 println("void* retObj[numRetObj];");
3882 println("int retPos = 0;");
3883 // Get the struct declaration for this struct and generate initialization code
3884 StructDecl structDecl = getStructDecl(simpleType);
3885 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3886 List<String> members = structDecl.getMembers(simpleType);
3887 if (isArrayOrList(retType, retType)) { // An array or list
3888 println("for(int i = 0; i < retLen; i++) {");
3889 for (int i = 0; i < members.size(); i++) {
3890 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3891 println("retCls[retPos] = \"" + prmTypeC + "\";");
3892 print("retObj[retPos++] = &retStruct[i].");
3893 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3897 } else { // Just one struct element
3898 for (int i = 0; i < members.size(); i++) {
3899 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3900 println("retCls[retPos] = \"" + prmTypeC + "\";");
3901 print("retObj[retPos++] = &retStruct.");
3902 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3911 * HELPER: writeMethodHelperStructCplusSkeleton() writes the struct in skeleton
3913 private void writeMethodHelperStructCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3914 List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3916 // Generate array of parameter objects
3917 boolean isCallbackMethod = false;
3918 Set<String> callbackType = new HashSet<String>();
3919 print("int numParam = ");
3920 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
3922 println("string paramCls[numParam];");
3923 println("void* paramObj[numParam];");
3924 println("int pos = 0;");
3925 // Iterate again over the parameters
3926 for (int i = 0; i < methParams.size(); i++) {
3927 String paramType = methPrmTypes.get(i);
3928 String param = methParams.get(i);
3929 String simpleType = getGenericType(paramType);
3930 if (isStructClass(simpleType)) {
3931 writeStructMembersCplusSkeleton(simpleType, paramType, param, method, intDecl, i);
3933 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
3934 if (callbackClasses.contains(prmType)) {
3935 isCallbackMethod = true;
3936 //callbackType = prmType;
3937 callbackType.add(prmType);
3938 //println("int numStubs" + i + " = 0;");
3939 println("vector<int> numStubIdArray" + i + ";");
3940 println("paramCls[pos] = \"int*\";");
3941 println("paramObj[pos++] = &numStubIdArray" + i + ";");
3942 } else { // Generate normal classes if it's not a callback object
3943 String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
3944 if (isEnumClass(getGenericType(paramTypeC))) { // Check if this is enum type
3945 println("vector<int> paramEnumInt" + i + ";");
3947 String methParamComplete = checkAndGetCplusArray(paramTypeC, methParams.get(i));
3948 println(methParamComplete + ";");
3950 String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3951 println("paramCls[pos] = \"" + prmTypeC + "\";");
3952 if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3953 println("paramObj[pos++] = ¶mEnumInt" + i + ";");
3955 println("paramObj[pos++] = &" + getSimpleIdentifier(methParams.get(i)) + ";");
3959 // Write the return value part
3960 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
3961 callbackType, methodId, callbackClasses);
3966 * HELPER: writeMethodHelperDeclCplusSkeleton() writes the method helper declarations of the skeleton class
3968 private void writeMethodHelperDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String newSkelClass) {
3970 // Use this set to handle two same methodIds
3971 Set<String> uniqueMethodIds = new HashSet<String>();
3972 for (String method : methods) {
3974 List<String> methParams = intDecl.getMethodParams(method);
3975 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3976 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
3977 String methodId = intDecl.getMethodId(method);
3979 String helperMethod = methodId;
3980 if (uniqueMethodIds.contains(methodId))
3981 helperMethod = helperMethod + intDecl.getMethodNumId(method);
3983 uniqueMethodIds.add(methodId);
3984 String retType = intDecl.getMethodType(method);
3985 print(helperMethod + "(");
3986 boolean begin = true;
3987 for (int i = 0; i < methParams.size(); i++) { // Print size variables
3988 String paramType = methPrmTypes.get(i);
3989 String param = methParams.get(i);
3990 String simpleType = getGenericType(paramType);
3991 if (isStructClass(simpleType)) {
3992 if (!begin) // Generate comma for not the beginning variable
3996 int methodNumId = intDecl.getMethodNumId(method);
3997 print("int struct" + methodNumId + "Size" + i);
4000 println(", " + newSkelClass + "* skel);");
4002 String methodId = intDecl.getMethodId(method);
4004 String helperMethod = methodId;
4005 if (uniqueMethodIds.contains(methodId))
4006 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4008 uniqueMethodIds.add(methodId);
4009 // Check if this is "void"
4010 String retType = intDecl.getMethodType(method);
4011 println(helperMethod + "(" + newSkelClass + "* skel);");
4014 // Write method helper for structs
4015 writeMethodHelperStructDeclSetupCplusSkeleton(methods, intDecl, newSkelClass);
4020 * HELPER: writeMethodHelperStructDeclSetupCplusSkeleton() writes the struct method helper declaration in skeleton class
4022 private void writeMethodHelperStructDeclSetupCplusSkeleton(Collection<String> methods,
4023 InterfaceDecl intDecl, String newSkelClass) {
4025 // Use this set to handle two same methodIds
4026 for (String method : methods) {
4028 List<String> methParams = intDecl.getMethodParams(method);
4029 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4030 // Check for params with structs
4031 for (int i = 0; i < methParams.size(); i++) {
4032 String paramType = methPrmTypes.get(i);
4033 String param = methParams.get(i);
4034 String simpleType = getGenericType(paramType);
4035 if (isStructClass(simpleType)) {
4036 int methodNumId = intDecl.getMethodNumId(method);
4038 String helperMethod = methodNumId + "struct" + i;
4039 println(helperMethod + "(" + newSkelClass + "* skel);");
4047 * HELPER: writeMethodBytesCopy() writes the methodBytes copy part in C++ skeleton
4049 private void writeMethodBytesCopy() {
4051 println("char* localMethodBytes = new char[methodLen];");
4052 println("memcpy(localMethodBytes, skel->methodBytes, methodLen);");
4053 println("didGetMethodBytes.exchange(true);");
4058 * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class
4060 private void writeMethodHelperCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
4061 Set<String> callbackClasses, String newSkelClass) {
4063 // Use this set to handle two same methodIds
4064 Set<String> uniqueMethodIds = new HashSet<String>();
4065 for (String method : methods) {
4067 List<String> methParams = intDecl.getMethodParams(method);
4068 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4069 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
4070 String methodId = intDecl.getMethodId(method);
4071 print("void " + newSkelClass + "::___");
4072 String helperMethod = methodId;
4073 if (uniqueMethodIds.contains(methodId))
4074 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4076 uniqueMethodIds.add(methodId);
4077 String retType = intDecl.getMethodType(method);
4078 print(helperMethod + "(");
4079 boolean begin = true;
4080 for (int i = 0; i < methParams.size(); i++) { // Print size variables
4081 String paramType = methPrmTypes.get(i);
4082 String param = methParams.get(i);
4083 String simpleType = getGenericType(paramType);
4084 if (isStructClass(simpleType)) {
4085 if (!begin) // Generate comma for not the beginning variable
4089 int methodNumId = intDecl.getMethodNumId(method);
4090 print("int struct" + methodNumId + "Size" + i);
4093 println(", " + newSkelClass + "* skel) {");
4094 writeMethodBytesCopy();
4095 writeMethodHelperStructCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4096 println("delete[] localMethodBytes;");
4099 String methodId = intDecl.getMethodId(method);
4100 print("void " + newSkelClass + "::___");
4101 String helperMethod = methodId;
4102 if (uniqueMethodIds.contains(methodId))
4103 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4105 uniqueMethodIds.add(methodId);
4106 // Check if this is "void"
4107 String retType = intDecl.getMethodType(method);
4108 println(helperMethod + "(" + newSkelClass + "* skel) {");
4109 writeMethodBytesCopy();
4110 // Now, write the helper body of skeleton!
4111 writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4112 println("delete[] localMethodBytes;");
4116 // Write method helper for structs
4117 writeMethodHelperStructSetupCplusSkeleton(methods, intDecl, newSkelClass);
4122 * HELPER: writeMethodHelperStructSetupCplusSkeleton() writes the method helper of struct in skeleton class
4124 private void writeMethodHelperStructSetupCplusSkeleton(Collection<String> methods,
4125 InterfaceDecl intDecl, String newSkelClass) {
4127 // Use this set to handle two same methodIds
4128 for (String method : methods) {
4130 List<String> methParams = intDecl.getMethodParams(method);
4131 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4132 // Check for params with structs
4133 for (int i = 0; i < methParams.size(); i++) {
4134 String paramType = methPrmTypes.get(i);
4135 String param = methParams.get(i);
4136 String simpleType = getGenericType(paramType);
4137 if (isStructClass(simpleType)) {
4138 int methodNumId = intDecl.getMethodNumId(method);
4139 print("int " + newSkelClass + "::___");
4140 String helperMethod = methodNumId + "struct" + i;
4141 println(helperMethod + "(" + newSkelClass + "* skel) {");
4142 // Now, write the helper body of skeleton!
4143 writeMethodBytesCopy();
4144 println("string paramCls[] = { \"int\" };");
4145 println("int numParam = 1;");
4146 println("int param0 = 0;");
4147 println("void* paramObj[] = { ¶m0 };");
4148 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
4149 println("return param0;");
4150 println("delete[] localMethodBytes;");
4159 * HELPER: writeMethodHelperStructSetupCplusCallbackSkeleton() writes the method helper of struct in skeleton class
4161 private void writeMethodHelperStructSetupCplusCallbackSkeleton(Collection<String> methods,
4162 InterfaceDecl intDecl) {
4164 // Use this set to handle two same methodIds
4165 for (String method : methods) {
4167 List<String> methParams = intDecl.getMethodParams(method);
4168 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4169 // Check for params with structs
4170 for (int i = 0; i < methParams.size(); i++) {
4171 String paramType = methPrmTypes.get(i);
4172 String param = methParams.get(i);
4173 String simpleType = getGenericType(paramType);
4174 if (isStructClass(simpleType)) {
4175 int methodNumId = intDecl.getMethodNumId(method);
4177 String helperMethod = methodNumId + "struct" + i;
4178 println(helperMethod + "(IoTRMIObject* rmiObj) {");
4179 // Now, write the helper body of skeleton!
4180 println("string paramCls[] = { \"int\" };");
4181 println("int numParam = 1;");
4182 println("int param0 = 0;");
4183 println("void* paramObj[] = { ¶m0 };");
4184 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
4185 println("return param0;");
4194 * HELPER: writeCplusMethodPermission() writes permission checks in skeleton
4196 private void writeCplusMethodPermission(String intface) {
4198 // Get all the different stubs
4199 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
4200 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
4201 String newIntface = intMeth.getKey();
4202 int newObjectId = getNewIntfaceObjectId(newIntface);
4203 println("if (_objectId == objectId) {");
4204 println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
4205 println("cerr << \"Object with object Id: \" << _objectId << \" is not allowed to access method: \" << methodId << endl;");
4210 println("continue;");
4217 * HELPER: writeCplusWaitRequestInvokeMethod() writes the main loop of the skeleton class
4219 private void writeCplusWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl,
4220 boolean callbackExist, String intface, String newSkelClass) {
4222 // Use this set to handle two same methodIds
4223 Set<String> uniqueMethodIds = new HashSet<String>();
4224 println("void " + newSkelClass + "::___waitRequestInvokeMethod(" + newSkelClass + "* skel) {");
4225 // Write variables here if we have callbacks or enums or structs
4226 writeCountVarStructSkeleton(methods, intDecl);
4227 println("skel->didAlreadyInitWaitInvoke = true;");
4228 println("while (true) {");
4229 println("if (!methodReceived) {");
4230 println("continue;");
4232 println("skel->methodBytes = skel->rmiComm->getMethodBytes();");
4233 println("skel->methodLen = skel->rmiComm->getMethodLength();");
4234 println("methodReceived = false;");
4235 println("int _objectId = skel->rmiComm->getObjectId(skel->methodBytes);");
4236 println("int methodId = skel->rmiComm->getMethodId(skel->methodBytes);");
4237 // Generate permission check
4238 writeCplusMethodPermission(intface);
4239 println("switch (methodId) {");
4240 // Print methods and method Ids
4241 for (String method : methods) {
4242 String methodId = intDecl.getMethodId(method);
4243 int methodNumId = intDecl.getMethodNumId(method);
4244 println("case " + methodNumId + ": {");
4245 print("thread th" + methodNumId + " (&" + newSkelClass + "::___");
4246 String helperMethod = methodId;
4247 if (uniqueMethodIds.contains(methodId))
4248 helperMethod = helperMethod + methodNumId;
4250 uniqueMethodIds.add(methodId);
4251 print(helperMethod + ", std::ref(skel), ");
4252 boolean structExists = writeInputCountVarStructCplusSkeleton(method, intDecl);
4256 println("th" + methodNumId + ".detach(); break;");
4259 writeMethodCallStructCplusSkeleton(methods, intDecl);
4260 println("default: ");
4261 println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;");
4270 * generateCplusSkeletonClassHpp() generate skeletons based on the methods list in C++ (.hpp file)
4272 public void generateCplusSkeletonClassHpp() throws IOException {
4274 // Create a new directory
4275 String path = createDirectories(dir, subdir);
4276 for (String intface : mapIntfacePTH.keySet()) {
4277 // Open a new file to write into
4278 String newSkelClass = intface + "_Skeleton";
4279 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
4280 pw = new PrintWriter(new BufferedWriter(fw));
4281 // Write file headers
4282 println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
4283 println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
4284 println("#include <iostream>");
4285 println("#include \"" + intface + ".hpp\"\n");
4286 // Pass in set of methods and get import classes
4287 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4288 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4289 List<String> methods = intDecl.getMethods();
4290 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
4291 printIncludeStatements(stdIncludeClasses); println("");
4292 println("using namespace std;\n");
4293 // Find out if there are callback objects
4294 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4295 boolean callbackExist = !callbackClasses.isEmpty();
4296 // Write class header
4297 println("class " + newSkelClass + " : public " + intface); println("{");
4298 println("private:\n");
4300 writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses);
4301 println("public:\n");
4302 // Write constructors
4303 println(newSkelClass + "();");
4304 println(newSkelClass + "(" + intface + "*_mainObj, int _portSend, int _portRecv);");
4305 println(newSkelClass + "(" + intface + "*_mainObj, IoTRMIComm *rmiComm, int _objectId);");
4306 // Write deconstructor
4307 println("~" + newSkelClass + "();");
4308 // Write method declarations
4309 println("bool didInitWaitInvoke();");
4310 writeMethodDeclCplusSkeleton(methods, intDecl, callbackClasses);
4311 // Write method helper declarations
4312 writeMethodHelperDeclCplusSkeleton(methods, intDecl, newSkelClass);
4313 // Write waitRequestInvokeMethod() declaration - main loop
4314 println("void ___waitRequestInvokeMethod(" + newSkelClass + "* skel);");
4316 writePermissionInitializationCplus(intface, newSkelClass, intDecl);
4319 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
4324 * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke
4326 private void writeReturnDidAlreadyInitWaitInvoke(String newSkelClass) {
4328 println("bool " + newSkelClass + "::didInitWaitInvoke() {");
4329 println("return didAlreadyInitWaitInvoke;");
4335 * writeSkelExternalCFunctions() generate external functions for .so file
4337 public void writeSkelExternalCFunctions(String newSkelClass, String intface) throws IOException {
4339 println("extern \"C\" void* create" + newSkelClass + "(void** params) {");
4340 println("// Args: *_mainObj, int _portSend, int _portRecv");
4341 println("return new " + newSkelClass + "((" + intface + "*) params[0], *((int*) params[1]), *((int*) params[2]));");
4343 println("extern \"C\" void destroy" + newSkelClass + "(void* t) {");
4344 println(newSkelClass + "* obj = (" + newSkelClass + "*) t;");
4345 println("delete obj;");
4347 println("extern \"C\" void init" + newSkelClass + "(void* t) {");
4348 //println(newSkelClass + "* obj = (" + newSkelClass + "*) t;");
4349 //println("obj->init();");
4350 //println("while(true);");
4356 * generateCplusSkeletonClassCpp() generate skeletons based on the methods list in C++ (.cpp file)
4358 public void generateCplusSkeletonClassCpp() throws IOException {
4360 // Create a new directory
4361 String path = createDirectories(dir, subdir);
4362 for (String intface : mapIntfacePTH.keySet()) {
4363 // Open a new file to write into
4364 String newSkelClass = intface + "_Skeleton";
4365 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".cpp");
4366 pw = new PrintWriter(new BufferedWriter(fw));
4367 // Write file headers
4368 println("#include <iostream>");
4369 println("#include \"" + newSkelClass + ".hpp\"\n");
4370 // Pass in set of methods and get import classes
4371 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4372 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4373 List<String> methods = intDecl.getMethods();
4374 // Find out if there are callback objects
4375 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4376 boolean callbackExist = !callbackClasses.isEmpty();
4377 for(String str: callbackClasses) {
4378 if (intface.equals(mainClass))
4379 println("#include \"" + getStubInterface(str) + "_Stub.cpp\"\n");
4381 println("#include \"" + getStubInterface(str) + "_Stub.hpp\"\n");
4383 println("using namespace std;\n");
4384 // Write constructor
4385 writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
4386 // Write callback constructor
4387 writeCallbackConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
4388 // Write deconstructor
4389 writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses);
4390 // Write didInitWaitInvoke() to return bool
4391 writeReturnDidAlreadyInitWaitInvoke(newSkelClass);
4393 writeMethodCplusSkeleton(methods, intDecl, newSkelClass);
4394 // Write method helper
4395 writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass);
4396 // Write waitRequestInvokeMethod() - main loop
4397 writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface, newSkelClass);
4398 // Write external functions for .so file
4399 writeSkelExternalCFunctions(newSkelClass, intface);
4400 // TODO: Remove this later
4401 if (intface.equals(mainClass)) {
4402 println("int main() {");
4403 println("return 0;");
4407 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".cpp...");
4413 * generateInitializer() generate initializer based on type
4415 public String generateCplusInitializer(String type) {
4417 // Generate dummy returns for now
4418 if (type.equals("short")||
4419 type.equals("int") ||
4420 type.equals("long") ||
4421 type.equals("float")||
4422 type.equals("double")) {
4425 } else if ( type.equals("String") ||
4426 type.equals("string")) {
4429 } else if ( type.equals("char") ||
4430 type.equals("byte")) {
4433 } else if ( type.equals("boolean")) {
4443 * setDirectory() sets a new directory for stub files
4445 public void setDirectory(String _subdir) {
4452 * printUsage() prints the usage of this compiler
4454 public static void printUsage() {
4456 System.out.println();
4457 System.out.println("Sentinel interface and stub compiler version 1.0");
4458 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
4459 System.out.println("All rights reserved.");
4460 System.out.println("Usage:");
4461 System.out.println("\tjava IoTCompiler -help / --help / -h\n");
4462 System.out.println("\t\tDisplay this help texts\n\n");
4463 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
4464 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
4465 System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
4466 System.out.println("Options:");
4467 System.out.println("\t-java\t<directory>\tGenerate Java stub files");
4468 System.out.println("\t-cplus\t<directory>\tGenerate C++ stub files");
4469 System.out.println();
4474 * parseFile() prepares Lexer and Parser objects, then parses the file
4476 public static ParseNode parseFile(String file) {
4478 ParseNode pn = null;
4480 ComplexSymbolFactory csf = new ComplexSymbolFactory();
4481 ScannerBuffer lexer =
4482 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(file)),csf));
4483 Parser parse = new Parser(lexer,csf);
4484 pn = (ParseNode) parse.parse().value;
4485 } catch (Exception e) {
4486 e.printStackTrace();
4487 throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file + "\n");
4495 * Basic helper functions
4498 boolean newline=true;
4501 private void print(String str) {
4504 if (str.equals("}"))
4506 for(int i=0; i<tab; i++)
4516 * This function converts Java to C++ type for compilation
4518 private String convertType(String type) {
4520 if (mapPrimitives.containsKey(type))
4521 return mapPrimitives.get(type);
4528 * A collection of methods with print-to-file functionality
4530 private void println(String str) {
4533 if (str.contains("}") && !str.contains("{"))
4535 for(int i=0; i<tab; i++)
4544 private void updatetabbing(String str) {
4546 tablevel+=count(str,'{')-count(str,'}');
4550 private int count(String str, char key) {
4551 char[] array = str.toCharArray();
4553 for(int i=0; i<array.length; i++) {
4554 if (array[i] == key)
4561 private void createDirectory(String dirName) {
4563 File file = new File(dirName);
4564 if (!file.exists()) {
4566 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
4568 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
4571 System.out.println("IoTCompiler: Directory " + dirName + " exists...");
4576 // Create a directory and possibly a sub directory
4577 private String createDirectories(String dir, String subdir) {
4580 createDirectory(path);
4581 if (subdir != null) {
4582 path = path + "/" + subdir;
4583 createDirectory(path);
4589 // Inserting array members into a Map object
4590 // that maps arrKey to arrVal objects
4591 private void arraysToMap(Map map, Object[] arrKey, Object[] arrVal) {
4593 for(int i = 0; i < arrKey.length; i++) {
4595 map.put(arrKey[i], arrVal[i]);
4600 // Check and find object Id for new interface in mapNewIntfaceObjId (callbacks)
4601 // Throw an error if the new interface is not found!
4602 // Basically the compiler needs to parse the policy (and requires) files for callback class first
4603 private int getNewIntfaceObjectId(String newIntface) {
4605 // if (!mapNewIntfaceObjId.containsKey(newIntface)) {
4606 // throw new Error("IoTCompiler: Need to parse policy and requires files for callback class first! " +
4607 // "Please place the two files for callback class in front...\n");
4610 int retObjId = mapNewIntfaceObjId.get(newIntface);
4616 // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, USERDEFINED, ENUM, or STRUCT
4617 private ParamCategory getParamCategory(String paramType) {
4619 if (mapPrimitives.containsKey(paramType)) {
4620 return ParamCategory.PRIMITIVES;
4621 // We can either use mapNonPrimitivesJava or mapNonPrimitivesCplus here
4622 } else if (mapNonPrimitivesJava.containsKey(getSimpleType(paramType))) {
4623 return ParamCategory.NONPRIMITIVES;
4624 } else if (isEnumClass(paramType)) {
4625 return ParamCategory.ENUM;
4626 } else if (isStructClass(paramType)) {
4627 return ParamCategory.STRUCT;
4629 return ParamCategory.USERDEFINED;
4633 // Return full class name for non-primitives to generate Java import statements
4634 // e.g. java.util.Set for Set
4635 private String getNonPrimitiveJavaClass(String paramNonPrimitives) {
4637 return mapNonPrimitivesJava.get(paramNonPrimitives);
4641 // Return full class name for non-primitives to generate Cplus include statements
4642 // e.g. #include <set> for Set
4643 private String getNonPrimitiveCplusClass(String paramNonPrimitives) {
4645 return mapNonPrimitivesCplus.get(paramNonPrimitives);
4649 // Get simple types, e.g. HashSet for HashSet<...>
4650 // Basically strip off the "<...>"
4651 private String getSimpleType(String paramType) {
4653 // Check if this is generics
4654 if(paramType.contains("<")) {
4655 String[] type = paramType.split("<");
4662 // Generate a set of standard classes for import statements
4663 private List<String> getStandardJavaIntfaceImportClasses() {
4665 List<String> importClasses = new ArrayList<String>();
4666 // Add the standard list first
4667 importClasses.add("java.util.List");
4668 importClasses.add("java.util.ArrayList");
4670 return importClasses;
4674 // Generate a set of standard classes for import statements
4675 private List<String> getStandardJavaImportClasses() {
4677 List<String> importClasses = new ArrayList<String>();
4678 // Add the standard list first
4679 importClasses.add("java.io.IOException");
4680 importClasses.add("java.util.List");
4681 importClasses.add("java.util.ArrayList");
4682 importClasses.add("java.util.Arrays");
4683 importClasses.add("java.util.Map");
4684 importClasses.add("java.util.HashMap");
4685 importClasses.add("java.util.concurrent.atomic.AtomicBoolean");
4686 importClasses.add("iotrmi.Java.IoTRMIComm");
4687 importClasses.add("iotrmi.Java.IoTRMICommClient");
4688 importClasses.add("iotrmi.Java.IoTRMICommServer");
4689 importClasses.add("iotrmi.Java.IoTRMIUtil");
4691 return importClasses;
4695 // Generate a set of standard classes for import statements
4696 private List<String> getStandardCplusIncludeClasses() {
4698 List<String> importClasses = new ArrayList<String>();
4699 // Add the standard list first
4700 importClasses.add("<vector>");
4701 importClasses.add("<set>");
4702 //importClasses.add("\"IoTRMICall.hpp\"");
4703 //importClasses.add("\"IoTRMIObject.hpp\"");
4704 importClasses.add("\"IoTRMIComm.hpp\"");
4705 importClasses.add("\"IoTRMICommClient.hpp\"");
4706 importClasses.add("\"IoTRMICommServer.hpp\"");
4708 return importClasses;
4712 // Combine all classes for import statements
4713 private List<String> getAllLibClasses(Collection<String> stdLibClasses, Collection<String> libClasses) {
4715 List<String> allLibClasses = new ArrayList<String>(stdLibClasses);
4716 // Iterate over the list of import classes
4717 for (String str : libClasses) {
4718 if (!allLibClasses.contains(str)) {
4719 allLibClasses.add(str);
4722 return allLibClasses;
4727 // Generate a set of classes for import statements
4728 private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
4730 Set<String> importClasses = new HashSet<String>();
4731 for (String method : methods) {
4732 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4733 for (String paramType : methPrmTypes) {
4735 String simpleType = getSimpleType(paramType);
4736 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4737 importClasses.add(getNonPrimitiveJavaClass(simpleType));
4741 return importClasses;
4745 // Handle and return the correct enum declaration
4746 // In Java, if we declare enum in Camera interface, then it becomes "Camera.<enum>"
4747 private String getEnumParamDecl(String type, InterfaceDecl intDecl) {
4749 // Strips off array "[]" for return type
4750 String pureType = getSimpleArrayType(type);
4751 // Take the inner type of generic
4752 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4753 pureType = getTypeOfGeneric(type)[0];
4754 if (isEnumClass(pureType)) {
4755 String enumType = intDecl.getInterface() + "." + type;
4762 // Handle and return the correct type
4763 private String getEnumParam(String type, String param, int i) {
4765 // Strips off array "[]" for return type
4766 String pureType = getSimpleArrayType(type);
4767 // Take the inner type of generic
4768 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4769 pureType = getTypeOfGeneric(type)[0];
4770 if (isEnumClass(pureType)) {
4771 String enumParam = "paramEnum" + i;
4778 // Handle and return the correct enum declaration translate into int[]
4779 private String getEnumType(String type) {
4781 // Strips off array "[]" for return type
4782 String pureType = getSimpleArrayType(type);
4783 // Take the inner type of generic
4784 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4785 pureType = getGenericType(type);
4786 if (isEnumClass(pureType)) {
4787 String enumType = "int[]";
4793 // Handle and return the correct enum declaration translate into int* for C
4794 private String getEnumCplusClsType(String type) {
4796 // Strips off array "[]" for return type
4797 String pureType = getSimpleArrayType(type);
4798 // Take the inner type of generic
4799 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4800 pureType = getGenericType(type);
4801 if (isEnumClass(pureType)) {
4802 String enumType = "int*";
4809 // Handle and return the correct struct declaration
4810 private String getStructType(String type) {
4812 // Strips off array "[]" for return type
4813 String pureType = getSimpleArrayType(type);
4814 // Take the inner type of generic
4815 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4816 pureType = getGenericType(type);
4817 if (isStructClass(pureType)) {
4818 String structType = "int";
4825 // Check if this an enum declaration
4826 private boolean isEnumClass(String type) {
4828 // Just iterate over the set of interfaces
4829 for (String intface : mapIntfacePTH.keySet()) {
4830 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4831 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
4832 Set<String> setEnumDecl = enumDecl.getEnumDeclarations();
4833 if (setEnumDecl.contains(type))
4840 // Check if this an struct declaration
4841 private boolean isStructClass(String type) {
4843 // Just iterate over the set of interfaces
4844 for (String intface : mapIntfacePTH.keySet()) {
4845 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4846 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4847 List<String> listStructDecl = structDecl.getStructTypes();
4848 if (listStructDecl.contains(type))
4855 // Return a struct declaration
4856 private StructDecl getStructDecl(String type) {
4858 // Just iterate over the set of interfaces
4859 for (String intface : mapIntfacePTH.keySet()) {
4860 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4861 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4862 List<String> listStructDecl = structDecl.getStructTypes();
4863 if (listStructDecl.contains(type))
4870 // Return number of members (-1 if not found)
4871 private int getNumOfMembers(String type) {
4873 // Just iterate over the set of interfaces
4874 for (String intface : mapIntfacePTH.keySet()) {
4875 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4876 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4877 List<String> listStructDecl = structDecl.getStructTypes();
4878 if (listStructDecl.contains(type))
4879 return structDecl.getNumOfMembers(type);
4885 // Generate a set of classes for include statements
4886 private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl, String intface, boolean needExchange) {
4888 Set<String> includeClasses = new HashSet<String>();
4889 for (String method : methods) {
4891 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4892 List<String> methParams = intDecl.getMethodParams(method);
4893 for (int i = 0; i < methPrmTypes.size(); i++) {
4895 String genericType = getGenericType(methPrmTypes.get(i));
4896 String simpleType = getSimpleType(methPrmTypes.get(i));
4897 String param = methParams.get(i);
4898 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4899 includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">");
4900 //} else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) {
4902 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.USERDEFINED) {
4903 // For original interface, we need it exchanged... not for stub interfaces
4905 //includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\"");
4906 includeClasses.add("\"" + exchangeParamType(getSimpleArrayType(genericType)) + ".hpp\"");
4908 //includeClasses.add("\"" + simpleType + ".hpp\"");
4909 includeClasses.add("\"" + getSimpleArrayType(genericType) + ".hpp\"");
4912 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.ENUM) {
4913 includeClasses.add("\"" + genericType + ".hpp\"");
4915 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.STRUCT) {
4916 includeClasses.add("\"" + genericType + ".hpp\"");
4918 if (param.contains("[]")) {
4919 // Check if this is array for C++; translate into vector
4920 includeClasses.add("<vector>");
4924 return includeClasses;
4928 // Generate a set of callback classes
4929 private Set<String> getCallbackClasses(Collection<String> methods, InterfaceDecl intDecl) {
4931 Set<String> callbackClasses = new HashSet<String>();
4932 for (String method : methods) {
4934 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4935 List<String> methParams = intDecl.getMethodParams(method);
4936 for (int i = 0; i < methPrmTypes.size(); i++) {
4938 String type = methPrmTypes.get(i);
4939 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4940 callbackClasses.add(type);
4941 } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
4942 // Can be a List<...> of callback objects ...
4943 String genericType = getTypeOfGeneric(type)[0];
4944 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4945 callbackClasses.add(type);
4950 return callbackClasses;
4954 // Print import statements into file
4955 private void printImportStatements(Collection<String> importClasses) {
4957 for(String cls : importClasses) {
4958 println("import " + cls + ";");
4963 // Print include statements into file
4964 private void printIncludeStatements(Collection<String> includeClasses) {
4966 for(String cls : includeClasses) {
4967 println("#include " + cls);
4972 // Get the C++ version of a non-primitive type
4973 // e.g. set for Set and map for Map
4974 // Input nonPrimitiveType has to be generics in format
4975 private String[] getTypeOfGeneric(String nonPrimitiveType) {
4977 // Handle <, >, and , for 2-type generic/template
4978 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
4983 // Gets generic type inside "<" and ">"
4984 private String getGenericType(String type) {
4986 // Handle <, >, and , for 2-type generic/template
4987 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
4988 String[] substr = type.split("<")[1].split(">")[0].split(",");
4995 // This helper function strips off array declaration, e.g. int[] becomes int
4996 private String getSimpleArrayType(String type) {
4998 // Handle [ for array declaration
4999 String substr = type;
5000 if (type.contains("[]")) {
5001 substr = type.split("\\[\\]")[0];
5007 // This helper function strips off array declaration, e.g. D[] becomes D
5008 private String getSimpleIdentifier(String ident) {
5010 // Handle [ for array declaration
5011 String substr = ident;
5012 if (ident.contains("[]")) {
5013 substr = ident.split("\\[\\]")[0];
5019 // Checks and gets type in C++
5020 private String checkAndGetCplusType(String paramType) {
5022 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
5023 return convertType(paramType);
5024 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
5026 // Check for generic/template format
5027 if (paramType.contains("<") && paramType.contains(">")) {
5029 String genericClass = getSimpleType(paramType);
5030 String genericType = getGenericType(paramType);
5031 String cplusTemplate = null;
5032 cplusTemplate = getNonPrimitiveCplusClass(genericClass);
5033 if(getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED) {
5034 cplusTemplate = cplusTemplate + "<" + genericType + "*>";
5036 cplusTemplate = cplusTemplate + "<" + convertType(genericType) + ">";
5038 return cplusTemplate;
5040 return getNonPrimitiveCplusClass(paramType);
5041 } else if(paramType.contains("[]")) { // Array type (used for return type only)
5042 String cArray = "vector<" + convertType(getSimpleArrayType(paramType)) + ">";
5044 } else if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
5045 return paramType + "*";
5047 // Just return it as is if it's not non-primitives
5052 // Detect array declaration, e.g. int A[],
5053 // then generate "int A[]" in C++ as "vector<int> A"
5054 private String checkAndGetCplusArray(String paramType, String param) {
5056 String paramComplete = null;
5057 // Check for array declaration
5058 if (param.contains("[]")) {
5059 paramComplete = "vector<" + paramType + "> " + param.replace("[]","");
5061 // Just return it as is if it's not an array
5062 paramComplete = paramType + " " + param;
5064 return paramComplete;
5068 // Detect array declaration, e.g. int A[],
5069 // then generate "int A[]" in C++ as "vector<int> A"
5070 // This method just returns the type
5071 private String checkAndGetCplusArrayType(String paramType) {
5073 String paramTypeRet = null;
5074 // Check for array declaration
5075 if (paramType.contains("[]")) {
5076 String type = paramType.split("\\[\\]")[0];
5077 paramTypeRet = checkAndGetCplusType(type) + "[]";
5078 } else if (paramType.contains("vector")) {
5079 // Just return it as is if it's not an array
5080 String type = paramType.split("<")[1].split(">")[0];
5081 paramTypeRet = checkAndGetCplusType(type) + "[]";
5083 paramTypeRet = paramType;
5085 return paramTypeRet;
5089 // Detect array declaration, e.g. int A[],
5090 // then generate "int A[]" in C++ as "vector<int> A"
5091 // This method just returns the type
5092 private String checkAndGetCplusArrayType(String paramType, String param) {
5094 String paramTypeRet = null;
5095 // Check for array declaration
5096 if (param.contains("[]")) {
5097 paramTypeRet = checkAndGetCplusType(paramType) + "[]";
5098 } else if (paramType.contains("vector")) {
5099 // Just return it as is if it's not an array
5100 String type = paramType.split("<")[1].split(">")[0];
5101 paramTypeRet = checkAndGetCplusType(type) + "[]";
5103 paramTypeRet = paramType;
5105 return paramTypeRet;
5109 // Return the class type for class resolution (for return value)
5110 // - Check and return C++ array class, e.g. int A[] into int*
5111 // - Check and return C++ vector class, e.g. List<Integer> A into vector<int>
5112 private String checkAndGetCplusRetClsType(String paramType) {
5114 String paramTypeRet = null;
5115 // Check for array declaration
5116 if (paramType.contains("[]")) {
5117 String type = paramType.split("\\[\\]")[0];
5118 paramTypeRet = getSimpleArrayType(type) + "*";
5119 } else if (paramType.contains("<") && paramType.contains(">")) {
5120 // Just return it as is if it's not an array
5121 String type = paramType.split("<")[1].split(">")[0];
5122 paramTypeRet = "vector<" + getGenericType(type) + ">";
5124 paramTypeRet = paramType;
5126 return paramTypeRet;
5130 // Return the class type for class resolution (for method arguments)
5131 // - Check and return C++ array class, e.g. int A[] into int*
5132 // - Check and return C++ vector class, e.g. List<Integer> A into vector<int>
5133 private String checkAndGetCplusArgClsType(String paramType, String param) {
5135 String paramTypeRet = getEnumCplusClsType(paramType);
5136 if (!paramTypeRet.equals(paramType))
5137 // Just return if it is an enum type
5138 // Type will still be the same if it's not an enum type
5139 return paramTypeRet;
5141 // Check for array declaration
5142 if (param.contains("[]")) {
5143 paramTypeRet = getSimpleArrayType(paramType) + "*";
5144 } else if (paramType.contains("<") && paramType.contains(">")) {
5145 // Just return it as is if it's not an array
5146 String type = paramType.split("<")[1].split(">")[0];
5147 paramTypeRet = "vector<" + getGenericType(type) + ">";
5149 paramTypeRet = paramType;
5151 return paramTypeRet;
5155 // Detect array declaration, e.g. int A[],
5156 // then generate type "int[]"
5157 private String checkAndGetArray(String paramType, String param) {
5159 String paramTypeRet = null;
5160 // Check for array declaration
5161 if (param.contains("[]")) {
5162 paramTypeRet = paramType + "[]";
5164 // Just return it as is if it's not an array
5165 paramTypeRet = paramType;
5167 return paramTypeRet;
5171 // Is array or list?
5172 private boolean isArrayOrList(String paramType, String param) {
5174 // Check for array declaration
5177 else if (isList(paramType))
5185 // For return type we use retType as input parameter
5186 private boolean isArray(String param) {
5188 // Check for array declaration
5189 if (param.contains("[]"))
5197 private boolean isList(String paramType) {
5199 // Check for array declaration
5200 if (paramType.contains("List"))
5207 // Get the right type for a callback object
5208 private String checkAndGetParamClass(String paramType) {
5210 // Check if this is generics
5211 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
5212 return exchangeParamType(paramType);
5213 } else if (isList(paramType) &&
5214 (getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED)) {
5215 return "List<" + exchangeParamType(getGenericType(paramType)) + ">";
5221 // Returns the other interface for type-checking purposes for USERDEFINED
5222 // classes based on the information provided in multiple policy files
5223 // e.g. return CameraWithXXX instead of Camera
5224 private String exchangeParamType(String intface) {
5226 // Param type that's passed is the interface name we need to look for
5227 // in the map of interfaces, based on available policy files.
5228 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
5229 if (decHandler != null) {
5230 // We've found the required interface policy files
5231 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(intface);
5232 Set<String> setExchInt = reqDecl.getInterfaces();
5233 if (setExchInt.size() == 1) {
5234 Iterator iter = setExchInt.iterator();
5235 return (String) iter.next();
5237 throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() +
5238 ". Only one new interface can be declared if the object " + intface +
5239 " needs to be passed in as an input parameter!\n");
5242 // NULL value - this means policy files missing
5243 throw new Error("IoTCompiler: Parameter type lookup failed for " + intface +
5244 "... Please provide the necessary policy files for user-defined types." +
5245 " If this is an array please type the brackets after the variable name," +
5246 " e.g. \"String str[]\", not \"String[] str\"." +
5247 " If this is a Collections (Java) / STL (C++) type, this compiler only" +
5248 " supports List/ArrayList (Java) or list (C++).\n");
5253 public static void main(String[] args) throws Exception {
5255 // If there is no argument or just "--help" or "-h", then invoke printUsage()
5256 if ((args[0].equals("-help") ||
5257 args[0].equals("--help")||
5258 args[0].equals("-h")) ||
5259 (args.length == 0)) {
5261 IoTCompiler.printUsage();
5263 } else if (args.length > 1) {
5265 IoTCompiler comp = new IoTCompiler();
5268 // Parse main policy file
5269 ParseNode pnPol = IoTCompiler.parseFile(args[i]);
5270 // Parse "requires" policy file
5271 ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
5272 // Get interface name
5273 String intface = ParseTreeHandler.getOrigIntface(pnPol);
5274 comp.setDataStructures(intface, pnPol, pnReq);
5275 comp.getMethodsForIntface(intface);
5277 // 1) Check if this is the last option before "-java" or "-cplus"
5278 // 2) Check if this is really the last option (no "-java" or "-cplus")
5279 } while(!args[i].equals("-java") &&
5280 !args[i].equals("-cplus") &&
5283 // Generate everything if we don't see "-java" or "-cplus"
5284 if (i == args.length) {
5285 comp.generateEnumJava();
5286 comp.generateStructJava();
5287 comp.generateJavaLocalInterfaces();
5288 comp.generateJavaInterfaces();
5289 comp.generateJavaStubClasses();
5290 comp.generateJavaSkeletonClass();
5291 comp.generateEnumCplus();
5292 comp.generateStructCplus();
5293 comp.generateCplusLocalInterfaces();
5294 comp.generateCPlusInterfaces();
5295 comp.generateCPlusStubClassesHpp();
5296 comp.generateCPlusStubClassesCpp();
5297 comp.generateCplusSkeletonClassHpp();
5298 comp.generateCplusSkeletonClassCpp();
5300 // Check other options
5301 while(i < args.length) {
5303 if (!args[i].equals("-java") &&
5304 !args[i].equals("-cplus")) {
5305 throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i] + "\n");
5307 if (i + 1 < args.length) {
5308 comp.setDirectory(args[i+1]);
5310 throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i] + "\n");
5312 if (args[i].equals("-java")) {
5313 comp.generateEnumJava();
5314 comp.generateStructJava();
5315 comp.generateJavaLocalInterfaces();
5316 comp.generateJavaInterfaces();
5317 comp.generateJavaStubClasses();
5318 comp.generateJavaSkeletonClass();
5320 comp.generateEnumCplus();
5321 comp.generateStructCplus();
5322 comp.generateCplusLocalInterfaces();
5323 comp.generateCPlusInterfaces();
5324 comp.generateCPlusStubClassesHpp();
5325 comp.generateCPlusStubClassesCpp();
5326 comp.generateCplusSkeletonClassHpp();
5327 comp.generateCplusSkeletonClassCpp();
5334 // Need to at least have exactly 2 parameters, i.e. main policy file and requires file
5335 IoTCompiler.printUsage();
5336 throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!\n");