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 static int countObjId = 1; // Always increment object Id for a new stub/skeleton
65 private String mainClass;
66 private String driverClass;
67 private String controllerClass;
73 private final static String OUTPUT_DIRECTORY = "output_files";
74 private final static String CODE_PREFIX = "iotcode";
75 private final static String INTERFACE_PACKAGE = "iotcode.interfaces";
78 private enum ParamCategory {
80 PRIMITIVES, // All the primitive types, e.g. byte, short, int, long, etc.
81 NONPRIMITIVES, // Non-primitive types, e.g. Set, Map, List, etc.
83 STRUCT, // Struct type
84 USERDEFINED // Assumed as driver classes
91 public IoTCompiler() {
93 mapIntfacePTH = new HashMap<String,ParseTreeHandler>();
94 mapIntDeclHand = new HashMap<String,DeclarationHandler>();
95 mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
96 mapInt2NewIntName = new HashMap<String,String>();
97 mapIntfaceObjId = new HashMap<String,Integer>();
98 mapNewIntfaceObjId = new HashMap<String,Integer>();
99 mapPrimitives = new HashMap<String,String>();
100 arraysToMap(mapPrimitives, IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus);
101 mapNonPrimitivesJava = new HashMap<String,String>();
102 arraysToMap(mapNonPrimitivesJava, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitiveJavaLibs);
103 mapNonPrimitivesCplus = new HashMap<String,String>();
104 arraysToMap(mapNonPrimitivesCplus, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus);
105 mapPortCount = new HashMap<String,Integer>();
107 dir = OUTPUT_DIRECTORY;
111 controllerClass = null;
116 * setDriverClass() sets the name of the driver class.
118 public void setDriverClass(String _driverClass) {
120 driverClass = _driverClass;
125 * setControllerClass() sets the name of the controller class.
127 public void setControllerClass(String _controllerClass) {
129 controllerClass = _controllerClass;
134 * setDataStructures() sets parse tree and other data structures based on policy files.
136 * It also generates parse tree (ParseTreeHandler) and
137 * copies useful information from parse tree into
138 * InterfaceDecl, CapabilityDecl, and RequiresDecl
140 * Additionally, the data structure handles are
141 * returned from tree-parsing for further process.
143 public void setDataStructures(String origInt, ParseNode pnPol, ParseNode pnReq) {
145 ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq);
146 DeclarationHandler decHandler = new DeclarationHandler();
147 // Process ParseNode and generate Declaration objects
149 ptHandler.processInterfaceDecl();
150 InterfaceDecl intDecl = ptHandler.getInterfaceDecl();
151 decHandler.addInterfaceDecl(origInt, intDecl);
153 ptHandler.processCapabilityDecl();
154 CapabilityDecl capDecl = ptHandler.getCapabilityDecl();
155 decHandler.addCapabilityDecl(origInt, capDecl);
157 ptHandler.processRequiresDecl();
158 RequiresDecl reqDecl = ptHandler.getRequiresDecl();
159 decHandler.addRequiresDecl(origInt, reqDecl);
161 ptHandler.processEnumDecl();
162 EnumDecl enumDecl = ptHandler.getEnumDecl();
163 decHandler.addEnumDecl(origInt, enumDecl);
165 ptHandler.processStructDecl();
166 StructDecl structDecl = ptHandler.getStructDecl();
167 decHandler.addStructDecl(origInt, structDecl);
169 mapIntfacePTH.put(origInt, ptHandler);
170 mapIntDeclHand.put(origInt, decHandler);
171 // Set object Id counter to 0 for each interface
172 mapIntfaceObjId.put(origInt, countObjId++);
177 * getMethodsForIntface() reads for methods in the data structure
179 * It is going to give list of methods for a certain interface
180 * based on the declaration of capabilities.
182 public void getMethodsForIntface(String origInt) {
184 ParseTreeHandler ptHandler = mapIntfacePTH.get(origInt);
185 Map<String,Set<String>> mapNewIntMethods = new HashMap<String,Set<String>>();
186 // Get set of new interfaces, e.g. CameraWithCaptureAndData
187 // Generate this new interface with all the methods it needs
188 // from different capabilities it declares
189 DeclarationHandler decHandler = mapIntDeclHand.get(origInt);
190 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(origInt);
191 Set<String> setIntfaces = reqDecl.getInterfaces();
192 for (String strInt : setIntfaces) {
194 // Initialize a set of methods
195 Set<String> setMethods = new HashSet<String>();
196 // Get list of capabilities, e.g. ImageCapture, VideoRecording, etc.
197 List<String> listCapab = reqDecl.getCapabList(strInt);
198 for (String strCap : listCapab) {
200 // Get list of methods for each capability
201 CapabilityDecl capDecl = (CapabilityDecl) decHandler.getCapabilityDecl(origInt);
202 List<String> listCapabMeth = capDecl.getMethods(strCap);
203 for (String strMeth : listCapabMeth) {
205 // Add methods into setMethods
206 // This is to also handle redundancies (say two capabilities
207 // share the same methods)
208 setMethods.add(strMeth);
211 // Add interface and methods information into map
212 mapNewIntMethods.put(strInt, setMethods);
213 // Map new interface method name to the original interface
214 // TODO: perhaps need to check in the future if we have more than 1 stub interface for one original interface
215 mapInt2NewIntName.put(origInt, strInt);
216 if (mainClass == null) // Take the first class as the main class (whichever is placed first in the order of compilation files)
219 // Map the map of interface-methods to the original interface
220 mapInt2NewInts.put(origInt, mapNewIntMethods);
229 * HELPER: writeMethodJavaLocalInterface() writes the method of the local interface
231 private void writeMethodJavaLocalInterface(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 = checkAndGetParamClass(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: writeMethodJavaInterface() writes the method of the interface
257 private void writeMethodJavaInterface(Collection<String> methods, InterfaceDecl intDecl) {
259 for (String method : methods) {
261 List<String> methParams = intDecl.getMethodParams(method);
262 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
263 print("public " + intDecl.getMethodType(method) + " " +
264 intDecl.getMethodId(method) + "(");
265 for (int i = 0; i < methParams.size(); i++) {
266 // Check for params with driver class types and exchange it
267 // with its remote interface
268 String paramType = methPrmTypes.get(i);
269 print(paramType + " " + methParams.get(i));
270 // Check if this is the last element (don't print a comma)
271 if (i != methParams.size() - 1) {
281 * HELPER: generateEnumJava() writes the enumeration declaration
283 private void generateEnumJava() throws IOException {
285 // Create a new directory
286 createDirectory(dir);
287 for (String intface : mapIntfacePTH.keySet()) {
288 // Get the right EnumDecl
289 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
290 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
291 Set<String> enumTypes = enumDecl.getEnumDeclarations();
292 // Iterate over enum declarations
293 for (String enType : enumTypes) {
294 // Open a new file to write into
295 FileWriter fw = new FileWriter(dir + "/" + enType + ".java");
296 pw = new PrintWriter(new BufferedWriter(fw));
297 println("public enum " + enType + " {");
298 List<String> enumMembers = enumDecl.getMembers(enType);
299 for (int i = 0; i < enumMembers.size(); i++) {
301 String member = enumMembers.get(i);
303 // Check if this is the last element (don't print a comma)
304 if (i != enumMembers.size() - 1)
311 System.out.println("IoTCompiler: Generated enum class " + enType + ".java...");
318 * HELPER: generateStructJava() writes the struct declaration
320 private void generateStructJava() throws IOException {
322 // Create a new directory
323 createDirectory(dir);
324 for (String intface : mapIntfacePTH.keySet()) {
325 // Get the right StructDecl
326 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
327 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
328 List<String> structTypes = structDecl.getStructTypes();
329 // Iterate over enum declarations
330 for (String stType : structTypes) {
331 // Open a new file to write into
332 FileWriter fw = new FileWriter(dir + "/" + stType + ".java");
333 pw = new PrintWriter(new BufferedWriter(fw));
334 println("public class " + stType + " {");
335 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
336 List<String> structMembers = structDecl.getMembers(stType);
337 for (int i = 0; i < structMembers.size(); i++) {
339 String memberType = structMemberTypes.get(i);
340 String member = structMembers.get(i);
341 println("public static " + memberType + " " + member + ";");
345 System.out.println("IoTCompiler: Generated struct class " + stType + ".java...");
352 * generateJavaLocalInterface() writes the local interface and provides type-checking.
354 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
355 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
356 * The local interface has to be the input parameter for the stub and the stub
357 * interface has to be the input parameter for the local class.
359 public void generateJavaLocalInterfaces() throws IOException {
361 // Create a new directory
362 createDirectory(dir);
363 for (String intface : mapIntfacePTH.keySet()) {
364 // Open a new file to write into
365 FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
366 pw = new PrintWriter(new BufferedWriter(fw));
367 // Pass in set of methods and get import classes
368 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
369 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
370 List<String> methods = intDecl.getMethods();
371 Set<String> importClasses = getImportClasses(methods, intDecl);
372 List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
373 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
374 println("package " + INTERFACE_PACKAGE + ";\n");
375 printImportStatements(allImportClasses);
376 // Write interface header
378 println("public interface " + intface + " {");
380 writeMethodJavaLocalInterface(methods, intDecl);
383 System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
389 * HELPER: updateIntfaceObjIdMap() updates the mapping between new interface and object Id
391 private void updateIntfaceObjIdMap(String intface, String newIntface) {
393 // We are assuming that we only generate one stub per one skeleton at this point @Feb 2017
394 Integer objId = mapIntfaceObjId.get(intface);
395 mapNewIntfaceObjId.put(newIntface, objId);
400 * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
402 public void generateJavaInterfaces() throws IOException {
404 // Create a new directory
405 String path = createDirectories(dir, subdir);
406 for (String intface : mapIntfacePTH.keySet()) {
408 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
409 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
411 // Open a new file to write into
412 String newIntface = intMeth.getKey();
413 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
414 pw = new PrintWriter(new BufferedWriter(fw));
415 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
416 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
417 // Pass in set of methods and get import classes
418 Set<String> methods = intMeth.getValue();
419 Set<String> importClasses = getImportClasses(methods, intDecl);
420 List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
421 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
422 println("package " + INTERFACE_PACKAGE + ";\n");
423 printImportStatements(allImportClasses);
424 // Write interface header
426 println("public interface " + newIntface + " {\n");
427 updateIntfaceObjIdMap(intface, newIntface);
429 writeMethodJavaInterface(methods, intDecl);
432 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
439 * HELPER: writePropertiesJavaPermission() writes the permission in properties
441 private void writePropertiesJavaPermission(String intface, InterfaceDecl intDecl) {
443 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
444 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
445 String newIntface = intMeth.getKey();
446 int newObjectId = getNewIntfaceObjectId(newIntface);
447 Set<String> methodIds = intMeth.getValue();
448 print("private static Integer[] object" + newObjectId + "Permission = { ");
450 for (String methodId : methodIds) {
451 int methodNumId = intDecl.getMethodNumId(methodId);
452 print(Integer.toString(methodNumId));
453 // Check if this is the last element (don't print a comma)
454 if (i != methodIds.size() - 1) {
460 println("private static List<Integer> set" + newObjectId + "Allowed;");
466 * HELPER: writePropertiesJavaStub() writes the properties of the stub class
468 private void writePropertiesJavaStub(String intface, Set<String> methods, InterfaceDecl intDecl) {
471 Integer objId = mapIntfaceObjId.get(intface);
472 println("private int objectId = " + objId + ";");
473 println("private IoTRMIComm rmiComm;");
474 // Write the list of AtomicBoolean variables
475 println("// Synchronization variables");
476 for (String method : methods) {
477 // Generate AtomicBooleans for methods that have return values
478 String returnType = intDecl.getMethodType(method);
479 int methodNumId = intDecl.getMethodNumId(method);
480 if (!returnType.equals("void")) {
481 println("private AtomicBoolean retValueReceived" + methodNumId + " = new AtomicBoolean(false);");
489 * HELPER: writeConstructorJavaPermission() writes the permission in constructor
491 private void writeConstructorJavaPermission(String intface) {
493 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
494 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
495 String newIntface = intMeth.getKey();
496 int newObjectId = getNewIntfaceObjectId(newIntface);
497 println("set" + newObjectId + "Allowed = new ArrayList<Integer>(Arrays.asList(object" + newObjectId +"Permission));");
503 * HELPER: writeConstructorJavaStub() writes the constructor of the stub class
505 private void writeConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
507 println("public " + newStubClass + "(int _localPortSend, int _localPortRecv, int _portSend, int _portRecv, String _skeletonAddress, int _rev) throws Exception {");
508 println("if (_localPortSend != 0 && _localPortRecv != 0) {");
509 println("rmiComm = new IoTRMICommClient(_localPortSend, _localPortRecv, _portSend, _portRecv, _skeletonAddress, _rev);");
512 println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev);");
514 // Register the AtomicBoolean variables
515 for (String method : methods) {
516 // Generate AtomicBooleans for methods that have return values
517 String returnType = intDecl.getMethodType(method);
518 int methodNumId = intDecl.getMethodNumId(method);
519 if (!returnType.equals("void")) {
520 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
523 println("IoTRMIUtil.mapStub.put(objectId, this);");
529 * HELPER: writeCallbackConstructorJavaStub() writes the callback constructor of the stub class
531 private void writeCallbackConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
533 println("public " + newStubClass + "(IoTRMIComm _rmiComm, int _objectId) throws Exception {");
534 println("rmiComm = _rmiComm;");
535 println("objectId = _objectId;");
536 // Register the AtomicBoolean variables
537 for (String method : methods) {
538 // Generate AtomicBooleans for methods that have return values
539 String returnType = intDecl.getMethodType(method);
540 int methodNumId = intDecl.getMethodNumId(method);
541 if (!returnType.equals("void")) {
542 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
550 * HELPER: getPortCount() gets port count for different stubs and skeletons
552 private int getPortCount(String intface) {
554 if (!mapPortCount.containsKey(intface))
555 mapPortCount.put(intface, portCount++);
556 return mapPortCount.get(intface);
561 * HELPER: checkAndWriteEnumTypeJavaStub() writes the enum type (convert from enum to int)
563 private void checkAndWriteEnumTypeJavaStub(List<String> methParams, List<String> methPrmTypes) {
565 // Iterate and find enum declarations
566 for (int i = 0; i < methParams.size(); i++) {
567 String paramType = methPrmTypes.get(i);
568 String param = methParams.get(i);
569 String simpleType = getGenericType(paramType);
570 if (isEnumClass(simpleType)) {
571 // Check if this is enum type
572 if (isArray(param)) { // An array
573 println("int len" + i + " = " + getSimpleIdentifier(param) + ".length;");
574 println("int paramEnum" + i + "[] = new int[len" + i + "];");
575 println("for (int i = 0; i < len" + i + "; i++) {");
576 println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + "[i].ordinal();");
578 } else if (isList(paramType)) { // A list
579 println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
580 println("int paramEnum" + i + "[] = new int[len" + i + "];");
581 println("for (int i = 0; i < len" + i + "; i++) {");
582 println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + ".get(i).ordinal();");
584 } else { // Just one element
585 println("int paramEnum" + i + "[] = new int[1];");
586 println("paramEnum" + i + "[0] = " + param + ".ordinal();");
594 * HELPER: checkAndWriteEnumRetTypeJavaStub() writes the enum return type (convert from enum to int)
596 private void checkAndWriteEnumRetTypeJavaStub(String retType, String method, InterfaceDecl intDecl) {
598 // Write the wait-for-return-value part
599 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
600 // Strips off array "[]" for return type
601 String pureType = getSimpleArrayType(getGenericType(retType));
602 // Take the inner type of generic
603 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
604 pureType = getGenericType(retType);
605 if (isEnumClass(pureType)) {
606 // Check if this is enum type
608 println("int[] retEnum = (int[]) retObj;");
609 println(pureType + "[] enumVals = " + pureType + ".values();");
610 if (isArray(retType)) { // An array
611 println("int retLen = retEnum.length;");
612 println(pureType + "[] enumRetVal = new " + pureType + "[retLen];");
613 println("for (int i = 0; i < retLen; i++) {");
614 println("enumRetVal[i] = enumVals[retEnum[i]];");
616 } else if (isList(retType)) { // A list
617 println("int retLen = retEnum.length;");
618 println("List<" + pureType + "> enumRetVal = new ArrayList<" + pureType + ">();");
619 println("for (int i = 0; i < retLen; i++) {");
620 println("enumRetVal.add(enumVals[retEnum[i]]);");
622 } else { // Just one element
623 println(pureType + " enumRetVal = enumVals[retEnum[0]];");
625 println("return enumRetVal;");
631 * HELPER: checkAndWriteStructSetupJavaStub() writes the struct type setup
633 private void checkAndWriteStructSetupJavaStub(List<String> methParams, List<String> methPrmTypes,
634 InterfaceDecl intDecl, String method) {
636 // Iterate and find struct declarations
637 for (int i = 0; i < methParams.size(); i++) {
638 String paramType = methPrmTypes.get(i);
639 String param = methParams.get(i);
640 String simpleType = getGenericType(paramType);
641 if (isStructClass(simpleType)) {
642 // Check if this is enum type
643 int methodNumId = intDecl.getMethodNumId(method);
644 String helperMethod = methodNumId + "struct" + i;
645 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
646 println("Class<?>[] paramClsStruct" + i + " = new Class<?>[] { int.class };");
647 if (isArray(param)) { // An array
648 println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".length };");
649 } else if (isList(paramType)) { // A list
650 println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".size() };");
651 } else { // Just one element
652 println("Object[] paramObjStruct" + i + " = new Object[] { new Integer(1) };");
654 println("rmiComm.remoteCall(objectId, methodIdStruct" + i +
655 ", paramClsStruct" + i + ", paramObjStruct" + i + ");\n");
662 * HELPER: isStructPresent() checks presence of struct
664 private boolean isStructPresent(List<String> methParams, List<String> methPrmTypes) {
666 // Iterate and find enum declarations
667 for (int i = 0; i < methParams.size(); i++) {
668 String paramType = methPrmTypes.get(i);
669 String param = methParams.get(i);
670 String simpleType = getGenericType(paramType);
671 if (isStructClass(simpleType))
679 * HELPER: writeLengthStructParamClassJavaStub() writes lengths of parameters
681 private void writeLengthStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes) {
683 // Iterate and find struct declarations - count number of params
684 for (int i = 0; i < methParams.size(); i++) {
685 String paramType = methPrmTypes.get(i);
686 String param = methParams.get(i);
687 String simpleType = getGenericType(paramType);
688 if (isStructClass(simpleType)) {
689 int members = getNumOfMembers(simpleType);
690 if (isArray(param)) { // An array
691 String structLen = getSimpleArrayType(param) + ".length";
692 print(members + "*" + structLen);
693 } else if (isList(paramType)) { // A list
694 String structLen = getSimpleArrayType(param) + ".size()";
695 print(members + "*" + structLen);
697 print(Integer.toString(members));
700 if (i != methParams.size() - 1) {
708 * HELPER: writeStructMembersJavaStub() writes parameters of struct
710 private void writeStructMembersJavaStub(String simpleType, String paramType, String param) {
712 // Get the struct declaration for this struct and generate initialization code
713 StructDecl structDecl = getStructDecl(simpleType);
714 List<String> memTypes = structDecl.getMemberTypes(simpleType);
715 List<String> members = structDecl.getMembers(simpleType);
716 if (isArray(param)) { // An array
717 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".length; i++) {");
718 for (int i = 0; i < members.size(); i++) {
719 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
720 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
721 print("paramObj[pos++] = " + getSimpleIdentifier(param) + "[i].");
722 print(getSimpleIdentifier(members.get(i)));
726 } else if (isList(paramType)) { // A list
727 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
728 for (int i = 0; i < members.size(); i++) {
729 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
730 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
731 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".get(i).");
732 print(getSimpleIdentifier(members.get(i)));
736 } else { // Just one struct element
737 for (int i = 0; i < members.size(); i++) {
738 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
739 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
740 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".");
741 print(getSimpleIdentifier(members.get(i)));
749 * HELPER: writeStructParamClassJavaStub() writes parameters if struct is present
751 private void writeStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
753 print("int paramLen = ");
754 writeLengthStructParamClassJavaStub(methParams, methPrmTypes);
756 println("Object[] paramObj = new Object[paramLen];");
757 println("Class<?>[] paramCls = new Class<?>[paramLen];");
758 println("int pos = 0;");
759 // Iterate again over the parameters
760 for (int i = 0; i < methParams.size(); i++) {
761 String paramType = methPrmTypes.get(i);
762 String param = methParams.get(i);
763 String simpleType = getGenericType(paramType);
764 if (isStructClass(simpleType)) {
765 writeStructMembersJavaStub(simpleType, paramType, param);
766 } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
767 println("paramCls[pos] = int[].class;");
768 println("paramObj[pos++] = objIdSent" + i + ";");
770 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
771 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
772 print("paramObj[pos++] = ");
773 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
782 * HELPER: writeStructRetMembersJavaStub() writes parameters of struct for return statement
784 private void writeStructRetMembersJavaStub(String simpleType, String retType) {
786 // Get the struct declaration for this struct and generate initialization code
787 StructDecl structDecl = getStructDecl(simpleType);
788 List<String> memTypes = structDecl.getMemberTypes(simpleType);
789 List<String> members = structDecl.getMembers(simpleType);
790 if (isArrayOrList(retType, retType)) { // An array or list
791 println("for(int i = 0; i < retLen; i++) {");
793 if (isArray(retType)) { // An array
794 for (int i = 0; i < members.size(); i++) {
795 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
796 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
797 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
800 } else if (isList(retType)) { // A list
801 println(simpleType + " structRetMem = new " + simpleType + "();");
802 for (int i = 0; i < members.size(); i++) {
803 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
804 print("structRetMem." + getSimpleIdentifier(members.get(i)));
805 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
807 println("structRet.add(structRetMem);");
809 } else { // Just one struct element
810 for (int i = 0; i < members.size(); i++) {
811 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
812 print("structRet." + getSimpleIdentifier(members.get(i)));
813 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
816 println("return structRet;");
821 * HELPER: writeStructReturnJavaStub() writes parameters if struct is present for return statement
823 private void writeStructReturnJavaStub(String simpleType, String retType, String method, InterfaceDecl intDecl) {
825 // Handle the returned struct size
826 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
827 // Minimum retLen is 1 if this is a single struct object
828 println("int retLen = (int) retObj;");
829 int numMem = getNumOfMembers(simpleType);
830 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
831 println("Class<?>[] retClsVal = new Class<?>[" + numMem + "*retLen];");
832 println("int retPos = 0;");
833 // Get the struct declaration for this struct and generate initialization code
834 StructDecl structDecl = getStructDecl(simpleType);
835 List<String> memTypes = structDecl.getMemberTypes(simpleType);
836 List<String> members = structDecl.getMembers(simpleType);
837 if (isArrayOrList(retType, retType)) { // An array or list
838 println("for(int i = 0; i < retLen; i++) {");
839 for (int i = 0; i < members.size(); i++) {
840 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
841 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
842 println("retClsVal[retPos++] = null;");
845 } else { // Just one struct element
846 for (int i = 0; i < members.size(); i++) {
847 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
848 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
849 println("retClsVal[retPos++] = null;");
852 // Handle the actual returned struct
853 writeWaitForReturnValueJava(method, intDecl, "Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);");
854 if (isArray(retType)) { // An array
855 println(simpleType + "[] structRet = new " + simpleType + "[retLen];");
856 println("for(int i = 0; i < retLen; i++) {");
857 println("structRet[i] = new " + simpleType + "();");
859 } else if (isList(retType)) { // A list
860 println("List<" + simpleType + "> structRet = new ArrayList<" + simpleType + ">();");
862 println(simpleType + " structRet = new " + simpleType + "();");
863 println("int retObjPos = 0;");
864 writeStructRetMembersJavaStub(simpleType, retType);
869 * HELPER: writeWaitForReturnValueJava() writes the synchronization part for return values
871 private void writeWaitForReturnValueJava(String method, InterfaceDecl intDecl, String getReturnValue) {
873 println("// Waiting for return value");
874 int methodNumId = intDecl.getMethodNumId(method);
875 println("while (!retValueReceived" + methodNumId + ".get());");
876 println(getReturnValue);
877 println("retValueReceived" + methodNumId + ".set(false);");
878 println("rmiComm.setGetReturnBytes();\n");
883 * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
885 private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
886 List<String> methPrmTypes, String method, Set<String> callbackType) {
888 checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method);
889 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
890 String retType = intDecl.getMethodType(method);
891 println("Class<?> retType = " + getSimpleType(getStructType(getEnumType(retType))) + ".class;");
892 checkAndWriteEnumTypeJavaStub(methParams, methPrmTypes);
893 // Generate array of parameter types
894 if (isStructPresent(methParams, methPrmTypes)) {
895 writeStructParamClassJavaStub(methParams, methPrmTypes, callbackType);
897 print("Class<?>[] paramCls = new Class<?>[] { ");
898 for (int i = 0; i < methParams.size(); i++) {
899 String prmType = methPrmTypes.get(i);
900 if (checkCallbackType(prmType, callbackType)) { // Check if this has callback object
901 print("int[].class");
902 } else { // Generate normal classes if it's not a callback object
903 String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
904 print(getSimpleType(getEnumType(paramType)) + ".class");
906 // Check if this is the last element (don't print a comma)
907 if (i != methParams.size() - 1) {
912 // Generate array of parameter objects
913 print("Object[] paramObj = new Object[] { ");
914 for (int i = 0; i < methParams.size(); i++) {
915 String paramType = methPrmTypes.get(i);
916 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
917 print("objIdSent" + i);
919 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
920 // Check if this is the last element (don't print a comma)
921 if (i != methParams.size() - 1) {
927 // Send method call first and wait for return value separately
928 println("rmiComm.remoteCall(objectId, methodId, paramCls, paramObj);");
929 // Check if this is "void"
930 if (!retType.equals("void")) { // We do have a return value
931 // Generate array of parameter types
932 if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
933 writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl);
935 // This is an enum type
936 if (getParamCategory(getGenericType(getSimpleArrayType(retType))) == ParamCategory.ENUM) {
937 //println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
938 checkAndWriteEnumRetTypeJavaStub(retType, method, intDecl);
939 } else if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
940 // Check if the return value NONPRIMITIVES
941 String retGenValType = getGenericType(retType);
942 println("Class<?> retGenValType = " + retGenValType + ".class;");
943 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, retGenValType);");
944 println("return (" + retType + ")retObj;");
946 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
947 println("return (" + retType + ")retObj;");
955 * HELPER: returnGenericCallbackType() returns the callback type
957 private String returnGenericCallbackType(String paramType) {
959 if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES)
960 return getGenericType(paramType);
967 * HELPER: checkCallbackType() checks the callback type
969 private boolean checkCallbackType(String paramType, Set<String> callbackType) {
971 String prmType = returnGenericCallbackType(paramType);
972 if (callbackType == null) // If there is no callbackType it means not a callback method
975 for (String type : callbackType) {
976 if (type.equals(prmType))
977 return true; // Check callbackType one by one
985 * HELPER: checkCallbackType() checks the callback type
987 private boolean checkCallbackType(String paramType, String callbackType) {
989 String prmType = returnGenericCallbackType(paramType);
990 if (callbackType == null) // If there is no callbackType it means not a callback method
993 return callbackType.equals(prmType);
998 * HELPER: writeCallbackInstantiationMethodBodyJavaStub() writes the callback object instantiation in the method of the stub class
1000 private void writeCallbackInstantiationMethodBodyJavaStub(String paramIdent, String callbackType, int counter, boolean isMultipleCallbacks) {
1002 println("if (!IoTRMIUtil.mapSkel.containsKey(" + paramIdent + ")) {");
1003 println("int newObjIdSent = rmiComm.getObjectIdCounter();");
1004 if (isMultipleCallbacks)
1005 println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
1007 println("objIdSent" + counter + "[0] = newObjIdSent;");
1008 println("rmiComm.decrementObjectIdCounter();");
1009 println(callbackType + "_Skeleton skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
1010 println("IoTRMIUtil.mapSkel.put(" + paramIdent + ", skel" + counter + ");");
1011 println("IoTRMIUtil.mapSkelId.put(" + paramIdent + ", newObjIdSent);");
1012 println("Thread thread = new Thread() {");
1013 println("public void run() {");
1015 println("skel" + counter + ".___waitRequestInvokeMethod();");
1016 println("} catch (Exception ex) {");
1017 println("ex.printStackTrace();");
1018 println("throw new Error(\"Exception when trying to run ___waitRequestInvokeMethod() for " +
1019 callbackType + "_Skeleton!\");");
1023 println("thread.start();");
1024 println("while(!skel" + counter + ".didAlreadyInitWaitInvoke());");
1028 println("int newObjIdSent = IoTRMIUtil.mapSkelId.get(" + paramIdent + ");");
1029 if (isMultipleCallbacks)
1030 println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
1032 println("objIdSent" + counter + "[0] = newObjIdSent;");
1038 * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class
1040 private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
1041 List<String> methPrmTypes, String method, Set<String> callbackType) {
1043 // Determine callback object counter type (List vs. single variable)
1044 for (int i = 0; i < methParams.size(); i++) {
1045 String paramType = methPrmTypes.get(i);
1046 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1047 print("int[] objIdSent" + i + " = ");
1048 String param = methParams.get(i);
1049 if (isArray(methParams.get(i)))
1050 println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".length];");
1051 else if (isList(methPrmTypes.get(i)))
1052 println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".size()];");
1054 println("new int[1];");
1058 // Check if this is single object, array, or list of objects
1059 for (int i = 0; i < methParams.size(); i++) {
1060 String paramType = methPrmTypes.get(i);
1061 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1062 String param = methParams.get(i);
1063 if (isArrayOrList(paramType, param)) { // Generate loop
1064 println("int cnt" + i + " = 0;");
1065 println("for (" + getGenericType(paramType) + " cb : " + getSimpleIdentifier(param) + ") {");
1066 writeCallbackInstantiationMethodBodyJavaStub("cb", returnGenericCallbackType(paramType), i, true);
1068 writeCallbackInstantiationMethodBodyJavaStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i, false);
1069 if (isArrayOrList(paramType, param))
1074 println(" catch (Exception ex) {");
1075 println("ex.printStackTrace();");
1076 println("throw new Error(\"Exception when generating skeleton objects!\");");
1082 * HELPER: writeMethodJavaStub() writes the methods of the stub class
1084 private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
1086 for (String method : methods) {
1088 List<String> methParams = intDecl.getMethodParams(method);
1089 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1090 print("public " + intDecl.getMethodType(method) + " " +
1091 intDecl.getMethodId(method) + "(");
1092 boolean isCallbackMethod = false;
1093 //String callbackType = null;
1094 Set<String> callbackType = new HashSet<String>();
1095 for (int i = 0; i < methParams.size(); i++) {
1097 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1098 // Check if this has callback object
1099 if (callbackClasses.contains(paramType)) {
1100 isCallbackMethod = true;
1101 //callbackType = paramType;
1102 callbackType.add(paramType);
1103 // Even if there're 2 callback arguments, we expect them to be of the same interface
1105 print(methPrmTypes.get(i) + " " + methParams.get(i));
1106 // Check if this is the last element (don't print a comma)
1107 if (i != methParams.size() - 1) {
1112 // Now, write the body of stub!
1113 if (isCallbackMethod)
1114 writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1115 writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1122 * HELPER: getStubInterface() gets stub interface name based on original interface
1124 public String getStubInterface(String intface) {
1126 return mapInt2NewIntName.get(intface);
1131 * generateJavaStubClasses() generate stubs based on the methods list in Java
1133 public void generateJavaStubClasses() throws IOException {
1135 // Create a new directory
1136 String path = createDirectories(dir, subdir);
1137 for (String intface : mapIntfacePTH.keySet()) {
1139 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1140 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1142 // Open a new file to write into
1143 String newIntface = intMeth.getKey();
1144 String newStubClass = newIntface + "_Stub";
1145 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
1146 pw = new PrintWriter(new BufferedWriter(fw));
1147 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1148 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1149 // Pass in set of methods and get import classes
1150 Set<String> methods = intMeth.getValue();
1151 Set<String> importClasses = getImportClasses(methods, intDecl);
1152 List<String> stdImportClasses = getStandardJavaImportClasses();
1153 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
1154 // Find out if there are callback objects
1155 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
1156 boolean callbackExist = !callbackClasses.isEmpty();
1158 println("package " + controllerClass + ";\n");
1160 println("package " + CODE_PREFIX + "." + driverClass + ";\n");
1161 printImportStatements(allImportClasses);
1162 println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
1163 // Write class header
1164 println("public class " + newStubClass + " implements " + newIntface + " {\n");
1166 writePropertiesJavaStub(intface, intMeth.getValue(), intDecl);
1167 // Write constructor
1168 writeConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1169 // Write callback constructor (used if this stub is treated as a callback stub)
1170 writeCallbackConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1172 writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass);
1175 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
1182 * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class
1184 private void writePropertiesJavaSkeleton(String intface, InterfaceDecl intDecl) {
1186 println("private " + intface + " mainObj;");
1187 Integer objId = mapIntfaceObjId.get(intface);
1188 println("private int objectId = " + objId + ";");
1189 println("// Communications and synchronizations");
1190 println("private IoTRMIComm rmiComm;");
1191 println("private AtomicBoolean didAlreadyInitWaitInvoke;");
1192 println("private AtomicBoolean methodReceived;");
1193 println("private byte[] methodBytes = null;");
1194 println("// Permissions");
1195 writePropertiesJavaPermission(intface, intDecl);
1201 * HELPER: writeStructPermissionJavaSkeleton() writes permission for struct helper
1203 private void writeStructPermissionJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
1205 // Use this set to handle two same methodIds
1206 for (String method : methods) {
1207 List<String> methParams = intDecl.getMethodParams(method);
1208 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1209 // Check for params with structs
1210 for (int i = 0; i < methParams.size(); i++) {
1211 String paramType = methPrmTypes.get(i);
1212 String param = methParams.get(i);
1213 String simpleType = getGenericType(paramType);
1214 if (isStructClass(simpleType)) {
1215 int methodNumId = intDecl.getMethodNumId(method);
1216 String helperMethod = methodNumId + "struct" + i;
1217 int methodHelperNumId = intDecl.getHelperMethodNumId(helperMethod);
1218 // Iterate over interfaces to give permissions to
1219 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1220 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1221 String newIntface = intMeth.getKey();
1222 int newObjectId = getNewIntfaceObjectId(newIntface);
1223 println("set" + newObjectId + "Allowed.add(" + methodHelperNumId + ");");
1232 * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class
1234 private void writeConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl,
1235 Collection<String> methods, boolean callbackExist) {
1237 println("public " + newSkelClass + "(" + intface + " _mainObj, int _portSend, int _portRecv) throws Exception {");
1238 println("mainObj = _mainObj;");
1239 println("rmiComm = new IoTRMICommServer(_portSend, _portRecv);");
1240 // Generate permission control initialization
1241 writeConstructorJavaPermission(intface);
1242 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1243 println("IoTRMIUtil.mapSkel.put(_mainObj, this);");
1244 println("IoTRMIUtil.mapSkelId.put(_mainObj, objectId);");
1245 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1246 println("methodReceived = new AtomicBoolean(false);");
1247 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1248 println("Thread thread1 = new Thread() {");
1249 println("public void run() {");
1251 println("___waitRequestInvokeMethod();");
1253 println("catch (Exception ex)");
1255 println("ex.printStackTrace();");
1259 println("thread1.start();");
1265 * HELPER: writeCallbackConstructorJavaSkeleton() writes the constructor of the skeleton class
1267 private void writeCallbackConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl,
1268 Collection<String> methods, boolean callbackExist) {
1270 println("public " + newSkelClass + "(" + intface + " _mainObj, IoTRMIComm _rmiComm, int _objectId) throws Exception {");
1271 println("mainObj = _mainObj;");
1272 println("rmiComm = _rmiComm;");
1273 println("objectId = _objectId;");
1274 // Generate permission control initialization
1275 writeConstructorJavaPermission(intface);
1276 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1277 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1278 println("methodReceived = new AtomicBoolean(false);");
1279 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1285 * HELPER: writeStdMethodBodyJavaSkeleton() writes the standard method body in the skeleton class
1287 private void writeStdMethodBodyJavaSkeleton(List<String> methParams, String methodId, String methodType) {
1289 if (methodType.equals("void"))
1290 print("mainObj." + methodId + "(");
1292 print("return mainObj." + methodId + "(");
1293 for (int i = 0; i < methParams.size(); i++) {
1295 print(getSimpleIdentifier(methParams.get(i)));
1296 // Check if this is the last element (don't print a comma)
1297 if (i != methParams.size() - 1) {
1306 * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class
1308 private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1310 for (String method : methods) {
1312 List<String> methParams = intDecl.getMethodParams(method);
1313 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1314 String methodId = intDecl.getMethodId(method);
1315 print("public " + intDecl.getMethodType(method) + " " + methodId + "(");
1316 for (int i = 0; i < methParams.size(); i++) {
1318 String origParamType = methPrmTypes.get(i);
1319 String paramType = checkAndGetParamClass(origParamType);
1320 print(paramType + " " + methParams.get(i));
1321 // Check if this is the last element (don't print a comma)
1322 if (i != methParams.size() - 1) {
1327 // Now, write the body of skeleton!
1328 writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method));
1335 * HELPER: writeCallbackInstantiationJavaStubGeneration() writes the instantiation of callback stubs
1337 private void writeCallbackInstantiationJavaStubGeneration(String exchParamType, int counter) {
1339 println(exchParamType + " newStub" + counter + " = null;");
1340 println("if(!IoTRMIUtil.mapStub.containsKey(objIdRecv" + counter + ")) {");
1341 println("newStub" + counter + " = new " + exchParamType + "_Stub(rmiComm, objIdRecv" + counter + ");");
1342 println("IoTRMIUtil.mapStub.put(objIdRecv" + counter + ", newStub" + counter + ");");
1343 println("rmiComm.setObjectIdCounter(objIdRecv" + counter + ");");
1344 println("rmiComm.decrementObjectIdCounter();");
1347 println("newStub" + counter + " = (" + exchParamType + "_Stub) IoTRMIUtil.mapStub.get(objIdRecv" + counter + ");");
1353 * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part
1355 private Map<Integer,String> writeCallbackJavaStubGeneration(List<String> methParams, List<String> methPrmTypes,
1356 Set<String> callbackType, boolean isStructMethod) {
1358 Map<Integer,String> mapStubParam = new HashMap<Integer,String>();
1359 String offsetPfx = "";
1361 offsetPfx = "offset";
1362 // Iterate over callback objects
1363 for (int i = 0; i < methParams.size(); i++) {
1364 String paramType = methPrmTypes.get(i);
1365 String param = methParams.get(i);
1366 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1367 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1368 // Print array if this is array or list if this is a list of callback objects
1369 println("int[] stubIdArray" + i + " = (int[]) paramObj[" + offsetPfx + i + "];");
1370 if (isArray(param)) {
1371 println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1372 println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];");
1373 } else if (isList(paramType)) {
1374 println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1375 println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();");
1377 println("int objIdRecv" + i + " = stubIdArray" + i + "[0];");
1378 writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1381 // Generate a loop if needed
1382 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1383 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1384 if (isArray(param)) {
1385 println("for (int i = 0; i < numStubs" + i + "; i++) {");
1386 println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
1387 writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1388 println("stub" + i + "[i] = newStub" + i + ";");
1390 } else if (isList(paramType)) {
1391 println("for (int i = 0; i < numStubs" + i + "; i++) {");
1392 println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
1393 writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1394 println("stub" + i + ".add(newStub" + i + ");");
1397 println(exchParamType + " stub" + i + " = newStub" + i + ";");
1398 mapStubParam.put(i, "stub" + i); // List of all stub parameters
1401 return mapStubParam;
1406 * HELPER: checkAndWriteEnumTypeJavaSkeleton() writes the enum type (convert from enum to int)
1408 private void checkAndWriteEnumTypeJavaSkeleton(List<String> methParams, List<String> methPrmTypes, boolean isStructMethod) {
1410 String offsetPfx = "";
1412 offsetPfx = "offset";
1413 // Iterate and find enum declarations
1414 boolean printed = false;
1415 for (int i = 0; i < methParams.size(); i++) {
1416 String paramType = methPrmTypes.get(i);
1417 String param = methParams.get(i);
1418 String simpleType = getGenericType(paramType);
1419 if (isEnumClass(simpleType)) {
1420 // Check if this is enum type
1421 println("int paramInt" + i + "[] = (int[]) paramObj[" + offsetPfx + i + "];");
1423 println(simpleType + "[] enumVals = " + simpleType + ".values();");
1426 if (isArray(param)) { // An array
1427 println("int len" + i + " = paramInt" + i + ".length;");
1428 println(simpleType + "[] paramEnum" + i + " = new " + simpleType + "[len" + i + "];");
1429 println("for (int i = 0; i < len" + i + "; i++) {");
1430 println("paramEnum" + i + "[i] = enumVals[paramInt" + i + "[i]];");
1432 } else if (isList(paramType)) { // A list
1433 println("int len" + i + " = paramInt" + i + ".length;");
1434 println("List<" + simpleType + "> paramEnum" + i + " = new ArrayList<" + simpleType + ">();");
1435 println("for (int i = 0; i < len" + i + "; i++) {");
1436 println("paramEnum" + i + ".add(enumVals[paramInt" + i + "[i]]);");
1438 } else { // Just one element
1439 println(simpleType + " paramEnum" + i + " = enumVals[paramInt" + i + "[0]];");
1447 * HELPER: checkAndWriteEnumRetTypeJavaSkeleton() writes the enum return type (convert from enum to int)
1449 private void checkAndWriteEnumRetTypeJavaSkeleton(String retType, String methodId) {
1451 // Strips off array "[]" for return type
1452 String pureType = getSimpleArrayType(getGenericType(retType));
1453 // Take the inner type of generic
1454 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1455 pureType = getGenericType(retType);
1456 if (isEnumClass(pureType)) {
1457 // Check if this is enum type
1459 if (isArray(retType)) { // An array
1460 print(pureType + "[] retEnum = " + methodId + "(");
1461 } else if (isList(retType)) { // A list
1462 print("List<" + pureType + "> retEnum = " + methodId + "(");
1463 } else { // Just one element
1464 print(pureType + " retEnum = " + methodId + "(");
1471 * HELPER: checkAndWriteEnumRetConvJavaSkeleton() writes the enum return type (convert from enum to int)
1473 private void checkAndWriteEnumRetConvJavaSkeleton(String retType) {
1475 // Strips off array "[]" for return type
1476 String pureType = getSimpleArrayType(getGenericType(retType));
1477 // Take the inner type of generic
1478 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1479 pureType = getGenericType(retType);
1480 if (isEnumClass(pureType)) {
1481 // Check if this is enum type
1482 if (isArray(retType)) { // An array
1483 println("int retLen = retEnum.length;");
1484 println("int[] retEnumVal = new int[retLen];");
1485 println("for (int i = 0; i < retLen; i++) {");
1486 println("retEnumVal[i] = retEnum[i].ordinal();");
1488 } else if (isList(retType)) { // A list
1489 println("int retLen = retEnum.size();");
1490 println("int[] retEnumVal = new int[retLen];");
1491 println("for (int i = 0; i < retLen; i++) {");
1492 println("retEnumVal[i] = retEnum.get(i).ordinal();");
1494 } else { // Just one element
1495 println("int[] retEnumVal = new int[1];");
1496 println("retEnumVal[0] = retEnum.ordinal();");
1498 println("Object retObj = retEnumVal;");
1504 * HELPER: writeLengthStructParamClassSkeleton() writes lengths of params
1506 private void writeLengthStructParamClassSkeleton(List<String> methParams, List<String> methPrmTypes,
1507 String method, InterfaceDecl intDecl) {
1509 // Iterate and find struct declarations - count number of params
1510 for (int i = 0; i < methParams.size(); i++) {
1511 String paramType = methPrmTypes.get(i);
1512 String param = methParams.get(i);
1513 String simpleType = getGenericType(paramType);
1514 if (isStructClass(simpleType)) {
1515 int members = getNumOfMembers(simpleType);
1516 print(Integer.toString(members) + "*");
1517 int methodNumId = intDecl.getMethodNumId(method);
1518 print("struct" + methodNumId + "Size" + i);
1521 if (i != methParams.size() - 1) {
1529 * HELPER: writeStructMembersJavaSkeleton() writes member parameters of struct
1531 private void writeStructMembersJavaSkeleton(String simpleType, String paramType,
1532 String param, String method, InterfaceDecl intDecl, int iVar) {
1534 // Get the struct declaration for this struct and generate initialization code
1535 StructDecl structDecl = getStructDecl(simpleType);
1536 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1537 List<String> members = structDecl.getMembers(simpleType);
1538 if (isArrayOrList(paramType, param)) { // An array or list
1539 int methodNumId = intDecl.getMethodNumId(method);
1540 String counter = "struct" + methodNumId + "Size" + iVar;
1541 println("for(int i = 0; i < " + counter + "; i++) {");
1543 if (isArrayOrList(paramType, param)) { // An array or list
1544 for (int i = 0; i < members.size(); i++) {
1545 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1546 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1547 println("paramClsGen[pos++] = null;");
1550 } else { // Just one struct element
1551 for (int i = 0; i < members.size(); i++) {
1552 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1553 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1554 println("paramClsGen[pos++] = null;");
1561 * HELPER: writeStructMembersInitJavaSkeleton() writes member parameters initialization of struct
1563 private void writeStructMembersInitJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1564 List<String> methPrmTypes, String method) {
1566 println("int objPos = 0;");
1567 for (int i = 0; i < methParams.size(); i++) {
1568 String paramType = methPrmTypes.get(i);
1569 String param = methParams.get(i);
1570 String simpleType = getGenericType(paramType);
1571 if (isStructClass(simpleType)) {
1572 int methodNumId = intDecl.getMethodNumId(method);
1573 String counter = "struct" + methodNumId + "Size" + i;
1575 if (isArray(param)) { // An array
1576 println(simpleType + "[] paramStruct" + i + " = new " + simpleType + "[" + counter + "];");
1577 println("for(int i = 0; i < " + counter + "; i++) {");
1578 println("paramStruct" + i + "[i] = new " + simpleType + "();");
1580 } else if (isList(paramType)) { // A list
1581 println("List<" + simpleType + "> paramStruct" + i + " = new ArrayList<" + simpleType + ">();");
1583 println(simpleType + " paramStruct" + i + " = new " + simpleType + "();");
1584 // Initialize members
1585 StructDecl structDecl = getStructDecl(simpleType);
1586 List<String> members = structDecl.getMembers(simpleType);
1587 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1588 if (isArrayOrList(paramType, param)) { // An array or list
1589 println("for(int i = 0; i < " + counter + "; i++) {");
1591 if (isArray(param)) { // An array
1592 for (int j = 0; j < members.size(); j++) {
1593 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1594 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
1595 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1598 } else if (isList(paramType)) { // A list
1599 println(simpleType + " paramStructMem = new " + simpleType + "();");
1600 for (int j = 0; j < members.size(); j++) {
1601 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1602 print("paramStructMem." + getSimpleIdentifier(members.get(j)));
1603 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1605 println("paramStruct" + i + ".add(paramStructMem);");
1607 } else { // Just one struct element
1608 for (int j = 0; j < members.size(); j++) {
1609 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1610 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
1611 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1615 // Take offsets of parameters
1616 println("int offset" + i +" = objPos++;");
1623 * HELPER: writeStructReturnJavaSkeleton() writes struct for return statement
1625 private void writeStructReturnJavaSkeleton(String simpleType, String retType) {
1627 // Minimum retLen is 1 if this is a single struct object
1628 if (isArray(retType))
1629 println("int retLen = retStruct.length;");
1630 else if (isList(retType))
1631 println("int retLen = retStruct.size();");
1632 else // Just single struct object
1633 println("int retLen = 1;");
1634 println("Object retLenObj = retLen;");
1635 println("rmiComm.sendReturnObj(retLenObj, localMethodBytes);");
1636 int numMem = getNumOfMembers(simpleType);
1637 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
1638 println("Object[] retObj = new Object[" + numMem + "*retLen];");
1639 println("int retPos = 0;");
1640 // Get the struct declaration for this struct and generate initialization code
1641 StructDecl structDecl = getStructDecl(simpleType);
1642 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1643 List<String> members = structDecl.getMembers(simpleType);
1644 if (isArray(retType)) { // An array or list
1645 println("for(int i = 0; i < retLen; i++) {");
1646 for (int i = 0; i < members.size(); i++) {
1647 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1648 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1649 print("retObj[retPos++] = retStruct[i].");
1650 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1654 } else if (isList(retType)) { // An array or list
1655 println("for(int i = 0; i < retLen; i++) {");
1656 for (int i = 0; i < members.size(); i++) {
1657 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1658 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1659 print("retObj[retPos++] = retStruct.get(i).");
1660 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1664 } else { // Just one struct element
1665 for (int i = 0; i < members.size(); i++) {
1666 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1667 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1668 print("retObj[retPos++] = retStruct.");
1669 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1678 * HELPER: writeMethodHelperReturnJavaSkeleton() writes return statement part in skeleton
1680 private void writeMethodHelperReturnJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1681 List<String> methPrmTypes, String method, boolean isCallbackMethod, Set<String> callbackType,
1682 boolean isStructMethod) {
1684 checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes, isStructMethod);
1685 Map<Integer,String> mapStubParam = null;
1686 if (isCallbackMethod) {
1688 mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType, isStructMethod);
1690 // Check if this is "void"
1691 String retType = intDecl.getMethodType(method);
1692 if (retType.equals("void")) {
1693 print(intDecl.getMethodId(method) + "(");
1694 } else if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
1695 checkAndWriteEnumRetTypeJavaSkeleton(retType, intDecl.getMethodId(method));
1696 } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
1697 print(retType + " retStruct = " + intDecl.getMethodId(method) + "(");
1698 } else { // We do have a return value
1699 print("Object retObj = " + intDecl.getMethodId(method) + "(");
1701 for (int i = 0; i < methParams.size(); i++) {
1703 String paramType = methPrmTypes.get(i);
1704 if (isCallbackMethod && checkCallbackType(paramType, callbackType)) {
1705 print(mapStubParam.get(i)); // Get the callback parameter
1706 } else if (isEnumClass(getGenericType(paramType))) { // Enum class
1707 print(getEnumParam(paramType, methParams.get(i), i));
1708 } else if (isStructClass(getGenericType(paramType))) {
1709 print("paramStruct" + i);
1711 String prmType = checkAndGetArray(paramType, methParams.get(i));
1713 print("(" + prmType + ") paramObj[offset" + i + "]");
1715 print("(" + prmType + ") paramObj[" + i + "]");
1717 if (i != methParams.size() - 1)
1721 if (!retType.equals("void")) {
1722 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
1723 checkAndWriteEnumRetConvJavaSkeleton(retType);
1724 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1725 } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
1726 writeStructReturnJavaSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
1727 println("rmiComm.sendReturnObj(retCls, retObj, localMethodBytes);");
1729 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1731 if (isCallbackMethod) { // Catch exception if this is callback
1733 println(" catch(Exception ex) {");
1734 println("ex.printStackTrace();");
1735 println("throw new Error(\"Exception from callback object instantiation!\");");
1742 * HELPER: writeMethodHelperStructJavaSkeleton() writes the struct in skeleton
1744 private void writeMethodHelperStructJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1745 List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1747 // Generate array of parameter objects
1748 boolean isCallbackMethod = false;
1749 Set<String> callbackType = new HashSet<String>();
1750 println("byte[] localMethodBytes = methodBytes;");
1751 println("rmiComm.setGetMethodBytes();");
1752 print("int paramLen = ");
1753 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
1755 println("Class<?>[] paramCls = new Class<?>[paramLen];");
1756 println("Class<?>[] paramClsGen = new Class<?>[paramLen];");
1757 println("int pos = 0;");
1758 // Iterate again over the parameters
1759 for (int i = 0; i < methParams.size(); i++) {
1760 String paramType = methPrmTypes.get(i);
1761 String param = methParams.get(i);
1762 String simpleType = getGenericType(paramType);
1763 if (isStructClass(simpleType)) {
1764 writeStructMembersJavaSkeleton(simpleType, paramType, param, method, intDecl, i);
1766 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
1767 if (callbackClasses.contains(prmType)) {
1768 isCallbackMethod = true;
1769 //callbackType = prmType;
1770 callbackType.add(prmType);
1771 println("paramCls[pos] = int[].class;");
1772 println("paramClsGen[pos++] = null;");
1773 } else { // Generate normal classes if it's not a callback object
1774 String paramTypeOth = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1775 println("paramCls[pos] = " + getSimpleType(getEnumType(paramTypeOth)) + ".class;");
1776 print("paramClsGen[pos++] = ");
1777 String prmTypeOth = methPrmTypes.get(i);
1778 if (getParamCategory(prmTypeOth) == ParamCategory.NONPRIMITIVES)
1779 println(getTypeOfGeneric(prmType)[0] + ".class;");
1785 println("Object[] paramObj = rmiComm.getMethodParams(paramCls, paramClsGen, localMethodBytes);");
1786 writeStructMembersInitJavaSkeleton(intDecl, methParams, methPrmTypes, method);
1787 // Write the return value part
1788 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, true);
1793 * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class
1795 private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1796 List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1798 // Generate array of parameter objects
1799 boolean isCallbackMethod = false;
1800 Set<String> callbackType = new HashSet<String>();
1801 println("byte[] localMethodBytes = methodBytes;");
1802 println("rmiComm.setGetMethodBytes();");
1803 print("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { ");
1804 for (int i = 0; i < methParams.size(); i++) {
1806 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1807 if (callbackClasses.contains(paramType)) {
1808 isCallbackMethod = true;
1809 callbackType.add(paramType);
1810 print("int[].class");
1811 } else { // Generate normal classes if it's not a callback object
1812 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1813 print(getSimpleType(getEnumType(prmType)) + ".class");
1815 if (i != methParams.size() - 1)
1818 // Generate generic class if it's a generic type.. null otherwise
1819 print(" }, new Class<?>[] { ");
1820 for (int i = 0; i < methParams.size(); i++) {
1821 String prmType = methPrmTypes.get(i);
1822 if ((getParamCategory(prmType) == ParamCategory.NONPRIMITIVES) &&
1823 !isEnumClass(getGenericType(prmType)) &&
1824 !callbackClasses.contains(getGenericType(prmType)))
1825 print(getGenericType(prmType) + ".class");
1828 if (i != methParams.size() - 1)
1831 println(" }, localMethodBytes);");
1832 // Write the return value part
1833 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, false);
1838 * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class
1840 private void writeMethodHelperJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1842 // Use this set to handle two same methodIds
1843 Set<String> uniqueMethodIds = new HashSet<String>();
1844 for (String method : methods) {
1846 List<String> methParams = intDecl.getMethodParams(method);
1847 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1848 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
1849 String methodId = intDecl.getMethodId(method);
1850 print("public void ___");
1851 String helperMethod = methodId;
1852 if (uniqueMethodIds.contains(methodId))
1853 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1855 uniqueMethodIds.add(methodId);
1856 String retType = intDecl.getMethodType(method);
1857 print(helperMethod + "(");
1858 boolean begin = true;
1859 for (int i = 0; i < methParams.size(); i++) { // Print size variables
1860 String paramType = methPrmTypes.get(i);
1861 String param = methParams.get(i);
1862 String simpleType = getGenericType(paramType);
1863 if (isStructClass(simpleType)) {
1864 if (!begin) // Generate comma for not the beginning variable
1868 int methodNumId = intDecl.getMethodNumId(method);
1869 print("int struct" + methodNumId + "Size" + i);
1872 // Check if this is "void"
1873 if (retType.equals("void"))
1876 println(") throws IOException {");
1877 writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1880 String methodId = intDecl.getMethodId(method);
1881 print("public void ___");
1882 String helperMethod = methodId;
1883 if (uniqueMethodIds.contains(methodId))
1884 helperMethod = helperMethod + intDecl.getMethodNumId(method);
1886 uniqueMethodIds.add(methodId);
1887 // Check if this is "void"
1888 String retType = intDecl.getMethodType(method);
1889 if (retType.equals("void"))
1890 println(helperMethod + "() {");
1892 println(helperMethod + "() throws IOException {");
1893 // Now, write the helper body of skeleton!
1894 writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1898 // Write method helper for structs
1899 writeMethodHelperStructSetupJavaSkeleton(methods, intDecl);
1904 * HELPER: writeMethodHelperStructSetupJavaSkeleton() writes the method helper of struct setup in skeleton class
1906 private void writeMethodHelperStructSetupJavaSkeleton(Collection<String> methods,
1907 InterfaceDecl intDecl) {
1909 // Use this set to handle two same methodIds
1910 for (String method : methods) {
1912 List<String> methParams = intDecl.getMethodParams(method);
1913 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1914 // Check for params with structs
1915 for (int i = 0; i < methParams.size(); i++) {
1916 String paramType = methPrmTypes.get(i);
1917 String param = methParams.get(i);
1918 String simpleType = getGenericType(paramType);
1919 if (isStructClass(simpleType)) {
1920 int methodNumId = intDecl.getMethodNumId(method);
1921 print("public int ___");
1922 String helperMethod = methodNumId + "struct" + i;
1923 println(helperMethod + "() {");
1924 // Now, write the helper body of skeleton!
1925 println("byte[] localMethodBytes = methodBytes;");
1926 println("rmiComm.setGetMethodBytes();");
1927 println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null }, localMethodBytes);");
1928 println("return (int) paramObj[0];");
1937 * HELPER: writeMethodHelperStructSetupJavaCallbackSkeleton() writes the method helper of struct setup in callback skeleton class
1939 private void writeMethodHelperStructSetupJavaCallbackSkeleton(Collection<String> methods,
1940 InterfaceDecl intDecl) {
1942 // Use this set to handle two same methodIds
1943 for (String method : methods) {
1945 List<String> methParams = intDecl.getMethodParams(method);
1946 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1947 // Check for params with structs
1948 for (int i = 0; i < methParams.size(); i++) {
1949 String paramType = methPrmTypes.get(i);
1950 String param = methParams.get(i);
1951 String simpleType = getGenericType(paramType);
1952 if (isStructClass(simpleType)) {
1953 int methodNumId = intDecl.getMethodNumId(method);
1954 print("public int ___");
1955 String helperMethod = methodNumId + "struct" + i;
1956 println(helperMethod + "(IoTRMIObject rmiObj) {");
1957 // Now, write the helper body of skeleton!
1958 println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null });");
1959 println("return (int) paramObj[0];");
1968 * HELPER: writeCountVarStructSkeleton() writes counter variable of struct for skeleton
1970 private void writeCountVarStructSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1972 // Use this set to handle two same methodIds
1973 for (String method : methods) {
1975 List<String> methParams = intDecl.getMethodParams(method);
1976 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1977 // Check for params with structs
1978 for (int i = 0; i < methParams.size(); i++) {
1979 String paramType = methPrmTypes.get(i);
1980 String param = methParams.get(i);
1981 String simpleType = getGenericType(paramType);
1982 if (isStructClass(simpleType)) {
1983 int methodNumId = intDecl.getMethodNumId(method);
1984 println("int struct" + methodNumId + "Size" + i + " = 0;");
1992 * HELPER: writeInputCountVarStructJavaSkeleton() writes input counter variable of struct for skeleton
1994 private boolean writeInputCountVarStructJavaSkeleton(String method, InterfaceDecl intDecl) {
1996 List<String> methParams = intDecl.getMethodParams(method);
1997 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1998 boolean structExist = false;
1999 boolean begin = true;
2000 // Check for params with structs
2001 for (int i = 0; i < methParams.size(); i++) {
2002 String paramType = methPrmTypes.get(i);
2003 String param = methParams.get(i);
2004 String simpleType = getGenericType(paramType);
2005 if (isStructClass(simpleType)) {
2011 int methodNumId = intDecl.getMethodNumId(method);
2012 print("struct" + methodNumId + "Size" + i + "Final");
2020 * HELPER: writeInputCountVarStructCplusSkeleton() writes input counter variable of struct for skeleton
2022 private boolean writeInputCountVarStructCplusSkeleton(String method, InterfaceDecl intDecl) {
2024 List<String> methParams = intDecl.getMethodParams(method);
2025 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2026 boolean structExist = false;
2027 boolean begin = true;
2028 // Check for params with structs
2029 for (int i = 0; i < methParams.size(); i++) {
2030 String paramType = methPrmTypes.get(i);
2031 String param = methParams.get(i);
2032 String simpleType = getGenericType(paramType);
2033 if (isStructClass(simpleType)) {
2039 int methodNumId = intDecl.getMethodNumId(method);
2040 print("struct" + methodNumId + "Size" + i);
2048 * HELPER: writeMethodCallStructJavaSkeleton() writes method call for wait invoke in skeleton
2050 private void writeMethodCallStructJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2052 // Use this set to handle two same methodIds
2053 for (String method : methods) {
2055 List<String> methParams = intDecl.getMethodParams(method);
2056 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2057 // Check for params with structs
2058 for (int i = 0; i < methParams.size(); i++) {
2059 String paramType = methPrmTypes.get(i);
2060 String param = methParams.get(i);
2061 String simpleType = getGenericType(paramType);
2062 if (isStructClass(simpleType)) {
2063 int methodNumId = intDecl.getMethodNumId(method);
2065 String helperMethod = methodNumId + "struct" + i;
2066 String tempVar = "struct" + methodNumId + "Size" + i;
2067 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2068 print(tempVar + " = ___");
2069 println(helperMethod + "(); break;");
2077 * HELPER: writeMethodCallStructCplusSkeleton() writes method call for wait invoke in skeleton
2079 private void writeMethodCallStructCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2081 // Use this set to handle two same methodIds
2082 for (String method : methods) {
2084 List<String> methParams = intDecl.getMethodParams(method);
2085 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2086 // Check for params with structs
2087 for (int i = 0; i < methParams.size(); i++) {
2088 String paramType = methPrmTypes.get(i);
2089 String param = methParams.get(i);
2090 String simpleType = getGenericType(paramType);
2091 if (isStructClass(simpleType)) {
2092 int methodNumId = intDecl.getMethodNumId(method);
2094 String helperMethod = methodNumId + "struct" + i;
2095 String tempVar = "struct" + methodNumId + "Size" + i;
2096 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2097 print(tempVar + " = ___");
2098 println(helperMethod + "(skel); break;");
2106 * HELPER: writeMethodCallStructCallbackSkeleton() writes method call for wait invoke in skeleton
2108 private void writeMethodCallStructCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2110 // Use this set to handle two same methodIds
2111 for (String method : methods) {
2113 List<String> methParams = intDecl.getMethodParams(method);
2114 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2115 // Check for params with structs
2116 for (int i = 0; i < methParams.size(); i++) {
2117 String paramType = methPrmTypes.get(i);
2118 String param = methParams.get(i);
2119 String simpleType = getGenericType(paramType);
2120 if (isStructClass(simpleType)) {
2121 int methodNumId = intDecl.getMethodNumId(method);
2123 String helperMethod = methodNumId + "struct" + i;
2124 String tempVar = "struct" + methodNumId + "Size" + i;
2125 print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2126 print(tempVar + " = ___");
2127 println(helperMethod + "(rmiObj); break;");
2135 * HELPER: writeJavaMethodPermission() writes permission checks in skeleton
2137 private void writeJavaMethodPermission(String intface) {
2139 // Get all the different stubs
2140 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2141 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2142 String newIntface = intMeth.getKey();
2143 int newObjectId = getNewIntfaceObjectId(newIntface);
2144 println("if (_objectId == objectId) {");
2145 println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
2146 println("throw new Error(\"Object with object Id: \" + _objectId + \" is not allowed to access method: \" + methodId);");
2150 println("continue;");
2157 * HELPER: writeFinalInputCountVarStructSkeleton() writes the final version of input counter variable of struct for skeleton
2159 private boolean writeFinalInputCountVarStructSkeleton(String method, InterfaceDecl intDecl) {
2161 List<String> methParams = intDecl.getMethodParams(method);
2162 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2163 boolean structExist = false;
2164 boolean begin = true;
2165 // Check for params with structs
2166 for (int i = 0; i < methParams.size(); i++) {
2167 String paramType = methPrmTypes.get(i);
2168 String param = methParams.get(i);
2169 String simpleType = getGenericType(paramType);
2170 if (isStructClass(simpleType)) {
2172 int methodNumId = intDecl.getMethodNumId(method);
2173 println("final int struct" + methodNumId + "Size" + i +
2174 "Final = struct" + methodNumId + "Size" + i + ";");
2182 * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class
2184 private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, String intface) {
2186 // Use this set to handle two same methodIds
2187 Set<String> uniqueMethodIds = new HashSet<String>();
2188 println("public void ___waitRequestInvokeMethod() throws IOException {");
2189 // Write variables here if we have callbacks or enums or structs
2190 writeCountVarStructSkeleton(methods, intDecl);
2191 println("didAlreadyInitWaitInvoke.compareAndSet(false, true);");
2192 println("while (true) {");
2193 println("if (!methodReceived.get()) {");
2194 println("continue;");
2196 println("methodBytes = rmiComm.getMethodBytes();");
2197 println("methodReceived.set(false);");
2198 println("int _objectId = IoTRMIComm.getObjectId(methodBytes);");
2199 println("int methodId = IoTRMIComm.getMethodId(methodBytes);");
2200 // Generate permission check
2201 writeJavaMethodPermission(intface);
2202 println("switch (methodId) {");
2203 // Print methods and method Ids
2204 for (String method : methods) {
2205 String methodId = intDecl.getMethodId(method);
2206 int methodNumId = intDecl.getMethodNumId(method);
2207 println("case " + methodNumId + ":");
2208 // Check for stuct counters
2209 writeFinalInputCountVarStructSkeleton(method, intDecl);
2210 println("new Thread() {");
2211 println("public void run() {");
2214 String helperMethod = methodId;
2215 if (uniqueMethodIds.contains(methodId))
2216 helperMethod = helperMethod + methodNumId;
2218 uniqueMethodIds.add(methodId);
2219 print(helperMethod + "(");
2220 writeInputCountVarStructJavaSkeleton(method, intDecl);
2223 println("catch (Exception ex) {");
2224 println("ex.printStackTrace();");
2227 println("}.start();");
2230 String method = "___initCallBack()";
2231 writeMethodCallStructJavaSkeleton(methods, intDecl);
2232 println("default: ");
2233 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
2241 * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke
2243 private void writeReturnDidAlreadyInitWaitInvoke() {
2245 println("public boolean didAlreadyInitWaitInvoke() {");
2246 println("return didAlreadyInitWaitInvoke.get();");
2252 * generateJavaSkeletonClass() generate skeletons based on the methods list in Java
2254 public void generateJavaSkeletonClass() throws IOException {
2256 // Create a new directory
2257 String path = createDirectories(dir, subdir);
2258 for (String intface : mapIntfacePTH.keySet()) {
2259 // Open a new file to write into
2260 String newSkelClass = intface + "_Skeleton";
2261 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
2262 pw = new PrintWriter(new BufferedWriter(fw));
2263 // Pass in set of methods and get import classes
2264 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2265 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2266 List<String> methods = intDecl.getMethods();
2267 Set<String> importClasses = getImportClasses(methods, intDecl);
2268 List<String> stdImportClasses = getStandardJavaImportClasses();
2269 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
2270 // Find out if there are callback objects
2271 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2272 boolean callbackExist = !callbackClasses.isEmpty();
2274 println("package " + CODE_PREFIX + "." + driverClass + ";\n");
2276 println("package " + controllerClass + ";\n");
2277 printImportStatements(allImportClasses);
2278 println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
2279 // Write class header
2280 println("public class " + newSkelClass + " implements " + intface + " {\n");
2282 writePropertiesJavaSkeleton(intface, intDecl);
2283 // Write constructor
2284 writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2285 // Write constructor that is called when this object is a callback object
2286 writeCallbackConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2287 // Write function to return didAlreadyInitWaitInvoke
2288 writeReturnDidAlreadyInitWaitInvoke();
2290 writeMethodJavaSkeleton(methods, intDecl);
2291 // Write method helper
2292 writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
2293 // Write waitRequestInvokeMethod() - main loop
2294 writeJavaWaitRequestInvokeMethod(methods, intDecl, intface);
2297 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
2302 /*================================================================================
2306 *================================================================================/
2309 * HELPER: writeMethodCplusLocalInterface() writes the method of the local interface
2311 private void writeMethodCplusLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
2313 for (String method : methods) {
2315 List<String> methParams = intDecl.getMethodParams(method);
2316 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2317 print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2318 intDecl.getMethodId(method) + "(");
2319 for (int i = 0; i < methParams.size(); i++) {
2320 // Check for params with driver class types and exchange it
2321 // with its remote interface
2322 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
2323 paramType = checkAndGetCplusType(paramType);
2324 // Check for arrays - translate into vector in C++
2325 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2326 print(paramComplete);
2327 // Check if this is the last element (don't print a comma)
2328 if (i != methParams.size() - 1) {
2338 * HELPER: writeMethodCplusInterface() writes the method of the interface
2340 private void writeMethodCplusInterface(Collection<String> methods, InterfaceDecl intDecl) {
2342 for (String method : methods) {
2344 List<String> methParams = intDecl.getMethodParams(method);
2345 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2346 print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2347 intDecl.getMethodId(method) + "(");
2348 for (int i = 0; i < methParams.size(); i++) {
2349 // Check for params with driver class types and exchange it
2350 // with its remote interface
2351 String paramType = methPrmTypes.get(i);
2352 paramType = checkAndGetCplusType(paramType);
2353 // Check for arrays - translate into vector in C++
2354 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2355 print(paramComplete);
2356 // Check if this is the last element (don't print a comma)
2357 if (i != methParams.size() - 1) {
2367 * HELPER: generateEnumCplus() writes the enumeration declaration
2369 public void generateEnumCplus() throws IOException {
2371 // Create a new directory
2372 createDirectory(dir);
2373 for (String intface : mapIntfacePTH.keySet()) {
2374 // Get the right StructDecl
2375 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2376 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
2377 Set<String> enumTypes = enumDecl.getEnumDeclarations();
2378 // Iterate over enum declarations
2379 for (String enType : enumTypes) {
2380 // Open a new file to write into
2381 FileWriter fw = new FileWriter(dir + "/" + enType + ".hpp");
2382 pw = new PrintWriter(new BufferedWriter(fw));
2383 // Write file headers
2384 println("#ifndef _" + enType.toUpperCase() + "_HPP__");
2385 println("#define _" + enType.toUpperCase() + "_HPP__");
2386 println("enum " + enType + " {");
2387 List<String> enumMembers = enumDecl.getMembers(enType);
2388 for (int i = 0; i < enumMembers.size(); i++) {
2390 String member = enumMembers.get(i);
2392 // Check if this is the last element (don't print a comma)
2393 if (i != enumMembers.size() - 1)
2401 System.out.println("IoTCompiler: Generated enum " + enType + ".hpp...");
2408 * HELPER: generateStructCplus() writes the struct declaration
2410 public void generateStructCplus() throws IOException {
2412 // Create a new directory
2413 createDirectory(dir);
2414 for (String intface : mapIntfacePTH.keySet()) {
2415 // Get the right StructDecl
2416 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2417 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
2418 List<String> structTypes = structDecl.getStructTypes();
2419 // Iterate over enum declarations
2420 for (String stType : structTypes) {
2421 // Open a new file to write into
2422 FileWriter fw = new FileWriter(dir + "/" + stType + ".hpp");
2423 pw = new PrintWriter(new BufferedWriter(fw));
2424 // Write file headers
2425 println("#ifndef _" + stType.toUpperCase() + "_HPP__");
2426 println("#define _" + stType.toUpperCase() + "_HPP__");
2427 println("using namespace std;");
2428 println("struct " + stType + " {");
2429 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
2430 List<String> structMembers = structDecl.getMembers(stType);
2431 for (int i = 0; i < structMembers.size(); i++) {
2433 String memberType = structMemberTypes.get(i);
2434 String member = structMembers.get(i);
2435 String structTypeC = checkAndGetCplusType(memberType);
2436 String structComplete = checkAndGetCplusArray(structTypeC, member);
2437 println(structComplete + ";");
2442 System.out.println("IoTCompiler: Generated struct " + stType + ".hpp...");
2449 * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
2451 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
2452 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
2453 * The local interface has to be the input parameter for the stub and the stub
2454 * interface has to be the input parameter for the local class.
2456 public void generateCplusLocalInterfaces() throws IOException {
2458 // Create a new directory
2459 createDirectory(dir);
2460 for (String intface : mapIntfacePTH.keySet()) {
2461 // Open a new file to write into
2462 FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
2463 pw = new PrintWriter(new BufferedWriter(fw));
2464 // Write file headers
2465 println("#ifndef _" + intface.toUpperCase() + "_HPP__");
2466 println("#define _" + intface.toUpperCase() + "_HPP__");
2467 println("#include <iostream>");
2468 // Pass in set of methods and get include classes
2469 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2470 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2471 List<String> methods = intDecl.getMethods();
2472 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, true);
2473 printIncludeStatements(includeClasses); println("");
2474 println("using namespace std;\n");
2475 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2476 if (!intface.equals(mainClass)) // Forward declare if not main class
2477 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, true);
2478 println("class " + intface); println("{");
2481 writeMethodCplusLocalInterface(methods, intDecl);
2485 System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
2491 * HELPER: writeMethodCplusInterfaceForwardDecl() writes the forward declaration of the interface
2493 private void writeMethodCplusInterfaceForwardDecl(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, boolean needNewIntface) {
2495 Set<String> isDefined = new HashSet<String>();
2496 for (String method : methods) {
2498 List<String> methParams = intDecl.getMethodParams(method);
2499 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2500 for (int i = 0; i < methParams.size(); i++) {
2501 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2502 // Check if this has callback object
2503 if (callbackClasses.contains(paramType)) {
2504 if (!isDefined.contains(paramType)) {
2506 println("class " + getStubInterface(paramType) + ";\n");
2508 println("class " + paramType + ";\n");
2509 isDefined.add(paramType);
2518 * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
2520 * For C++ we use virtual classe as interface
2522 public void generateCPlusInterfaces() throws IOException {
2524 // Create a new directory
2525 String path = createDirectories(dir, subdir);
2526 for (String intface : mapIntfacePTH.keySet()) {
2528 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2529 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2531 // Open a new file to write into
2532 String newIntface = intMeth.getKey();
2533 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
2534 pw = new PrintWriter(new BufferedWriter(fw));
2535 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2536 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2537 // Write file headers
2538 println("#ifndef _" + newIntface.toUpperCase() + "_HPP__");
2539 println("#define _" + newIntface.toUpperCase() + "_HPP__");
2540 println("#include <iostream>");
2541 updateIntfaceObjIdMap(intface, newIntface);
2542 // Pass in set of methods and get import classes
2543 Set<String> methods = intMeth.getValue();
2544 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, false);
2545 printIncludeStatements(includeClasses); println("");
2546 println("using namespace std;\n");
2547 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2548 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, false);
2549 println("class " + newIntface);
2553 writeMethodCplusInterface(methods, intDecl);
2557 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
2564 * HELPER: writeMethodDeclCplusStub() writes the method declarations of the stub
2566 private void writeMethodDeclCplusStub(Collection<String> methods, InterfaceDecl intDecl) {
2568 for (String method : methods) {
2570 List<String> methParams = intDecl.getMethodParams(method);
2571 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2572 print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2573 intDecl.getMethodId(method) + "(");
2574 for (int i = 0; i < methParams.size(); i++) {
2576 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2577 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2578 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2579 print(methParamComplete);
2580 // Check if this is the last element (don't print a comma)
2581 if (i != methParams.size() - 1) {
2591 * HELPER: writeMethodCplusStub() writes the methods of the stub
2593 private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
2595 for (String method : methods) {
2597 List<String> methParams = intDecl.getMethodParams(method);
2598 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2599 // Print the mutex lock first
2600 int methodNumId = intDecl.getMethodNumId(method);
2601 String mutexVar = "mtx" + newStubClass + "MethodExec" + methodNumId;
2602 println("mutex " + mutexVar + ";");
2603 print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " + newStubClass + "::" +
2604 intDecl.getMethodId(method) + "(");
2605 boolean isCallbackMethod = false;
2606 Set<String> callbackType = new HashSet<String>();
2607 for (int i = 0; i < methParams.size(); i++) {
2609 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2610 // Check if this has callback object
2611 if (callbackClasses.contains(paramType)) {
2612 isCallbackMethod = true;
2613 //callbackType = paramType;
2614 callbackType.add(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" + counter + " = IoTRMIUtil::mapSkel->find(" + paramIdent + ");");
2642 println("if (it" + counter + " == IoTRMIUtil::mapSkel->end()) {");
2643 println("int newObjIdSent = rmiComm->getObjectIdCounter();");
2644 println("objIdSent" + counter + ".push_back(newObjIdSent);");
2645 println("rmiComm->decrementObjectIdCounter();");
2646 println(callbackType + "_Skeleton* skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
2647 println("IoTRMIUtil::mapSkel->insert(make_pair(" + paramIdent + ", skel" + counter + "));");
2648 println("IoTRMIUtil::mapSkelId->insert(make_pair(" + paramIdent + ", newObjIdSent));");
2649 println("thread th" + counter + " (&" + callbackType + "_Skeleton::___waitRequestInvokeMethod, skel" + counter +
2650 ", skel" + counter +");");
2651 println("th" + counter + ".detach();");
2652 println("while(!skel" + counter + "->didInitWaitInvoke());");
2656 println("auto itId = IoTRMIUtil::mapSkelId->find(" + paramIdent + ");");
2657 println("objIdSent" + counter + ".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, Set<String> callbackType) {
2668 // Check if this is single object, array, or list of objects
2669 boolean isArrayOrList = false;
2670 String callbackParam = null;
2671 for (int i = 0; i < methParams.size(); i++) {
2672 String paramType = methPrmTypes.get(i);
2673 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2674 println("vector<int> objIdSent" + i + ";");
2675 String param = methParams.get(i);
2676 if (isArrayOrList(paramType, param)) { // Generate loop
2677 println("for (" + getGenericType(paramType) + "* cb : " + getSimpleIdentifier(param) + ") {");
2678 writeCallbackInstantiationMethodBodyCplusStub("cb", returnGenericCallbackType(paramType), i);
2679 isArrayOrList = true;
2680 callbackParam = getSimpleIdentifier(param);
2682 writeCallbackInstantiationMethodBodyCplusStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i);
2686 println("vector<int> ___paramCB" + i + " = objIdSent" + i + ";");
2693 * HELPER: checkAndWriteEnumTypeCplusStub() writes the enum type (convert from enum to int)
2695 private void checkAndWriteEnumTypeCplusStub(List<String> methParams, List<String> methPrmTypes) {
2697 // Iterate and find enum declarations
2698 for (int i = 0; i < methParams.size(); i++) {
2699 String paramType = methPrmTypes.get(i);
2700 String param = methParams.get(i);
2701 if (isEnumClass(getGenericType(paramType))) {
2702 // Check if this is enum type
2703 if (isArrayOrList(paramType, param)) { // An array or vector
2704 println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
2705 println("vector<int> paramEnum" + i + "(len" + i + ");");
2706 println("for (int i = 0; i < len" + i + "; i++) {");
2707 println("paramEnum" + i + "[i] = (int) " + getSimpleIdentifier(param) + "[i];");
2709 } else { // Just one element
2710 println("vector<int> paramEnum" + i + "(1);");
2711 println("paramEnum" + i + "[0] = (int) " + param + ";");
2719 * HELPER: checkAndWriteEnumRetTypeCplusStub() writes the enum return type (convert from enum to int)
2721 private void checkAndWriteEnumRetTypeCplusStub(String retType, String method, InterfaceDecl intDecl) {
2723 // Strips off array "[]" for return type
2724 String pureType = getSimpleArrayType(getGenericType(retType));
2725 // Take the inner type of generic
2726 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
2727 pureType = getGenericType(retType);
2728 if (isEnumClass(pureType)) {
2729 // Check if this is enum type
2730 println("vector<int> retEnumInt;");
2731 println("void* retObj = &retEnumInt;");
2732 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
2733 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
2734 if (isArrayOrList(retType, retType)) { // An array or vector
2735 println("int retLen = retEnumInt.size();");
2736 println("vector<" + pureType + "> retVal(retLen);");
2737 println("for (int i = 0; i < retLen; i++) {");
2738 println("retVal[i] = (" + pureType + ") retEnumInt[i];");
2740 } else { // Just one element
2741 println(pureType + " retVal = (" + pureType + ") retEnumInt[0];");
2743 println("return retVal;");
2749 * HELPER: checkAndWriteStructSetupCplusStub() writes the struct type setup
2751 private void checkAndWriteStructSetupCplusStub(List<String> methParams, List<String> methPrmTypes,
2752 InterfaceDecl intDecl, String method) {
2754 // Iterate and find struct declarations
2755 for (int i = 0; i < methParams.size(); i++) {
2756 String paramType = methPrmTypes.get(i);
2757 String param = methParams.get(i);
2758 String simpleType = getGenericType(paramType);
2759 if (isStructClass(simpleType)) {
2760 // Check if this is enum type
2761 println("int numParam" + i + " = 1;");
2762 int methodNumId = intDecl.getMethodNumId(method);
2763 String helperMethod = methodNumId + "struct" + i;
2764 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
2765 //println("string retTypeStruct" + i + " = \"void\";");
2766 println("string paramClsStruct" + i + "[] = { \"int\" };");
2767 print("int structLen" + i + " = ");
2768 if (isArrayOrList(paramType, param)) { // An array
2769 println(getSimpleArrayType(param) + ".size();");
2770 } else { // Just one element
2773 println("void* paramObjStruct" + i + "[] = { &structLen" + i + " };");
2774 println("rmiComm->remoteCall(objectId, methodIdStruct" + i +
2775 ", paramClsStruct" + i + ", paramObjStruct" + i +
2776 ", numParam" + i + ");\n");
2783 * HELPER: writeLengthStructParamClassCplusStub() writes lengths of params
2785 private void writeLengthStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes) {
2787 // Iterate and find struct declarations - count number of params
2788 for (int i = 0; i < methParams.size(); i++) {
2789 String paramType = methPrmTypes.get(i);
2790 String param = methParams.get(i);
2791 String simpleType = getGenericType(paramType);
2792 if (isStructClass(simpleType)) {
2793 int members = getNumOfMembers(simpleType);
2794 if (isArrayOrList(paramType, param)) { // An array or list
2795 String structLen = getSimpleIdentifier(param) + ".size()";
2796 print(members + "*" + structLen);
2798 print(Integer.toString(members));
2801 if (i != methParams.size() - 1) {
2809 * HELPER: writeStructMembersCplusStub() writes member parameters of struct
2811 private void writeStructMembersCplusStub(String simpleType, String paramType, String param) {
2813 // Get the struct declaration for this struct and generate initialization code
2814 StructDecl structDecl = getStructDecl(simpleType);
2815 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2816 List<String> members = structDecl.getMembers(simpleType);
2817 if (isArrayOrList(paramType, param)) { // An array or list
2818 println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
2820 if (isArrayOrList(paramType, param)) { // An array or list
2821 for (int i = 0; i < members.size(); i++) {
2822 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2823 println("paramCls[pos] = \"" + prmTypeC + "\";");
2824 print("paramObj[pos++] = &" + getSimpleIdentifier(param) + "[i].");
2825 print(getSimpleIdentifier(members.get(i)));
2829 } else { // Just one struct element
2830 for (int i = 0; i < members.size(); i++) {
2831 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2832 println("paramCls[pos] = \"" + prmTypeC + "\";");
2833 print("paramObj[pos++] = &" + param + ".");
2834 print(getSimpleIdentifier(members.get(i)));
2842 * HELPER: writeStructParamClassCplusStub() writes member parameters of struct
2844 private void writeStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
2846 print("int numParam = ");
2847 writeLengthStructParamClassCplusStub(methParams, methPrmTypes);
2849 println("void* paramObj[numParam];");
2850 println("string paramCls[numParam];");
2851 println("int pos = 0;");
2852 // Iterate again over the parameters
2853 for (int i = 0; i < methParams.size(); i++) {
2854 String paramType = methPrmTypes.get(i);
2855 String param = methParams.get(i);
2856 String simpleType = getGenericType(paramType);
2857 if (isStructClass(simpleType)) {
2858 writeStructMembersCplusStub(simpleType, paramType, param);
2859 } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2860 println("paramCls[pos] = \"int\";");
2861 println("paramObj[pos++] = &___paramCB" + i + ";");
2863 String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
2864 println("paramCls[pos] = \"" + prmTypeC + "\";");
2865 print("paramObj[pos++] = &");
2866 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
2875 * HELPER: writeStructRetMembersCplusStub() writes member parameters of struct for return statement
2877 private void writeStructRetMembersCplusStub(String simpleType, String retType) {
2879 // Get the struct declaration for this struct and generate initialization code
2880 StructDecl structDecl = getStructDecl(simpleType);
2881 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2882 List<String> members = structDecl.getMembers(simpleType);
2883 if (isArrayOrList(retType, retType)) { // An array or list
2884 println("for(int i = 0; i < retLen; i++) {");
2886 if (isArrayOrList(retType, retType)) { // An array or list
2887 for (int i = 0; i < members.size(); i++) {
2888 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2889 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
2890 println(" = retParam" + i + "[i];");
2893 } else { // Just one struct element
2894 for (int i = 0; i < members.size(); i++) {
2895 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2896 print("structRet." + getSimpleIdentifier(members.get(i)));
2897 println(" = retParam" + i + ";");
2900 println("return structRet;");
2905 * HELPER: writeStructReturnCplusStub() writes member parameters of struct for return statement
2907 private void writeStructReturnCplusStub(String simpleType, String retType, String method, InterfaceDecl intDecl) {
2909 // Minimum retLen is 1 if this is a single struct object
2910 println("int retLen = 0;");
2911 println("void* retLenObj = { &retLen };");
2912 // Handle the returned struct!!!
2913 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
2914 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retLenObj);");
2915 int numMem = getNumOfMembers(simpleType);
2916 println("int numRet = " + numMem + "*retLen;");
2917 println("string retCls[numRet];");
2918 println("void* retObj[numRet];");
2919 StructDecl structDecl = getStructDecl(simpleType);
2920 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2921 List<String> members = structDecl.getMembers(simpleType);
2923 if (isArrayOrList(retType, retType)) { // An array or list
2924 for (int i = 0; i < members.size(); i++) {
2925 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2926 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2927 println(getSimpleType(getEnumType(prmType)) + " retParam" + i + "[retLen];");
2929 } else { // Just one struct element
2930 for (int i = 0; i < members.size(); i++) {
2931 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2932 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2933 println(getSimpleType(getEnumType(prmType)) + " retParam" + i + ";");
2936 println("int retPos = 0;");
2937 // Get the struct declaration for this struct and generate initialization code
2938 if (isArrayOrList(retType, retType)) { // An array or list
2939 println("for(int i = 0; i < retLen; i++) {");
2940 for (int i = 0; i < members.size(); i++) {
2941 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2942 println("retCls[retPos] = \"" + prmTypeC + "\";");
2943 println("retObj[retPos++] = &retParam" + i + "[i];");
2946 } else { // Just one struct element
2947 for (int i = 0; i < members.size(); i++) {
2948 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2949 println("retCls[retPos] = \"" + prmTypeC + "\";");
2950 println("retObj[retPos++] = &retParam" + i + ";");
2953 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getStructObjects(retCls, numRet, retObj);");
2954 if (isArrayOrList(retType, retType)) { // An array or list
2955 println("vector<" + simpleType + "> structRet(retLen);");
2957 println(simpleType + " structRet;");
2958 writeStructRetMembersCplusStub(simpleType, retType);
2963 * HELPER: writeWaitForReturnValueCplus() writes the synchronization part for return values
2965 private void writeWaitForReturnValueCplus(String method, InterfaceDecl intDecl, String getReturnValue) {
2967 println("// Waiting for return value");
2968 int methodNumId = intDecl.getMethodNumId(method);
2969 println("while (!retValueReceived" + methodNumId + ");");
2970 println(getReturnValue);
2971 println("retValueReceived" + methodNumId + " = false;");
2972 println("didGetReturnBytes.exchange(true);\n");
2977 * HELPER: writeStdMethodBodyCplusStub() writes the standard method body in the stub class
2979 private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
2980 List<String> methPrmTypes, String method, Set<String> callbackType, boolean isCallbackMethod) {
2982 checkAndWriteStructSetupCplusStub(methParams, methPrmTypes, intDecl, method);
2983 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
2984 String retType = intDecl.getMethodType(method);
2985 println("string retType = \"" + checkAndGetCplusRetClsType(getStructType(getEnumType(retType))) + "\";");
2986 checkAndWriteEnumTypeCplusStub(methParams, methPrmTypes);
2987 // Generate array of parameter types
2988 if (isStructPresent(methParams, methPrmTypes)) {
2989 writeStructParamClassCplusStub(methParams, methPrmTypes, callbackType);
2991 println("int numParam = " + methParams.size() + ";");
2992 print("string paramCls[] = { ");
2993 for (int i = 0; i < methParams.size(); i++) {
2994 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2995 if (checkCallbackType(paramType, callbackType)) {
2998 String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
2999 print("\"" + paramTypeC + "\"");
3001 // Check if this is the last element (don't print a comma)
3002 if (i != methParams.size() - 1) {
3007 // Generate array of parameter objects
3008 print("void* paramObj[] = { ");
3009 for (int i = 0; i < methParams.size(); i++) {
3010 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3011 if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
3012 print("&___paramCB" + i);
3014 print("&" + getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
3015 // Check if this is the last element (don't print a comma)
3016 if (i != methParams.size() - 1) {
3022 // Check if this is "void"
3023 if (retType.equals("void")) {
3024 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
3025 } else { // We do have a return value
3026 // Generate array of parameter types
3027 if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
3028 writeStructReturnCplusStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl);
3030 // Check if the return value NONPRIMITIVES
3031 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) {
3032 checkAndWriteEnumRetTypeCplusStub(retType, method, intDecl);
3034 //if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
3035 if (isArrayOrList(retType,retType))
3036 println(checkAndGetCplusType(retType) + " retVal;");
3038 println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";");
3040 println("void* retObj = &retVal;");
3041 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
3042 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
3043 println("return retVal;");
3051 * HELPER: writePropertiesCplusPermission() writes the properties of the stub class
3053 private void writePropertiesCplusPermission(String intface) {
3055 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3056 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3057 String newIntface = intMeth.getKey();
3058 int newObjectId = getNewIntfaceObjectId(newIntface);
3059 println("static set<int> set" + newObjectId + "Allowed;");
3064 * HELPER: writePropertiesCplusStub() writes the properties of the stub class
3066 private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist,
3067 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3069 println("IoTRMIComm *rmiComm;");
3070 // Get the object Id
3071 Integer objId = mapIntfaceObjId.get(intface);
3072 println("int objectId = " + objId + ";");
3073 println("// Synchronization variables");
3074 for (String method : methods) {
3075 // Generate AtomicBooleans for methods that have return values
3076 String returnType = intDecl.getMethodType(method);
3077 int methodNumId = intDecl.getMethodNumId(method);
3078 if (!returnType.equals("void")) {
3079 println("bool retValueReceived" + methodNumId + " = false;");
3087 * HELPER: writeConstructorCplusStub() writes the constructor of the stub class
3089 private void writeConstructorCplusStub(String newStubClass, boolean callbackExist,
3090 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3092 println(newStubClass + "::" + newStubClass +
3093 "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult) {");
3094 println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev, _bResult);");
3095 // Register the AtomicBoolean variables
3096 for (String method : methods) {
3097 // Generate AtomicBooleans for methods that have return values
3098 String returnType = intDecl.getMethodType(method);
3099 int methodNumId = intDecl.getMethodNumId(method);
3100 if (!returnType.equals("void")) {
3101 println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");");
3104 println("IoTRMIUtil::mapStub->insert(make_pair(objectId, this));");
3110 * HELPER: writeCallbackConstructorCplusStub() writes the callback constructor of the stub class
3112 private void writeCallbackConstructorCplusStub(String newStubClass, boolean callbackExist,
3113 Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3115 println(newStubClass + "::" + newStubClass + "(IoTRMIComm* _rmiComm, int _objectId) {");
3116 println("rmiComm = _rmiComm;");
3117 println("objectId = _objectId;");
3118 // Register the AtomicBoolean variables
3119 for (String method : methods) {
3120 // Generate AtomicBooleans for methods that have return values
3121 String returnType = intDecl.getMethodType(method);
3122 int methodNumId = intDecl.getMethodNumId(method);
3123 if (!returnType.equals("void")) {
3124 println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");");
3132 * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
3134 private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
3136 println(newStubClass + "::~" + newStubClass + "() {");
3137 println("if (rmiComm != NULL) {");
3138 println("delete rmiComm;");
3139 println("rmiComm = NULL;");
3147 * generateCPlusStubClassesHpp() generate stubs based on the methods list in C++ (.hpp file)
3149 public void generateCPlusStubClassesHpp() throws IOException {
3151 // Create a new directory
3152 String path = createDirectories(dir, subdir);
3153 for (String intface : mapIntfacePTH.keySet()) {
3155 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3156 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3157 // Open a new file to write into
3158 String newIntface = intMeth.getKey();
3159 String newStubClass = newIntface + "_Stub";
3160 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
3161 pw = new PrintWriter(new BufferedWriter(fw));
3162 // Write file headers
3163 println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
3164 println("#define _" + newStubClass.toUpperCase() + "_HPP__");
3165 println("#include <iostream>");
3166 // Find out if there are callback objects
3167 Set<String> methods = intMeth.getValue();
3168 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3169 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3170 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3171 boolean callbackExist = !callbackClasses.isEmpty();
3172 println("#include <thread>");
3173 println("#include <mutex>");
3174 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
3175 printIncludeStatements(stdIncludeClasses); println("");
3176 println("#include \"" + newIntface + ".hpp\""); println("");
3177 println("using namespace std;"); println("");
3178 println("class " + newStubClass + " : public " + newIntface); println("{");
3179 println("private:\n");
3180 writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses, methods, intDecl);
3181 println("public:\n");
3182 // Add default constructor and destructor
3183 println(newStubClass + "();");
3185 println(newStubClass + "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult);");
3186 println(newStubClass + "(IoTRMIComm* _rmiComm, int _objectId);");
3187 println("~" + newStubClass + "();");
3189 writeMethodDeclCplusStub(methods, intDecl);
3190 print("}"); println(";");
3193 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
3200 * writeStubExternalCFunctions() generate external functions for .so file
3202 public void writeStubExternalCFunctions(String newStubClass) throws IOException {
3204 println("extern \"C\" void* create" + newStubClass + "(void** params) {");
3205 println("// Args: int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult");
3206 println("return new " + newStubClass + "(*((int*) params[0]), *((int*) params[1]), ((string*) params[2])->c_str(), " +
3207 "*((int*) params[3]), (bool*) params[4]);");
3209 println("extern \"C\" void destroy" + newStubClass + "(void* t) {");
3210 println(newStubClass + "* obj = (" + newStubClass + "*) t;");
3211 println("delete obj;");
3213 println("extern \"C\" void init" + newStubClass + "(void* t) {");
3219 * generateCPlusStubClassesCpp() generate stubs based on the methods list in C++ (.cpp file)
3221 public void generateCPlusStubClassesCpp() throws IOException {
3223 // Create a new directory
3224 String path = createDirectories(dir, subdir);
3225 for (String intface : mapIntfacePTH.keySet()) {
3227 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3228 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3229 // Open a new file to write into
3230 String newIntface = intMeth.getKey();
3231 String newStubClass = newIntface + "_Stub";
3232 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".cpp");
3233 pw = new PrintWriter(new BufferedWriter(fw));
3234 // Write file headers
3235 println("#include <iostream>");
3236 // Find out if there are callback objects
3237 Set<String> methods = intMeth.getValue();
3238 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3239 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3240 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3241 boolean callbackExist = !callbackClasses.isEmpty();
3242 println("#include \"" + newStubClass + ".hpp\""); println("");
3243 for(String str: callbackClasses) {
3244 if (intface.equals(mainClass))
3245 println("#include \"" + str + "_Skeleton.cpp\"\n");
3247 println("#include \"" + str + "_Skeleton.hpp\"\n");
3249 println("using namespace std;"); println("");
3250 // Add default constructor and destructor
3251 writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
3252 writeCallbackConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
3253 writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
3255 writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass);
3256 // Write external functions for .so file
3257 writeStubExternalCFunctions(newStubClass);
3258 // TODO: Remove this later
3259 if (intface.equals(mainClass)) {
3260 println("int main() {");
3261 println("return 0;");
3265 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".cpp...");
3272 * HELPER: writePropertiesCplusSkeleton() writes the properties of the skeleton class
3274 private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
3276 println(intface + " *mainObj;");
3277 println("IoTRMIComm *rmiComm;");
3278 println("char* methodBytes;");
3279 println("int methodLen;");
3280 Integer objId = mapIntfaceObjId.get(intface);
3281 println("int objectId = " + objId + ";");
3282 // Keep track of object Ids of all stubs registered to this interface
3283 writePropertiesCplusPermission(intface);
3284 println("// Synchronization variables");
3285 println("bool methodReceived = false;");
3286 println("bool didAlreadyInitWaitInvoke = false;");
3292 * HELPER: writeObjectIdCountInitializationCplus() writes the initialization of objIdCnt variable
3294 private void writeObjectIdCountInitializationCplus(String newSkelClass, boolean callbackExist) {
3297 println("int " + newSkelClass + "::objIdCnt = 0;");
3302 * HELPER: writePermissionInitializationCplus() writes the initialization of permission set
3304 private void writePermissionInitializationCplus(String intface, String newSkelClass, InterfaceDecl intDecl) {
3306 // Keep track of object Ids of all stubs registered to this interface
3307 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3308 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3309 String newIntface = intMeth.getKey();
3310 int newObjectId = getNewIntfaceObjectId(newIntface);
3311 print("set<int> " + newSkelClass + "::set" + newObjectId + "Allowed { ");
3312 Set<String> methodIds = intMeth.getValue();
3314 for (String methodId : methodIds) {
3315 int methodNumId = intDecl.getMethodNumId(methodId);
3316 print(Integer.toString(methodNumId));
3317 // Check if this is the last element (don't print a comma)
3318 if (i != methodIds.size() - 1) {
3329 * HELPER: writeStructPermissionCplusSkeleton() writes permission for struct helper
3331 private void writeStructPermissionCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
3333 // Use this set to handle two same methodIds
3334 for (String method : methods) {
3335 List<String> methParams = intDecl.getMethodParams(method);
3336 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3337 // Check for params with structs
3338 for (int i = 0; i < methParams.size(); i++) {
3339 String paramType = methPrmTypes.get(i);
3340 String param = methParams.get(i);
3341 String simpleType = getGenericType(paramType);
3342 if (isStructClass(simpleType)) {
3343 int methodNumId = intDecl.getMethodNumId(method);
3344 String helperMethod = methodNumId + "struct" + i;
3345 int helperMethodNumId = intDecl.getHelperMethodNumId(helperMethod);
3346 // Iterate over interfaces to give permissions to
3347 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3348 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3349 String newIntface = intMeth.getKey();
3350 int newObjectId = getNewIntfaceObjectId(newIntface);
3351 println("set" + newObjectId + "Allowed.insert(" + helperMethodNumId + ");");
3360 * HELPER: writeConstructorCplusSkeleton() writes the constructor of the skeleton class
3362 private void writeConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
3364 println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, int _portSend, int _portRecv) {");
3365 println("bool _bResult = false;");
3366 println("mainObj = _mainObj;");
3367 println("rmiComm = new IoTRMICommServer(_portSend, _portRecv, &_bResult);");
3368 println("IoTRMIUtil::mapSkel->insert(make_pair(_mainObj, this));");
3369 println("IoTRMIUtil::mapSkelId->insert(make_pair(_mainObj, objectId));");
3370 println("rmiComm->registerSkeleton(objectId, &methodReceived);");
3371 writeStructPermissionCplusSkeleton(methods, intDecl, intface);
3372 println("thread th1 (&" + newSkelClass + "::___waitRequestInvokeMethod, this, this);");
3373 println("th1.join();");
3379 * HELPER: writeCallbackConstructorCplusSkeleton() writes the callback constructor of the skeleton class
3381 private void writeCallbackConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
3383 println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, IoTRMIComm *_rmiComm, int _objectId) {");
3384 println("bool _bResult = false;");
3385 println("mainObj = _mainObj;");
3386 println("rmiComm = _rmiComm;");
3387 println("objectId = _objectId;");
3388 println("rmiComm->registerSkeleton(objectId, &methodReceived);");
3389 writeStructPermissionCplusSkeleton(methods, intDecl, intface);
3395 * HELPER: writeDeconstructorCplusSkeleton() writes the deconstructor of the skeleton class
3397 private void writeDeconstructorCplusSkeleton(String newSkelClass, boolean callbackExist, Set<String> callbackClasses) {
3399 println(newSkelClass + "::~" + newSkelClass + "() {");
3400 println("if (rmiComm != NULL) {");
3401 println("delete rmiComm;");
3402 println("rmiComm = NULL;");
3410 * HELPER: writeStdMethodBodyCplusSkeleton() writes the standard method body in the skeleton class
3412 private void writeStdMethodBodyCplusSkeleton(List<String> methParams, String methodId, String methodType) {
3414 if (methodType.equals("void"))
3415 print("mainObj->" + methodId + "(");
3417 print("return mainObj->" + methodId + "(");
3418 for (int i = 0; i < methParams.size(); i++) {
3420 print(getSimpleIdentifier(methParams.get(i)));
3421 // Check if this is the last element (don't print a comma)
3422 if (i != methParams.size() - 1) {
3431 * HELPER: writeMethodDeclCplusSkeleton() writes the method declaration of the skeleton class
3433 private void writeMethodDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
3434 Set<String> callbackClasses) {
3436 for (String method : methods) {
3438 List<String> methParams = intDecl.getMethodParams(method);
3439 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3440 String methodId = intDecl.getMethodId(method);
3441 String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
3442 print(methodType + " " + methodId + "(");
3443 boolean isCallbackMethod = false;
3444 String callbackType = null;
3445 for (int i = 0; i < methParams.size(); i++) {
3447 String origParamType = methPrmTypes.get(i);
3448 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
3449 isCallbackMethod = true;
3450 callbackType = origParamType;
3452 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
3453 String methPrmType = checkAndGetCplusType(paramType);
3454 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3455 print(methParamComplete);
3456 // Check if this is the last element (don't print a comma)
3457 if (i != methParams.size() - 1) {
3467 * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class
3469 private void writeMethodCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String newSkelClass) {
3471 for (String method : methods) {
3473 List<String> methParams = intDecl.getMethodParams(method);
3474 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3475 String methodId = intDecl.getMethodId(method);
3476 String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
3477 print(methodType + " " + newSkelClass + "::" + methodId + "(");
3478 for (int i = 0; i < methParams.size(); i++) {
3480 String origParamType = methPrmTypes.get(i);
3481 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
3482 String methPrmType = checkAndGetCplusType(paramType);
3483 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3484 print(methParamComplete);
3485 // Check if this is the last element (don't print a comma)
3486 if (i != methParams.size() - 1) {
3491 // Now, write the body of skeleton!
3492 writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method));
3499 * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable
3501 private void writeCallbackCplusNumStubs(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
3503 for (int i = 0; i < methParams.size(); i++) {
3504 String paramType = methPrmTypes.get(i);
3505 String param = methParams.get(i);
3506 if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
3507 println("vector<int> numStubIdArray" + i + ";");
3513 * HELPER: writeCallbackInstantiationCplusStubGeneration() writes the instantiation of callback stubs
3515 private void writeCallbackInstantiationCplusStubGeneration(String exchParamType, int counter) {
3517 println(exchParamType + "* newStub" + counter + " = NULL;");
3518 println("auto it" + counter + " = IoTRMIUtil::mapStub->find(objIdRecv" + counter + ");");
3519 println("if (it" + counter + " == IoTRMIUtil::mapStub->end()) {");
3520 println("newStub" + counter + " = new " + exchParamType + "_Stub(rmiComm, objIdRecv" + counter + ");");
3521 println("IoTRMIUtil::mapStub->insert(make_pair(objIdRecv" + counter + ", newStub" + counter + "));");
3522 println("rmiComm->setObjectIdCounter(objIdRecv" + counter + ");");
3523 println("rmiComm->decrementObjectIdCounter();");
3526 println("newStub" + counter + " = (" + exchParamType + "_Stub*) it" + counter + "->second;");
3532 * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part
3534 private void writeCallbackCplusStubGeneration(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
3536 // Iterate over callback objects
3537 for (int i = 0; i < methParams.size(); i++) {
3538 String paramType = methPrmTypes.get(i);
3539 String param = methParams.get(i);
3540 // Generate a loop if needed
3541 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
3542 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
3543 if (isArrayOrList(paramType, param)) {
3544 println("vector<" + exchParamType + "*> stub" + i + ";");
3545 println("for (int i = 0; i < numStubIdArray" + i + ".size(); i++) {");
3546 println("int objIdRecv" + i + " = numStubIdArray" + i + "[i];");
3547 writeCallbackInstantiationCplusStubGeneration(exchParamType, i);
3548 println("stub" + i + ".push_back(newStub" + i + ");");
3551 println("int objIdRecv" + i + " = numStubIdArray" + i + "[0];");
3552 writeCallbackInstantiationCplusStubGeneration(exchParamType, i);
3553 println(exchParamType + "* stub" + i + " = newStub" + i + ";");
3561 * HELPER: checkAndWriteEnumTypeCplusSkeleton() writes the enum type (convert from enum to int)
3563 private void checkAndWriteEnumTypeCplusSkeleton(List<String> methParams, List<String> methPrmTypes) {
3565 // Iterate and find enum declarations
3566 for (int i = 0; i < methParams.size(); i++) {
3567 String paramType = methPrmTypes.get(i);
3568 String param = methParams.get(i);
3569 String simpleType = getGenericType(paramType);
3570 if (isEnumClass(simpleType)) {
3571 // Check if this is enum type
3572 if (isArrayOrList(paramType, param)) { // An array
3573 println("int len" + i + " = paramEnumInt" + i + ".size();");
3574 println("vector<" + simpleType + "> paramEnum" + i + "(len" + i + ");");
3575 println("for (int i=0; i < len" + i + "; i++) {");
3576 println("paramEnum" + i + "[i] = (" + simpleType + ") paramEnumInt" + i + "[i];");
3578 } else { // Just one element
3579 println(simpleType + " paramEnum" + i + ";");
3580 println("paramEnum" + i + " = (" + simpleType + ") paramEnumInt" + i + "[0];");
3588 * HELPER: checkAndWriteEnumRetTypeCplusSkeleton() writes the enum return type (convert from enum to int)
3590 private void checkAndWriteEnumRetTypeCplusSkeleton(String retType) {
3592 // Strips off array "[]" for return type
3593 String pureType = getSimpleArrayType(getGenericType(retType));
3594 // Take the inner type of generic
3595 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
3596 pureType = getGenericType(retType);
3597 if (isEnumClass(pureType)) {
3598 // Check if this is enum type
3600 if (isArrayOrList(retType, retType)) { // An array
3601 println("int retLen = retEnum.size();");
3602 println("vector<int> retEnumInt(retLen);");
3603 println("for (int i=0; i < retLen; i++) {");
3604 println("retEnumInt[i] = (int) retEnum[i];");
3606 } else { // Just one element
3607 println("vector<int> retEnumInt(1);");
3608 println("retEnumInt[0] = (int) retEnum;");
3615 * HELPER: writeMethodInputParameters() writes the parameter variables for C++ skeleton
3617 private void writeMethodInputParameters(List<String> methParams, List<String> methPrmTypes,
3618 Set<String> callbackClasses, String methodId) {
3620 print(methodId + "(");
3621 for (int i = 0; i < methParams.size(); i++) {
3622 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3623 if (callbackClasses.contains(paramType))
3625 else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3626 print("paramEnum" + i);
3627 else if (isStructClass(getGenericType(paramType))) // Struct type
3628 print("paramStruct" + i);
3630 print(getSimpleIdentifier(methParams.get(i)));
3631 if (i != methParams.size() - 1) {
3640 * HELPER: writeMethodHelperReturnCplusSkeleton() writes the return statement part in skeleton
3642 private void writeMethodHelperReturnCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3643 List<String> methPrmTypes, String method, boolean isCallbackMethod, Set<String> callbackType,
3644 String methodId, Set<String> callbackClasses) {
3646 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
3647 if (isCallbackMethod)
3648 writeCallbackCplusStubGeneration(methParams, methPrmTypes, callbackType);
3649 checkAndWriteEnumTypeCplusSkeleton(methParams, methPrmTypes);
3650 writeStructMembersInitCplusSkeleton(intDecl, methParams, methPrmTypes, method);
3651 // Check if this is "void"
3652 String retType = intDecl.getMethodType(method);
3653 // Check if this is "void"
3654 if (retType.equals("void")) {
3655 writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3656 } else { // We do have a return value
3657 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
3658 print(checkAndGetCplusType(retType) + " retEnum = ");
3659 else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3660 print(checkAndGetCplusType(retType) + " retStruct = ");
3662 print(checkAndGetCplusType(retType) + " retVal = ");
3663 writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3664 checkAndWriteEnumRetTypeCplusSkeleton(retType);
3665 if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3666 writeStructReturnCplusSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
3667 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
3668 println("void* retObj = &retEnumInt;");
3670 if (!isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3671 println("void* retObj = &retVal;");
3672 String retTypeC = checkAndGetCplusType(retType);
3673 if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3674 println("rmiComm->sendReturnObj(retObj, retCls, numRetObj, localMethodBytes);");
3676 println("rmiComm->sendReturnObj(retObj, \"" + checkAndGetCplusRetClsType(getEnumType(retType)) + "\", localMethodBytes);");
3682 * HELPER: writeStdMethodHelperBodyCplusSkeleton() writes the standard method body helper in the skeleton class
3684 private void writeStdMethodHelperBodyCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3685 List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3687 // Generate array of parameter types
3688 boolean isCallbackMethod = false;
3689 Set<String> callbackType = new HashSet<String>();
3690 print("string paramCls[] = { ");
3691 for (int i = 0; i < methParams.size(); i++) {
3692 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3693 if (callbackClasses.contains(paramType)) {
3694 isCallbackMethod = true;
3695 callbackType.add(paramType);
3697 } else { // Generate normal classes if it's not a callback object
3698 String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3699 print("\"" + paramTypeC + "\"");
3701 if (i != methParams.size() - 1) {
3706 println("int numParam = " + methParams.size() + ";");
3707 if (isCallbackMethod)
3708 writeCallbackCplusNumStubs(methParams, methPrmTypes, callbackType);
3709 // Generate parameters
3710 for (int i = 0; i < methParams.size(); i++) {
3711 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3712 if (!callbackClasses.contains(paramType)) {
3713 String methParamType = methPrmTypes.get(i);
3714 if (isEnumClass(getSimpleArrayType(getGenericType(methParamType)))) {
3715 // Check if this is enum type
3716 println("vector<int> paramEnumInt" + i + ";");
3718 String methPrmType = checkAndGetCplusType(methParamType);
3719 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3720 println(methParamComplete + ";");
3724 // Generate array of parameter objects
3725 print("void* paramObj[] = { ");
3726 for (int i = 0; i < methParams.size(); i++) {
3727 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3728 if (callbackClasses.contains(paramType))
3729 print("&numStubIdArray" + i);
3730 else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3731 print("¶mEnumInt" + i);
3733 print("&" + getSimpleIdentifier(methParams.get(i)));
3734 if (i != methParams.size() - 1) {
3739 // Write the return value part
3740 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
3741 callbackType, methodId, callbackClasses);
3746 * HELPER: writeStructMembersCplusSkeleton() writes member parameters of struct
3748 private void writeStructMembersCplusSkeleton(String simpleType, String paramType,
3749 String param, String method, InterfaceDecl intDecl, int iVar) {
3751 // Get the struct declaration for this struct and generate initialization code
3752 StructDecl structDecl = getStructDecl(simpleType);
3753 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3754 List<String> members = structDecl.getMembers(simpleType);
3755 int methodNumId = intDecl.getMethodNumId(method);
3756 String counter = "struct" + methodNumId + "Size" + iVar;
3758 if (isArrayOrList(paramType, param)) { // An array or list
3759 for (int i = 0; i < members.size(); i++) {
3760 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3761 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3762 println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + "[" + counter + "];");
3764 } else { // Just one struct element
3765 for (int i = 0; i < members.size(); i++) {
3766 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3767 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3768 println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + ";");
3771 if (isArrayOrList(paramType, param)) { // An array or list
3772 println("for(int i = 0; i < " + counter + "; i++) {");
3774 if (isArrayOrList(paramType, param)) { // An array or list
3775 for (int i = 0; i < members.size(); i++) {
3776 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3777 println("paramCls[pos] = \"" + prmTypeC + "\";");
3778 println("paramObj[pos++] = ¶m" + iVar + i + "[i];");
3781 } else { // Just one struct element
3782 for (int i = 0; i < members.size(); i++) {
3783 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3784 println("paramCls[pos] = \"" + prmTypeC + "\";");
3785 println("paramObj[pos++] = ¶m" + iVar + i + ";");
3792 * HELPER: writeStructMembersInitCplusSkeleton() writes member parameters initialization of struct
3794 private void writeStructMembersInitCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3795 List<String> methPrmTypes, String method) {
3797 for (int i = 0; i < methParams.size(); i++) {
3798 String paramType = methPrmTypes.get(i);
3799 String param = methParams.get(i);
3800 String simpleType = getGenericType(paramType);
3801 if (isStructClass(simpleType)) {
3802 int methodNumId = intDecl.getMethodNumId(method);
3803 String counter = "struct" + methodNumId + "Size" + i;
3805 if (isArrayOrList(paramType, param)) { // An array or list
3806 println("vector<" + simpleType + "> paramStruct" + i + "(" + counter + ");");
3808 println(simpleType + " paramStruct" + i + ";");
3809 // Initialize members
3810 StructDecl structDecl = getStructDecl(simpleType);
3811 List<String> members = structDecl.getMembers(simpleType);
3812 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3813 if (isArrayOrList(paramType, param)) { // An array or list
3814 println("for(int i = 0; i < " + counter + "; i++) {");
3815 for (int j = 0; j < members.size(); j++) {
3816 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
3817 println(" = param" + i + j + "[i];");
3820 } else { // Just one struct element
3821 for (int j = 0; j < members.size(); j++) {
3822 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
3823 println(" = param" + i + j + ";");
3832 * HELPER: writeStructReturnCplusSkeleton() writes parameters of struct for return statement
3834 private void writeStructReturnCplusSkeleton(String simpleType, String retType) {
3836 // Minimum retLen is 1 if this is a single struct object
3837 if (isArrayOrList(retType, retType))
3838 println("int retLen = retStruct.size();");
3839 else // Just single struct object
3840 println("int retLen = 1;");
3841 println("void* retLenObj = &retLen;");
3842 println("rmiComm->sendReturnObj(retLenObj, \"int\", localMethodBytes);");
3843 int numMem = getNumOfMembers(simpleType);
3844 println("int numRetObj = " + numMem + "*retLen;");
3845 println("string retCls[numRetObj];");
3846 println("void* retObj[numRetObj];");
3847 println("int retPos = 0;");
3848 // Get the struct declaration for this struct and generate initialization code
3849 StructDecl structDecl = getStructDecl(simpleType);
3850 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3851 List<String> members = structDecl.getMembers(simpleType);
3852 if (isArrayOrList(retType, retType)) { // An array or list
3853 println("for(int i = 0; i < retLen; i++) {");
3854 for (int i = 0; i < members.size(); i++) {
3855 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3856 println("retCls[retPos] = \"" + prmTypeC + "\";");
3857 print("retObj[retPos++] = &retStruct[i].");
3858 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3862 } else { // Just one struct element
3863 for (int i = 0; i < members.size(); i++) {
3864 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3865 println("retCls[retPos] = \"" + prmTypeC + "\";");
3866 print("retObj[retPos++] = &retStruct.");
3867 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3876 * HELPER: writeMethodHelperStructCplusSkeleton() writes the struct in skeleton
3878 private void writeMethodHelperStructCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3879 List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3881 // Generate array of parameter objects
3882 boolean isCallbackMethod = false;
3883 Set<String> callbackType = new HashSet<String>();
3884 print("int numParam = ");
3885 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
3887 println("string paramCls[numParam];");
3888 println("void* paramObj[numParam];");
3889 println("int pos = 0;");
3890 // Iterate again over the parameters
3891 for (int i = 0; i < methParams.size(); i++) {
3892 String paramType = methPrmTypes.get(i);
3893 String param = methParams.get(i);
3894 String simpleType = getGenericType(paramType);
3895 if (isStructClass(simpleType)) {
3896 writeStructMembersCplusSkeleton(simpleType, paramType, param, method, intDecl, i);
3898 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
3899 if (callbackClasses.contains(prmType)) {
3900 isCallbackMethod = true;
3901 callbackType.add(prmType);
3902 println("vector<int> numStubIdArray" + i + ";");
3903 println("paramCls[pos] = \"int*\";");
3904 println("paramObj[pos++] = &numStubIdArray" + i + ";");
3905 } else { // Generate normal classes if it's not a callback object
3906 String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
3907 if (isEnumClass(getGenericType(paramTypeC))) { // Check if this is enum type
3908 println("vector<int> paramEnumInt" + i + ";");
3910 String methParamComplete = checkAndGetCplusArray(paramTypeC, methParams.get(i));
3911 println(methParamComplete + ";");
3913 String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3914 println("paramCls[pos] = \"" + prmTypeC + "\";");
3915 if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
3916 println("paramObj[pos++] = ¶mEnumInt" + i + ";");
3918 println("paramObj[pos++] = &" + getSimpleIdentifier(methParams.get(i)) + ";");
3922 // Write the return value part
3923 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
3924 callbackType, methodId, callbackClasses);
3929 * HELPER: writeMethodHelperDeclCplusSkeleton() writes the method helper declarations of the skeleton class
3931 private void writeMethodHelperDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String newSkelClass) {
3933 // Use this set to handle two same methodIds
3934 Set<String> uniqueMethodIds = new HashSet<String>();
3935 for (String method : methods) {
3937 List<String> methParams = intDecl.getMethodParams(method);
3938 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3939 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
3940 String methodId = intDecl.getMethodId(method);
3942 String helperMethod = methodId;
3943 if (uniqueMethodIds.contains(methodId))
3944 helperMethod = helperMethod + intDecl.getMethodNumId(method);
3946 uniqueMethodIds.add(methodId);
3947 String retType = intDecl.getMethodType(method);
3948 print(helperMethod + "(");
3949 boolean begin = true;
3950 for (int i = 0; i < methParams.size(); i++) { // Print size variables
3951 String paramType = methPrmTypes.get(i);
3952 String param = methParams.get(i);
3953 String simpleType = getGenericType(paramType);
3954 if (isStructClass(simpleType)) {
3955 if (!begin) // Generate comma for not the beginning variable
3959 int methodNumId = intDecl.getMethodNumId(method);
3960 print("int struct" + methodNumId + "Size" + i);
3963 println(", " + newSkelClass + "* skel);");
3965 String methodId = intDecl.getMethodId(method);
3967 String helperMethod = methodId;
3968 if (uniqueMethodIds.contains(methodId))
3969 helperMethod = helperMethod + intDecl.getMethodNumId(method);
3971 uniqueMethodIds.add(methodId);
3972 // Check if this is "void"
3973 String retType = intDecl.getMethodType(method);
3974 println(helperMethod + "(" + newSkelClass + "* skel);");
3977 // Write method helper for structs
3978 writeMethodHelperStructDeclSetupCplusSkeleton(methods, intDecl, newSkelClass);
3983 * HELPER: writeMethodHelperStructDeclSetupCplusSkeleton() writes the struct method helper declaration in skeleton class
3985 private void writeMethodHelperStructDeclSetupCplusSkeleton(Collection<String> methods,
3986 InterfaceDecl intDecl, String newSkelClass) {
3988 // Use this set to handle two same methodIds
3989 for (String method : methods) {
3991 List<String> methParams = intDecl.getMethodParams(method);
3992 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3993 // Check for params with structs
3994 for (int i = 0; i < methParams.size(); i++) {
3995 String paramType = methPrmTypes.get(i);
3996 String param = methParams.get(i);
3997 String simpleType = getGenericType(paramType);
3998 if (isStructClass(simpleType)) {
3999 int methodNumId = intDecl.getMethodNumId(method);
4001 String helperMethod = methodNumId + "struct" + i;
4002 println(helperMethod + "(" + newSkelClass + "* skel);");
4010 * HELPER: writeMethodBytesCopy() writes the methodBytes copy part in C++ skeleton
4012 private void writeMethodBytesCopy() {
4014 println("char* localMethodBytes = new char[methodLen];");
4015 println("memcpy(localMethodBytes, skel->methodBytes, methodLen);");
4016 println("didGetMethodBytes.exchange(true);");
4021 * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class
4023 private void writeMethodHelperCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
4024 Set<String> callbackClasses, String newSkelClass) {
4026 // Use this set to handle two same methodIds
4027 Set<String> uniqueMethodIds = new HashSet<String>();
4028 for (String method : methods) {
4030 List<String> methParams = intDecl.getMethodParams(method);
4031 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4032 if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
4033 String methodId = intDecl.getMethodId(method);
4034 print("void " + newSkelClass + "::___");
4035 String helperMethod = methodId;
4036 if (uniqueMethodIds.contains(methodId))
4037 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4039 uniqueMethodIds.add(methodId);
4040 String retType = intDecl.getMethodType(method);
4041 print(helperMethod + "(");
4042 boolean begin = true;
4043 for (int i = 0; i < methParams.size(); i++) { // Print size variables
4044 String paramType = methPrmTypes.get(i);
4045 String param = methParams.get(i);
4046 String simpleType = getGenericType(paramType);
4047 if (isStructClass(simpleType)) {
4048 if (!begin) // Generate comma for not the beginning variable
4052 int methodNumId = intDecl.getMethodNumId(method);
4053 print("int struct" + methodNumId + "Size" + i);
4056 println(", " + newSkelClass + "* skel) {");
4057 writeMethodBytesCopy();
4058 writeMethodHelperStructCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4059 println("delete[] localMethodBytes;");
4062 String methodId = intDecl.getMethodId(method);
4063 print("void " + newSkelClass + "::___");
4064 String helperMethod = methodId;
4065 if (uniqueMethodIds.contains(methodId))
4066 helperMethod = helperMethod + intDecl.getMethodNumId(method);
4068 uniqueMethodIds.add(methodId);
4069 // Check if this is "void"
4070 String retType = intDecl.getMethodType(method);
4071 println(helperMethod + "(" + newSkelClass + "* skel) {");
4072 writeMethodBytesCopy();
4073 // Now, write the helper body of skeleton!
4074 writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4075 println("delete[] localMethodBytes;");
4079 // Write method helper for structs
4080 writeMethodHelperStructSetupCplusSkeleton(methods, intDecl, newSkelClass);
4085 * HELPER: writeMethodHelperStructSetupCplusSkeleton() writes the method helper of struct in skeleton class
4087 private void writeMethodHelperStructSetupCplusSkeleton(Collection<String> methods,
4088 InterfaceDecl intDecl, String newSkelClass) {
4090 // Use this set to handle two same methodIds
4091 for (String method : methods) {
4093 List<String> methParams = intDecl.getMethodParams(method);
4094 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4095 // Check for params with structs
4096 for (int i = 0; i < methParams.size(); i++) {
4097 String paramType = methPrmTypes.get(i);
4098 String param = methParams.get(i);
4099 String simpleType = getGenericType(paramType);
4100 if (isStructClass(simpleType)) {
4101 int methodNumId = intDecl.getMethodNumId(method);
4102 print("int " + newSkelClass + "::___");
4103 String helperMethod = methodNumId + "struct" + i;
4104 println(helperMethod + "(" + newSkelClass + "* skel) {");
4105 // Now, write the helper body of skeleton!
4106 writeMethodBytesCopy();
4107 println("string paramCls[] = { \"int\" };");
4108 println("int numParam = 1;");
4109 println("int param0 = 0;");
4110 println("void* paramObj[] = { ¶m0 };");
4111 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
4112 println("return param0;");
4113 println("delete[] localMethodBytes;");
4122 * HELPER: writeMethodHelperStructSetupCplusCallbackSkeleton() writes the method helper of struct in skeleton class
4124 private void writeMethodHelperStructSetupCplusCallbackSkeleton(Collection<String> methods,
4125 InterfaceDecl intDecl) {
4127 // Use this set to handle two same methodIds
4128 for (String method : methods) {
4130 List<String> methParams = intDecl.getMethodParams(method);
4131 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4132 // Check for params with structs
4133 for (int i = 0; i < methParams.size(); i++) {
4134 String paramType = methPrmTypes.get(i);
4135 String param = methParams.get(i);
4136 String simpleType = getGenericType(paramType);
4137 if (isStructClass(simpleType)) {
4138 int methodNumId = intDecl.getMethodNumId(method);
4140 String helperMethod = methodNumId + "struct" + i;
4141 println(helperMethod + "(IoTRMIObject* rmiObj) {");
4142 // Now, write the helper body of skeleton!
4143 println("string paramCls[] = { \"int\" };");
4144 println("int numParam = 1;");
4145 println("int param0 = 0;");
4146 println("void* paramObj[] = { ¶m0 };");
4147 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
4148 println("return param0;");
4157 * HELPER: writeCplusMethodPermission() writes permission checks in skeleton
4159 private void writeCplusMethodPermission(String intface) {
4161 // Get all the different stubs
4162 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
4163 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
4164 String newIntface = intMeth.getKey();
4165 int newObjectId = getNewIntfaceObjectId(newIntface);
4166 println("if (_objectId == objectId) {");
4167 println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
4168 println("cerr << \"Object with object Id: \" << _objectId << \" is not allowed to access method: \" << methodId << endl;");
4173 println("continue;");
4180 * HELPER: writeCplusWaitRequestInvokeMethod() writes the main loop of the skeleton class
4182 private void writeCplusWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl,
4183 boolean callbackExist, String intface, String newSkelClass) {
4185 // Use this set to handle two same methodIds
4186 Set<String> uniqueMethodIds = new HashSet<String>();
4187 println("void " + newSkelClass + "::___waitRequestInvokeMethod(" + newSkelClass + "* skel) {");
4188 // Write variables here if we have callbacks or enums or structs
4189 writeCountVarStructSkeleton(methods, intDecl);
4190 println("skel->didAlreadyInitWaitInvoke = true;");
4191 println("while (true) {");
4192 println("if (!methodReceived) {");
4193 println("continue;");
4195 println("skel->methodBytes = skel->rmiComm->getMethodBytes();");
4196 println("skel->methodLen = skel->rmiComm->getMethodLength();");
4197 println("methodReceived = false;");
4198 println("int _objectId = skel->rmiComm->getObjectId(skel->methodBytes);");
4199 println("int methodId = skel->rmiComm->getMethodId(skel->methodBytes);");
4200 // Generate permission check
4201 writeCplusMethodPermission(intface);
4202 println("switch (methodId) {");
4203 // Print methods and method Ids
4204 for (String method : methods) {
4205 String methodId = intDecl.getMethodId(method);
4206 int methodNumId = intDecl.getMethodNumId(method);
4207 println("case " + methodNumId + ": {");
4208 print("thread th" + methodNumId + " (&" + newSkelClass + "::___");
4209 String helperMethod = methodId;
4210 if (uniqueMethodIds.contains(methodId))
4211 helperMethod = helperMethod + methodNumId;
4213 uniqueMethodIds.add(methodId);
4214 print(helperMethod + ", skel, ");
4215 boolean structExists = writeInputCountVarStructCplusSkeleton(method, intDecl);
4219 println("th" + methodNumId + ".detach(); break;");
4222 writeMethodCallStructCplusSkeleton(methods, intDecl);
4223 println("default: ");
4224 println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;");
4233 * generateCplusSkeletonClassHpp() generate skeletons based on the methods list in C++ (.hpp file)
4235 public void generateCplusSkeletonClassHpp() throws IOException {
4237 // Create a new directory
4238 String path = createDirectories(dir, subdir);
4239 for (String intface : mapIntfacePTH.keySet()) {
4240 // Open a new file to write into
4241 String newSkelClass = intface + "_Skeleton";
4242 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
4243 pw = new PrintWriter(new BufferedWriter(fw));
4244 // Write file headers
4245 println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
4246 println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
4247 println("#include <iostream>");
4248 println("#include \"" + intface + ".hpp\"\n");
4249 // Pass in set of methods and get import classes
4250 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4251 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4252 List<String> methods = intDecl.getMethods();
4253 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
4254 printIncludeStatements(stdIncludeClasses); println("");
4255 println("using namespace std;\n");
4256 // Find out if there are callback objects
4257 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4258 boolean callbackExist = !callbackClasses.isEmpty();
4259 // Write class header
4260 println("class " + newSkelClass + " : public " + intface); println("{");
4261 println("private:\n");
4263 writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses);
4264 println("public:\n");
4265 // Write constructors
4266 println(newSkelClass + "();");
4267 println(newSkelClass + "(" + intface + "*_mainObj, int _portSend, int _portRecv);");
4268 println(newSkelClass + "(" + intface + "*_mainObj, IoTRMIComm *rmiComm, int _objectId);");
4269 // Write deconstructor
4270 println("~" + newSkelClass + "();");
4271 // Write method declarations
4272 println("bool didInitWaitInvoke();");
4273 writeMethodDeclCplusSkeleton(methods, intDecl, callbackClasses);
4274 // Write method helper declarations
4275 writeMethodHelperDeclCplusSkeleton(methods, intDecl, newSkelClass);
4276 // Write waitRequestInvokeMethod() declaration - main loop
4277 println("void ___waitRequestInvokeMethod(" + newSkelClass + "* skel);");
4279 writePermissionInitializationCplus(intface, newSkelClass, intDecl);
4282 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
4287 * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke
4289 private void writeReturnDidAlreadyInitWaitInvoke(String newSkelClass) {
4291 println("bool " + newSkelClass + "::didInitWaitInvoke() {");
4292 println("return didAlreadyInitWaitInvoke;");
4298 * writeSkelExternalCFunctions() generate external functions for .so file
4300 public void writeSkelExternalCFunctions(String newSkelClass, String intface) throws IOException {
4302 println("extern \"C\" void* create" + newSkelClass + "(void** params) {");
4303 println("// Args: *_mainObj, int _portSend, int _portRecv");
4304 println("return new " + newSkelClass + "((" + intface + "*) params[0], *((int*) params[1]), *((int*) params[2]));");
4306 println("extern \"C\" void destroy" + newSkelClass + "(void* t) {");
4307 println(newSkelClass + "* obj = (" + newSkelClass + "*) t;");
4308 println("delete obj;");
4310 println("extern \"C\" void init" + newSkelClass + "(void* t) {");
4316 * generateCplusSkeletonClassCpp() generate skeletons based on the methods list in C++ (.cpp file)
4318 public void generateCplusSkeletonClassCpp() throws IOException {
4320 // Create a new directory
4321 String path = createDirectories(dir, subdir);
4322 for (String intface : mapIntfacePTH.keySet()) {
4323 // Open a new file to write into
4324 String newSkelClass = intface + "_Skeleton";
4325 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".cpp");
4326 pw = new PrintWriter(new BufferedWriter(fw));
4327 // Write file headers
4328 println("#include <iostream>");
4329 println("#include \"" + newSkelClass + ".hpp\"\n");
4330 // Pass in set of methods and get import classes
4331 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4332 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4333 List<String> methods = intDecl.getMethods();
4334 // Find out if there are callback objects
4335 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4336 boolean callbackExist = !callbackClasses.isEmpty();
4337 for(String str: callbackClasses) {
4338 if (intface.equals(mainClass))
4339 println("#include \"" + getStubInterface(str) + "_Stub.cpp\"\n");
4341 println("#include \"" + getStubInterface(str) + "_Stub.hpp\"\n");
4343 println("using namespace std;\n");
4344 // Write constructor
4345 writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
4346 // Write callback constructor
4347 writeCallbackConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
4348 // Write deconstructor
4349 writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses);
4350 // Write didInitWaitInvoke() to return bool
4351 writeReturnDidAlreadyInitWaitInvoke(newSkelClass);
4353 writeMethodCplusSkeleton(methods, intDecl, newSkelClass);
4354 // Write method helper
4355 writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass);
4356 // Write waitRequestInvokeMethod() - main loop
4357 writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface, newSkelClass);
4358 // Write external functions for .so file
4359 writeSkelExternalCFunctions(newSkelClass, intface);
4360 // TODO: Remove this later
4361 if (intface.equals(mainClass)) {
4362 println("int main() {");
4363 println("return 0;");
4367 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".cpp...");
4373 * generateInitializer() generate initializer based on type
4375 public String generateCplusInitializer(String type) {
4377 // Generate dummy returns for now
4378 if (type.equals("short")||
4379 type.equals("int") ||
4380 type.equals("long") ||
4381 type.equals("float")||
4382 type.equals("double")) {
4385 } else if ( type.equals("String") ||
4386 type.equals("string")) {
4389 } else if ( type.equals("char") ||
4390 type.equals("byte")) {
4393 } else if ( type.equals("boolean")) {
4403 * setDirectory() sets a new directory for stub files
4405 public void setDirectory(String _subdir) {
4412 * printUsage() prints the usage of this compiler
4414 public static void printUsage() {
4416 System.out.println();
4417 System.out.println("Vigilia interface and stub compiler version 1.0");
4418 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
4419 System.out.println("All rights reserved.");
4420 System.out.println("Usage:");
4421 System.out.println("\tjava IoTCompiler -help / --help / -h\n");
4422 System.out.println("\t\tDisplay this help texts\n\n");
4423 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
4424 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
4425 System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
4426 System.out.println("Options:");
4427 System.out.println("\t-cont\t<controller-class>\tSpecify controller class name");
4428 System.out.println("\t-drv\t<driver-class>\t\tSpecify driver class name");
4429 System.out.println("\t-cplus\t<directory>\t\tGenerate C++ stub files");
4430 System.out.println("\t-java\t<directory>\t\tGenerate Java stub files\n");
4431 System.out.println("\t\tNote: The options -cont and -drv have to be defined before -cplus and -java");
4432 System.out.println();
4437 * parseFile() prepares Lexer and Parser objects, then parses the file
4439 public static ParseNode parseFile(String file) {
4441 ParseNode pn = null;
4443 ComplexSymbolFactory csf = new ComplexSymbolFactory();
4444 ScannerBuffer lexer =
4445 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(file)),csf));
4446 Parser parse = new Parser(lexer,csf);
4447 pn = (ParseNode) parse.parse().value;
4448 } catch (Exception e) {
4449 e.printStackTrace();
4450 throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file + "\n");
4458 * Basic helper functions
4461 boolean newline=true;
4464 private void print(String str) {
4467 if (str.equals("}"))
4469 for(int i=0; i<tab; i++)
4479 * This function converts Java to C++ type for compilation
4481 private String convertType(String type) {
4483 if (mapPrimitives.containsKey(type))
4484 return mapPrimitives.get(type);
4491 * A collection of methods with print-to-file functionality
4493 private void println(String str) {
4496 if (str.contains("}") && !str.contains("{"))
4498 for(int i=0; i<tab; i++)
4507 private void updatetabbing(String str) {
4509 tablevel+=count(str,'{')-count(str,'}');
4513 private int count(String str, char key) {
4514 char[] array = str.toCharArray();
4516 for(int i=0; i<array.length; i++) {
4517 if (array[i] == key)
4524 private void createDirectory(String dirName) {
4526 File file = new File(dirName);
4527 if (!file.exists()) {
4529 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
4531 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
4534 System.out.println("IoTCompiler: Directory " + dirName + " exists...");
4539 // Create a directory and possibly a sub directory
4540 private String createDirectories(String dir, String subdir) {
4543 createDirectory(path);
4544 if (subdir != null) {
4545 path = path + "/" + subdir;
4546 createDirectory(path);
4552 // Inserting array members into a Map object
4553 // that maps arrKey to arrVal objects
4554 private void arraysToMap(Map map, Object[] arrKey, Object[] arrVal) {
4556 for(int i = 0; i < arrKey.length; i++) {
4558 map.put(arrKey[i], arrVal[i]);
4563 // Check and find object Id for new interface in mapNewIntfaceObjId (callbacks)
4564 // Throw an error if the new interface is not found!
4565 // Basically the compiler needs to parse the policy (and requires) files for callback class first
4566 private int getNewIntfaceObjectId(String newIntface) {
4568 int retObjId = mapNewIntfaceObjId.get(newIntface);
4573 // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, USERDEFINED, ENUM, or STRUCT
4574 private ParamCategory getParamCategory(String paramType) {
4576 if (mapPrimitives.containsKey(paramType)) {
4577 return ParamCategory.PRIMITIVES;
4578 // We can either use mapNonPrimitivesJava or mapNonPrimitivesCplus here
4579 } else if (mapNonPrimitivesJava.containsKey(getSimpleType(paramType))) {
4580 return ParamCategory.NONPRIMITIVES;
4581 } else if (isEnumClass(paramType)) {
4582 return ParamCategory.ENUM;
4583 } else if (isStructClass(paramType)) {
4584 return ParamCategory.STRUCT;
4586 return ParamCategory.USERDEFINED;
4590 // Return full class name for non-primitives to generate Java import statements
4591 // e.g. java.util.Set for Set
4592 private String getNonPrimitiveJavaClass(String paramNonPrimitives) {
4594 return mapNonPrimitivesJava.get(paramNonPrimitives);
4598 // Return full class name for non-primitives to generate Cplus include statements
4599 // e.g. #include <set> for Set
4600 private String getNonPrimitiveCplusClass(String paramNonPrimitives) {
4602 return mapNonPrimitivesCplus.get(paramNonPrimitives);
4606 // Get simple types, e.g. HashSet for HashSet<...>
4607 // Basically strip off the "<...>"
4608 private String getSimpleType(String paramType) {
4610 // Check if this is generics
4611 if(paramType.contains("<")) {
4612 String[] type = paramType.split("<");
4619 // Generate a set of standard classes for import statements
4620 private List<String> getStandardJavaIntfaceImportClasses() {
4622 List<String> importClasses = new ArrayList<String>();
4623 // Add the standard list first
4624 importClasses.add("java.util.List");
4625 importClasses.add("java.util.ArrayList");
4627 return importClasses;
4631 // Generate a set of standard classes for import statements
4632 private List<String> getStandardJavaImportClasses() {
4634 List<String> importClasses = new ArrayList<String>();
4635 // Add the standard list first
4636 importClasses.add("java.io.IOException");
4637 importClasses.add("java.util.List");
4638 importClasses.add("java.util.ArrayList");
4639 importClasses.add("java.util.Arrays");
4640 importClasses.add("java.util.Map");
4641 importClasses.add("java.util.HashMap");
4642 importClasses.add("java.util.concurrent.atomic.AtomicBoolean");
4643 importClasses.add("iotrmi.Java.IoTRMIComm");
4644 importClasses.add("iotrmi.Java.IoTRMICommClient");
4645 importClasses.add("iotrmi.Java.IoTRMICommServer");
4646 importClasses.add("iotrmi.Java.IoTRMIUtil");
4648 return importClasses;
4652 // Generate a set of standard classes for import statements
4653 private List<String> getStandardCplusIncludeClasses() {
4655 List<String> importClasses = new ArrayList<String>();
4656 // Add the standard list first
4657 importClasses.add("<vector>");
4658 importClasses.add("<set>");
4659 importClasses.add("\"IoTRMIComm.hpp\"");
4660 importClasses.add("\"IoTRMICommClient.hpp\"");
4661 importClasses.add("\"IoTRMICommServer.hpp\"");
4663 return importClasses;
4667 // Combine all classes for import statements
4668 private List<String> getAllLibClasses(Collection<String> stdLibClasses, Collection<String> libClasses) {
4670 List<String> allLibClasses = new ArrayList<String>(stdLibClasses);
4671 // Iterate over the list of import classes
4672 for (String str : libClasses) {
4673 if (!allLibClasses.contains(str)) {
4674 allLibClasses.add(str);
4677 return allLibClasses;
4682 // Generate a set of classes for import statements
4683 private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
4685 Set<String> importClasses = new HashSet<String>();
4686 for (String method : methods) {
4687 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4688 for (String paramType : methPrmTypes) {
4690 String simpleType = getSimpleType(paramType);
4691 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4692 importClasses.add(getNonPrimitiveJavaClass(simpleType));
4696 return importClasses;
4700 // Handle and return the correct enum declaration
4701 // In Java, if we declare enum in Camera interface, then it becomes "Camera.<enum>"
4702 private String getEnumParamDecl(String type, InterfaceDecl intDecl) {
4704 // Strips off array "[]" for return type
4705 String pureType = getSimpleArrayType(type);
4706 // Take the inner type of generic
4707 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4708 pureType = getTypeOfGeneric(type)[0];
4709 if (isEnumClass(pureType)) {
4710 String enumType = intDecl.getInterface() + "." + type;
4717 // Handle and return the correct type
4718 private String getEnumParam(String type, String param, int i) {
4720 // Strips off array "[]" for return type
4721 String pureType = getSimpleArrayType(type);
4722 // Take the inner type of generic
4723 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4724 pureType = getTypeOfGeneric(type)[0];
4725 if (isEnumClass(pureType)) {
4726 String enumParam = "paramEnum" + i;
4733 // Handle and return the correct enum declaration translate into int[]
4734 private String getEnumType(String type) {
4736 // Strips off array "[]" for return type
4737 String pureType = getSimpleArrayType(type);
4738 // Take the inner type of generic
4739 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4740 pureType = getGenericType(type);
4741 if (isEnumClass(pureType)) {
4742 String enumType = "int[]";
4748 // Handle and return the correct enum declaration translate into int* for C
4749 private String getEnumCplusClsType(String type) {
4751 // Strips off array "[]" for return type
4752 String pureType = getSimpleArrayType(type);
4753 // Take the inner type of generic
4754 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4755 pureType = getGenericType(type);
4756 if (isEnumClass(pureType)) {
4757 String enumType = "int*";
4764 // Handle and return the correct struct declaration
4765 private String getStructType(String type) {
4767 // Strips off array "[]" for return type
4768 String pureType = getSimpleArrayType(type);
4769 // Take the inner type of generic
4770 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4771 pureType = getGenericType(type);
4772 if (isStructClass(pureType)) {
4773 String structType = "int";
4780 // Check if this an enum declaration
4781 private boolean isEnumClass(String type) {
4783 // Just iterate over the set of interfaces
4784 for (String intface : mapIntfacePTH.keySet()) {
4785 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4786 EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
4787 Set<String> setEnumDecl = enumDecl.getEnumDeclarations();
4788 if (setEnumDecl.contains(type))
4795 // Check if this an struct declaration
4796 private boolean isStructClass(String type) {
4798 // Just iterate over the set of interfaces
4799 for (String intface : mapIntfacePTH.keySet()) {
4800 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4801 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4802 List<String> listStructDecl = structDecl.getStructTypes();
4803 if (listStructDecl.contains(type))
4810 // Return a struct declaration
4811 private StructDecl getStructDecl(String type) {
4813 // Just iterate over the set of interfaces
4814 for (String intface : mapIntfacePTH.keySet()) {
4815 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4816 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4817 List<String> listStructDecl = structDecl.getStructTypes();
4818 if (listStructDecl.contains(type))
4825 // Return number of members (-1 if not found)
4826 private int getNumOfMembers(String type) {
4828 // Just iterate over the set of interfaces
4829 for (String intface : mapIntfacePTH.keySet()) {
4830 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4831 StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4832 List<String> listStructDecl = structDecl.getStructTypes();
4833 if (listStructDecl.contains(type))
4834 return structDecl.getNumOfMembers(type);
4840 // Generate a set of classes for include statements
4841 private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl, String intface, boolean needExchange) {
4843 Set<String> includeClasses = new HashSet<String>();
4844 for (String method : methods) {
4846 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4847 List<String> methParams = intDecl.getMethodParams(method);
4848 for (int i = 0; i < methPrmTypes.size(); i++) {
4850 String genericType = getGenericType(methPrmTypes.get(i));
4851 String simpleType = getSimpleType(methPrmTypes.get(i));
4852 String param = methParams.get(i);
4853 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4854 includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">");
4855 //} else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) {
4857 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.USERDEFINED) {
4858 // For original interface, we need it exchanged... not for stub interfaces
4860 //includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\"");
4861 includeClasses.add("\"" + exchangeParamType(getSimpleArrayType(genericType)) + ".hpp\"");
4863 //includeClasses.add("\"" + simpleType + ".hpp\"");
4864 includeClasses.add("\"" + getSimpleArrayType(genericType) + ".hpp\"");
4867 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.ENUM) {
4868 includeClasses.add("\"" + genericType + ".hpp\"");
4870 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.STRUCT) {
4871 includeClasses.add("\"" + genericType + ".hpp\"");
4873 if (param.contains("[]")) {
4874 // Check if this is array for C++; translate into vector
4875 includeClasses.add("<vector>");
4879 return includeClasses;
4883 // Generate a set of callback classes
4884 private Set<String> getCallbackClasses(Collection<String> methods, InterfaceDecl intDecl) {
4886 Set<String> callbackClasses = new HashSet<String>();
4887 for (String method : methods) {
4889 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4890 List<String> methParams = intDecl.getMethodParams(method);
4891 for (int i = 0; i < methPrmTypes.size(); i++) {
4893 String type = methPrmTypes.get(i);
4894 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4895 callbackClasses.add(type);
4896 } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
4897 // Can be a List<...> of callback objects ...
4898 String genericType = getTypeOfGeneric(type)[0];
4899 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4900 callbackClasses.add(type);
4905 return callbackClasses;
4909 // Print import statements into file
4910 private void printImportStatements(Collection<String> importClasses) {
4912 for(String cls : importClasses) {
4913 println("import " + cls + ";");
4918 // Print include statements into file
4919 private void printIncludeStatements(Collection<String> includeClasses) {
4921 for(String cls : includeClasses) {
4922 println("#include " + cls);
4927 // Get the C++ version of a non-primitive type
4928 // e.g. set for Set and map for Map
4929 // Input nonPrimitiveType has to be generics in format
4930 private String[] getTypeOfGeneric(String nonPrimitiveType) {
4932 // Handle <, >, and , for 2-type generic/template
4933 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
4938 // Gets generic type inside "<" and ">"
4939 private String getGenericType(String type) {
4941 // Handle <, >, and , for 2-type generic/template
4942 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
4943 String[] substr = type.split("<")[1].split(">")[0].split(",");
4950 // This helper function strips off array declaration, e.g. int[] becomes int
4951 private String getSimpleArrayType(String type) {
4953 // Handle [ for array declaration
4954 String substr = type;
4955 if (type.contains("[]")) {
4956 substr = type.split("\\[\\]")[0];
4962 // This helper function strips off array declaration, e.g. D[] becomes D
4963 private String getSimpleIdentifier(String ident) {
4965 // Handle [ for array declaration
4966 String substr = ident;
4967 if (ident.contains("[]")) {
4968 substr = ident.split("\\[\\]")[0];
4974 // Checks and gets type in C++
4975 private String checkAndGetCplusType(String paramType) {
4977 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
4978 return convertType(paramType);
4979 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
4981 // Check for generic/template format
4982 if (paramType.contains("<") && paramType.contains(">")) {
4984 String genericClass = getSimpleType(paramType);
4985 String genericType = getGenericType(paramType);
4986 String cplusTemplate = null;
4987 cplusTemplate = getNonPrimitiveCplusClass(genericClass);
4988 if(getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED) {
4989 cplusTemplate = cplusTemplate + "<" + genericType + "*>";
4991 cplusTemplate = cplusTemplate + "<" + convertType(genericType) + ">";
4993 return cplusTemplate;
4995 return getNonPrimitiveCplusClass(paramType);
4996 } else if(paramType.contains("[]")) { // Array type (used for return type only)
4997 String cArray = "vector<" + convertType(getSimpleArrayType(paramType)) + ">";
4999 } else if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
5000 return paramType + "*";
5002 // Just return it as is if it's not non-primitives
5007 // Detect array declaration, e.g. int A[],
5008 // then generate "int A[]" in C++ as "vector<int> A"
5009 private String checkAndGetCplusArray(String paramType, String param) {
5011 String paramComplete = null;
5012 // Check for array declaration
5013 if (param.contains("[]")) {
5014 paramComplete = "vector<" + paramType + "> " + param.replace("[]","");
5016 // Just return it as is if it's not an array
5017 paramComplete = paramType + " " + param;
5019 return paramComplete;
5023 // Detect array declaration, e.g. int A[],
5024 // then generate "int A[]" in C++ as "vector<int> A"
5025 // This method just returns the type
5026 private String checkAndGetCplusArrayType(String paramType) {
5028 String paramTypeRet = null;
5029 // Check for array declaration
5030 if (paramType.contains("[]")) {
5031 String type = paramType.split("\\[\\]")[0];
5032 paramTypeRet = checkAndGetCplusType(type) + "[]";
5033 } else if (paramType.contains("vector")) {
5034 // Just return it as is if it's not an array
5035 String type = paramType.split("<")[1].split(">")[0];
5036 paramTypeRet = checkAndGetCplusType(type) + "[]";
5038 paramTypeRet = paramType;
5040 return paramTypeRet;
5044 // Detect array declaration, e.g. int A[],
5045 // then generate "int A[]" in C++ as "vector<int> A"
5046 // This method just returns the type
5047 private String checkAndGetCplusArrayType(String paramType, String param) {
5049 String paramTypeRet = null;
5050 // Check for array declaration
5051 if (param.contains("[]")) {
5052 paramTypeRet = checkAndGetCplusType(paramType) + "[]";
5053 } else if (paramType.contains("vector")) {
5054 // Just return it as is if it's not an array
5055 String type = paramType.split("<")[1].split(">")[0];
5056 paramTypeRet = checkAndGetCplusType(type) + "[]";
5058 paramTypeRet = paramType;
5060 return paramTypeRet;
5064 // Return the class type for class resolution (for return value)
5065 // - Check and return C++ array class, e.g. int A[] into int*
5066 // - Check and return C++ vector class, e.g. List<Integer> A into vector<int>
5067 private String checkAndGetCplusRetClsType(String paramType) {
5069 String paramTypeRet = null;
5070 // Check for array declaration
5071 if (paramType.contains("[]")) {
5072 String type = paramType.split("\\[\\]")[0];
5073 paramTypeRet = getSimpleArrayType(type) + "*";
5074 } else if (paramType.contains("<") && paramType.contains(">")) {
5075 // Just return it as is if it's not an array
5076 String type = paramType.split("<")[1].split(">")[0];
5077 paramTypeRet = "vector<" + getGenericType(type) + ">";
5079 paramTypeRet = paramType;
5081 return paramTypeRet;
5085 // Return the class type for class resolution (for method arguments)
5086 // - Check and return C++ array class, e.g. int A[] into int*
5087 // - Check and return C++ vector class, e.g. List<Integer> A into vector<int>
5088 private String checkAndGetCplusArgClsType(String paramType, String param) {
5090 String paramTypeRet = getEnumCplusClsType(paramType);
5091 if (!paramTypeRet.equals(paramType))
5092 // Just return if it is an enum type
5093 // Type will still be the same if it's not an enum type
5094 return paramTypeRet;
5096 // Check for array declaration
5097 if (param.contains("[]")) {
5098 paramTypeRet = getSimpleArrayType(paramType) + "*";
5099 } else if (paramType.contains("<") && paramType.contains(">")) {
5100 // Just return it as is if it's not an array
5101 String type = paramType.split("<")[1].split(">")[0];
5102 paramTypeRet = "vector<" + getGenericType(type) + ">";
5104 paramTypeRet = paramType;
5106 return paramTypeRet;
5110 // Detect array declaration, e.g. int A[],
5111 // then generate type "int[]"
5112 private String checkAndGetArray(String paramType, String param) {
5114 String paramTypeRet = null;
5115 // Check for array declaration
5116 if (param.contains("[]")) {
5117 paramTypeRet = paramType + "[]";
5119 // Just return it as is if it's not an array
5120 paramTypeRet = paramType;
5122 return paramTypeRet;
5126 // Is array or list?
5127 private boolean isArrayOrList(String paramType, String param) {
5129 // Check for array declaration
5132 else if (isList(paramType))
5140 // For return type we use retType as input parameter
5141 private boolean isArray(String param) {
5143 // Check for array declaration
5144 if (param.contains("[]"))
5152 private boolean isList(String paramType) {
5154 // Check for array declaration
5155 if (paramType.contains("List"))
5162 // Get the right type for a callback object
5163 private String checkAndGetParamClass(String paramType) {
5165 // Check if this is generics
5166 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
5167 return exchangeParamType(paramType);
5168 } else if (isList(paramType) &&
5169 (getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED)) {
5170 return "List<" + exchangeParamType(getGenericType(paramType)) + ">";
5176 // Returns the other interface for type-checking purposes for USERDEFINED
5177 // classes based on the information provided in multiple policy files
5178 // e.g. return CameraWithXXX instead of Camera
5179 private String exchangeParamType(String intface) {
5181 // Param type that's passed is the interface name we need to look for
5182 // in the map of interfaces, based on available policy files.
5183 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
5184 if (decHandler != null) {
5185 // We've found the required interface policy files
5186 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(intface);
5187 Set<String> setExchInt = reqDecl.getInterfaces();
5188 if (setExchInt.size() == 1) {
5189 Iterator iter = setExchInt.iterator();
5190 return (String) iter.next();
5192 throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() +
5193 ". Only one new interface can be declared if the object " + intface +
5194 " needs to be passed in as an input parameter!\n");
5197 // NULL value - this means policy files missing
5198 throw new Error("IoTCompiler: Parameter type lookup failed for " + intface +
5199 "... Please provide the necessary policy files for user-defined types." +
5200 " If this is an array please type the brackets after the variable name," +
5201 " e.g. \"String str[]\", not \"String[] str\"." +
5202 " If this is a Collections (Java) / STL (C++) type, this compiler only" +
5203 " supports List/ArrayList (Java) or list (C++).\n");
5208 public static void main(String[] args) throws Exception {
5210 // If there is no argument or just "--help" or "-h", then invoke printUsage()
5211 if ((args.length == 0 ||
5212 args[0].equals("-help") ||
5213 args[0].equals("--help")||
5214 args[0].equals("-h"))) {
5216 IoTCompiler.printUsage();
5218 } else if (args.length > 1) {
5220 IoTCompiler comp = new IoTCompiler();
5222 boolean driverDefined = false;
5223 boolean controllerDefined = false;
5225 // Look for "-drv" and "-cont"
5226 // These two need to be defined to complete the stub/skeleton generation
5227 // with the appropriate headers
5228 if (args[i].equals("-drv")) {
5229 comp.setDriverClass(args[i+1]);
5230 driverDefined = true;
5231 } else if (args[i].equals("-cont")) {
5232 System.out.println("DEBUG: Controller: " + args[i+1]);
5233 comp.setControllerClass(args[i+1]);
5234 controllerDefined = true;
5236 // Parse main policy file
5237 ParseNode pnPol = IoTCompiler.parseFile(args[i]);
5238 // Parse "requires" policy file
5239 ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
5240 // Get interface name
5241 String intface = ParseTreeHandler.getOrigIntface(pnPol);
5242 comp.setDataStructures(intface, pnPol, pnReq);
5243 comp.getMethodsForIntface(intface);
5246 // 1) Check if this is the last option before "-java" or "-cplus"
5247 // 2) Check if this is really the last option
5248 } while(!args[i].equals("-java") &&
5249 !args[i].equals("-cplus") &&
5252 // Generate error if we haven't seen -drv and -cont at this point
5253 if (!driverDefined || !controllerDefined) {
5254 String error = "IoTCompiler: ERROR - please provide arguments -drv and -cont " +
5255 "to specify both driver and controller class names.\n" +
5256 "Note: The two options have to come before -java and -cplus.\n";
5257 throw new Error(error);
5260 // Generate everything if we don't see "-java" or "-cplus"
5261 if (i == args.length) {
5262 comp.generateEnumJava();
5263 comp.generateStructJava();
5264 comp.generateJavaLocalInterfaces();
5265 comp.generateJavaInterfaces();
5266 comp.generateJavaStubClasses();
5267 comp.generateJavaSkeletonClass();
5268 comp.generateEnumCplus();
5269 comp.generateStructCplus();
5270 comp.generateCplusLocalInterfaces();
5271 comp.generateCPlusInterfaces();
5272 comp.generateCPlusStubClassesHpp();
5273 comp.generateCPlusStubClassesCpp();
5274 comp.generateCplusSkeletonClassHpp();
5275 comp.generateCplusSkeletonClassCpp();
5277 // Check other options
5278 while(i < args.length) {
5280 if (!args[i].equals("-java") &&
5281 !args[i].equals("-cplus")) {
5282 throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i] + "\n");
5284 if (i + 1 < args.length) {
5285 comp.setDirectory(args[i+1]);
5287 throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i] + "\n");
5289 if (args[i].equals("-java")) {
5290 comp.generateEnumJava();
5291 comp.generateStructJava();
5292 comp.generateJavaLocalInterfaces();
5293 comp.generateJavaInterfaces();
5294 comp.generateJavaStubClasses();
5295 comp.generateJavaSkeletonClass();
5297 comp.generateEnumCplus();
5298 comp.generateStructCplus();
5299 comp.generateCplusLocalInterfaces();
5300 comp.generateCPlusInterfaces();
5301 comp.generateCPlusStubClassesHpp();
5302 comp.generateCPlusStubClassesCpp();
5303 comp.generateCplusSkeletonClassHpp();
5304 comp.generateCplusSkeletonClassCpp();
5311 // Need to at least have exactly 2 parameters, i.e. main policy file and requires file
5312 IoTCompiler.printUsage();
5313 throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!\n");