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("rmiComm = new IoTRMICommClient(_localPortSend, _localPortRecv, _portSend, _portRecv, _skeletonAddress, _rev);");
483 // Register the AtomicBoolean variables
484 for (String method : methods) {
485 // Generate AtomicBooleans for methods that have return values
486 String returnType = intDecl.getMethodType(method);
487 int methodNumId = intDecl.getMethodNumId(method);
488 if (!returnType.equals("void")) {
489 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
492 println("IoTRMIUtil.mapStub.put(objectId, this);");
498 * HELPER: writeCallbackConstructorJavaStub() writes the callback constructor of the stub class
500 private void writeCallbackConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
502 println("public " + newStubClass + "(IoTRMIComm _rmiComm, int _objectId) throws Exception {");
503 println("rmiComm = _rmiComm;");
504 println("objectId = _objectId;");
505 // Register the AtomicBoolean variables
506 for (String method : methods) {
507 // Generate AtomicBooleans for methods that have return values
508 String returnType = intDecl.getMethodType(method);
509 int methodNumId = intDecl.getMethodNumId(method);
510 if (!returnType.equals("void")) {
511 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
519 * HELPER: writeJavaMethodCallbackPermission() writes permission checks in stub for callbacks
521 private void writeJavaMethodCallbackPermission(String intface) {
523 println("int methodId = IoTRMIObject.getMethodId(method);");
524 // Get all the different stubs
525 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
526 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
527 String newIntface = intMeth.getKey();
528 int newObjectId = getNewIntfaceObjectId(newIntface);
529 println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
530 println("throw new Error(\"Callback object for " + intface + " is not allowed to access method: \" + methodId);");
537 * HELPER: writeJavaInitCallbackPermission() writes the permission for callback
539 private void writeJavaInitCallbackPermission(String intface, InterfaceDecl intDecl, boolean callbackExist) {
542 String method = "___initCallBack()";
543 int methodNumId = intDecl.getHelperMethodNumId(method);
544 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
545 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
546 String newIntface = intMeth.getKey();
547 int newObjectId = getNewIntfaceObjectId(newIntface);
548 println("set" + newObjectId + "Allowed.add(" + methodNumId + ");");
555 * HELPER: getPortCount() gets port count for different stubs and skeletons
557 private int getPortCount(String intface) {
559 if (!mapPortCount.containsKey(intface))
560 mapPortCount.put(intface, portCount++);
561 return mapPortCount.get(intface);
566 * HELPER: checkAndWriteEnumTypeJavaStub() writes the enum type (convert from enum to int)
568 private void checkAndWriteEnumTypeJavaStub(List<String> methParams, List<String> methPrmTypes) {
570 // Iterate and find enum declarations
571 for (int i = 0; i < methParams.size(); i++) {
572 String paramType = methPrmTypes.get(i);
573 String param = methParams.get(i);
574 String simpleType = getGenericType(paramType);
575 if (isEnumClass(simpleType)) {
576 // Check if this is enum type
577 if (isArray(param)) { // An array
578 println("int len" + i + " = " + getSimpleIdentifier(param) + ".length;");
579 println("int paramEnum" + i + "[] = new int[len" + i + "];");
580 println("for (int i = 0; i < len" + i + "; i++) {");
581 println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + "[i].ordinal();");
583 } else if (isList(paramType)) { // A list
584 println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
585 println("int paramEnum" + i + "[] = new int[len" + i + "];");
586 println("for (int i = 0; i < len" + i + "; i++) {");
587 println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + ".get(i).ordinal();");
589 } else { // Just one element
590 println("int paramEnum" + i + "[] = new int[1];");
591 println("paramEnum" + i + "[0] = " + param + ".ordinal();");
599 * HELPER: checkAndWriteEnumRetTypeJavaStub() writes the enum return type (convert from enum to int)
601 private void checkAndWriteEnumRetTypeJavaStub(String retType, String method, InterfaceDecl intDecl) {
603 // Write the wait-for-return-value part
604 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
605 // Strips off array "[]" for return type
606 String pureType = getSimpleArrayType(getGenericType(retType));
607 // Take the inner type of generic
608 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
609 pureType = getGenericType(retType);
610 if (isEnumClass(pureType)) {
611 // Check if this is enum type
613 println("int[] retEnum = (int[]) retObj;");
614 println(pureType + "[] enumVals = " + pureType + ".values();");
615 if (isArray(retType)) { // An array
616 println("int retLen = retEnum.length;");
617 println(pureType + "[] enumRetVal = new " + pureType + "[retLen];");
618 println("for (int i = 0; i < retLen; i++) {");
619 println("enumRetVal[i] = enumVals[retEnum[i]];");
621 } else if (isList(retType)) { // A list
622 println("int retLen = retEnum.length;");
623 println("List<" + pureType + "> enumRetVal = new ArrayList<" + pureType + ">();");
624 println("for (int i = 0; i < retLen; i++) {");
625 println("enumRetVal.add(enumVals[retEnum[i]]);");
627 } else { // Just one element
628 println(pureType + " enumRetVal = enumVals[retEnum[0]];");
630 println("return enumRetVal;");
636 * HELPER: checkAndWriteStructSetupJavaStub() writes the struct type setup
638 private void checkAndWriteStructSetupJavaStub(List<String> methParams, List<String> methPrmTypes,
639 InterfaceDecl intDecl, String method) {
641 // Iterate and find struct declarations
642 for (int i = 0; i < methParams.size(); i++) {
643 String paramType = methPrmTypes.get(i);
644 String param = methParams.get(i);
645 String simpleType = getGenericType(paramType);
646 if (isStructClass(simpleType)) {
647 // Check if this is enum type
648 int methodNumId = intDecl.getMethodNumId(method);
649 String helperMethod = methodNumId + "struct" + i;
650 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
651 println("Class<?>[] paramClsStruct" + i + " = new Class<?>[] { int.class };");
652 if (isArray(param)) { // An array
653 println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".length };");
654 } else if (isList(paramType)) { // A list
655 println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".size() };");
656 } else { // Just one element
657 println("Object[] paramObjStruct" + i + " = new Object[] { new Integer(1) };");
659 println("rmiComm.remoteCall(objectId, methodIdStruct" + i +
660 ", paramClsStruct" + i + ", paramObjStruct" + i + ");\n");
667 * HELPER: isStructPresent() checks presence of struct
669 private boolean isStructPresent(List<String> methParams, List<String> methPrmTypes) {
671 // Iterate and find enum declarations
672 for (int i = 0; i < methParams.size(); i++) {
673 String paramType = methPrmTypes.get(i);
674 String param = methParams.get(i);
675 String simpleType = getGenericType(paramType);
676 if (isStructClass(simpleType))
684 * HELPER: writeLengthStructParamClassJavaStub() writes lengths of parameters
686 private void writeLengthStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes) {
688 // Iterate and find struct declarations - count number of params
689 for (int i = 0; i < methParams.size(); i++) {
690 String paramType = methPrmTypes.get(i);
691 String param = methParams.get(i);
692 String simpleType = getGenericType(paramType);
693 if (isStructClass(simpleType)) {
694 int members = getNumOfMembers(simpleType);
695 if (isArray(param)) { // An array
696 String structLen = getSimpleArrayType(param) + ".length";
697 print(members + "*" + structLen);
698 } else if (isList(paramType)) { // A list
699 String structLen = getSimpleArrayType(param) + ".size()";
700 print(members + "*" + structLen);
702 print(Integer.toString(members));
705 if (i != methParams.size() - 1) {
713 * HELPER: writeStructMembersJavaStub() writes parameters of struct
715 private void writeStructMembersJavaStub(String simpleType, String paramType, String param) {
717 // Get the struct declaration for this struct and generate initialization code
718 StructDecl structDecl = getStructDecl(simpleType);
719 List<String> memTypes = structDecl.getMemberTypes(simpleType);
720 List<String> members = structDecl.getMembers(simpleType);
721 if (isArray(param)) { // An array
722 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".length; i++) {");
723 for (int i = 0; i < members.size(); i++) {
724 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
725 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
726 print("paramObj[pos++] = " + getSimpleIdentifier(param) + "[i].");
727 print(getSimpleIdentifier(members.get(i)));
731 } else if (isList(paramType)) { // A list
732 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
733 for (int i = 0; i < members.size(); i++) {
734 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
735 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
736 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".get(i).");
737 print(getSimpleIdentifier(members.get(i)));
741 } else { // Just one struct element
742 for (int i = 0; i < members.size(); i++) {
743 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
744 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
745 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".");
746 print(getSimpleIdentifier(members.get(i)));
754 * HELPER: writeStructParamClassJavaStub() writes parameters if struct is present
756 private void writeStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes, String callbackType) {
758 print("int paramLen = ");
759 writeLengthStructParamClassJavaStub(methParams, methPrmTypes);
761 println("Object[] paramObj = new Object[paramLen];");
762 println("Class<?>[] paramCls = new Class<?>[paramLen];");
763 println("int pos = 0;");
764 // Iterate again over the parameters
765 for (int i = 0; i < methParams.size(); i++) {
766 String paramType = methPrmTypes.get(i);
767 String param = methParams.get(i);
768 String simpleType = getGenericType(paramType);
769 if (isStructClass(simpleType)) {
770 writeStructMembersJavaStub(simpleType, paramType, param);
771 } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
772 println("paramCls[pos] = int.class;");
773 print("paramObj[pos++] = ");
774 if (isArray(methParams.get(i)))
775 print(getSimpleIdentifier(methParams.get(i)) + ".length");
776 else if (isList(methPrmTypes.get(i)))
777 print(getSimpleIdentifier(methParams.get(i)) + ".size()");
779 print("new Integer(1)");
782 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
783 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
784 print("paramObj[pos++] = ");
785 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
794 * HELPER: writeStructRetMembersJavaStub() writes parameters of struct for return statement
796 private void writeStructRetMembersJavaStub(String simpleType, String retType) {
798 // Get the struct declaration for this struct and generate initialization code
799 StructDecl structDecl = getStructDecl(simpleType);
800 List<String> memTypes = structDecl.getMemberTypes(simpleType);
801 List<String> members = structDecl.getMembers(simpleType);
802 if (isArrayOrList(retType, retType)) { // An array or list
803 println("for(int i = 0; i < retLen; i++) {");
805 if (isArray(retType)) { // An array
806 for (int i = 0; i < members.size(); i++) {
807 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
808 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
809 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
812 } else if (isList(retType)) { // A list
813 println(simpleType + " structRetMem = new " + simpleType + "();");
814 for (int i = 0; i < members.size(); i++) {
815 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
816 print("structRetMem." + getSimpleIdentifier(members.get(i)));
817 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
819 println("structRet.add(structRetMem);");
821 } else { // Just one struct element
822 for (int i = 0; i < members.size(); i++) {
823 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
824 print("structRet." + getSimpleIdentifier(members.get(i)));
825 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
828 println("return structRet;");
833 * HELPER: writeStructReturnJavaStub() writes parameters if struct is present for return statement
835 private void writeStructReturnJavaStub(String simpleType, String retType, String method, InterfaceDecl intDecl) {
837 // Handle the returned struct size
838 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
839 // Minimum retLen is 1 if this is a single struct object
840 println("int retLen = (int) retObj;");
841 int numMem = getNumOfMembers(simpleType);
842 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
843 println("Class<?>[] retClsVal = new Class<?>[" + numMem + "*retLen];");
844 println("int retPos = 0;");
845 // Get the struct declaration for this struct and generate initialization code
846 StructDecl structDecl = getStructDecl(simpleType);
847 List<String> memTypes = structDecl.getMemberTypes(simpleType);
848 List<String> members = structDecl.getMembers(simpleType);
849 if (isArrayOrList(retType, retType)) { // An array or list
850 println("for(int i = 0; i < retLen; i++) {");
851 for (int i = 0; i < members.size(); i++) {
852 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
853 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
854 println("retClsVal[retPos++] = null;");
857 } else { // Just one struct element
858 for (int i = 0; i < members.size(); i++) {
859 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
860 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
861 println("retClsVal[retPos++] = null;");
864 //println("Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);");
865 // Handle the actual returned struct
866 writeWaitForReturnValueJava(method, intDecl, "Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);");
867 if (isArray(retType)) { // An array
868 println(simpleType + "[] structRet = new " + simpleType + "[retLen];");
869 println("for(int i = 0; i < retLen; i++) {");
870 println("structRet[i] = new " + simpleType + "();");
872 } else if (isList(retType)) { // A list
873 println("List<" + simpleType + "> structRet = new ArrayList<" + simpleType + ">();");
875 println(simpleType + " structRet = new " + simpleType + "();");
876 println("int retObjPos = 0;");
877 writeStructRetMembersJavaStub(simpleType, retType);
882 * HELPER: writeWaitForReturnValueJava() writes the synchronization part for return values
884 private void writeWaitForReturnValueJava(String method, InterfaceDecl intDecl, String getReturnValue) {
886 println("// Waiting for return value");
887 int methodNumId = intDecl.getMethodNumId(method);
888 println("while (!retValueReceived" + methodNumId + ".get());");
889 println(getReturnValue);
890 println("retValueReceived" + methodNumId + ".set(false);");
891 println("rmiComm.setGetReturnBytes();\n");
896 * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
898 private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
899 List<String> methPrmTypes, String method, String callbackType) {
901 checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method);
902 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
903 String retType = intDecl.getMethodType(method);
904 println("Class<?> retType = " + getSimpleType(getStructType(getEnumType(retType))) + ".class;");
905 checkAndWriteEnumTypeJavaStub(methParams, methPrmTypes);
906 // Generate array of parameter types
907 if (isStructPresent(methParams, methPrmTypes)) {
908 writeStructParamClassJavaStub(methParams, methPrmTypes, callbackType);
910 print("Class<?>[] paramCls = new Class<?>[] { ");
911 for (int i = 0; i < methParams.size(); i++) {
912 String prmType = methPrmTypes.get(i);
913 if (checkCallbackType(prmType, callbackType)) { // Check if this has callback object
914 print("int[].class");
915 } else { // Generate normal classes if it's not a callback object
916 String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
917 print(getSimpleType(getEnumType(paramType)) + ".class");
919 // Check if this is the last element (don't print a comma)
920 if (i != methParams.size() - 1) {
925 // Generate array of parameter objects
926 print("Object[] paramObj = new Object[] { ");
927 for (int i = 0; i < methParams.size(); i++) {
928 String paramType = methPrmTypes.get(i);
929 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
932 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
933 // Check if this is the last element (don't print a comma)
934 if (i != methParams.size() - 1) {
940 // Send method call first and wait for return value separately
941 println("rmiComm.remoteCall(objectId, methodId, paramCls, paramObj);");
942 // Check if this is "void"
943 if (!retType.equals("void")) { // We do have a return value
944 // Generate array of parameter types
945 if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
946 writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl);
948 // This is an enum type
949 if (getParamCategory(getGenericType(getSimpleArrayType(retType))) == ParamCategory.ENUM) {
950 //println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
951 checkAndWriteEnumRetTypeJavaStub(retType, method, intDecl);
952 } else if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
953 // Check if the return value NONPRIMITIVES
954 String retGenValType = getGenericType(retType);
955 println("Class<?> retGenValType = " + retGenValType + ".class;");
956 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, retGenValType);");
957 println("return (" + retType + ")retObj;");
959 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
960 println("return (" + retType + ")retObj;");
968 * HELPER: returnGenericCallbackType() returns the callback type
970 private String returnGenericCallbackType(String paramType) {
972 if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES)
973 return getGenericType(paramType);
980 * HELPER: checkCallbackType() checks the callback type
982 private boolean checkCallbackType(String paramType, String callbackType) {
984 String prmType = returnGenericCallbackType(paramType);
985 if (callbackType == null) // If there is no callbackType it means not a callback method
988 return callbackType.equals(prmType);
993 * HELPER: writeCallbackInstantiationMethodBodyJavaStub() writes the callback object instantiation in the method of the stub class
995 private void writeCallbackInstantiationMethodBodyJavaStub(String paramIdent, String callbackType, int counter, boolean isMultipleCallbacks) {
997 println("if (!IoTRMIUtil.mapSkel.containsKey(" + paramIdent + ")) {");
998 println("int newObjIdSent = rmiComm.getObjectIdCounter();");
999 if (isMultipleCallbacks)
1000 println("objIdSent[i++] = newObjIdSent;");
1002 println("objIdSent[0] = newObjIdSent;");
1003 println("rmiComm.decrementObjectIdCounter();");
1004 println(callbackType + "_Skeleton skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
1005 println("IoTRMIUtil.mapSkel.put(" + paramIdent + ", skel0);");
1006 println("IoTRMIUtil.mapSkelId.put(" + paramIdent + ", newObjIdSent);");
1007 println("Thread thread = new Thread() {");
1008 println("public void run() {");
1010 println("skel0.___waitRequestInvokeMethod();");
1011 println("} catch (Exception ex) {");
1012 println("ex.printStackTrace();");
1013 println("throw new Error(\"Exception when trying to run ___waitRequestInvokeMethod() for " +
1014 callbackType + "_Skeleton!\");");
1018 println("thread.start();");
1019 println("while(!skel" + counter + ".didAlreadyInitWaitInvoke());");
1023 println("int newObjIdSent = IoTRMIUtil.mapSkelId.get(" + paramIdent + ");");
1024 if (isMultipleCallbacks)
1025 println("objIdSent[i++] = newObjIdSent;");
1027 println("objIdSent[0] = newObjIdSent;");
1033 * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class
1035 private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
1036 List<String> methPrmTypes, String method, String callbackType) {
1038 // Determine callback object counter type (List vs. single variable)
1039 print("int[] objIdSent = ");
1040 for (int i = 0; i < methParams.size(); i++) {
1041 String paramType = methPrmTypes.get(i);
1042 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1043 String param = methParams.get(i);
1044 if (isArray(methParams.get(i)))
1045 println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".length];");
1046 else if (isList(methPrmTypes.get(i)))
1047 println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".size()];");
1049 println("new int[1];");
1053 // Check if this is single object, array, or list of objects
1054 for (int i = 0; i < methParams.size(); i++) {
1055 String paramType = methPrmTypes.get(i);
1056 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1057 String param = methParams.get(i);
1058 if (isArrayOrList(paramType, param)) { // Generate loop
1059 println("int i = 0;");
1060 println("for (" + getGenericType(paramType) + " cb : " + getSimpleIdentifier(param) + ") {");
1061 writeCallbackInstantiationMethodBodyJavaStub("cb", callbackType, i, true);
1063 writeCallbackInstantiationMethodBodyJavaStub(getSimpleIdentifier(param), callbackType, i, false);
1064 if (isArrayOrList(paramType, param))
1069 println(" catch (Exception ex) {");
1070 println("ex.printStackTrace();");
1071 println("throw new Error(\"Exception when generating skeleton objects!\");");
1077 * HELPER: writeMethodJavaStub() writes the methods of the stub class
1079 private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
1081 for (String method : methods) {
1083 List<String> methParams = intDecl.getMethodParams(method);
1084 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1085 print("public " + intDecl.getMethodType(method) + " " +
1086 intDecl.getMethodId(method) + "(");
1087 boolean isCallbackMethod = false;
1088 String callbackType = null;
1089 for (int i = 0; i < methParams.size(); i++) {
1091 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1092 // Check if this has callback object
1093 if (callbackClasses.contains(paramType)) {
1094 isCallbackMethod = true;
1095 callbackType = paramType;
1096 // Even if there're 2 callback arguments, we expect them to be of the same interface
1098 print(methPrmTypes.get(i) + " " + methParams.get(i));
1099 // Check if this is the last element (don't print a comma)
1100 if (i != methParams.size() - 1) {
1105 // Now, write the body of stub!
1106 if (isCallbackMethod)
1107 writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1109 writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1116 * HELPER: getStubInterface() gets stub interface name based on original interface
1118 public String getStubInterface(String intface) {
1120 return mapInt2NewIntName.get(intface);
1125 * generateJavaStubClasses() generate stubs based on the methods list in Java
1127 public void generateJavaStubClasses() throws IOException {
1129 // Create a new directory
1130 String path = createDirectories(dir, subdir);
1131 for (String intface : mapIntfacePTH.keySet()) {
1133 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1134 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1136 // Open a new file to write into
1137 String newIntface = intMeth.getKey();
1138 String newStubClass = newIntface + "_Stub";
1139 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
1140 pw = new PrintWriter(new BufferedWriter(fw));
1141 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1142 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1143 // Pass in set of methods and get import classes
1144 Set<String> methods = intMeth.getValue();
1145 Set<String> importClasses = getImportClasses(methods, intDecl);
1146 List<String> stdImportClasses = getStandardJavaImportClasses();
1147 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
1148 printImportStatements(allImportClasses); println("");
1149 // Find out if there are callback objects
1150 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
1151 boolean callbackExist = !callbackClasses.isEmpty();
1152 // Write class header
1153 println("public class " + newStubClass + " implements " + newIntface + " {\n");
1155 writePropertiesJavaStub(intface, intMeth.getValue(), intDecl);
1156 // Write constructor
1157 writeConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1158 // Write callback constructor (used if this stub is treated as a callback stub)
1159 writeCallbackConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1161 writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass);
1164 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
1171 * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class
1173 private void writePropertiesJavaSkeleton(String intface, InterfaceDecl intDecl) {
1175 println("private " + intface + " mainObj;");
1176 println("private int objectId = 0;");
1177 println("// Communications and synchronizations");
1178 println("private IoTRMIComm rmiComm;");
1179 println("private AtomicBoolean didAlreadyInitWaitInvoke;");
1180 println("private AtomicBoolean methodReceived;");
1181 println("private byte[] methodBytes = null;");
1182 println("// Permissions");
1183 writePropertiesJavaPermission(intface, intDecl);
1189 * HELPER: writeStructPermissionJavaSkeleton() writes permission for struct helper
1191 private void writeStructPermissionJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
1193 // Use this set to handle two same methodIds
1194 for (String method : methods) {
1195 List<String> methParams = intDecl.getMethodParams(method);
1196 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1197 // Check for params with structs
1198 for (int i = 0; i < methParams.size(); i++) {
1199 String paramType = methPrmTypes.get(i);
1200 String param = methParams.get(i);
1201 String simpleType = getGenericType(paramType);
1202 if (isStructClass(simpleType)) {
1203 int methodNumId = intDecl.getMethodNumId(method);
1204 String helperMethod = methodNumId + "struct" + i;
1205 int methodHelperNumId = intDecl.getHelperMethodNumId(helperMethod);
1206 // Iterate over interfaces to give permissions to
1207 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1208 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1209 String newIntface = intMeth.getKey();
1210 int newObjectId = getNewIntfaceObjectId(newIntface);
1211 println("set" + newObjectId + "Allowed.add(" + methodHelperNumId + ");");
1220 * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class
1222 private void writeConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl,
1223 Collection<String> methods, boolean callbackExist) {
1225 println("public " + newSkelClass + "(" + intface + " _mainObj, int _portSend, int _portRecv) throws Exception {");
1226 println("mainObj = _mainObj;");
1227 println("rmiComm = new IoTRMICommServer(_portSend, _portRecv);");
1228 // Generate permission control initialization
1229 writeConstructorJavaPermission(intface);
1230 //writeJavaInitCallbackPermission(intface, intDecl, callbackExist);
1231 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1232 println("IoTRMIUtil.mapSkel.put(_mainObj, this);");
1233 println("IoTRMIUtil.mapSkelId.put(_mainObj, objectId);");
1234 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1235 println("methodReceived = new AtomicBoolean(false);");
1236 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1237 println("Thread thread1 = new Thread() {");
1238 println("public void run() {");
1240 println("___waitRequestInvokeMethod();");
1242 println("catch (Exception ex)");
1244 println("ex.printStackTrace();");
1248 println("thread1.start();");
1254 * HELPER: writeCallbackConstructorJavaSkeleton() writes the constructor of the skeleton class
1256 private void writeCallbackConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl,
1257 Collection<String> methods, boolean callbackExist) {
1259 println("public " + newSkelClass + "(" + intface + " _mainObj, IoTRMIComm _rmiComm, int _objectId) throws Exception {");
1260 println("mainObj = _mainObj;");
1261 println("rmiComm = _rmiComm;");
1262 println("objectId = _objectId;");
1263 // Generate permission control initialization
1264 writeConstructorJavaPermission(intface);
1265 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1266 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1267 println("methodReceived = new AtomicBoolean(false);");
1268 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1274 * HELPER: writeStdMethodBodyJavaSkeleton() writes the standard method body in the skeleton class
1276 private void writeStdMethodBodyJavaSkeleton(List<String> methParams, String methodId, String methodType) {
1278 if (methodType.equals("void"))
1279 print("mainObj." + methodId + "(");
1281 print("return mainObj." + methodId + "(");
1282 for (int i = 0; i < methParams.size(); i++) {
1284 print(getSimpleIdentifier(methParams.get(i)));
1285 // Check if this is the last element (don't print a comma)
1286 if (i != methParams.size() - 1) {
1295 * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class
1297 private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses,
1298 boolean callbackSkeleton, String intface) {
1300 for (String method : methods) {
1302 List<String> methParams = intDecl.getMethodParams(method);
1303 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1304 String methodId = intDecl.getMethodId(method);
1305 print("public " + intDecl.getMethodType(method) + " " + methodId + "(");
1306 boolean isCallbackMethod = false;
1307 String callbackType = null;
1308 for (int i = 0; i < methParams.size(); i++) {
1310 String origParamType = methPrmTypes.get(i);
1311 String paramType = checkAndGetParamClass(origParamType);
1312 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
1313 isCallbackMethod = true;
1314 callbackType = origParamType;
1316 print(paramType + " " + methParams.get(i));
1317 // Check if this is the last element (don't print a comma)
1318 if (i != methParams.size() - 1) {
1323 // Now, write the body of skeleton!
1324 writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method));
1331 * HELPER: writeCallbackInstantiationJavaStubGeneration() writes the instantiation of callback stubs
1333 private void writeCallbackInstantiationJavaStubGeneration(String exchParamType) {
1335 //println("int objIdRecv = (int[]) paramObj[0];");
1336 println(exchParamType + " newStub = null;");
1337 println("if(!IoTRMIUtil.mapStub.containsKey(objIdRecv)) {");
1338 println("newStub = new " + exchParamType + "_Stub(rmiComm, objIdRecv);");
1339 println("IoTRMIUtil.mapStub.put(objIdRecv, newStub);");
1340 println("rmiComm.setObjectIdCounter(objIdRecv);");
1341 println("rmiComm.decrementObjectIdCounter();");
1344 println("newStub = (" + exchParamType + "_Stub) IoTRMIUtil.mapStub.get(objIdRecv);");
1350 * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part
1352 private Map<Integer,String> writeCallbackJavaStubGeneration(List<String> methParams, List<String> methPrmTypes,
1353 String callbackType, boolean isStructMethod) {
1355 Map<Integer,String> mapStubParam = new HashMap<Integer,String>();
1356 String offsetPfx = "";
1358 offsetPfx = "offset";
1359 // Iterate over callback objects
1360 for (int i = 0; i < methParams.size(); i++) {
1361 String paramType = methPrmTypes.get(i);
1362 String param = methParams.get(i);
1363 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1364 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1365 // Print array if this is array or list if this is a list of callback objects
1366 println("int[] stubIdArray" + i + " = (int[]) paramObj[" + offsetPfx + i + "];");
1367 if (isArray(param)) {
1368 println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1369 println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];");
1370 } else if (isList(paramType)) {
1371 println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1372 println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();");
1374 println("int objIdRecv = stubIdArray" + i + "[0];");
1375 writeCallbackInstantiationJavaStubGeneration(exchParamType);
1378 // Generate a loop if needed
1379 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1380 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1381 if (isArray(param)) {
1382 println("for (int i = 0; i < numStubs" + i + "; i++) {");
1383 println("int objIdRecv = stubIdArray" + i + "[i];");
1384 writeCallbackInstantiationJavaStubGeneration(exchParamType);
1385 println("stub" + i + "[i] = newStub;");
1387 } else if (isList(paramType)) {
1388 println("for (int i = 0; i < numStubs" + i + "; i++) {");
1389 println("int objIdRecv = stubIdArray" + i + "[i];");
1390 writeCallbackInstantiationJavaStubGeneration(exchParamType);
1391 println("stub" + i + ".add(newStub);");
1394 println(exchParamType + " stub" + i + " = newStub;");
1395 mapStubParam.put(i, "stub" + i); // List of all stub parameters
1398 return mapStubParam;
1403 * HELPER: checkAndWriteEnumTypeJavaSkeleton() writes the enum type (convert from enum to int)
1405 private void checkAndWriteEnumTypeJavaSkeleton(List<String> methParams, List<String> methPrmTypes, boolean isStructMethod) {
1407 String offsetPfx = "";
1409 offsetPfx = "offset";
1410 // Iterate and find enum declarations
1411 boolean printed = false;
1412 for (int i = 0; i < methParams.size(); i++) {
1413 String paramType = methPrmTypes.get(i);
1414 String param = methParams.get(i);
1415 String simpleType = getGenericType(paramType);
1416 if (isEnumClass(simpleType)) {
1417 // Check if this is enum type
1418 println("int paramInt" + i + "[] = (int[]) paramObj[" + offsetPfx + i + "];");
1420 println(simpleType + "[] enumVals = " + simpleType + ".values();");
1423 if (isArray(param)) { // An array
1424 println("int len" + i + " = paramInt" + i + ".length;");
1425 println(simpleType + "[] paramEnum" + i + " = new " + simpleType + "[len" + i + "];");
1426 println("for (int i = 0; i < len" + i + "; i++) {");
1427 println("paramEnum" + i + "[i] = enumVals[paramInt" + i + "[i]];");
1429 } else if (isList(paramType)) { // A list
1430 println("int len" + i + " = paramInt" + i + ".length;");
1431 println("List<" + simpleType + "> paramEnum" + i + " = new ArrayList<" + simpleType + ">();");
1432 println("for (int i = 0; i < len" + i + "; i++) {");
1433 println("paramEnum" + i + ".add(enumVals[paramInt" + i + "[i]]);");
1435 } else { // Just one element
1436 println(simpleType + " paramEnum" + i + " = enumVals[paramInt" + i + "[0]];");
1444 * HELPER: checkAndWriteEnumRetTypeJavaSkeleton() writes the enum return type (convert from enum to int)
1446 private void checkAndWriteEnumRetTypeJavaSkeleton(String retType, String methodId) {
1448 // Strips off array "[]" for return type
1449 String pureType = getSimpleArrayType(getGenericType(retType));
1450 // Take the inner type of generic
1451 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1452 pureType = getGenericType(retType);
1453 if (isEnumClass(pureType)) {
1454 // Check if this is enum type
1456 if (isArray(retType)) { // An array
1457 print(pureType + "[] retEnum = " + methodId + "(");
1458 } else if (isList(retType)) { // A list
1459 print("List<" + pureType + "> retEnum = " + methodId + "(");
1460 } else { // Just one element
1461 print(pureType + " retEnum = " + methodId + "(");
1468 * HELPER: checkAndWriteEnumRetConvJavaSkeleton() writes the enum return type (convert from enum to int)
1470 private void checkAndWriteEnumRetConvJavaSkeleton(String retType) {
1472 // Strips off array "[]" for return type
1473 String pureType = getSimpleArrayType(getGenericType(retType));
1474 // Take the inner type of generic
1475 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1476 pureType = getGenericType(retType);
1477 if (isEnumClass(pureType)) {
1478 // Check if this is enum type
1479 if (isArray(retType)) { // An array
1480 println("int retLen = retEnum.length;");
1481 println("int[] retEnumVal = new int[retLen];");
1482 println("for (int i = 0; i < retLen; i++) {");
1483 println("retEnumVal[i] = retEnum[i].ordinal();");
1485 } else if (isList(retType)) { // A list
1486 println("int retLen = retEnum.size();");
1487 println("int[] retEnumVal = new int[retLen];");
1488 println("for (int i = 0; i < retLen; i++) {");
1489 println("retEnumVal[i] = retEnum.get(i).ordinal();");
1491 } else { // Just one element
1492 println("int[] retEnumVal = new int[1];");
1493 println("retEnumVal[0] = retEnum.ordinal();");
1495 println("Object retObj = retEnumVal;");
1501 * HELPER: writeLengthStructParamClassSkeleton() writes lengths of params
1503 private void writeLengthStructParamClassSkeleton(List<String> methParams, List<String> methPrmTypes,
1504 String method, InterfaceDecl intDecl) {
1506 // Iterate and find struct declarations - count number of params
1507 for (int i = 0; i < methParams.size(); i++) {
1508 String paramType = methPrmTypes.get(i);
1509 String param = methParams.get(i);
1510 String simpleType = getGenericType(paramType);
1511 if (isStructClass(simpleType)) {
1512 int members = getNumOfMembers(simpleType);
1513 print(Integer.toString(members) + "*");
1514 int methodNumId = intDecl.getMethodNumId(method);
1515 print("struct" + methodNumId + "Size" + i);
1518 if (i != methParams.size() - 1) {
1526 * HELPER: writeStructMembersJavaSkeleton() writes member parameters of struct
1528 private void writeStructMembersJavaSkeleton(String simpleType, String paramType,
1529 String param, String method, InterfaceDecl intDecl, int iVar) {
1531 // Get the struct declaration for this struct and generate initialization code
1532 StructDecl structDecl = getStructDecl(simpleType);
1533 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1534 List<String> members = structDecl.getMembers(simpleType);
1535 if (isArrayOrList(paramType, param)) { // An array or list
1536 int methodNumId = intDecl.getMethodNumId(method);
1537 String counter = "struct" + methodNumId + "Size" + iVar;
1538 println("for(int i = 0; i < " + counter + "; i++) {");
1540 if (isArrayOrList(paramType, param)) { // An array or list
1541 for (int i = 0; i < members.size(); i++) {
1542 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1543 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1544 println("paramClsGen[pos++] = null;");
1547 } else { // Just one struct element
1548 for (int i = 0; i < members.size(); i++) {
1549 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1550 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1551 println("paramClsGen[pos++] = null;");
1558 * HELPER: writeStructMembersInitJavaSkeleton() writes member parameters initialization of struct
1560 private void writeStructMembersInitJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1561 List<String> methPrmTypes, String method) {
1563 println("int objPos = 0;");
1564 for (int i = 0; i < methParams.size(); i++) {
1565 String paramType = methPrmTypes.get(i);
1566 String param = methParams.get(i);
1567 String simpleType = getGenericType(paramType);
1568 if (isStructClass(simpleType)) {
1569 int methodNumId = intDecl.getMethodNumId(method);
1570 String counter = "struct" + methodNumId + "Size" + i;
1572 if (isArray(param)) { // An array
1573 println(simpleType + "[] paramStruct" + i + " = new " + simpleType + "[" + counter + "];");
1574 println("for(int i = 0; i < " + counter + "; i++) {");
1575 println("paramStruct" + i + "[i] = new " + simpleType + "();");
1577 } else if (isList(paramType)) { // A list
1578 println("List<" + simpleType + "> paramStruct" + i + " = new ArrayList<" + simpleType + ">();");
1580 println(simpleType + " paramStruct" + i + " = new " + simpleType + "();");
1581 // Initialize members
1582 StructDecl structDecl = getStructDecl(simpleType);
1583 List<String> members = structDecl.getMembers(simpleType);
1584 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1585 if (isArrayOrList(paramType, param)) { // An array or list
1586 println("for(int i = 0; i < " + counter + "; i++) {");
1588 if (isArray(param)) { // An array
1589 for (int j = 0; j < members.size(); j++) {
1590 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1591 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
1592 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1595 } else if (isList(paramType)) { // A list
1596 println(simpleType + " paramStructMem = new " + simpleType + "();");
1597 for (int j = 0; j < members.size(); j++) {
1598 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1599 print("paramStructMem." + getSimpleIdentifier(members.get(j)));
1600 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1602 println("paramStruct" + i + ".add(paramStructMem);");
1604 } else { // Just one struct element
1605 for (int j = 0; j < members.size(); j++) {
1606 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1607 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
1608 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1612 // Take offsets of parameters
1613 println("int offset" + i +" = objPos++;");
1620 * HELPER: writeStructReturnJavaSkeleton() writes struct for return statement
1622 private void writeStructReturnJavaSkeleton(String simpleType, String retType) {
1624 // Minimum retLen is 1 if this is a single struct object
1625 if (isArray(retType))
1626 println("int retLen = retStruct.length;");
1627 else if (isList(retType))
1628 println("int retLen = retStruct.size();");
1629 else // Just single struct object
1630 println("int retLen = 1;");
1631 println("Object retLenObj = retLen;");
1632 println("rmiComm.sendReturnObj(retLenObj, localMethodBytes);");
1633 int numMem = getNumOfMembers(simpleType);
1634 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
1635 println("Object[] retObj = new Object[" + numMem + "*retLen];");
1636 println("int retPos = 0;");
1637 // Get the struct declaration for this struct and generate initialization code
1638 StructDecl structDecl = getStructDecl(simpleType);
1639 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1640 List<String> members = structDecl.getMembers(simpleType);
1641 if (isArray(retType)) { // An array or list
1642 println("for(int i = 0; i < retLen; i++) {");
1643 for (int i = 0; i < members.size(); i++) {
1644 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1645 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1646 print("retObj[retPos++] = retStruct[i].");
1647 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1651 } else if (isList(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.get(i).");
1657 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1661 } else { // Just one struct element
1662 for (int i = 0; i < members.size(); i++) {
1663 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1664 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1665 print("retObj[retPos++] = retStruct.");
1666 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1675 * HELPER: writeMethodHelperReturnJavaSkeleton() writes return statement part in skeleton
1677 private void writeMethodHelperReturnJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1678 List<String> methPrmTypes, String method, boolean isCallbackMethod, String callbackType,
1679 boolean isStructMethod) {
1681 checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes, isStructMethod);
1682 Map<Integer,String> mapStubParam = null;
1683 if (isCallbackMethod) {
1685 mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType, isStructMethod);
1687 // Check if this is "void"
1688 String retType = intDecl.getMethodType(method);
1689 if (retType.equals("void")) {
1690 print(intDecl.getMethodId(method) + "(");
1691 } else if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
1692 checkAndWriteEnumRetTypeJavaSkeleton(retType, intDecl.getMethodId(method));
1693 } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
1694 print(retType + " retStruct = " + intDecl.getMethodId(method) + "(");
1695 } else { // We do have a return value
1696 print("Object retObj = " + intDecl.getMethodId(method) + "(");
1698 for (int i = 0; i < methParams.size(); i++) {
1700 String paramType = methPrmTypes.get(i);
1701 if (isCallbackMethod && checkCallbackType(paramType, callbackType)) {
1702 print(mapStubParam.get(i)); // Get the callback parameter
1703 } else if (isEnumClass(getGenericType(paramType))) { // Enum class
1704 print(getEnumParam(paramType, methParams.get(i), i));
1705 } else if (isStructClass(getGenericType(paramType))) {
1706 print("paramStruct" + i);
1708 String prmType = checkAndGetArray(paramType, methParams.get(i));
1710 print("(" + prmType + ") paramObj[offset" + i + "]");
1712 print("(" + prmType + ") paramObj[" + i + "]");
1714 if (i != methParams.size() - 1)
1718 if (!retType.equals("void")) {
1719 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
1720 checkAndWriteEnumRetConvJavaSkeleton(retType);
1721 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1722 } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
1723 writeStructReturnJavaSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
1724 println("rmiComm.sendReturnObj(retCls, retObj, localMethodBytes);");
1726 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1728 if (isCallbackMethod) { // Catch exception if this is callback
1730 println(" catch(Exception ex) {");
1731 println("ex.printStackTrace();");
1732 println("throw new Error(\"Exception from callback object instantiation!\");");
1739 * HELPER: writeMethodHelperStructJavaSkeleton() writes the struct in skeleton
1741 private void writeMethodHelperStructJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1742 List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1744 // Generate array of parameter objects
1745 boolean isCallbackMethod = false;
1746 String callbackType = null;
1747 println("byte[] localMethodBytes = methodBytes;");
1748 println("rmiComm.setGetMethodBytes();");
1749 print("int paramLen = ");
1750 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
1752 println("Class<?>[] paramCls = new Class<?>[paramLen];");
1753 println("Class<?>[] paramClsGen = new Class<?>[paramLen];");
1754 println("int pos = 0;");
1755 // Iterate again over the parameters
1756 for (int i = 0; i < methParams.size(); i++) {
1757 String paramType = methPrmTypes.get(i);
1758 String param = methParams.get(i);
1759 String simpleType = getGenericType(paramType);
1760 if (isStructClass(simpleType)) {
1761 writeStructMembersJavaSkeleton(simpleType, paramType, param, method, intDecl, i);
1763 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
1764 if (callbackClasses.contains(prmType)) {
1765 isCallbackMethod = true;
1766 callbackType = prmType;
1767 println("paramCls[pos] = int[].class;");
1768 println("paramClsGen[pos++] = null;");
1769 } else { // Generate normal classes if it's not a callback object
1770 String paramTypeOth = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1771 println("paramCls[pos] = " + getSimpleType(getEnumType(paramTypeOth)) + ".class;");
1772 print("paramClsGen[pos++] = ");
1773 String prmTypeOth = methPrmTypes.get(i);
1774 if (getParamCategory(prmTypeOth) == ParamCategory.NONPRIMITIVES)
1775 println(getTypeOfGeneric(prmType)[0] + ".class;");
1781 println("Object[] paramObj = rmiComm.getMethodParams(paramCls, paramClsGen, localMethodBytes);");
1782 writeStructMembersInitJavaSkeleton(intDecl, methParams, methPrmTypes, method);
1783 // Write the return value part
1784 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, true);
1789 * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class
1791 private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1792 List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1794 // Generate array of parameter objects
1795 boolean isCallbackMethod = false;
1796 String callbackType = null;
1797 println("byte[] localMethodBytes = methodBytes;");
1798 println("rmiComm.setGetMethodBytes();");
1799 print("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { ");
1800 for (int i = 0; i < methParams.size(); i++) {
1802 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1803 if (callbackClasses.contains(paramType)) {
1804 isCallbackMethod = true;
1805 callbackType = paramType;
1806 print("int[].class");
1807 } else { // Generate normal classes if it's not a callback object
1808 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1809 print(getSimpleType(getEnumType(prmType)) + ".class");
1811 if (i != methParams.size() - 1)
1815 // Generate generic class if it's a generic type.. null otherwise
1816 print(" }, new Class<?>[] { ");
1817 for (int i = 0; i < methParams.size(); i++) {
1818 String prmType = methPrmTypes.get(i);
1819 if ((getParamCategory(prmType) == ParamCategory.NONPRIMITIVES) &&
1820 !isEnumClass(getGenericType(prmType)) &&
1821 !callbackClasses.contains(getGenericType(prmType)))
1822 print(getGenericType(prmType) + ".class");
1825 if (i != methParams.size() - 1)
1828 println(" }, localMethodBytes);");
1829 // Write the return value part
1830 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, false);
1835 * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class
1837 private void writeMethodHelperJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1839 // Use this set to handle two same methodIds
1840 Set<String> uniqueMethodIds = new HashSet<String>();
1841 for (String method : methods) {
1843 List<String> methParams = intDecl.getMethodParams(method);
1844 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1845 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
1846 String methodId = intDecl.getMethodId(method);
1847 print("public void ___");
1848 String helperMethod = methodId;
1849 if (uniqueMethodIds.contains(methodId))
1850 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1852 uniqueMethodIds.add(methodId);
1853 String retType = intDecl.getMethodType(method);
1854 print(helperMethod + "(");
1855 boolean begin = true;
1856 for (int i = 0; i < methParams.size(); i++) { // Print size variables
1857 String paramType = methPrmTypes.get(i);
1858 String param = methParams.get(i);
1859 String simpleType = getGenericType(paramType);
1860 if (isStructClass(simpleType)) {
1861 if (!begin) // Generate comma for not the beginning variable
1865 int methodNumId = intDecl.getMethodNumId(method);
1866 print("int struct" + methodNumId + "Size" + i);
1869 // Check if this is "void"
1870 if (retType.equals("void"))
1873 println(") throws IOException {");
1874 writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1877 String methodId = intDecl.getMethodId(method);
1878 print("public void ___");
1879 String helperMethod = methodId;
1880 if (uniqueMethodIds.contains(methodId))
1881 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1883 uniqueMethodIds.add(methodId);
1884 // Check if this is "void"
1885 String retType = intDecl.getMethodType(method);
1886 if (retType.equals("void"))
1887 println(helperMethod + "() {");
1889 println(helperMethod + "() throws IOException {");
1890 // Now, write the helper body of skeleton!
1891 writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1895 // Write method helper for structs
1896 writeMethodHelperStructSetupJavaSkeleton(methods, intDecl);
1901 * HELPER: writeMethodHelperStructSetupJavaSkeleton() writes the method helper of struct setup in skeleton class
1903 private void writeMethodHelperStructSetupJavaSkeleton(Collection<String> methods,
1904 InterfaceDecl intDecl) {
1906 // Use this set to handle two same methodIds
1907 for (String method : methods) {
1909 List<String> methParams = intDecl.getMethodParams(method);
1910 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1911 // Check for params with structs
1912 for (int i = 0; i < methParams.size(); i++) {
1913 String paramType = methPrmTypes.get(i);
1914 String param = methParams.get(i);
1915 String simpleType = getGenericType(paramType);
1916 if (isStructClass(simpleType)) {
1917 int methodNumId = intDecl.getMethodNumId(method);
1918 print("public int ___");
1919 String helperMethod = methodNumId + "struct" + i;
1920 println(helperMethod + "() {");
1921 // Now, write the helper body of skeleton!
1922 println("byte[] localMethodBytes = methodBytes;");
1923 println("rmiComm.setGetMethodBytes();");
1924 println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null }, localMethodBytes);");
1925 println("return (int) paramObj[0];");
1934 * HELPER: writeMethodHelperStructSetupJavaCallbackSkeleton() writes the method helper of struct setup in callback skeleton class
1936 private void writeMethodHelperStructSetupJavaCallbackSkeleton(Collection<String> methods,
1937 InterfaceDecl intDecl) {
1939 // Use this set to handle two same methodIds
1940 for (String method : methods) {
1942 List<String> methParams = intDecl.getMethodParams(method);
1943 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1944 // Check for params with structs
1945 for (int i = 0; i < methParams.size(); i++) {
1946 String paramType = methPrmTypes.get(i);
1947 String param = methParams.get(i);
1948 String simpleType = getGenericType(paramType);
1949 if (isStructClass(simpleType)) {
1950 int methodNumId = intDecl.getMethodNumId(method);
1951 print("public int ___");
1952 String helperMethod = methodNumId + "struct" + i;
1953 println(helperMethod + "(IoTRMIObject rmiObj) {");
1954 // Now, write the helper body of skeleton!
1955 println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null });");
1956 println("return (int) paramObj[0];");
1965 * HELPER: writeCountVarStructSkeleton() writes counter variable of struct for skeleton
1967 private void writeCountVarStructSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1969 // Use this set to handle two same methodIds
1970 for (String method : methods) {
1972 List<String> methParams = intDecl.getMethodParams(method);
1973 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1974 // Check for params with structs
1975 for (int i = 0; i < methParams.size(); i++) {
1976 String paramType = methPrmTypes.get(i);
1977 String param = methParams.get(i);
1978 String simpleType = getGenericType(paramType);
1979 if (isStructClass(simpleType)) {
1980 int methodNumId = intDecl.getMethodNumId(method);
1981 println("int struct" + methodNumId + "Size" + i + " = 0;");
1989 * HELPER: writeInputCountVarStructJavaSkeleton() writes input counter variable of struct for skeleton
1991 private boolean writeInputCountVarStructJavaSkeleton(String method, InterfaceDecl intDecl) {
1993 List<String> methParams = intDecl.getMethodParams(method);
1994 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1995 boolean structExist = false;
1996 boolean begin = true;
1997 // Check for params with structs
1998 for (int i = 0; i < methParams.size(); i++) {
1999 String paramType = methPrmTypes.get(i);
2000 String param = methParams.get(i);
2001 String simpleType = getGenericType(paramType);
2002 if (isStructClass(simpleType)) {
2008 int methodNumId = intDecl.getMethodNumId(method);
2009 print("struct" + methodNumId + "Size" + i + "Final");
2017 * HELPER: writeInputCountVarStructCplusSkeleton() writes input counter variable of struct for skeleton
2019 private boolean writeInputCountVarStructCplusSkeleton(String method, InterfaceDecl intDecl) {
2021 List<String> methParams = intDecl.getMethodParams(method);
2022 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2023 boolean structExist = false;
2024 boolean begin = true;
2025 // Check for params with structs
2026 for (int i = 0; i < methParams.size(); i++) {
2027 String paramType = methPrmTypes.get(i);
2028 String param = methParams.get(i);
2029 String simpleType = getGenericType(paramType);
2030 if (isStructClass(simpleType)) {
2036 int methodNumId = intDecl.getMethodNumId(method);
2037 print("struct" + methodNumId + "Size" + i);
2045 * HELPER: writeMethodCallStructJavaSkeleton() writes method call for wait invoke in skeleton
2047 private void writeMethodCallStructJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2049 // Use this set to handle two same methodIds
2050 for (String method : methods) {
2052 List<String> methParams = intDecl.getMethodParams(method);
2053 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2054 // Check for params with structs
2055 for (int i = 0; i < methParams.size(); i++) {
2056 String paramType = methPrmTypes.get(i);
2057 String param = methParams.get(i);
2058 String simpleType = getGenericType(paramType);
2059 if (isStructClass(simpleType)) {
2060 int methodNumId = intDecl.getMethodNumId(method);
2062 String helperMethod = methodNumId + "struct" + i;
2063 String tempVar = "struct" + methodNumId + "Size" + i;
2064 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2065 print(tempVar + " = ___");
2066 println(helperMethod + "(); break;");
2074 * HELPER: writeMethodCallStructCplusSkeleton() writes method call for wait invoke in skeleton
2076 private void writeMethodCallStructCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2078 // Use this set to handle two same methodIds
2079 for (String method : methods) {
2081 List<String> methParams = intDecl.getMethodParams(method);
2082 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2083 // Check for params with structs
2084 for (int i = 0; i < methParams.size(); i++) {
2085 String paramType = methPrmTypes.get(i);
2086 String param = methParams.get(i);
2087 String simpleType = getGenericType(paramType);
2088 if (isStructClass(simpleType)) {
2089 int methodNumId = intDecl.getMethodNumId(method);
2091 String helperMethod = methodNumId + "struct" + i;
2092 String tempVar = "struct" + methodNumId + "Size" + i;
2093 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2094 print(tempVar + " = ___");
2095 println(helperMethod + "(skel); break;");
2103 * HELPER: writeMethodCallStructCallbackSkeleton() writes method call for wait invoke in skeleton
2105 private void writeMethodCallStructCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2107 // Use this set to handle two same methodIds
2108 for (String method : methods) {
2110 List<String> methParams = intDecl.getMethodParams(method);
2111 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2112 // Check for params with structs
2113 for (int i = 0; i < methParams.size(); i++) {
2114 String paramType = methPrmTypes.get(i);
2115 String param = methParams.get(i);
2116 String simpleType = getGenericType(paramType);
2117 if (isStructClass(simpleType)) {
2118 int methodNumId = intDecl.getMethodNumId(method);
2120 String helperMethod = methodNumId + "struct" + i;
2121 String tempVar = "struct" + methodNumId + "Size" + i;
2122 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2123 print(tempVar + " = ___");
2124 println(helperMethod + "(rmiObj); break;");
2132 * HELPER: writeJavaMethodPermission() writes permission checks in skeleton
2134 private void writeJavaMethodPermission(String intface) {
2136 // Get all the different stubs
2137 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2138 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2139 String newIntface = intMeth.getKey();
2140 int newObjectId = getNewIntfaceObjectId(newIntface);
2141 println("if (_objectId == objectId) {");
2142 println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
2143 println("throw new Error(\"Object with object Id: \" + _objectId + \" is not allowed to access method: \" + methodId);");
2147 println("continue;");
2154 * HELPER: writeFinalInputCountVarStructSkeleton() writes the final version of input counter variable of struct for skeleton
2156 private boolean writeFinalInputCountVarStructSkeleton(String method, InterfaceDecl intDecl) {
2158 List<String> methParams = intDecl.getMethodParams(method);
2159 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2160 boolean structExist = false;
2161 boolean begin = true;
2162 // Check for params with structs
2163 for (int i = 0; i < methParams.size(); i++) {
2164 String paramType = methPrmTypes.get(i);
2165 String param = methParams.get(i);
2166 String simpleType = getGenericType(paramType);
2167 if (isStructClass(simpleType)) {
2169 int methodNumId = intDecl.getMethodNumId(method);
2170 println("final int struct" + methodNumId + "Size" + i +
2171 "Final = struct" + methodNumId + "Size" + i + ";");
2179 * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class
2181 private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, String intface) {
2183 // Use this set to handle two same methodIds
2184 Set<String> uniqueMethodIds = new HashSet<String>();
2185 println("public void ___waitRequestInvokeMethod() throws IOException {");
2186 // Write variables here if we have callbacks or enums or structs
2187 writeCountVarStructSkeleton(methods, intDecl);
2188 println("didAlreadyInitWaitInvoke.compareAndSet(false, true);");
2189 println("while (true) {");
2190 println("if (!methodReceived.get()) {");
2191 println("continue;");
2193 println("methodBytes = rmiComm.getMethodBytes();");
2194 println("methodReceived.set(false);");
2195 println("int _objectId = IoTRMIComm.getObjectId(methodBytes);");
2196 println("int methodId = IoTRMIComm.getMethodId(methodBytes);");
2197 // Generate permission check
2198 writeJavaMethodPermission(intface);
2199 println("switch (methodId) {");
2200 // Print methods and method Ids
2201 for (String method : methods) {
2202 String methodId = intDecl.getMethodId(method);
2203 int methodNumId = intDecl.getMethodNumId(method);
2204 println("case " + methodNumId + ":");
2205 // Check for stuct counters
2206 writeFinalInputCountVarStructSkeleton(method, intDecl);
2207 println("new Thread() {");
2208 println("public void run() {");
2211 String helperMethod = methodId;
2212 if (uniqueMethodIds.contains(methodId))
2213 helperMethod = helperMethod + methodNumId;
2215 uniqueMethodIds.add(methodId);
2216 print(helperMethod + "(");
2217 writeInputCountVarStructJavaSkeleton(method, intDecl);
2220 println("catch (Exception ex) {");
2221 println("ex.printStackTrace();");
2224 println("}.start();");
2227 String method = "___initCallBack()";
2228 writeMethodCallStructJavaSkeleton(methods, intDecl);
2229 println("default: ");
2230 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
2238 * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke
2240 private void writeReturnDidAlreadyInitWaitInvoke() {
2242 println("public boolean didAlreadyInitWaitInvoke() {");
2243 println("return didAlreadyInitWaitInvoke.get();");
2249 * generateJavaSkeletonClass() generate skeletons based on the methods list in Java
2251 public void generateJavaSkeletonClass() throws IOException {
2253 // Create a new directory
2254 String path = createDirectories(dir, subdir);
2255 for (String intface : mapIntfacePTH.keySet()) {
2256 // Open a new file to write into
2257 String newSkelClass = intface + "_Skeleton";
2258 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
2259 pw = new PrintWriter(new BufferedWriter(fw));
2260 // Pass in set of methods and get import classes
2261 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2262 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2263 List<String> methods = intDecl.getMethods();
2264 Set<String> importClasses = getImportClasses(methods, intDecl);
2265 List<String> stdImportClasses = getStandardJavaImportClasses();
2266 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
2267 printImportStatements(allImportClasses);
2268 // Find out if there are callback objects
2269 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2270 boolean callbackExist = !callbackClasses.isEmpty();
2271 // Write class header
2273 println("public class " + newSkelClass + " implements " + intface + " {\n");
2275 writePropertiesJavaSkeleton(intface, intDecl);
2276 // Write constructor
2277 writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2278 // Write constructor that is called when this object is a callback object
2279 writeCallbackConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2280 // Write function to return didAlreadyInitWaitInvoke
2281 writeReturnDidAlreadyInitWaitInvoke();
2283 writeMethodJavaSkeleton(methods, intDecl, callbackClasses, false, intface);
2284 // Write method helper
2285 writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
2286 // Write waitRequestInvokeMethod() - main loop
2287 writeJavaWaitRequestInvokeMethod(methods, intDecl, intface);
2290 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
2295 /*================================================================================
2299 *================================================================================/
2302 * HELPER: writeMethodCplusLocalInterface() writes the method of the local interface
2304 private void writeMethodCplusLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
2306 for (String method : methods) {
2308 List<String> methParams = intDecl.getMethodParams(method);
2309 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2310 print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2311 intDecl.getMethodId(method) + "(");
2312 for (int i = 0; i < methParams.size(); i++) {
2313 // Check for params with driver class types and exchange it
2314 // with its remote interface
2315 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
2316 paramType = checkAndGetCplusType(paramType);
2317 // Check for arrays - translate into vector in C++
2318 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2319 print(paramComplete);
2320 // Check if this is the last element (don't print a comma)
2321 if (i != methParams.size() - 1) {
2331 * HELPER: writeMethodCplusInterface() writes the method of the interface
2333 private void writeMethodCplusInterface(Collection<String> methods, InterfaceDecl intDecl) {
2335 for (String method : methods) {
2337 List<String> methParams = intDecl.getMethodParams(method);
2338 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2339 print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2340 intDecl.getMethodId(method) + "(");
2341 for (int i = 0; i < methParams.size(); i++) {
2342 // Check for params with driver class types and exchange it
2343 // with its remote interface
2344 String paramType = methPrmTypes.get(i);
2345 paramType = checkAndGetCplusType(paramType);
2346 // Check for arrays - translate into vector in C++
2347 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2348 print(paramComplete);
2349 // Check if this is the last element (don't print a comma)
2350 if (i != methParams.size() - 1) {
2360 * HELPER: generateEnumCplus() writes the enumeration declaration
2362 public void generateEnumCplus() throws IOException {
2364 // Create a new directory
2365 createDirectory(dir);
2366 for (String intface : mapIntfacePTH.keySet()) {
2367 // Get the right StructDecl
2368 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2369 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
2370 Set<String> enumTypes = enumDecl.getEnumDeclarations();
2371 // Iterate over enum declarations
2372 for (String enType : enumTypes) {
2373 // Open a new file to write into
2374 FileWriter fw = new FileWriter(dir + "/" + enType + ".hpp");
2375 pw = new PrintWriter(new BufferedWriter(fw));
2376 // Write file headers
2377 println("#ifndef _" + enType.toUpperCase() + "_HPP__");
2378 println("#define _" + enType.toUpperCase() + "_HPP__");
2379 println("enum " + enType + " {");
2380 List<String> enumMembers = enumDecl.getMembers(enType);
2381 for (int i = 0; i < enumMembers.size(); i++) {
2383 String member = enumMembers.get(i);
2385 // Check if this is the last element (don't print a comma)
2386 if (i != enumMembers.size() - 1)
2394 System.out.println("IoTCompiler: Generated enum " + enType + ".hpp...");
2401 * HELPER: generateStructCplus() writes the struct declaration
2403 public void generateStructCplus() throws IOException {
2405 // Create a new directory
2406 createDirectory(dir);
2407 for (String intface : mapIntfacePTH.keySet()) {
2408 // Get the right StructDecl
2409 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2410 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
2411 List<String> structTypes = structDecl.getStructTypes();
2412 // Iterate over enum declarations
2413 for (String stType : structTypes) {
2414 // Open a new file to write into
2415 FileWriter fw = new FileWriter(dir + "/" + stType + ".hpp");
2416 pw = new PrintWriter(new BufferedWriter(fw));
2417 // Write file headers
2418 println("#ifndef _" + stType.toUpperCase() + "_HPP__");
2419 println("#define _" + stType.toUpperCase() + "_HPP__");
2420 println("using namespace std;");
2421 println("struct " + stType + " {");
2422 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
2423 List<String> structMembers = structDecl.getMembers(stType);
2424 for (int i = 0; i < structMembers.size(); i++) {
2426 String memberType = structMemberTypes.get(i);
2427 String member = structMembers.get(i);
2428 String structTypeC = checkAndGetCplusType(memberType);
2429 String structComplete = checkAndGetCplusArray(structTypeC, member);
2430 println(structComplete + ";");
2435 System.out.println("IoTCompiler: Generated struct " + stType + ".hpp...");
2442 * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
2444 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
2445 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
2446 * The local interface has to be the input parameter for the stub and the stub
2447 * interface has to be the input parameter for the local class.
2449 public void generateCplusLocalInterfaces() throws IOException {
2451 // Create a new directory
2452 createDirectory(dir);
2453 for (String intface : mapIntfacePTH.keySet()) {
2454 // Open a new file to write into
2455 FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
2456 pw = new PrintWriter(new BufferedWriter(fw));
2457 // Write file headers
2458 println("#ifndef _" + intface.toUpperCase() + "_HPP__");
2459 println("#define _" + intface.toUpperCase() + "_HPP__");
2460 println("#include <iostream>");
2461 // Pass in set of methods and get include classes
2462 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2463 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2464 List<String> methods = intDecl.getMethods();
2465 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, true);
2466 printIncludeStatements(includeClasses); println("");
2467 println("using namespace std;\n");
2468 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2469 if (!intface.equals(mainClass)) // Forward declare if not main class
2470 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, true);
2471 println("class " + intface); println("{");
2474 writeMethodCplusLocalInterface(methods, intDecl);
2478 System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
2484 * HELPER: writeMethodCplusInterfaceForwardDecl() writes the forward declaration of the interface
2486 private void writeMethodCplusInterfaceForwardDecl(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, boolean needNewIntface) {
2488 Set<String> isDefined = new HashSet<String>();
2489 for (String method : methods) {
2491 List<String> methParams = intDecl.getMethodParams(method);
2492 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2493 for (int i = 0; i < methParams.size(); i++) {
2494 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2495 // Check if this has callback object
2496 if (callbackClasses.contains(paramType)) {
2497 if (!isDefined.contains(paramType)) {
2499 println("class " + getStubInterface(paramType) + ";\n");
2501 println("class " + paramType + ";\n");
2502 isDefined.add(paramType);
2511 * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
2513 * For C++ we use virtual classe as interface
2515 public void generateCPlusInterfaces() throws IOException {
2517 // Create a new directory
2518 String path = createDirectories(dir, subdir);
2519 for (String intface : mapIntfacePTH.keySet()) {
2521 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2522 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2524 // Open a new file to write into
2525 String newIntface = intMeth.getKey();
2526 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
2527 pw = new PrintWriter(new BufferedWriter(fw));
2528 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2529 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2530 // Write file headers
2531 println("#ifndef _" + newIntface.toUpperCase() + "_HPP__");
2532 println("#define _" + newIntface.toUpperCase() + "_HPP__");
2533 println("#include <iostream>");
2534 updateIntfaceObjIdMap(intface, newIntface);
2535 // Pass in set of methods and get import classes
2536 Set<String> methods = intMeth.getValue();
2537 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, false);
2538 printIncludeStatements(includeClasses); println("");
2539 println("using namespace std;\n");
2540 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2541 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, false);
2542 println("class " + newIntface);
2546 writeMethodCplusInterface(methods, intDecl);
2550 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
2557 * HELPER: writeMethodDeclCplusStub() writes the method declarations of the stub
2559 private void writeMethodDeclCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
2561 for (String method : methods) {
2563 List<String> methParams = intDecl.getMethodParams(method);
2564 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2565 print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2566 intDecl.getMethodId(method) + "(");
2567 boolean isCallbackMethod = false;
2568 String callbackType = null;
2569 for (int i = 0; i < methParams.size(); i++) {
2571 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2572 // Check if this has callback object
2573 if (callbackClasses.contains(paramType)) {
2574 isCallbackMethod = true;
2575 callbackType = paramType;
2576 // Even if there're 2 callback arguments, we expect them to be of the same interface
2578 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2579 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2580 print(methParamComplete);
2581 // Check if this is the last element (don't print a comma)
2582 if (i != methParams.size() - 1) {
2592 * HELPER: writeMethodCplusStub() writes the methods of the stub
2594 private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
2596 for (String method : methods) {
2598 List<String> methParams = intDecl.getMethodParams(method);
2599 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2600 // Print the mutex lock first
2601 int methodNumId = intDecl.getMethodNumId(method);
2602 String mutexVar = "mtx" + newStubClass + "MethodExec" + methodNumId;
2603 println("mutex " + mutexVar + ";");
2604 print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " + newStubClass + "::" +
2605 intDecl.getMethodId(method) + "(");
2606 boolean isCallbackMethod = false;
2607 String callbackType = null;
2608 for (int i = 0; i < methParams.size(); i++) {
2610 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2611 // Check if this has callback object
2612 if (callbackClasses.contains(paramType)) {
2613 isCallbackMethod = true;
2614 callbackType = paramType;
2615 // Even if there're 2 callback arguments, we expect them to be of the same interface
2617 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2618 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2619 print(methParamComplete);
2620 // Check if this is the last element (don't print a comma)
2621 if (i != methParams.size() - 1) {
2626 println("lock_guard<mutex> guard(" + mutexVar + ");");
2627 if (isCallbackMethod)
2628 writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType);
2629 writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType, isCallbackMethod);
2637 * HELPER: writeCallbackInstantiationMethodBodyCplusStub() writes the callback object instantiation in the method of the stub class
2639 private void writeCallbackInstantiationMethodBodyCplusStub(String paramIdent, String callbackType, int counter) {
2641 println("auto it = IoTRMIUtil::mapSkel->find(" + paramIdent + ");");
2642 println("if (it == IoTRMIUtil::mapSkel->end()) {");
2643 println("int newObjIdSent = rmiComm->getObjectIdCounter();");
2644 println("objIdSent.push_back(newObjIdSent);");
2645 println("rmiComm->decrementObjectIdCounter();");
2646 println(callbackType + "_Skeleton* skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
2647 println("vecCallbackObj.push_back(skel0);");
2648 println("IoTRMIUtil::mapSkel->insert(make_pair(" + paramIdent + ", skel0));");
2649 println("IoTRMIUtil::mapSkelId->insert(make_pair(" + paramIdent + ", newObjIdSent));");
2650 println("thread th0 (&" + callbackType + "_Skeleton::___waitRequestInvokeMethod, std::ref(skel0), std::ref(skel0));");
2651 println("th0.detach();");
2652 println("while(!skel" + counter + "->didInitWaitInvoke());");
2656 println("auto itId = IoTRMIUtil::mapSkelId->find(" + paramIdent + ");");
2657 println("objIdSent.push_back(itId->second);");
2663 * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class
2665 private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
2666 List<String> methPrmTypes, String method, String callbackType) {
2668 // Check if this is single object, array, or list of objects
2669 boolean isArrayOrList = false;
2670 String callbackParam = null;
2671 println("vector<int> objIdSent;");
2672 for (int i = 0; i < methParams.size(); i++) {
2674 String paramType = methPrmTypes.get(i);
2675 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2676 String param = methParams.get(i);
2677 if (isArrayOrList(paramType, param)) { // Generate loop
2678 println("for (" + getGenericType(paramType) + "* cb : " + getSimpleIdentifier(param) + ") {");
2679 writeCallbackInstantiationMethodBodyCplusStub("cb", callbackType, i);
2680 isArrayOrList = true;
2681 callbackParam = getSimpleIdentifier(param);
2683 writeCallbackInstantiationMethodBodyCplusStub(getSimpleIdentifier(param), callbackType, i);
2687 println("vector<int> ___paramCB" + i + " = objIdSent;");
2694 * HELPER: checkAndWriteEnumTypeCplusStub() writes the enum type (convert from enum to int)
2696 private void checkAndWriteEnumTypeCplusStub(List<String> methParams, List<String> methPrmTypes) {
2698 // Iterate and find enum declarations
2699 for (int i = 0; i < methParams.size(); i++) {
2700 String paramType = methPrmTypes.get(i);
2701 String param = methParams.get(i);
2702 if (isEnumClass(getGenericType(paramType))) {
2703 // Check if this is enum type
2704 if (isArrayOrList(paramType, param)) { // An array or vector
2705 println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
2706 println("vector<int> paramEnum" + i + "(len" + i + ");");
2707 println("for (int i = 0; i < len" + i + "; i++) {");
2708 println("paramEnum" + i + "[i] = (int) " + getSimpleIdentifier(param) + "[i];");
2710 } else { // Just one element
2711 println("vector<int> paramEnum" + i + "(1);");
2712 println("paramEnum" + i + "[0] = (int) " + param + ";");
2720 * HELPER: checkAndWriteEnumRetTypeCplusStub() writes the enum return type (convert from enum to int)
2722 private void checkAndWriteEnumRetTypeCplusStub(String retType, String method, InterfaceDecl intDecl) {
2724 // Strips off array "[]" for return type
2725 String pureType = getSimpleArrayType(getGenericType(retType));
2726 // Take the inner type of generic
2727 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
2728 pureType = getGenericType(retType);
2729 if (isEnumClass(pureType)) {
2730 // Check if this is enum type
2731 println("vector<int> retEnumInt;");
2732 println("void* retObj = &retEnumInt;");
2733 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
2734 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
2735 if (isArrayOrList(retType, retType)) { // An array or vector
2736 println("int retLen = retEnumInt.size();");
2737 println("vector<" + pureType + "> retVal(retLen);");
2738 println("for (int i = 0; i < retLen; i++) {");
2739 println("retVal[i] = (" + pureType + ") retEnumInt[i];");
2741 } else { // Just one element
2742 println(pureType + " retVal = (" + pureType + ") retEnumInt[0];");
2744 println("return retVal;");
2750 * HELPER: checkAndWriteStructSetupCplusStub() writes the struct type setup
2752 private void checkAndWriteStructSetupCplusStub(List<String> methParams, List<String> methPrmTypes,
2753 InterfaceDecl intDecl, String method) {
2755 // Iterate and find struct declarations
2756 for (int i = 0; i < methParams.size(); i++) {
2757 String paramType = methPrmTypes.get(i);
2758 String param = methParams.get(i);
2759 String simpleType = getGenericType(paramType);
2760 if (isStructClass(simpleType)) {
2761 // Check if this is enum type
2762 println("int numParam" + i + " = 1;");
2763 int methodNumId = intDecl.getMethodNumId(method);
2764 String helperMethod = methodNumId + "struct" + i;
2765 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
2766 //println("string retTypeStruct" + i + " = \"void\";");
2767 println("string paramClsStruct" + i + "[] = { \"int\" };");
2768 print("int structLen" + i + " = ");
2769 if (isArrayOrList(paramType, param)) { // An array
2770 println(getSimpleArrayType(param) + ".size();");
2771 } else { // Just one element
2774 println("void* paramObjStruct" + i + "[] = { &structLen" + i + " };");
2775 //println("void* retStructLen" + i + " = NULL;");
2776 println("rmiComm->remoteCall(objectId, methodIdStruct" + i +
2777 ", paramClsStruct" + i + ", paramObjStruct" + i +
2778 ", numParam" + i + ");\n");
2785 * HELPER: writeLengthStructParamClassCplusStub() writes lengths of params
2787 private void writeLengthStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes) {
2789 // Iterate and find struct declarations - count number of params
2790 for (int i = 0; i < methParams.size(); i++) {
2791 String paramType = methPrmTypes.get(i);
2792 String param = methParams.get(i);
2793 String simpleType = getGenericType(paramType);
2794 if (isStructClass(simpleType)) {
2795 int members = getNumOfMembers(simpleType);
2796 if (isArrayOrList(paramType, param)) { // An array or list
2797 String structLen = getSimpleIdentifier(param) + ".size()";
2798 print(members + "*" + structLen);
2800 print(Integer.toString(members));
2803 if (i != methParams.size() - 1) {
2811 * HELPER: writeStructMembersCplusStub() writes member parameters of struct
2813 private void writeStructMembersCplusStub(String simpleType, String paramType, String param) {
2815 // Get the struct declaration for this struct and generate initialization code
2816 StructDecl structDecl = getStructDecl(simpleType);
2817 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2818 List<String> members = structDecl.getMembers(simpleType);
2819 if (isArrayOrList(paramType, param)) { // An array or list
2820 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
2822 if (isArrayOrList(paramType, param)) { // An array or list
2823 for (int i = 0; i < members.size(); i++) {
2824 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2825 println("paramCls[pos] = \"" + prmTypeC + "\";");
2826 print("paramObj[pos++] = &" + getSimpleIdentifier(param) + "[i].");
2827 print(getSimpleIdentifier(members.get(i)));
2831 } else { // Just one struct element
2832 for (int i = 0; i < members.size(); i++) {
2833 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2834 println("paramCls[pos] = \"" + prmTypeC + "\";");
2835 print("paramObj[pos++] = &" + param + ".");
2836 print(getSimpleIdentifier(members.get(i)));
2844 * HELPER: writeStructParamClassCplusStub() writes member parameters of struct
2846 private void writeStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes, String callbackType) {
2848 print("int numParam = ");
2849 writeLengthStructParamClassCplusStub(methParams, methPrmTypes);
2851 println("void* paramObj[numParam];");
2852 println("string paramCls[numParam];");
2853 println("int pos = 0;");
2854 // Iterate again over the parameters
2855 for (int i = 0; i < methParams.size(); i++) {
2856 String paramType = methPrmTypes.get(i);
2857 String param = methParams.get(i);
2858 String simpleType = getGenericType(paramType);
2859 if (isStructClass(simpleType)) {
2860 writeStructMembersCplusStub(simpleType, paramType, param);
2861 } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2862 println("paramCls[pos] = \"int\";");
2863 println("paramObj[pos++] = &___paramCB" + i + ";");
2865 String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
2866 println("paramCls[pos] = \"" + prmTypeC + "\";");
2867 print("paramObj[pos++] = &");
2868 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
2877 * HELPER: writeStructRetMembersCplusStub() writes member parameters of struct for return statement
2879 private void writeStructRetMembersCplusStub(String simpleType, String retType) {
2881 // Get the struct declaration for this struct and generate initialization code
2882 StructDecl structDecl = getStructDecl(simpleType);
2883 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2884 List<String> members = structDecl.getMembers(simpleType);
2885 if (isArrayOrList(retType, retType)) { // An array or list
2886 println("for(int i = 0; i < retLen; i++) {");
2888 if (isArrayOrList(retType, retType)) { // An array or list
2889 for (int i = 0; i < members.size(); i++) {
2890 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2891 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
2892 println(" = retParam" + i + "[i];");
2895 } else { // Just one struct element
2896 for (int i = 0; i < members.size(); i++) {
2897 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2898 print("structRet." + getSimpleIdentifier(members.get(i)));
2899 println(" = retParam" + i + ";");
2902 println("return structRet;");
2907 * HELPER: writeStructReturnCplusStub() writes member parameters of struct for return statement
2909 private void writeStructReturnCplusStub(String simpleType, String retType, String method, InterfaceDecl intDecl) {
2911 // Minimum retLen is 1 if this is a single struct object
2912 println("int retLen = 0;");
2913 println("void* retLenObj = { &retLen };");
2914 // Handle the returned struct!!!
2915 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
2916 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retLenObj);");
2917 int numMem = getNumOfMembers(simpleType);
2918 println("int numRet = " + numMem + "*retLen;");
2919 println("string retCls[numRet];");
2920 println("void* retObj[numRet];");
2921 StructDecl structDecl = getStructDecl(simpleType);
2922 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2923 List<String> members = structDecl.getMembers(simpleType);
2925 if (isArrayOrList(retType, retType)) { // An array or list
2926 for (int i = 0; i < members.size(); i++) {
2927 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2928 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2929 println(getSimpleType(getEnumType(prmType)) + " retParam" + i + "[retLen];");
2931 } else { // Just one struct element
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 + ";");
2938 println("int retPos = 0;");
2939 // Get the struct declaration for this struct and generate initialization code
2940 if (isArrayOrList(retType, retType)) { // An array or list
2941 println("for(int i = 0; i < retLen; i++) {");
2942 for (int i = 0; i < members.size(); i++) {
2943 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2944 println("retCls[retPos] = \"" + prmTypeC + "\";");
2945 println("retObj[retPos++] = &retParam" + i + "[i];");
2948 } else { // Just one struct element
2949 for (int i = 0; i < members.size(); i++) {
2950 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2951 println("retCls[retPos] = \"" + prmTypeC + "\";");
2952 println("retObj[retPos++] = &retParam" + i + ";");
2955 //println("rmiComm->getStructObjects(retCls, numRet, retObj);");
2956 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getStructObjects(retCls, numRet, retObj);");
2957 if (isArrayOrList(retType, retType)) { // An array or list
2958 println("vector<" + simpleType + "> structRet(retLen);");
2960 println(simpleType + " structRet;");
2961 writeStructRetMembersCplusStub(simpleType, retType);
2966 * HELPER: writeWaitForReturnValueCplus() writes the synchronization part for return values
2968 private void writeWaitForReturnValueCplus(String method, InterfaceDecl intDecl, String getReturnValue) {
2970 println("// Waiting for return value");
2971 int methodNumId = intDecl.getMethodNumId(method);
2972 println("while (!retValueReceived" + methodNumId + ");");
2973 println(getReturnValue);
2974 println("retValueReceived" + methodNumId + " = false;");
2975 println("didGetReturnBytes.exchange(true);\n");
2980 * HELPER: writeStdMethodBodyCplusStub() writes the standard method body in the stub class
2982 private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
2983 List<String> methPrmTypes, String method, String callbackType, boolean isCallbackMethod) {
2985 checkAndWriteStructSetupCplusStub(methParams, methPrmTypes, intDecl, method);
2986 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
2987 String retType = intDecl.getMethodType(method);
2988 println("string retType = \"" + checkAndGetCplusRetClsType(getStructType(getEnumType(retType))) + "\";");
2989 checkAndWriteEnumTypeCplusStub(methParams, methPrmTypes);
2990 // Generate array of parameter types
2991 if (isStructPresent(methParams, methPrmTypes)) {
2992 writeStructParamClassCplusStub(methParams, methPrmTypes, callbackType);
2994 println("int numParam = " + methParams.size() + ";");
2995 print("string paramCls[] = { ");
2996 for (int i = 0; i < methParams.size(); i++) {
2997 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2998 if (checkCallbackType(paramType, callbackType)) {
3001 String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3002 print("\"" + paramTypeC + "\"");
3004 // Check if this is the last element (don't print a comma)
3005 if (i != methParams.size() - 1) {
3010 // Generate array of parameter objects
3011 print("void* paramObj[] = { ");
3012 for (int i = 0; i < methParams.size(); i++) {
3013 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3014 if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
3015 print("&___paramCB" + i);
3017 print("&" + getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
3018 // Check if this is the last element (don't print a comma)
3019 if (i != methParams.size() - 1) {
3025 // Check if this is "void"
3026 if (retType.equals("void")) {
3027 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
3028 } else { // We do have a return value
3029 // Generate array of parameter types
3030 if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
3031 writeStructReturnCplusStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl);
3033 // Check if the return value NONPRIMITIVES
3034 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) {
3035 checkAndWriteEnumRetTypeCplusStub(retType, method, intDecl);
3037 //if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
3038 if (isArrayOrList(retType,retType))
3039 println(checkAndGetCplusType(retType) + " retVal;");
3041 println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";");
3043 println("void* retObj = &retVal;");
3044 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
3045 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
3046 println("return retVal;");
3054 * HELPER: writePropertiesCplusPermission() writes the properties of the stub class
3056 private void writePropertiesCplusPermission(String intface) {
3058 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3059 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3060 String newIntface = intMeth.getKey();
3061 int newObjectId = getNewIntfaceObjectId(newIntface);
3062 println("int objectId = " + newObjectId + ";");
3063 println("static set<int> set" + newObjectId + "Allowed;");
3068 * HELPER: writePropertiesCplusStub() writes the properties of the stub class
3070 private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist,
3071 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3073 println("IoTRMIComm *rmiComm;");
3074 // Get the object Id
3075 Integer objId = mapIntfaceObjId.get(intface);
3076 println("int objectId = " + objId + ";");
3077 if (callbackExist) {
3078 // We assume that each class only has one callback interface for now
3079 Iterator it = callbackClasses.iterator();
3080 String callbackType = (String) it.next();
3081 println("// Callback properties");
3082 println("vector<" + callbackType + "*> vecCallbackObj;");
3084 println("// Synchronization variables");
3085 for (String method : methods) {
3086 // Generate AtomicBooleans for methods that have return values
3087 String returnType = intDecl.getMethodType(method);
3088 int methodNumId = intDecl.getMethodNumId(method);
3089 if (!returnType.equals("void")) {
3090 println("bool retValueReceived" + methodNumId + " = false;");
3098 * HELPER: writeConstructorCplusStub() writes the constructor of the stub class
3100 private void writeConstructorCplusStub(String newStubClass, boolean callbackExist,
3101 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3103 println(newStubClass + "::" + newStubClass +
3104 "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult) {");
3105 println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev, _bResult);");
3106 // Register the AtomicBoolean variables
3107 for (String method : methods) {
3108 // Generate AtomicBooleans for methods that have return values
3109 String returnType = intDecl.getMethodType(method);
3110 int methodNumId = intDecl.getMethodNumId(method);
3111 if (!returnType.equals("void")) {
3112 println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");");
3115 println("IoTRMIUtil::mapStub->insert(make_pair(objectId, this));");
3121 * HELPER: writeCallbackConstructorCplusStub() writes the callback constructor of the stub class
3123 private void writeCallbackConstructorCplusStub(String newStubClass, boolean callbackExist,
3124 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3126 println(newStubClass + "::" + newStubClass + "(IoTRMIComm* _rmiComm, int _objectId) {");
3127 println("rmiComm = _rmiComm;");
3128 println("objectId = _objectId;");
3129 // Register the AtomicBoolean variables
3130 for (String method : methods) {
3131 // Generate AtomicBooleans for methods that have return values
3132 String returnType = intDecl.getMethodType(method);
3133 int methodNumId = intDecl.getMethodNumId(method);
3134 if (!returnType.equals("void")) {
3135 println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");");
3143 * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
3145 private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
3147 println(newStubClass + "::~" + newStubClass + "() {");
3148 println("if (rmiComm != NULL) {");
3149 println("delete rmiComm;");
3150 println("rmiComm = NULL;");
3152 if (callbackExist) {
3153 // We assume that each class only has one callback interface for now
3154 Iterator it = callbackClasses.iterator();
3155 String callbackType = (String) it.next();
3156 println("for(" + callbackType + "* cb : vecCallbackObj) {");
3157 println("delete cb;");
3158 println("cb = NULL;");
3167 * HELPER: writeCplusMethodCallbackPermission() writes permission checks in stub for callbacks
3169 private void writeCplusMethodCallbackPermission(String intface) {
3171 println("int methodId = IoTRMIObject::getMethodId(method);");
3172 // Get all the different stubs
3173 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3174 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3175 String newIntface = intMeth.getKey();
3176 int newObjectId = getNewIntfaceObjectId(newIntface);
3177 println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
3178 println("cerr << \"Callback object for " + intface + " is not allowed to access method: \" << methodId;");
3186 * generateCPlusStubClassesHpp() generate stubs based on the methods list in C++ (.hpp file)
3188 public void generateCPlusStubClassesHpp() throws IOException {
3190 // Create a new directory
3191 String path = createDirectories(dir, subdir);
3192 for (String intface : mapIntfacePTH.keySet()) {
3194 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3195 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3196 // Open a new file to write into
3197 String newIntface = intMeth.getKey();
3198 String newStubClass = newIntface + "_Stub";
3199 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
3200 pw = new PrintWriter(new BufferedWriter(fw));
3201 // Write file headers
3202 println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
3203 println("#define _" + newStubClass.toUpperCase() + "_HPP__");
3204 println("#include <iostream>");
3205 // Find out if there are callback objects
3206 Set<String> methods = intMeth.getValue();
3207 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3208 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3209 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3210 boolean callbackExist = !callbackClasses.isEmpty();
3211 println("#include <thread>");
3212 println("#include <mutex>");
3213 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
3214 printIncludeStatements(stdIncludeClasses); println("");
3215 println("#include \"" + newIntface + ".hpp\""); println("");
3216 println("using namespace std;"); println("");
3217 println("class " + newStubClass + " : public " + newIntface); println("{");
3218 println("private:\n");
3219 writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses, methods, intDecl);
3220 println("public:\n");
3221 // Add default constructor and destructor
3222 println(newStubClass + "();");
3224 println(newStubClass + "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult);");
3225 println(newStubClass + "(IoTRMIComm* _rmiComm, int _objectId);");
3226 println("~" + newStubClass + "();");
3228 writeMethodDeclCplusStub(methods, intDecl, callbackClasses, newStubClass);
3229 print("}"); println(";");
3232 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
3239 * writeStubExternalCFunctions() generate external functions for .so file
3241 public void writeStubExternalCFunctions(String newStubClass) throws IOException {
3243 println("extern \"C\" void* create" + newStubClass + "(void** params) {");
3244 println("// Args: int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult");
3245 println("return new " + newStubClass + "(*((int*) params[0]), *((int*) params[1]), ((string*) params[2])->c_str(), " +
3246 "*((int*) params[3]), (bool*) params[4]);");
3248 println("extern \"C\" void destroy" + newStubClass + "(void* t) {");
3249 println(newStubClass + "* obj = (" + newStubClass + "*) t;");
3250 println("delete obj;");
3252 //println("extern \"C\" void init" + newStubClass + "(void* t) {");
3253 //println(newStubClass + "* obj = (" + newStubClass + "*) t;");
3254 //println("obj->init();");
3255 //println("while(true);");
3261 * generateCPlusStubClassesCpp() generate stubs based on the methods list in C++ (.cpp file)
3263 public void generateCPlusStubClassesCpp() throws IOException {
3265 // Create a new directory
3266 String path = createDirectories(dir, subdir);
3267 for (String intface : mapIntfacePTH.keySet()) {
3269 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3270 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3271 // Open a new file to write into
3272 String newIntface = intMeth.getKey();
3273 String newStubClass = newIntface + "_Stub";
3274 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".cpp");
3275 pw = new PrintWriter(new BufferedWriter(fw));
3276 // Write file headers
3277 println("#include <iostream>");
3278 // Find out if there are callback objects
3279 Set<String> methods = intMeth.getValue();
3280 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3281 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3282 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3283 boolean callbackExist = !callbackClasses.isEmpty();
3284 println("#include \"" + newStubClass + ".hpp\""); println("");
3285 for(String str: callbackClasses) {
3286 if (intface.equals(mainClass))
3287 println("#include \"" + str + "_Skeleton.cpp\"\n");
3289 println("#include \"" + str + "_Skeleton.hpp\"\n");
3291 println("using namespace std;"); println("");
3292 // Add default constructor and destructor
3293 //println(newStubClass + "() { }"); println("");
3294 writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
3295 writeCallbackConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
3296 writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
3298 writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass);
3299 // Write external functions for .so file
3300 writeStubExternalCFunctions(newStubClass);
3301 // TODO: Remove this later
3302 if (intface.equals(mainClass)) {
3303 println("int main() {");
3304 println("return 0;");
3308 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".cpp...");
3315 * HELPER: writePropertiesCplusSkeleton() writes the properties of the skeleton class
3317 private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
3319 println(intface + " *mainObj;");
3321 if (callbackExist) {
3322 Iterator it = callbackClasses.iterator();
3323 String callbackType = (String) it.next();
3324 String exchangeType = checkAndGetParamClass(callbackType);
3325 println("// Callback properties");
3326 println("vector<" + exchangeType + "*> vecCallbackObj;");
3328 println("IoTRMIComm *rmiComm;");
3329 println("char* methodBytes;");
3330 println("int methodLen;");
3331 // Keep track of object Ids of all stubs registered to this interface
3332 writePropertiesCplusPermission(intface);
3333 println("// Synchronization variables");
3334 println("bool methodReceived = false;");
3335 println("bool didAlreadyInitWaitInvoke = false;");
3341 * HELPER: writeObjectIdCountInitializationCplus() writes the initialization of objIdCnt variable
3343 private void writeObjectIdCountInitializationCplus(String newSkelClass, boolean callbackExist) {
3346 println("int " + newSkelClass + "::objIdCnt = 0;");
3351 * HELPER: writePermissionInitializationCplus() writes the initialization of permission set
3353 private void writePermissionInitializationCplus(String intface, String newSkelClass, InterfaceDecl intDecl) {
3355 // Keep track of object Ids of all stubs registered to this interface
3356 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3357 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3358 String newIntface = intMeth.getKey();
3359 int newObjectId = getNewIntfaceObjectId(newIntface);
3360 print("set<int> " + newSkelClass + "::set" + newObjectId + "Allowed { ");
3361 Set<String> methodIds = intMeth.getValue();
3363 for (String methodId : methodIds) {
3364 int methodNumId = intDecl.getMethodNumId(methodId);
3365 print(Integer.toString(methodNumId));
3366 // Check if this is the last element (don't print a comma)
3367 if (i != methodIds.size() - 1) {
3378 * HELPER: writeStructPermissionCplusSkeleton() writes permission for struct helper
3380 private void writeStructPermissionCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
3382 // Use this set to handle two same methodIds
3383 for (String method : methods) {
3384 List<String> methParams = intDecl.getMethodParams(method);
3385 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3386 // Check for params with structs
3387 for (int i = 0; i < methParams.size(); i++) {
3388 String paramType = methPrmTypes.get(i);
3389 String param = methParams.get(i);
3390 String simpleType = getGenericType(paramType);
3391 if (isStructClass(simpleType)) {
3392 int methodNumId = intDecl.getMethodNumId(method);
3393 String helperMethod = methodNumId + "struct" + i;
3394 int helperMethodNumId = intDecl.getHelperMethodNumId(helperMethod);
3395 // Iterate over interfaces to give permissions to
3396 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3397 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3398 String newIntface = intMeth.getKey();
3399 int newObjectId = getNewIntfaceObjectId(newIntface);
3400 println("set" + newObjectId + "Allowed.insert(" + helperMethodNumId + ");");
3409 * HELPER: writeConstructorCplusSkeleton() writes the constructor of the skeleton class
3411 private void writeConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
3413 println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, int _portSend, int _portRecv) {");
3414 println("bool _bResult = false;");
3415 println("mainObj = _mainObj;");
3416 println("rmiComm = new IoTRMICommServer(_portSend, _portRecv, &_bResult);");
3417 println("IoTRMIUtil::mapSkel->insert(make_pair(_mainObj, this));");
3418 println("IoTRMIUtil::mapSkelId->insert(make_pair(_mainObj, objectId));");
3419 println("rmiComm->registerSkeleton(objectId, &methodReceived);");
3420 writeStructPermissionCplusSkeleton(methods, intDecl, intface);
3421 println("thread th1 (&" + newSkelClass + "::___waitRequestInvokeMethod, this, this);");
3422 println("th1.join();");
3428 * HELPER: writeCallbackConstructorCplusSkeleton() writes the callback constructor of the skeleton class
3430 private void writeCallbackConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
3432 println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, IoTRMIComm *_rmiComm, int _objectId) {");
3433 println("bool _bResult = false;");
3434 println("mainObj = _mainObj;");
3435 println("rmiComm = _rmiComm;");
3436 println("objectId = _objectId;");
3437 println("rmiComm->registerSkeleton(objectId, &methodReceived);");
3438 writeStructPermissionCplusSkeleton(methods, intDecl, intface);
3444 * HELPER: writeDeconstructorCplusSkeleton() writes the deconstructor of the skeleton class
3446 private void writeDeconstructorCplusSkeleton(String newSkelClass, boolean callbackExist, Set<String> callbackClasses) {
3448 println(newSkelClass + "::~" + newSkelClass + "() {");
3449 println("if (rmiComm != NULL) {");
3450 println("delete rmiComm;");
3451 println("rmiComm = NULL;");
3453 if (callbackExist) {
3454 // We assume that each class only has one callback interface for now
3455 Iterator it = callbackClasses.iterator();
3456 String callbackType = (String) it.next();
3457 String exchangeType = checkAndGetParamClass(callbackType);
3458 println("for(" + exchangeType + "* cb : vecCallbackObj) {");
3459 println("delete cb;");
3460 println("cb = NULL;");
3469 * HELPER: writeStdMethodBodyCplusSkeleton() writes the standard method body in the skeleton class
3471 private void writeStdMethodBodyCplusSkeleton(List<String> methParams, String methodId, String methodType) {
3473 if (methodType.equals("void"))
3474 print("mainObj->" + methodId + "(");
3476 print("return mainObj->" + methodId + "(");
3477 for (int i = 0; i < methParams.size(); i++) {
3479 print(getSimpleIdentifier(methParams.get(i)));
3480 // Check if this is the last element (don't print a comma)
3481 if (i != methParams.size() - 1) {
3490 * HELPER: writeMethodDeclCplusSkeleton() writes the method declaration of the skeleton class
3492 private void writeMethodDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
3493 Set<String> callbackClasses) {
3495 for (String method : methods) {
3497 List<String> methParams = intDecl.getMethodParams(method);
3498 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3499 String methodId = intDecl.getMethodId(method);
3500 String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
3501 print(methodType + " " + methodId + "(");
3502 boolean isCallbackMethod = false;
3503 String callbackType = null;
3504 for (int i = 0; i < methParams.size(); i++) {
3506 String origParamType = methPrmTypes.get(i);
3507 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
3508 isCallbackMethod = true;
3509 callbackType = origParamType;
3511 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
3512 String methPrmType = checkAndGetCplusType(paramType);
3513 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3514 print(methParamComplete);
3515 // Check if this is the last element (don't print a comma)
3516 if (i != methParams.size() - 1) {
3526 * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class
3528 private void writeMethodCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
3529 Set<String> callbackClasses, boolean callbackSkeleton, String intface, String newSkelClass) {
3531 for (String method : methods) {
3533 List<String> methParams = intDecl.getMethodParams(method);
3534 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3535 String methodId = intDecl.getMethodId(method);
3536 String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
3537 print(methodType + " " + newSkelClass + "::" + methodId + "(");
3538 boolean isCallbackMethod = false;
3539 String callbackType = null;
3540 for (int i = 0; i < methParams.size(); i++) {
3542 String origParamType = methPrmTypes.get(i);
3543 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
3544 isCallbackMethod = true;
3545 callbackType = origParamType;
3547 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
3548 String methPrmType = checkAndGetCplusType(paramType);
3549 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3550 print(methParamComplete);
3551 // Check if this is the last element (don't print a comma)
3552 if (i != methParams.size() - 1) {
3557 // Now, write the body of skeleton!
3558 writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method));
3565 * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable
3567 private void writeCallbackCplusNumStubs(List<String> methParams, List<String> methPrmTypes, String callbackType) {
3569 for (int i = 0; i < methParams.size(); i++) {
3570 String paramType = methPrmTypes.get(i);
3571 String param = methParams.get(i);
3572 //if (callbackType.equals(paramType)) {
3573 if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
3574 //println("int numStubs" + i + " = 0;");
3575 println("vector<int> numStubIdArray" + i + ";");
3581 * HELPER: writeCallbackInstantiationCplusStubGeneration() writes the instantiation of callback stubs
3583 private void writeCallbackInstantiationCplusStubGeneration(String exchParamType) {
3585 //println("int objIdRecv = (int[]) paramObj[0];");
3586 println(exchParamType + "* newStub = NULL;");
3587 println("auto it = IoTRMIUtil::mapStub->find(objIdRecv);");
3588 println("if (it == IoTRMIUtil::mapStub->end()) {");
3589 println("newStub = new " + exchParamType + "_Stub(rmiComm, objIdRecv);");
3590 println("IoTRMIUtil::mapStub->insert(make_pair(objIdRecv, newStub));");
3591 println("rmiComm->setObjectIdCounter(objIdRecv);");
3592 println("rmiComm->decrementObjectIdCounter();");
3593 println("skel->vecCallbackObj.push_back(newStub);");
3596 println("newStub = (" + exchParamType + "_Stub*) it->second;");
3602 * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part
3604 private void writeCallbackCplusStubGeneration(List<String> methParams, List<String> methPrmTypes, String callbackType) {
3606 // Iterate over callback objects
3607 for (int i = 0; i < methParams.size(); i++) {
3608 String paramType = methPrmTypes.get(i);
3609 String param = methParams.get(i);
3610 // Generate a loop if needed
3611 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
3612 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
3613 if (isArrayOrList(paramType, param)) {
3614 println("vector<" + exchParamType + "*> stub" + i + ";");
3615 println("for (int i = 0; i < numStubIdArray" + i + ".size(); i++) {");
3616 println("int objIdRecv = numStubIdArray" + i + "[i];");
3617 writeCallbackInstantiationCplusStubGeneration(exchParamType);
3618 println("stub" + i + ".push_back(newStub);");
3621 println("int objIdRecv = numStubIdArray" + i + "[0];");
3622 writeCallbackInstantiationCplusStubGeneration(exchParamType);
3623 println(exchParamType + "* stub" + i + " = newStub;");
3631 * HELPER: checkAndWriteEnumTypeCplusSkeleton() writes the enum type (convert from enum to int)
3633 private void checkAndWriteEnumTypeCplusSkeleton(List<String> methParams, List<String> methPrmTypes) {
3635 // Iterate and find enum declarations
3636 for (int i = 0; i < methParams.size(); i++) {
3637 String paramType = methPrmTypes.get(i);
3638 String param = methParams.get(i);
3639 String simpleType = getGenericType(paramType);
3640 if (isEnumClass(simpleType)) {
3641 // Check if this is enum type
3642 if (isArrayOrList(paramType, param)) { // An array
3643 println("int len" + i + " = paramEnumInt" + i + ".size();");
3644 println("vector<" + simpleType + "> paramEnum" + i + "(len" + i + ");");
3645 println("for (int i=0; i < len" + i + "; i++) {");
3646 println("paramEnum" + i + "[i] = (" + simpleType + ") paramEnumInt" + i + "[i];");
3648 } else { // Just one element
3649 println(simpleType + " paramEnum" + i + ";");
3650 println("paramEnum" + i + " = (" + simpleType + ") paramEnumInt" + i + "[0];");
3658 * HELPER: checkAndWriteEnumRetTypeCplusSkeleton() writes the enum return type (convert from enum to int)
3660 private void checkAndWriteEnumRetTypeCplusSkeleton(String retType) {
3662 // Strips off array "[]" for return type
3663 String pureType = getSimpleArrayType(getGenericType(retType));
3664 // Take the inner type of generic
3665 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
3666 pureType = getGenericType(retType);
3667 if (isEnumClass(pureType)) {
3668 // Check if this is enum type
3670 if (isArrayOrList(retType, retType)) { // An array
3671 println("int retLen = retEnum.size();");
3672 println("vector<int> retEnumInt(retLen);");
3673 println("for (int i=0; i < retLen; i++) {");
3674 println("retEnumInt[i] = (int) retEnum[i];");
3676 } else { // Just one element
3677 println("vector<int> retEnumInt(1);");
3678 println("retEnumInt[0] = (int) retEnum;");
3685 * HELPER: writeMethodInputParameters() writes the parameter variables for C++ skeleton
3687 private void writeMethodInputParameters(List<String> methParams, List<String> methPrmTypes,
3688 Set<String> callbackClasses, String methodId) {
3690 print(methodId + "(");
3691 for (int i = 0; i < methParams.size(); i++) {
3692 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3693 if (callbackClasses.contains(paramType))
3695 else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3696 print("paramEnum" + i);
3697 else if (isStructClass(getGenericType(paramType))) // Struct type
3698 print("paramStruct" + i);
3700 print(getSimpleIdentifier(methParams.get(i)));
3701 if (i != methParams.size() - 1) {
3710 * HELPER: writeMethodHelperReturnCplusSkeleton() writes the return statement part in skeleton
3712 private void writeMethodHelperReturnCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3713 List<String> methPrmTypes, String method, boolean isCallbackMethod, String callbackType,
3714 String methodId, Set<String> callbackClasses) {
3716 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
3717 if (isCallbackMethod)
3718 writeCallbackCplusStubGeneration(methParams, methPrmTypes, callbackType);
3719 checkAndWriteEnumTypeCplusSkeleton(methParams, methPrmTypes);
3720 writeStructMembersInitCplusSkeleton(intDecl, methParams, methPrmTypes, method);
3721 // Check if this is "void"
3722 String retType = intDecl.getMethodType(method);
3723 // Check if this is "void"
3724 if (retType.equals("void")) {
3725 writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3726 } else { // We do have a return value
3727 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
3728 print(checkAndGetCplusType(retType) + " retEnum = ");
3729 else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3730 print(checkAndGetCplusType(retType) + " retStruct = ");
3732 print(checkAndGetCplusType(retType) + " retVal = ");
3733 writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3734 checkAndWriteEnumRetTypeCplusSkeleton(retType);
3735 if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3736 writeStructReturnCplusSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
3737 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
3738 println("void* retObj = &retEnumInt;");
3740 if (!isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3741 println("void* retObj = &retVal;");
3742 String retTypeC = checkAndGetCplusType(retType);
3743 if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3744 println("rmiComm->sendReturnObj(retObj, retCls, numRetObj, localMethodBytes);");
3746 println("rmiComm->sendReturnObj(retObj, \"" + checkAndGetCplusRetClsType(getEnumType(retType)) + "\", localMethodBytes);");
3752 * HELPER: writeStdMethodHelperBodyCplusSkeleton() writes the standard method body helper in the skeleton class
3754 private void writeStdMethodHelperBodyCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3755 List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3757 // Generate array of parameter types
3758 boolean isCallbackMethod = false;
3759 String callbackType = null;
3760 print("string paramCls[] = { ");
3761 for (int i = 0; i < methParams.size(); i++) {
3762 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3763 if (callbackClasses.contains(paramType)) {
3764 isCallbackMethod = true;
3765 callbackType = paramType;
3767 } else { // Generate normal classes if it's not a callback object
3768 String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3769 print("\"" + paramTypeC + "\"");
3771 if (i != methParams.size() - 1) {
3776 println("int numParam = " + methParams.size() + ";");
3777 if (isCallbackMethod)
3778 writeCallbackCplusNumStubs(methParams, methPrmTypes, callbackType);
3779 // Generate parameters
3780 for (int i = 0; i < methParams.size(); i++) {
3781 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3782 if (!callbackClasses.contains(paramType)) {
3783 String methParamType = methPrmTypes.get(i);
3784 if (isEnumClass(getSimpleArrayType(getGenericType(methParamType)))) {
3785 // Check if this is enum type
3786 println("vector<int> paramEnumInt" + i + ";");
3788 String methPrmType = checkAndGetCplusType(methParamType);
3789 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3790 println(methParamComplete + ";");
3794 // Generate array of parameter objects
3795 print("void* paramObj[] = { ");
3796 for (int i = 0; i < methParams.size(); i++) {
3797 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3798 if (callbackClasses.contains(paramType))
3799 print("&numStubIdArray" + i);
3800 else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3801 print("¶mEnumInt" + i);
3803 print("&" + getSimpleIdentifier(methParams.get(i)));
3804 if (i != methParams.size() - 1) {
3809 // Write the return value part
3810 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
3811 callbackType, methodId, callbackClasses);
3816 * HELPER: writeStructMembersCplusSkeleton() writes member parameters of struct
3818 private void writeStructMembersCplusSkeleton(String simpleType, String paramType,
3819 String param, String method, InterfaceDecl intDecl, int iVar) {
3821 // Get the struct declaration for this struct and generate initialization code
3822 StructDecl structDecl = getStructDecl(simpleType);
3823 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3824 List<String> members = structDecl.getMembers(simpleType);
3825 int methodNumId = intDecl.getMethodNumId(method);
3826 String counter = "struct" + methodNumId + "Size" + iVar;
3828 if (isArrayOrList(paramType, param)) { // An array or list
3829 for (int i = 0; i < members.size(); i++) {
3830 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3831 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3832 println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + "[" + counter + "];");
3834 } else { // Just one struct element
3835 for (int i = 0; i < members.size(); i++) {
3836 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3837 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3838 println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + ";");
3841 if (isArrayOrList(paramType, param)) { // An array or list
3842 println("for(int i = 0; i < " + counter + "; i++) {");
3844 if (isArrayOrList(paramType, param)) { // An array or list
3845 for (int i = 0; i < members.size(); i++) {
3846 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3847 println("paramCls[pos] = \"" + prmTypeC + "\";");
3848 println("paramObj[pos++] = ¶m" + iVar + i + "[i];");
3851 } else { // Just one struct element
3852 for (int i = 0; i < members.size(); i++) {
3853 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3854 println("paramCls[pos] = \"" + prmTypeC + "\";");
3855 println("paramObj[pos++] = ¶m" + iVar + i + ";");
3862 * HELPER: writeStructMembersInitCplusSkeleton() writes member parameters initialization of struct
3864 private void writeStructMembersInitCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3865 List<String> methPrmTypes, String method) {
3867 for (int i = 0; i < methParams.size(); i++) {
3868 String paramType = methPrmTypes.get(i);
3869 String param = methParams.get(i);
3870 String simpleType = getGenericType(paramType);
3871 if (isStructClass(simpleType)) {
3872 int methodNumId = intDecl.getMethodNumId(method);
3873 String counter = "struct" + methodNumId + "Size" + i;
3875 if (isArrayOrList(paramType, param)) { // An array or list
3876 println("vector<" + simpleType + "> paramStruct" + i + "(" + counter + ");");
3878 println(simpleType + " paramStruct" + i + ";");
3879 // Initialize members
3880 StructDecl structDecl = getStructDecl(simpleType);
3881 List<String> members = structDecl.getMembers(simpleType);
3882 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3883 if (isArrayOrList(paramType, param)) { // An array or list
3884 println("for(int i = 0; i < " + counter + "; i++) {");
3885 for (int j = 0; j < members.size(); j++) {
3886 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
3887 println(" = param" + i + j + "[i];");
3890 } else { // Just one struct element
3891 for (int j = 0; j < members.size(); j++) {
3892 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
3893 println(" = param" + i + j + ";");
3902 * HELPER: writeStructReturnCplusSkeleton() writes parameters of struct for return statement
3904 private void writeStructReturnCplusSkeleton(String simpleType, String retType) {
3906 // Minimum retLen is 1 if this is a single struct object
3907 if (isArrayOrList(retType, retType))
3908 println("int retLen = retStruct.size();");
3909 else // Just single struct object
3910 println("int retLen = 1;");
3911 println("void* retLenObj = &retLen;");
3912 println("rmiComm->sendReturnObj(retLenObj, \"int\", localMethodBytes);");
3913 int numMem = getNumOfMembers(simpleType);
3914 println("int numRetObj = " + numMem + "*retLen;");
3915 println("string retCls[numRetObj];");
3916 println("void* retObj[numRetObj];");
3917 println("int retPos = 0;");
3918 // Get the struct declaration for this struct and generate initialization code
3919 StructDecl structDecl = getStructDecl(simpleType);
3920 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3921 List<String> members = structDecl.getMembers(simpleType);
3922 if (isArrayOrList(retType, retType)) { // An array or list
3923 println("for(int i = 0; i < retLen; i++) {");
3924 for (int i = 0; i < members.size(); i++) {
3925 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3926 println("retCls[retPos] = \"" + prmTypeC + "\";");
3927 print("retObj[retPos++] = &retStruct[i].");
3928 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3932 } else { // Just one struct element
3933 for (int i = 0; i < members.size(); i++) {
3934 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3935 println("retCls[retPos] = \"" + prmTypeC + "\";");
3936 print("retObj[retPos++] = &retStruct.");
3937 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3946 * HELPER: writeMethodHelperStructCplusSkeleton() writes the struct in skeleton
3948 private void writeMethodHelperStructCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3949 List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3951 // Generate array of parameter objects
3952 boolean isCallbackMethod = false;
3953 String callbackType = null;
3954 print("int numParam = ");
3955 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
3957 println("string paramCls[numParam];");
3958 println("void* paramObj[numParam];");
3959 println("int pos = 0;");
3960 // Iterate again over the parameters
3961 for (int i = 0; i < methParams.size(); i++) {
3962 String paramType = methPrmTypes.get(i);
3963 String param = methParams.get(i);
3964 String simpleType = getGenericType(paramType);
3965 if (isStructClass(simpleType)) {
3966 writeStructMembersCplusSkeleton(simpleType, paramType, param, method, intDecl, i);
3968 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
3969 if (callbackClasses.contains(prmType)) {
3970 isCallbackMethod = true;
3971 callbackType = prmType;
3972 //println("int numStubs" + i + " = 0;");
3973 println("vector<int> numStubIdArray" + i + ";");
3974 println("paramCls[pos] = \"int*\";");
3975 println("paramObj[pos++] = &numStubIdArray" + i + ";");
3976 } else { // Generate normal classes if it's not a callback object
3977 String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
3978 if (isEnumClass(getGenericType(paramTypeC))) { // Check if this is enum type
3979 println("vector<int> paramEnumInt" + i + ";");
3981 String methParamComplete = checkAndGetCplusArray(paramTypeC, methParams.get(i));
3982 println(methParamComplete + ";");
3984 String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3985 println("paramCls[pos] = \"" + prmTypeC + "\";");
3986 if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3987 println("paramObj[pos++] = ¶mEnumInt" + i + ";");
3989 println("paramObj[pos++] = &" + getSimpleIdentifier(methParams.get(i)) + ";");
3993 // Write the return value part
3994 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
3995 callbackType, methodId, callbackClasses);
4000 * HELPER: writeMethodHelperDeclCplusSkeleton() writes the method helper declarations of the skeleton class
4002 private void writeMethodHelperDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
4003 Set<String> callbackClasses, String newSkelClass) {
4005 // Use this set to handle two same methodIds
4006 Set<String> uniqueMethodIds = new HashSet<String>();
4007 for (String method : methods) {
4009 List<String> methParams = intDecl.getMethodParams(method);
4010 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4011 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
4012 String methodId = intDecl.getMethodId(method);
4014 String helperMethod = methodId;
4015 if (uniqueMethodIds.contains(methodId))
4016 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4018 uniqueMethodIds.add(methodId);
4019 String retType = intDecl.getMethodType(method);
4020 print(helperMethod + "(");
4021 boolean begin = true;
4022 for (int i = 0; i < methParams.size(); i++) { // Print size variables
4023 String paramType = methPrmTypes.get(i);
4024 String param = methParams.get(i);
4025 String simpleType = getGenericType(paramType);
4026 if (isStructClass(simpleType)) {
4027 if (!begin) // Generate comma for not the beginning variable
4031 int methodNumId = intDecl.getMethodNumId(method);
4032 print("int struct" + methodNumId + "Size" + i);
4035 println(", " + newSkelClass + "* skel);");
4037 String methodId = intDecl.getMethodId(method);
4039 String helperMethod = methodId;
4040 if (uniqueMethodIds.contains(methodId))
4041 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4043 uniqueMethodIds.add(methodId);
4044 // Check if this is "void"
4045 String retType = intDecl.getMethodType(method);
4046 println(helperMethod + "(" + newSkelClass + "* skel);");
4049 // Write method helper for structs
4050 writeMethodHelperStructDeclSetupCplusSkeleton(methods, intDecl, newSkelClass);
4055 * HELPER: writeMethodHelperStructDeclSetupCplusSkeleton() writes the struct method helper declaration in skeleton class
4057 private void writeMethodHelperStructDeclSetupCplusSkeleton(Collection<String> methods,
4058 InterfaceDecl intDecl, String newSkelClass) {
4060 // Use this set to handle two same methodIds
4061 for (String method : methods) {
4063 List<String> methParams = intDecl.getMethodParams(method);
4064 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4065 // Check for params with structs
4066 for (int i = 0; i < methParams.size(); i++) {
4067 String paramType = methPrmTypes.get(i);
4068 String param = methParams.get(i);
4069 String simpleType = getGenericType(paramType);
4070 if (isStructClass(simpleType)) {
4071 int methodNumId = intDecl.getMethodNumId(method);
4073 String helperMethod = methodNumId + "struct" + i;
4074 println(helperMethod + "(" + newSkelClass + "* skel);");
4082 * HELPER: writeMethodBytesCopy() writes the methodBytes copy part in C++ skeleton
4084 private void writeMethodBytesCopy() {
4086 println("char* localMethodBytes = new char[methodLen];");
4087 println("memcpy(localMethodBytes, skel->methodBytes, methodLen);");
4088 println("didGetMethodBytes.exchange(true);");
4093 * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class
4095 private void writeMethodHelperCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
4096 Set<String> callbackClasses, String newSkelClass) {
4098 // Use this set to handle two same methodIds
4099 Set<String> uniqueMethodIds = new HashSet<String>();
4100 for (String method : methods) {
4102 List<String> methParams = intDecl.getMethodParams(method);
4103 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4104 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
4105 String methodId = intDecl.getMethodId(method);
4106 print("void " + newSkelClass + "::___");
4107 String helperMethod = methodId;
4108 if (uniqueMethodIds.contains(methodId))
4109 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4111 uniqueMethodIds.add(methodId);
4112 String retType = intDecl.getMethodType(method);
4113 print(helperMethod + "(");
4114 boolean begin = true;
4115 for (int i = 0; i < methParams.size(); i++) { // Print size variables
4116 String paramType = methPrmTypes.get(i);
4117 String param = methParams.get(i);
4118 String simpleType = getGenericType(paramType);
4119 if (isStructClass(simpleType)) {
4120 if (!begin) // Generate comma for not the beginning variable
4124 int methodNumId = intDecl.getMethodNumId(method);
4125 print("int struct" + methodNumId + "Size" + i);
4128 println(", " + newSkelClass + "* skel) {");
4129 writeMethodBytesCopy();
4130 writeMethodHelperStructCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4131 println("delete[] localMethodBytes;");
4134 String methodId = intDecl.getMethodId(method);
4135 print("void " + newSkelClass + "::___");
4136 String helperMethod = methodId;
4137 if (uniqueMethodIds.contains(methodId))
4138 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4140 uniqueMethodIds.add(methodId);
4141 // Check if this is "void"
4142 String retType = intDecl.getMethodType(method);
4143 println(helperMethod + "(" + newSkelClass + "* skel) {");
4144 writeMethodBytesCopy();
4145 // Now, write the helper body of skeleton!
4146 writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4147 println("delete[] localMethodBytes;");
4151 // Write method helper for structs
4152 writeMethodHelperStructSetupCplusSkeleton(methods, intDecl, newSkelClass);
4157 * HELPER: writeMethodHelperStructSetupCplusSkeleton() writes the method helper of struct in skeleton class
4159 private void writeMethodHelperStructSetupCplusSkeleton(Collection<String> methods,
4160 InterfaceDecl intDecl, String newSkelClass) {
4162 // Use this set to handle two same methodIds
4163 for (String method : methods) {
4165 List<String> methParams = intDecl.getMethodParams(method);
4166 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4167 // Check for params with structs
4168 for (int i = 0; i < methParams.size(); i++) {
4169 String paramType = methPrmTypes.get(i);
4170 String param = methParams.get(i);
4171 String simpleType = getGenericType(paramType);
4172 if (isStructClass(simpleType)) {
4173 int methodNumId = intDecl.getMethodNumId(method);
4174 print("int " + newSkelClass + "::___");
4175 String helperMethod = methodNumId + "struct" + i;
4176 println(helperMethod + "(" + newSkelClass + "* skel) {");
4177 // Now, write the helper body of skeleton!
4178 writeMethodBytesCopy();
4179 println("string paramCls[] = { \"int\" };");
4180 println("int numParam = 1;");
4181 println("int param0 = 0;");
4182 println("void* paramObj[] = { ¶m0 };");
4183 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
4184 println("return param0;");
4185 println("delete[] localMethodBytes;");
4194 * HELPER: writeMethodHelperStructSetupCplusCallbackSkeleton() writes the method helper of struct in skeleton class
4196 private void writeMethodHelperStructSetupCplusCallbackSkeleton(Collection<String> methods,
4197 InterfaceDecl intDecl) {
4199 // Use this set to handle two same methodIds
4200 for (String method : methods) {
4202 List<String> methParams = intDecl.getMethodParams(method);
4203 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4204 // Check for params with structs
4205 for (int i = 0; i < methParams.size(); i++) {
4206 String paramType = methPrmTypes.get(i);
4207 String param = methParams.get(i);
4208 String simpleType = getGenericType(paramType);
4209 if (isStructClass(simpleType)) {
4210 int methodNumId = intDecl.getMethodNumId(method);
4212 String helperMethod = methodNumId + "struct" + i;
4213 println(helperMethod + "(IoTRMIObject* rmiObj) {");
4214 // Now, write the helper body of skeleton!
4215 println("string paramCls[] = { \"int\" };");
4216 println("int numParam = 1;");
4217 println("int param0 = 0;");
4218 println("void* paramObj[] = { ¶m0 };");
4219 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
4220 println("return param0;");
4229 * HELPER: writeCplusMethodPermission() writes permission checks in skeleton
4231 private void writeCplusMethodPermission(String intface) {
4233 // Get all the different stubs
4234 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
4235 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
4236 String newIntface = intMeth.getKey();
4237 int newObjectId = getNewIntfaceObjectId(newIntface);
4238 println("if (_objectId == objectId) {");
4239 println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
4240 println("cerr << \"Object with object Id: \" << _objectId << \" is not allowed to access method: \" << methodId << endl;");
4245 println("continue;");
4252 * HELPER: writeCplusWaitRequestInvokeMethod() writes the main loop of the skeleton class
4254 private void writeCplusWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl,
4255 boolean callbackExist, String intface, String newSkelClass) {
4257 // Use this set to handle two same methodIds
4258 Set<String> uniqueMethodIds = new HashSet<String>();
4259 println("void " + newSkelClass + "::___waitRequestInvokeMethod(" + newSkelClass + "* skel) {");
4260 // Write variables here if we have callbacks or enums or structs
4261 writeCountVarStructSkeleton(methods, intDecl);
4262 println("skel->didAlreadyInitWaitInvoke = true;");
4263 println("while (true) {");
4264 println("if (!methodReceived) {");
4265 println("continue;");
4267 println("skel->methodBytes = skel->rmiComm->getMethodBytes();");
4268 println("skel->methodLen = skel->rmiComm->getMethodLength();");
4269 println("methodReceived = false;");
4270 println("int _objectId = skel->rmiComm->getObjectId(skel->methodBytes);");
4271 println("int methodId = skel->rmiComm->getMethodId(skel->methodBytes);");
4272 // Generate permission check
4273 writeCplusMethodPermission(intface);
4274 println("switch (methodId) {");
4275 // Print methods and method Ids
4276 for (String method : methods) {
4277 String methodId = intDecl.getMethodId(method);
4278 int methodNumId = intDecl.getMethodNumId(method);
4279 println("case " + methodNumId + ": {");
4280 print("thread th" + methodNumId + " (&" + newSkelClass + "::___");
4281 String helperMethod = methodId;
4282 if (uniqueMethodIds.contains(methodId))
4283 helperMethod = helperMethod + methodNumId;
4285 uniqueMethodIds.add(methodId);
4286 print(helperMethod + ", std::ref(skel), ");
4287 boolean structExists = writeInputCountVarStructCplusSkeleton(method, intDecl);
4291 println("th" + methodNumId + ".detach(); break;");
4294 writeMethodCallStructCplusSkeleton(methods, intDecl);
4295 println("default: ");
4296 println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;");
4305 * generateCplusSkeletonClassHpp() generate skeletons based on the methods list in C++ (.hpp file)
4307 public void generateCplusSkeletonClassHpp() throws IOException {
4309 // Create a new directory
4310 String path = createDirectories(dir, subdir);
4311 for (String intface : mapIntfacePTH.keySet()) {
4312 // Open a new file to write into
4313 String newSkelClass = intface + "_Skeleton";
4314 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
4315 pw = new PrintWriter(new BufferedWriter(fw));
4316 // Write file headers
4317 println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
4318 println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
4319 println("#include <iostream>");
4320 println("#include \"" + intface + ".hpp\"\n");
4321 // Pass in set of methods and get import classes
4322 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4323 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4324 List<String> methods = intDecl.getMethods();
4325 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
4326 printIncludeStatements(stdIncludeClasses); println("");
4327 println("using namespace std;\n");
4328 // Find out if there are callback objects
4329 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4330 boolean callbackExist = !callbackClasses.isEmpty();
4331 // Write class header
4332 println("class " + newSkelClass + " : public " + intface); println("{");
4333 println("private:\n");
4335 writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses);
4336 println("public:\n");
4337 // Write constructors
4338 println(newSkelClass + "();");
4339 println(newSkelClass + "(" + intface + "*_mainObj, int _portSend, int _portRecv);");
4340 println(newSkelClass + "(" + intface + "*_mainObj, IoTRMIComm *rmiComm, int _objectId);");
4341 // Write deconstructor
4342 println("~" + newSkelClass + "();");
4343 // Write method declarations
4344 println("bool didInitWaitInvoke();");
4345 writeMethodDeclCplusSkeleton(methods, intDecl, callbackClasses);
4346 // Write method helper declarations
4347 writeMethodHelperDeclCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass);
4348 // Write waitRequestInvokeMethod() declaration - main loop
4349 println("void ___waitRequestInvokeMethod(" + newSkelClass + "* skel);");
4351 writePermissionInitializationCplus(intface, newSkelClass, intDecl);
4354 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
4359 * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke
4361 private void writeReturnDidAlreadyInitWaitInvoke(String newSkelClass) {
4363 println("bool " + newSkelClass + "::didInitWaitInvoke() {");
4364 println("return didAlreadyInitWaitInvoke;");
4370 * writeSkelExternalCFunctions() generate external functions for .so file
4372 public void writeSkelExternalCFunctions(String newSkelClass, String intface) throws IOException {
4374 println("extern \"C\" void* create" + newSkelClass + "(void** params) {");
4375 println("// Args: *_mainObj, int _portSend, int _portRecv");
4376 println("return new " + newSkelClass + "((" + intface + "*) params[0], *((int*) params[0]), *((int*) params[1]));");
4378 println("extern \"C\" void destroy" + newSkelClass + "(void* t) {");
4379 println(newSkelClass + "* obj = (" + newSkelClass + "*) t;");
4380 println("delete obj;");
4382 //println("extern \"C\" void init" + newSkelClass + "(void* t) {");
4383 //println(newSkelClass + "* obj = (" + newSkelClass + "*) t;");
4384 //println("obj->init();");
4385 //println("while(true);");
4391 * generateCplusSkeletonClassCpp() generate skeletons based on the methods list in C++ (.cpp file)
4393 public void generateCplusSkeletonClassCpp() throws IOException {
4395 // Create a new directory
4396 String path = createDirectories(dir, subdir);
4397 for (String intface : mapIntfacePTH.keySet()) {
4398 // Open a new file to write into
4399 String newSkelClass = intface + "_Skeleton";
4400 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".cpp");
4401 pw = new PrintWriter(new BufferedWriter(fw));
4402 // Write file headers
4403 println("#include <iostream>");
4404 println("#include \"" + newSkelClass + ".hpp\"\n");
4405 // Pass in set of methods and get import classes
4406 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4407 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4408 List<String> methods = intDecl.getMethods();
4409 // Find out if there are callback objects
4410 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4411 boolean callbackExist = !callbackClasses.isEmpty();
4412 for(String str: callbackClasses) {
4413 if (intface.equals(mainClass))
4414 println("#include \"" + getStubInterface(str) + "_Stub.cpp\"\n");
4416 println("#include \"" + getStubInterface(str) + "_Stub.hpp\"\n");
4418 println("using namespace std;\n");
4419 // Write constructor
4420 writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
4421 // Write callback constructor
4422 writeCallbackConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
4423 // Write deconstructor
4424 writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses);
4425 // Write didInitWaitInvoke() to return bool
4426 writeReturnDidAlreadyInitWaitInvoke(newSkelClass);
4428 writeMethodCplusSkeleton(methods, intDecl, callbackClasses, false, intface, newSkelClass);
4429 // Write method helper
4430 writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass);
4431 // Write waitRequestInvokeMethod() - main loop
4432 writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface, newSkelClass);
4433 // Write external functions for .so file
4434 writeSkelExternalCFunctions(newSkelClass, intface);
4435 // TODO: Remove this later
4436 if (intface.equals(mainClass)) {
4437 println("int main() {");
4438 println("return 0;");
4442 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".cpp...");
4448 * generateInitializer() generate initializer based on type
4450 public String generateCplusInitializer(String type) {
4452 // Generate dummy returns for now
4453 if (type.equals("short")||
4454 type.equals("int") ||
4455 type.equals("long") ||
4456 type.equals("float")||
4457 type.equals("double")) {
4460 } else if ( type.equals("String") ||
4461 type.equals("string")) {
4464 } else if ( type.equals("char") ||
4465 type.equals("byte")) {
4468 } else if ( type.equals("boolean")) {
4478 * setDirectory() sets a new directory for stub files
4480 public void setDirectory(String _subdir) {
4487 * printUsage() prints the usage of this compiler
4489 public static void printUsage() {
4491 System.out.println();
4492 System.out.println("Sentinel interface and stub compiler version 1.0");
4493 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
4494 System.out.println("All rights reserved.");
4495 System.out.println("Usage:");
4496 System.out.println("\tjava IoTCompiler -help / --help / -h\n");
4497 System.out.println("\t\tDisplay this help texts\n\n");
4498 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
4499 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
4500 System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
4501 System.out.println("Options:");
4502 System.out.println("\t-java\t<directory>\tGenerate Java stub files");
4503 System.out.println("\t-cplus\t<directory>\tGenerate C++ stub files");
4504 System.out.println();
4509 * parseFile() prepares Lexer and Parser objects, then parses the file
4511 public static ParseNode parseFile(String file) {
4513 ParseNode pn = null;
4515 ComplexSymbolFactory csf = new ComplexSymbolFactory();
4516 ScannerBuffer lexer =
4517 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(file)),csf));
4518 Parser parse = new Parser(lexer,csf);
4519 pn = (ParseNode) parse.parse().value;
4520 } catch (Exception e) {
4521 e.printStackTrace();
4522 throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file + "\n");
4530 * Basic helper functions
4533 boolean newline=true;
4536 private void print(String str) {
4539 if (str.equals("}"))
4541 for(int i=0; i<tab; i++)
4551 * This function converts Java to C++ type for compilation
4553 private String convertType(String type) {
4555 if (mapPrimitives.containsKey(type))
4556 return mapPrimitives.get(type);
4563 * A collection of methods with print-to-file functionality
4565 private void println(String str) {
4568 if (str.contains("}") && !str.contains("{"))
4570 for(int i=0; i<tab; i++)
4579 private void updatetabbing(String str) {
4581 tablevel+=count(str,'{')-count(str,'}');
4585 private int count(String str, char key) {
4586 char[] array = str.toCharArray();
4588 for(int i=0; i<array.length; i++) {
4589 if (array[i] == key)
4596 private void createDirectory(String dirName) {
4598 File file = new File(dirName);
4599 if (!file.exists()) {
4601 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
4603 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
4606 System.out.println("IoTCompiler: Directory " + dirName + " exists...");
4611 // Create a directory and possibly a sub directory
4612 private String createDirectories(String dir, String subdir) {
4615 createDirectory(path);
4616 if (subdir != null) {
4617 path = path + "/" + subdir;
4618 createDirectory(path);
4624 // Inserting array members into a Map object
4625 // that maps arrKey to arrVal objects
4626 private void arraysToMap(Map map, Object[] arrKey, Object[] arrVal) {
4628 for(int i = 0; i < arrKey.length; i++) {
4630 map.put(arrKey[i], arrVal[i]);
4635 // Check and find object Id for new interface in mapNewIntfaceObjId (callbacks)
4636 // Throw an error if the new interface is not found!
4637 // Basically the compiler needs to parse the policy (and requires) files for callback class first
4638 private int getNewIntfaceObjectId(String newIntface) {
4640 // if (!mapNewIntfaceObjId.containsKey(newIntface)) {
4641 // throw new Error("IoTCompiler: Need to parse policy and requires files for callback class first! " +
4642 // "Please place the two files for callback class in front...\n");
4645 int retObjId = mapNewIntfaceObjId.get(newIntface);
4651 // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, USERDEFINED, ENUM, or STRUCT
4652 private ParamCategory getParamCategory(String paramType) {
4654 if (mapPrimitives.containsKey(paramType)) {
4655 return ParamCategory.PRIMITIVES;
4656 // We can either use mapNonPrimitivesJava or mapNonPrimitivesCplus here
4657 } else if (mapNonPrimitivesJava.containsKey(getSimpleType(paramType))) {
4658 return ParamCategory.NONPRIMITIVES;
4659 } else if (isEnumClass(paramType)) {
4660 return ParamCategory.ENUM;
4661 } else if (isStructClass(paramType)) {
4662 return ParamCategory.STRUCT;
4664 return ParamCategory.USERDEFINED;
4668 // Return full class name for non-primitives to generate Java import statements
4669 // e.g. java.util.Set for Set
4670 private String getNonPrimitiveJavaClass(String paramNonPrimitives) {
4672 return mapNonPrimitivesJava.get(paramNonPrimitives);
4676 // Return full class name for non-primitives to generate Cplus include statements
4677 // e.g. #include <set> for Set
4678 private String getNonPrimitiveCplusClass(String paramNonPrimitives) {
4680 return mapNonPrimitivesCplus.get(paramNonPrimitives);
4684 // Get simple types, e.g. HashSet for HashSet<...>
4685 // Basically strip off the "<...>"
4686 private String getSimpleType(String paramType) {
4688 // Check if this is generics
4689 if(paramType.contains("<")) {
4690 String[] type = paramType.split("<");
4697 // Generate a set of standard classes for import statements
4698 private List<String> getStandardJavaIntfaceImportClasses() {
4700 List<String> importClasses = new ArrayList<String>();
4701 // Add the standard list first
4702 importClasses.add("java.util.List");
4703 importClasses.add("java.util.ArrayList");
4705 return importClasses;
4709 // Generate a set of standard classes for import statements
4710 private List<String> getStandardJavaImportClasses() {
4712 List<String> importClasses = new ArrayList<String>();
4713 // Add the standard list first
4714 importClasses.add("java.io.IOException");
4715 importClasses.add("java.util.List");
4716 importClasses.add("java.util.ArrayList");
4717 importClasses.add("java.util.Arrays");
4718 importClasses.add("java.util.Map");
4719 importClasses.add("java.util.HashMap");
4720 importClasses.add("java.util.concurrent.atomic.AtomicBoolean");
4721 importClasses.add("iotrmi.Java.IoTRMIComm");
4722 importClasses.add("iotrmi.Java.IoTRMICommClient");
4723 importClasses.add("iotrmi.Java.IoTRMICommServer");
4724 importClasses.add("iotrmi.Java.IoTRMIUtil");
4726 return importClasses;
4730 // Generate a set of standard classes for import statements
4731 private List<String> getStandardCplusIncludeClasses() {
4733 List<String> importClasses = new ArrayList<String>();
4734 // Add the standard list first
4735 importClasses.add("<vector>");
4736 importClasses.add("<set>");
4737 //importClasses.add("\"IoTRMICall.hpp\"");
4738 //importClasses.add("\"IoTRMIObject.hpp\"");
4739 importClasses.add("\"IoTRMIComm.hpp\"");
4740 importClasses.add("\"IoTRMICommClient.hpp\"");
4741 importClasses.add("\"IoTRMICommServer.hpp\"");
4743 return importClasses;
4747 // Combine all classes for import statements
4748 private List<String> getAllLibClasses(Collection<String> stdLibClasses, Collection<String> libClasses) {
4750 List<String> allLibClasses = new ArrayList<String>(stdLibClasses);
4751 // Iterate over the list of import classes
4752 for (String str : libClasses) {
4753 if (!allLibClasses.contains(str)) {
4754 allLibClasses.add(str);
4757 return allLibClasses;
4762 // Generate a set of classes for import statements
4763 private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
4765 Set<String> importClasses = new HashSet<String>();
4766 for (String method : methods) {
4767 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4768 for (String paramType : methPrmTypes) {
4770 String simpleType = getSimpleType(paramType);
4771 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4772 importClasses.add(getNonPrimitiveJavaClass(simpleType));
4776 return importClasses;
4780 // Handle and return the correct enum declaration
4781 // In Java, if we declare enum in Camera interface, then it becomes "Camera.<enum>"
4782 private String getEnumParamDecl(String type, InterfaceDecl intDecl) {
4784 // Strips off array "[]" for return type
4785 String pureType = getSimpleArrayType(type);
4786 // Take the inner type of generic
4787 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4788 pureType = getTypeOfGeneric(type)[0];
4789 if (isEnumClass(pureType)) {
4790 String enumType = intDecl.getInterface() + "." + type;
4797 // Handle and return the correct type
4798 private String getEnumParam(String type, String param, int i) {
4800 // Strips off array "[]" for return type
4801 String pureType = getSimpleArrayType(type);
4802 // Take the inner type of generic
4803 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4804 pureType = getTypeOfGeneric(type)[0];
4805 if (isEnumClass(pureType)) {
4806 String enumParam = "paramEnum" + i;
4813 // Handle and return the correct enum declaration translate into int[]
4814 private String getEnumType(String type) {
4816 // Strips off array "[]" for return type
4817 String pureType = getSimpleArrayType(type);
4818 // Take the inner type of generic
4819 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4820 pureType = getGenericType(type);
4821 if (isEnumClass(pureType)) {
4822 String enumType = "int[]";
4828 // Handle and return the correct enum declaration translate into int* for C
4829 private String getEnumCplusClsType(String type) {
4831 // Strips off array "[]" for return type
4832 String pureType = getSimpleArrayType(type);
4833 // Take the inner type of generic
4834 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4835 pureType = getGenericType(type);
4836 if (isEnumClass(pureType)) {
4837 String enumType = "int*";
4844 // Handle and return the correct struct declaration
4845 private String getStructType(String type) {
4847 // Strips off array "[]" for return type
4848 String pureType = getSimpleArrayType(type);
4849 // Take the inner type of generic
4850 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4851 pureType = getGenericType(type);
4852 if (isStructClass(pureType)) {
4853 String structType = "int";
4860 // Check if this an enum declaration
4861 private boolean isEnumClass(String type) {
4863 // Just iterate over the set of interfaces
4864 for (String intface : mapIntfacePTH.keySet()) {
4865 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4866 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
4867 Set<String> setEnumDecl = enumDecl.getEnumDeclarations();
4868 if (setEnumDecl.contains(type))
4875 // Check if this an struct declaration
4876 private boolean isStructClass(String type) {
4878 // Just iterate over the set of interfaces
4879 for (String intface : mapIntfacePTH.keySet()) {
4880 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4881 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4882 List<String> listStructDecl = structDecl.getStructTypes();
4883 if (listStructDecl.contains(type))
4890 // Return a struct declaration
4891 private StructDecl getStructDecl(String type) {
4893 // Just iterate over the set of interfaces
4894 for (String intface : mapIntfacePTH.keySet()) {
4895 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4896 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4897 List<String> listStructDecl = structDecl.getStructTypes();
4898 if (listStructDecl.contains(type))
4905 // Return number of members (-1 if not found)
4906 private int getNumOfMembers(String type) {
4908 // Just iterate over the set of interfaces
4909 for (String intface : mapIntfacePTH.keySet()) {
4910 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4911 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4912 List<String> listStructDecl = structDecl.getStructTypes();
4913 if (listStructDecl.contains(type))
4914 return structDecl.getNumOfMembers(type);
4920 // Generate a set of classes for include statements
4921 private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl, String intface, boolean needExchange) {
4923 Set<String> includeClasses = new HashSet<String>();
4924 for (String method : methods) {
4926 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4927 List<String> methParams = intDecl.getMethodParams(method);
4928 for (int i = 0; i < methPrmTypes.size(); i++) {
4930 String genericType = getGenericType(methPrmTypes.get(i));
4931 String simpleType = getSimpleType(methPrmTypes.get(i));
4932 String param = methParams.get(i);
4933 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4934 includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">");
4935 //} else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) {
4937 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.USERDEFINED) {
4938 // For original interface, we need it exchanged... not for stub interfaces
4940 //includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\"");
4941 includeClasses.add("\"" + exchangeParamType(getSimpleArrayType(genericType)) + ".hpp\"");
4943 //includeClasses.add("\"" + simpleType + ".hpp\"");
4944 includeClasses.add("\"" + getSimpleArrayType(genericType) + ".hpp\"");
4947 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.ENUM) {
4948 includeClasses.add("\"" + genericType + ".hpp\"");
4950 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.STRUCT) {
4951 includeClasses.add("\"" + genericType + ".hpp\"");
4953 if (param.contains("[]")) {
4954 // Check if this is array for C++; translate into vector
4955 includeClasses.add("<vector>");
4959 return includeClasses;
4963 // Generate a set of callback classes
4964 private Set<String> getCallbackClasses(Collection<String> methods, InterfaceDecl intDecl) {
4966 Set<String> callbackClasses = new HashSet<String>();
4967 for (String method : methods) {
4969 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4970 List<String> methParams = intDecl.getMethodParams(method);
4971 for (int i = 0; i < methPrmTypes.size(); i++) {
4973 String type = methPrmTypes.get(i);
4974 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4975 callbackClasses.add(type);
4976 } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
4977 // Can be a List<...> of callback objects ...
4978 String genericType = getTypeOfGeneric(type)[0];
4979 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4980 callbackClasses.add(type);
4985 return callbackClasses;
4989 // Print import statements into file
4990 private void printImportStatements(Collection<String> importClasses) {
4992 for(String cls : importClasses) {
4993 println("import " + cls + ";");
4998 // Print include statements into file
4999 private void printIncludeStatements(Collection<String> includeClasses) {
5001 for(String cls : includeClasses) {
5002 println("#include " + cls);
5007 // Get the C++ version of a non-primitive type
5008 // e.g. set for Set and map for Map
5009 // Input nonPrimitiveType has to be generics in format
5010 private String[] getTypeOfGeneric(String nonPrimitiveType) {
5012 // Handle <, >, and , for 2-type generic/template
5013 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
5018 // Gets generic type inside "<" and ">"
5019 private String getGenericType(String type) {
5021 // Handle <, >, and , for 2-type generic/template
5022 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
5023 String[] substr = type.split("<")[1].split(">")[0].split(",");
5030 // This helper function strips off array declaration, e.g. int[] becomes int
5031 private String getSimpleArrayType(String type) {
5033 // Handle [ for array declaration
5034 String substr = type;
5035 if (type.contains("[]")) {
5036 substr = type.split("\\[\\]")[0];
5042 // This helper function strips off array declaration, e.g. D[] becomes D
5043 private String getSimpleIdentifier(String ident) {
5045 // Handle [ for array declaration
5046 String substr = ident;
5047 if (ident.contains("[]")) {
5048 substr = ident.split("\\[\\]")[0];
5054 // Checks and gets type in C++
5055 private String checkAndGetCplusType(String paramType) {
5057 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
5058 return convertType(paramType);
5059 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
5061 // Check for generic/template format
5062 if (paramType.contains("<") && paramType.contains(">")) {
5064 String genericClass = getSimpleType(paramType);
5065 String genericType = getGenericType(paramType);
5066 String cplusTemplate = null;
5067 cplusTemplate = getNonPrimitiveCplusClass(genericClass);
5068 if(getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED) {
5069 cplusTemplate = cplusTemplate + "<" + genericType + "*>";
5071 cplusTemplate = cplusTemplate + "<" + convertType(genericType) + ">";
5073 return cplusTemplate;
5075 return getNonPrimitiveCplusClass(paramType);
5076 } else if(paramType.contains("[]")) { // Array type (used for return type only)
5077 String cArray = "vector<" + convertType(getSimpleArrayType(paramType)) + ">";
5079 } else if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
5080 return paramType + "*";
5082 // Just return it as is if it's not non-primitives
5087 // Detect array declaration, e.g. int A[],
5088 // then generate "int A[]" in C++ as "vector<int> A"
5089 private String checkAndGetCplusArray(String paramType, String param) {
5091 String paramComplete = null;
5092 // Check for array declaration
5093 if (param.contains("[]")) {
5094 paramComplete = "vector<" + paramType + "> " + param.replace("[]","");
5096 // Just return it as is if it's not an array
5097 paramComplete = paramType + " " + param;
5099 return paramComplete;
5103 // Detect array declaration, e.g. int A[],
5104 // then generate "int A[]" in C++ as "vector<int> A"
5105 // This method just returns the type
5106 private String checkAndGetCplusArrayType(String paramType) {
5108 String paramTypeRet = null;
5109 // Check for array declaration
5110 if (paramType.contains("[]")) {
5111 String type = paramType.split("\\[\\]")[0];
5112 paramTypeRet = checkAndGetCplusType(type) + "[]";
5113 } else if (paramType.contains("vector")) {
5114 // Just return it as is if it's not an array
5115 String type = paramType.split("<")[1].split(">")[0];
5116 paramTypeRet = checkAndGetCplusType(type) + "[]";
5118 paramTypeRet = paramType;
5120 return paramTypeRet;
5124 // Detect array declaration, e.g. int A[],
5125 // then generate "int A[]" in C++ as "vector<int> A"
5126 // This method just returns the type
5127 private String checkAndGetCplusArrayType(String paramType, String param) {
5129 String paramTypeRet = null;
5130 // Check for array declaration
5131 if (param.contains("[]")) {
5132 paramTypeRet = checkAndGetCplusType(paramType) + "[]";
5133 } else if (paramType.contains("vector")) {
5134 // Just return it as is if it's not an array
5135 String type = paramType.split("<")[1].split(">")[0];
5136 paramTypeRet = checkAndGetCplusType(type) + "[]";
5138 paramTypeRet = paramType;
5140 return paramTypeRet;
5144 // Return the class type for class resolution (for return value)
5145 // - Check and return C++ array class, e.g. int A[] into int*
5146 // - Check and return C++ vector class, e.g. List<Integer> A into vector<int>
5147 private String checkAndGetCplusRetClsType(String paramType) {
5149 String paramTypeRet = null;
5150 // Check for array declaration
5151 if (paramType.contains("[]")) {
5152 String type = paramType.split("\\[\\]")[0];
5153 paramTypeRet = getSimpleArrayType(type) + "*";
5154 } else if (paramType.contains("<") && paramType.contains(">")) {
5155 // Just return it as is if it's not an array
5156 String type = paramType.split("<")[1].split(">")[0];
5157 paramTypeRet = "vector<" + getGenericType(type) + ">";
5159 paramTypeRet = paramType;
5161 return paramTypeRet;
5165 // Return the class type for class resolution (for method arguments)
5166 // - Check and return C++ array class, e.g. int A[] into int*
5167 // - Check and return C++ vector class, e.g. List<Integer> A into vector<int>
5168 private String checkAndGetCplusArgClsType(String paramType, String param) {
5170 String paramTypeRet = getEnumCplusClsType(paramType);
5171 if (!paramTypeRet.equals(paramType))
5172 // Just return if it is an enum type
5173 // Type will still be the same if it's not an enum type
5174 return paramTypeRet;
5176 // Check for array declaration
5177 if (param.contains("[]")) {
5178 paramTypeRet = getSimpleArrayType(paramType) + "*";
5179 } else if (paramType.contains("<") && paramType.contains(">")) {
5180 // Just return it as is if it's not an array
5181 String type = paramType.split("<")[1].split(">")[0];
5182 paramTypeRet = "vector<" + getGenericType(type) + ">";
5184 paramTypeRet = paramType;
5186 return paramTypeRet;
5190 // Detect array declaration, e.g. int A[],
5191 // then generate type "int[]"
5192 private String checkAndGetArray(String paramType, String param) {
5194 String paramTypeRet = null;
5195 // Check for array declaration
5196 if (param.contains("[]")) {
5197 paramTypeRet = paramType + "[]";
5199 // Just return it as is if it's not an array
5200 paramTypeRet = paramType;
5202 return paramTypeRet;
5206 // Is array or list?
5207 private boolean isArrayOrList(String paramType, String param) {
5209 // Check for array declaration
5212 else if (isList(paramType))
5220 // For return type we use retType as input parameter
5221 private boolean isArray(String param) {
5223 // Check for array declaration
5224 if (param.contains("[]"))
5232 private boolean isList(String paramType) {
5234 // Check for array declaration
5235 if (paramType.contains("List"))
5242 // Get the right type for a callback object
5243 private String checkAndGetParamClass(String paramType) {
5245 // Check if this is generics
5246 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
5247 return exchangeParamType(paramType);
5248 } else if (isList(paramType) &&
5249 (getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED)) {
5250 return "List<" + exchangeParamType(getGenericType(paramType)) + ">";
5256 // Returns the other interface for type-checking purposes for USERDEFINED
5257 // classes based on the information provided in multiple policy files
5258 // e.g. return CameraWithXXX instead of Camera
5259 private String exchangeParamType(String intface) {
5261 // Param type that's passed is the interface name we need to look for
5262 // in the map of interfaces, based on available policy files.
5263 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
5264 if (decHandler != null) {
5265 // We've found the required interface policy files
5266 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(intface);
5267 Set<String> setExchInt = reqDecl.getInterfaces();
5268 if (setExchInt.size() == 1) {
5269 Iterator iter = setExchInt.iterator();
5270 return (String) iter.next();
5272 throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() +
5273 ". Only one new interface can be declared if the object " + intface +
5274 " needs to be passed in as an input parameter!\n");
5277 // NULL value - this means policy files missing
5278 throw new Error("IoTCompiler: Parameter type lookup failed for " + intface +
5279 "... Please provide the necessary policy files for user-defined types." +
5280 " If this is an array please type the brackets after the variable name," +
5281 " e.g. \"String str[]\", not \"String[] str\"." +
5282 " If this is a Collections (Java) / STL (C++) type, this compiler only" +
5283 " supports List/ArrayList (Java) or list (C++).\n");
5288 public static void main(String[] args) throws Exception {
5290 // If there is no argument or just "--help" or "-h", then invoke printUsage()
5291 if ((args[0].equals("-help") ||
5292 args[0].equals("--help")||
5293 args[0].equals("-h")) ||
5294 (args.length == 0)) {
5296 IoTCompiler.printUsage();
5298 } else if (args.length > 1) {
5300 IoTCompiler comp = new IoTCompiler();
5303 // Parse main policy file
5304 ParseNode pnPol = IoTCompiler.parseFile(args[i]);
5305 // Parse "requires" policy file
5306 ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
5307 // Get interface name
5308 String intface = ParseTreeHandler.getOrigIntface(pnPol);
5309 comp.setDataStructures(intface, pnPol, pnReq);
5310 comp.getMethodsForIntface(intface);
5312 // 1) Check if this is the last option before "-java" or "-cplus"
5313 // 2) Check if this is really the last option (no "-java" or "-cplus")
5314 } while(!args[i].equals("-java") &&
5315 !args[i].equals("-cplus") &&
5318 // Generate everything if we don't see "-java" or "-cplus"
5319 if (i == args.length) {
5320 comp.generateEnumJava();
5321 comp.generateStructJava();
5322 comp.generateJavaLocalInterfaces();
5323 comp.generateJavaInterfaces();
5324 comp.generateJavaStubClasses();
5325 comp.generateJavaSkeletonClass();
5326 comp.generateEnumCplus();
5327 comp.generateStructCplus();
5328 comp.generateCplusLocalInterfaces();
5329 comp.generateCPlusInterfaces();
5330 comp.generateCPlusStubClassesHpp();
5331 comp.generateCPlusStubClassesCpp();
5332 //comp.generateCPlusCallbackStubClasses();
5333 comp.generateCplusSkeletonClassHpp();
5334 comp.generateCplusSkeletonClassCpp();
5335 //comp.generateCplusCallbackSkeletonClass();
5337 // Check other options
5338 while(i < args.length) {
5340 if (!args[i].equals("-java") &&
5341 !args[i].equals("-cplus")) {
5342 throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i] + "\n");
5344 if (i + 1 < args.length) {
5345 comp.setDirectory(args[i+1]);
5347 throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i] + "\n");
5349 if (args[i].equals("-java")) {
5350 comp.generateEnumJava();
5351 comp.generateStructJava();
5352 comp.generateJavaLocalInterfaces();
5353 comp.generateJavaInterfaces();
5354 comp.generateJavaStubClasses();
5355 comp.generateJavaSkeletonClass();
5357 comp.generateEnumCplus();
5358 comp.generateStructCplus();
5359 comp.generateCplusLocalInterfaces();
5360 comp.generateCPlusInterfaces();
5361 comp.generateCPlusStubClassesHpp();
5362 comp.generateCPlusStubClassesCpp();
5363 //comp.generateCPlusCallbackStubClasses();
5364 comp.generateCplusSkeletonClassHpp();
5365 comp.generateCplusSkeletonClassCpp();
5366 //comp.generateCplusCallbackSkeletonClass();
5373 // Need to at least have exactly 2 parameters, i.e. main policy file and requires file
5374 IoTCompiler.printUsage();
5375 throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!\n");